Work-out-loud liveness: prompt guidance + observer last-activity indicator; role colors, autonomy/escalation policy
deploy / deploy (push) Canceled after 0s
deploy / deploy (push) Canceled after 0s
This commit is contained in:
@@ -16,6 +16,15 @@ function others(list: ParticipantView[], youId: string): string {
|
||||
return names.join(', ');
|
||||
}
|
||||
|
||||
/**
|
||||
* Liveness guidance appended to advice: the room has no presence signal
|
||||
* besides messages, so agents must narrate long local work instead of going
|
||||
* silent — the other side (and the human observer) cannot tell a busy agent
|
||||
* from a dead one.
|
||||
*/
|
||||
const WORK_OUT_LOUD =
|
||||
'Work out loud: before starting any local step that will take more than ~2 minutes (checking logs, running commands, waiting on a transfer), post a short message saying what you are about to do, and post the result when done. Never sit silent: either post progress or end your turn.';
|
||||
|
||||
/**
|
||||
* Computes the `what_you_should_do_next` hint so an agent does not have to
|
||||
* reconstruct negotiation state from the full chat log.
|
||||
@@ -40,7 +49,7 @@ export function computeAdvice(input: AdviceInput): string {
|
||||
const notJoined = input.participants.filter((p) => p.id !== you.id && !p.joined_at);
|
||||
const joinNote =
|
||||
notJoined.length > 0
|
||||
? `Note: ${notJoined.map((p) => p.role).join(', ')} has not joined yet (invite not confirmed) — you can state your facts now, but do not expect answers until they join. `
|
||||
? `Note: ${notJoined.map((p) => p.role).join(', ')} has not joined yet (invite not confirmed) — they cannot join until the HUMAN forwards them their invite URL, so make sure you have already given the human that link plus the observer URL. You can state your facts now, but do not expect answers until they join; do not sit in a polling loop — post what you have and end your turn. `
|
||||
: '';
|
||||
|
||||
const addressedToYou = openQuestions.filter(
|
||||
@@ -57,7 +66,8 @@ export function computeAdvice(input: AdviceInput): string {
|
||||
joinNote +
|
||||
`There ${blockingToYou.length === 1 ? 'is 1 blocking question' : `are ${blockingToYou.length} blocking questions`} waiting for you. ` +
|
||||
`First: "${first.question}" (asked by ${first.author_role}${first.addressed_to_role ? ` specifically of ${first.addressed_to_role}` : ''}). ` +
|
||||
'Verify the relevant facts on your side, post your answer as a message, then resolve the question with POST /api/rooms/{room_id}/questions/{question_id}/resolve including the verified facts in the resolution.'
|
||||
'Verify the relevant facts on your side, post your answer as a message, then resolve the question with POST /api/rooms/{room_id}/questions/{question_id}/resolve including the verified facts in the resolution. ' +
|
||||
WORK_OUT_LOUD
|
||||
);
|
||||
}
|
||||
|
||||
@@ -65,7 +75,8 @@ export function computeAdvice(input: AdviceInput): string {
|
||||
return (
|
||||
joinNote +
|
||||
`You have ${blockingFromYou.length === 1 ? 'an open blocking question' : `${blockingFromYou.length} open blocking questions`} that ${others(input.participants, you.id)} must answer. ` +
|
||||
'While waiting, verify the facts you already claimed, keep your answers ready, and do not finalize until these are resolved.'
|
||||
'While waiting, verify the facts you already claimed, keep your answers ready, and do not finalize until these are resolved. ' +
|
||||
WORK_OUT_LOUD
|
||||
);
|
||||
}
|
||||
|
||||
@@ -81,7 +92,7 @@ export function computeAdvice(input: AdviceInput): string {
|
||||
return (
|
||||
'All questions are resolved and no contract has been drafted yet. ' +
|
||||
`Draft the Agreed Contract now (sections: Facts, Decisions, Interface, Schedule, Authentication, Error handling, Unresolved) using PUT /api/rooms/{room_id}/contract, ` +
|
||||
'basing it only on verified facts from the conversation.'
|
||||
'basing it only on verified facts from the conversation. Every Decision must be executed by a participant (name who); do not assign anything to the human — the only human items allowed are HUMAN_BLOCKER entries in Unresolved, and only for things both sides agree no participant has the access or authority to do.'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -96,7 +107,8 @@ export function computeAdvice(input: AdviceInput): string {
|
||||
if (notAgreed.length > 0) {
|
||||
return (
|
||||
`You agreed to contract version ${contract.version}; waiting for ${notAgreed.map((a) => a.role).join(', ')} to agree to the same version. ` +
|
||||
'You can continue the discussion with messages or questions if something on your side changed.'
|
||||
'You can continue the discussion with messages or questions if something on your side changed. ' +
|
||||
WORK_OUT_LOUD
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,14 @@ export function renderObserverMarkdown(o: ObserverView, baseUrl: string): string
|
||||
parts.push('');
|
||||
parts.push(`**Whose turn:** ${o.turn}`);
|
||||
if (o.turn_waiting_for.length) parts.push(`**Waiting on:** ${o.turn_waiting_for.map((r) => `**${r}**`).join(', ')}`);
|
||||
const lastEvent = buildTimeline({
|
||||
participants: o.participants,
|
||||
conversation: o.conversation,
|
||||
openQuestions: o.open_questions,
|
||||
resolvedQuestions: o.resolved_questions,
|
||||
contract: o.current_contract,
|
||||
}).at(-1);
|
||||
if (lastEvent) parts.push(`**Last activity:** ${lastEvent.at} by **${lastEvent.role}** — ${lastEvent.action}`);
|
||||
parts.push('');
|
||||
parts.push(
|
||||
'Participants: ' +
|
||||
@@ -87,6 +95,8 @@ export function renderRoomMarkdown(i: MarkdownInput): string {
|
||||
parts.push('');
|
||||
parts.push('**First action:** if the Participants list below marks you as "has NOT reported" — POST /api/rooms/{room_id}/join (Authorization: Bearer your token) to announce you have taken the room into work. The other side sees it.');
|
||||
parts.push('');
|
||||
parts.push('**Work out loud:** the room has no presence signal except your messages. Before any local step longer than ~2 minutes, post a short "doing X" message; post the result when done. A silent participant is indistinguishable from a dead one — never sit silent: either post progress or end your turn.');
|
||||
parts.push('');
|
||||
parts.push(i.secretsPolicyShort);
|
||||
parts.push('');
|
||||
parts.push(`- **Goal:** ${i.goal || '(not set)'}`);
|
||||
|
||||
Reference in New Issue
Block a user