@ctrl-spc/cs 0.6.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,945 @@
1
+ /**
2
+ * ═══ AGENT PANEL v3: what an agent is told. ═══
3
+ *
4
+ * THIS FILE BELONGS TO AGENT PANEL v3. Nothing outside `src/panel3/` may
5
+ * import it.
6
+ *
7
+ * ---------------------------------------------------------------------------
8
+ * WHY THE WORDS LIVE HERE AND NOT IN THE DAEMON.
9
+ *
10
+ * `run.ts` is about leases, processes and rows: what may be taken, what is
11
+ * written before a spawn, what happens when a machine dies. This is product
12
+ * copy — it decides the words a person ends up reading — and the rules that
13
+ * govern it are not the rules that govern a lease. Kept in the daemon, the
14
+ * paragraph explaining why a reply may not say "dispatch" would sit three
15
+ * hundred lines from the sentence it is about.
16
+ *
17
+ * ---------------------------------------------------------------------------
18
+ * ═══ THE STRUCTURE IS ONE SENTENCE PLUS THE TOOL DESCRIPTIONS. NOTHING ELSE. ═══
19
+ *
20
+ * ux.md: "The structure v3 provides is exactly two things: a core responsibility
21
+ * per level, and the tools that level can reach. Everything else about how an
22
+ * agent behaves is left loose on purpose. There is no procedure, no required
23
+ * sequence, no router."
24
+ *
25
+ * So there is deliberately NO order of tool calls here, no mapping from a kind
26
+ * of request to the tool that answers it, and no instruction to read before
27
+ * writing. That flexibility is the thing the whole design exists to keep, and a
28
+ * prompt is exactly where it gets quietly spent.
29
+ *
30
+ * WHAT IS HERE BESIDES THE ONE SENTENCE IS NOT PROCEDURE. It is the facts of the
31
+ * situation an agent cannot discover for itself: that a person is reading the
32
+ * reply, that a person is watching while it works, that it cannot see code, and
33
+ * what that person has already said. None of those is a step.
34
+ *
35
+ * AND IT DOES NOT LIST WHAT THE RECORD HOLDS. An earlier draft enumerated
36
+ * projects, work items and artifacts here, which is the job ux.md gives to the
37
+ * tool's own description "because they travel with the tool" — and this is the
38
+ * one place in the file that would silently go stale the first time a tool is
39
+ * added and nobody thinks to look at a prompt.
40
+ *
41
+ * ---------------------------------------------------------------------------
42
+ * ═══ THE HOUSE VOCABULARY IS BANNED IN ANYTHING A PERSON READS. ═══
43
+ *
44
+ * ux.md: "The user perceives one voice, because no agent uses house vocabulary
45
+ * and the brief is the same at every level. Nothing in a reply reveals which
46
+ * level wrote it."
47
+ *
48
+ * The person asked about their own work. Agent, run, dispatch, level, card,
49
+ * turn, coordinator, orchestrator and worker all describe how the product went
50
+ * about answering them, which is not what they asked and not a vocabulary they
51
+ * should have to learn to read their own board. The ban is stated as a ban
52
+ * because it is not obvious: every one of those words is the natural one to
53
+ * reach for from inside, which is exactly why it leaks.
54
+ *
55
+ * ---------------------------------------------------------------------------
56
+ * ═══ WHAT IS MADE GOES IN THE THING. THE REPLY POINTS AT IT. ═══
57
+ *
58
+ * ux.md: "Output goes into the code or into a CTRL+SPC object, never into the
59
+ * chat. The chat carries pointers."
60
+ *
61
+ * THIS IS A FACT ABOUT THE SITUATION, WHICH IS WHY IT IS HERE AND NOT PROCEDURE.
62
+ * An agent writing into a plain chat window has no choice: prose is the only
63
+ * place its work can land, so restating what it produced is the only way the
64
+ * person sees it. Here it is the opposite, and the agent cannot tell from where
65
+ * it sits: every epic, item and document it creates is recorded against the
66
+ * conversation as it is made, and is already in front of the person as something
67
+ * they can open. Nothing about that is discoverable from a tool description,
68
+ * which says what a tool does and not what the screen already shows.
69
+ *
70
+ * SO THE FAILURE IS SPECIFIC, AND IT WAS MEASURED BEFORE THIS PARAGRAPH EXISTED.
71
+ * Asked for an epic with two items under it, level 1 created all three correctly
72
+ * and then wrote a summary of each item's description back into the reply. Both
73
+ * copies were real; only one of them is the one the person can edit, and the
74
+ * other starts going stale the moment they do. The rule is not about length.
75
+ *
76
+ * ---------------------------------------------------------------------------
77
+ * ═══ IT MUST NOT IMPLY A CODE TOOL, AND IT MUST NAME THE HONEST MOVE. ═══
78
+ *
79
+ * ux.md: "level 1 is never granted a code tool, so it cannot become the thing
80
+ * that does the work." That is already true mechanically — `spawn.ts` starts
81
+ * level 1 with `--tools ''` and the tools server serves no code tool at any
82
+ * level — so this file's job is not to enforce it. It is to stop the absence
83
+ * being expensive.
84
+ *
85
+ * THE FAILURE THAT COSTS THE USER IS NOT THE ABSENCE. It is an agent that
86
+ * answers a question about code from what it can infer and writes the answer in
87
+ * the voice of something that looked. The user cannot tell that apart from a
88
+ * real answer, and one of those makes every other answer untrustworthy. So the
89
+ * absence is stated plainly as a fact, and the honest move — send somebody who
90
+ * can look — is named beside it.
91
+ *
92
+ * ---------------------------------------------------------------------------
93
+ * ═══ A DISPATCHED WORK BRIEF HOLDS THE JOB, NOT THE CONVERSATION. ═══
94
+ *
95
+ * ux.md: "a fresh subagent needs its task, the interfaces it touches, and the
96
+ * global constraints. Nothing else", with the measured cost of the alternative —
97
+ * "a real session's dispatch hit 42k chars of which 99% was pasted history."
98
+ *
99
+ * So `workBrief` carries exactly two things written by judgement, the
100
+ * responsibility and the boundary, and the facts the product attaches. It
101
+ * carries NO messages, no earlier replies and no history. A level 3 worker gets
102
+ * that brief directly. A level 2 owner gets it inside `ownerActivationPrompt`,
103
+ * beside the visible conversation read from the card rather than a launcher
104
+ * retelling of it.
105
+ *
106
+ * ═══ AND IT IS THE SAME VOICE, WHICH IS WHY THE OUTBOUND RULES ARE SHARED. ═══
107
+ * ux.md: "the brief is the same at every level. Nothing in a reply reveals which
108
+ * level wrote it." Two copies of the ban on house vocabulary would be two copies
109
+ * that drift, and the drift is invisible: it shows up as one reply in ten
110
+ * mentioning a dispatch, from the level nobody re-read.
111
+ *
112
+ * ---------------------------------------------------------------------------
113
+ * ═══ WHAT SURVIVES A RESPAWN IS HANDED OVER AS THE INPUT, NOT OFFERED AS A
114
+ * TOOL. ═══
115
+ *
116
+ * ux.md: "The brief and the report are in the spawn's prompt, not behind a tool
117
+ * call the agent has to choose to make. An agent cannot fail to read its own
118
+ * input. This is the difference between a guarantee and a hope."
119
+ *
120
+ * `get_my_brief_and_report` still exists, for re-reading mid-run. It is not the
121
+ * delivery mechanism, and this file is: `resumePrompt` puts the brief and the
122
+ * report in front of an agent before it has decided anything.
123
+ *
124
+ * ═══ AND WHAT IT IS TOLD ABOUT WRITING ONE IS A FACT, NOT A PROCEDURE. ═══ The
125
+ * header above bans procedure here, and the ban holds: nothing below says when
126
+ * to write, in what order, or what to do first. What an agent CANNOT discover
127
+ * for itself is that it can be stopped and started again, and that the only
128
+ * thing that comes back with it is what it wrote down. Given that fact, writing
129
+ * it down is the obvious move rather than an instruction to comply with — and
130
+ * how to write it travels with `write_report`'s own description, where ux.md
131
+ * says the how belongs.
132
+ */
133
+ /**
134
+ * ═══ WHAT EVERY LEVEL IS TOLD ABOUT THE THING IT SENDS BACK. ═══
135
+ *
136
+ * One owner for the rules that decide how a reply reads, because the person is
137
+ * meant to hear one voice however many agents were involved. The one line that
138
+ * differs between levels is what an agent PRODUCED, and it differs for a real
139
+ * reason: level 1 makes objects the person can already open, and a dispatched
140
+ * agent changes code they cannot see from here.
141
+ */
142
+ const whatYouSendBack = (produced) => [
143
+ 'WHAT YOU SEND BACK',
144
+ 'Your reply is the whole of what they read, so write it to them, about their own work.',
145
+ '- By default, be very brief: use the shortest accurate reply that lets them understand the',
146
+ ' outcome, decide, or unblock the work.',
147
+ '- A routine update is absent unless it is useful, and then it is one short sentence or phrase.',
148
+ '- An ordinary completion starts with the outcome, includes only the result they need, and is one',
149
+ ' or two short sentences; never add a third.',
150
+ '- If the work cannot continue without a decision or input only the person can supply, you MUST',
151
+ ' call `ask_question`. This includes asking them to choose between options. That tool is the only',
152
+ ' person-question path: writing the question in an ordinary reply or completing the card with it',
153
+ ' is wrong. After the call, stop without repeating the question in an ordinary reply. Use only',
154
+ ' the minimum context they need to answer safely.',
155
+ '- Do not copy explanations, logs, prompts, internal reasoning, test inventories or internal',
156
+ ' orchestration into an ordinary reply.',
157
+ '- If they explicitly ask for detail, give it for that reply, then return to the brief default.',
158
+ ' Accuracy and truthful failures are never shortened away.',
159
+ '- Name the real things: the actual items, projects and people, by the names they have.',
160
+ ...produced,
161
+ '- Never name the machinery. Words like agent, run, dispatch, level, card, turn, coordinator,',
162
+ ' orchestrator and worker are ours and not theirs, and none of them belongs in something a',
163
+ ' person reads. The same goes for the line about what you are doing.',
164
+ '',
165
+ 'Reply with the text they should read, and nothing else.',
166
+ ];
167
+ /**
168
+ * ═══ WHAT A WORKER SENDS BACK, WHICH DOES NOT GO TO THE PERSON. ═══
169
+ *
170
+ * ux.md: "Each worker writes what it found into the record, and the level 2 agent
171
+ * reads them back", and the reply that reaches the person is written by that
172
+ * agent, once, covering all of them. So a worker's own words go to whoever sent
173
+ * it and nowhere else — `panel3_answer` puts them in its report rather than on
174
+ * the card — and it is TOLD so, because from where it sits the two are
175
+ * indistinguishable and the difference decides how it writes.
176
+ *
177
+ * THE BAN ON HOUSE VOCABULARY STAYS, for a reason it did not have at the other
178
+ * levels: what a worker writes is read by the agent that has to answer the
179
+ * person, and the phrases most likely to be quoted straight through are the ones
180
+ * that summarise. A sentence about dispatching a worker is one paste away from
181
+ * something a person reads.
182
+ */
183
+ const whatAWorkerSendsBack = () => [
184
+ 'WHAT YOU SEND BACK, AND WHO READS IT',
185
+ 'What you write at the end goes to whoever sent you, and to nobody else. They asked several',
186
+ 'people for several pieces and they put the answer together out of them, so nothing you write',
187
+ 'reaches the person except through them.',
188
+ '- Write it to somebody who has not seen any of this. They know what they asked you for and',
189
+ ' nothing about what you found, so say what you found or changed and where.',
190
+ '- Be complete about the things they could not know, and brief about everything else. Do not',
191
+ ' paste the code back: they can read it.',
192
+ '- If part of what you were given turned out not to be yours, or not to be there, say so plainly',
193
+ ' rather than working around it quietly.',
194
+ '- Never name the machinery. Words like agent, run, dispatch, level, card, turn, coordinator,',
195
+ ' orchestrator and worker are ours, and what you write may go on to a person word for word.',
196
+ '',
197
+ 'Reply with what they need to know, and nothing else.',
198
+ ];
199
+ /** The one line about being watched, which is true at every level: the activity
200
+ * line is the only sign a person has that anything is happening. */
201
+ const WHILE_YOU_ARE_WORKING = [
202
+ 'WHILE YOU ARE WORKING',
203
+ 'One line saying what you are doing is on their screen for as long as you are here, and it is',
204
+ 'the only sign that anything is happening at all. Say what you ARE doing, never what you are',
205
+ 'about to do: an intention that then falls through leaves them watching a sentence that was',
206
+ 'never true.',
207
+ ];
208
+ /**
209
+ * ═══ WHAT THE PERSON ATTACHED, AS A FACT AND NOTHING MORE. ═══
210
+ *
211
+ * plan-work-items.md constraint 5: "no agent is asked in prose to go and find
212
+ * what a card is about." So the LIST is one sentence saying the attaching
213
+ * happened and to whom it belongs, and nothing more. What it cannot discover on
214
+ * its own is that these specific ids are the ones the person meant, and that is
215
+ * the fact the list states.
216
+ *
217
+ * ═══ EACH KIND THEN GETS ONE SENTENCE SAYING WHAT THAT WORD MEANS. ═══ Three
218
+ * of them now, and the work item's is the one added last (the
219
+ * `work-lands-on-the-item-6` slice, off ux.md's "before an agent begins working
220
+ * on it, it must read the description, and any artifacts"). An earlier draft of
221
+ * this comment said none of them may tell the agent what to DO; that was true
222
+ * when a work item was only a subject. It is not the same rule as constraint 5,
223
+ * which forbids sending an agent LOOKING for which item a card is about. The id
224
+ * is handed over here by the product; reading the item it was handed is not
225
+ * finding it.
226
+ *
227
+ * SHARED between `levelOnePrompt` and `workBrief` for the same reason
228
+ * `whatYouSendBack` is: one wording for "what was attached", never two that
229
+ * drift.
230
+ */
231
+ const whatWasAttached = (attachments) => {
232
+ const codebases = attachments.filter((attachment) => attachment.startsWith('codebase '));
233
+ const personAttachments = attachments.filter((attachment) => !attachment.startsWith('codebase '));
234
+ const personAttachmentLines = personAttachments.length === 0 ? [] : [
235
+ '',
236
+ 'WHAT THE PERSON ATTACHED',
237
+ 'They attached these when they sent this, so what is asked belongs against them.',
238
+ ...personAttachments,
239
+ /* ═══ READ BEFORE YOU DECIDE, WHICH IS THE WHOLE OF THIS SLICE. ═══ ux.md:
240
+ "Before an agent begins working on it, it must read the description, and
241
+ any artifacts, and intelligently decide what to do next." An agent that
242
+ decides first and reads afterwards writes a second plan onto an item that
243
+ already carries one, against a description it never opened.
244
+
245
+ ═══ AND IT LIVES HERE, NOT UNDER `THE WORK ITEM THIS IS ABOUT`. ═══ That
246
+ header is the obvious home and it is the wrong one: `workItemId` comes
247
+ only from `dispatch`'s OPTIONAL `work_item_id`, which no prompt asks a
248
+ launcher to supply, and which the launcher MUST NOT supply when several
249
+ items are attached (the selection is the person's, below). So at exactly
250
+ the moment reading the items decides the answer, that header is absent.
251
+ This block is written from the person's own attachment rows, travels to
252
+ every dispatch on the card, and is shared by `levelOnePrompt` and
253
+ `workBrief`, so the sentence reaches all three levels. The tools it needs
254
+ — `get_work_item`, `list_artifacts`, `get_artifact` — are `levels: ALL`.
255
+
256
+ NO TOOL NAMES IN IT. `get_work_item` already says it returns "its
257
+ description, status, placement, and the artifacts on it", and
258
+ `list_artifacts` already ends "Use get_artifact to read one". The prompt
259
+ carries the obligation; the tool descriptions carry the mechanics. */
260
+ 'A `work_item` is what the work is about. Read its description and the artifacts already on it',
261
+ 'before you decide anything.',
262
+ /* ═══ THE KIND THAT IS A METHOD RATHER THAN A SUBJECT. ═══ A skill is not
263
+ one more thing the request belongs against: it is a method a person
264
+ chose, and an agent that read it as a subject would quote it back and
265
+ carry on doing the work its own way. That is the fact it cannot discover
266
+ from the line above, so it is the sentence added, and the tool's own
267
+ description carries the rest.
268
+
269
+ ═══ SAID WHENEVER ANYTHING IS ATTACHED, WHICH IS A CHOICE AND NOT AN
270
+ ACCIDENT. ═══ Both callers hold the rows, `kind` and all, so narrowing
271
+ this to cards that actually have a skill is available and was not
272
+ taken. The sentence is a DEFINITION of what that word means in the list
273
+ above, not an instruction to go and do something: a card with only a
274
+ work item attached reads past it, exactly as it reads past any other
275
+ word it has no use for. What narrowing would buy is one line on some
276
+ cards, against a second rule to keep true in a second place.
277
+
278
+ AND THE WORST CASE IS CHEAP AND HONEST. An agent that called
279
+ `get_skill` with a work item's id gets a failure through `only`, which
280
+ says there is no such row, rather than somebody else's document. */
281
+ 'A `skill` is a document written to be followed. Call `get_skill` with its id, read all of it,',
282
+ 'and do what it says for the rest of this work.',
283
+ /* ═══ THE ONE SENTENCE THAT IS TRUE AT EVERY LEVEL, WHICH IS WHY IT IS ONE
284
+ SENTENCE. ═══ `get_credential` is levels 2 and 3 only (Lane, 2026-08-19:
285
+ level 1 reads the NAME, the levels that do the work read the value), and
286
+ this wording is shared by `levelOnePrompt` and `workBrief` both. So it
287
+ says where the name is and who may read the value, rather than telling
288
+ anybody to call a tool: a coordinator reading it learns to write "use the
289
+ Stripe test key" into what it dispatches, and a worker reading it learns
290
+ there is a tool and an id to call it with. A "call get_credential"
291
+ sentence would be an instruction level 1 cannot follow, in level 1's own
292
+ prompt. */
293
+ 'A `credential` is a secret the person authorised for this work. Its name is above; the value',
294
+ 'is readable only by the agents doing the work, with `get_credential`.',
295
+ /* ═══ THE KIND THAT IS A SEQUENCE RATHER THAN A METHOD OR A SUBJECT. ═══ A
296
+ workflow says what happens in what order, and the fact an agent cannot
297
+ discover from the line above is that ONE of the three levels is the one
298
+ that reads it. So this names the ROLE rather than instructing anybody,
299
+ following the credential sentence's shape of naming a tool the reader may
300
+ not hold: `get_workflow` is level 2's alone, and `levelOnePrompt` already
301
+ calls the level 2 agent "the owner", so the word lands at every level this
302
+ one sentence reaches.
303
+
304
+ AND IT SAYS NOTHING ABOUT WORKING STAGES ONE AT A TIME. That rule
305
+ overrides a default written in `workBrief`'s own IF YOU SPLIT IT block, so
306
+ it lives inside that block and nowhere else. A second copy here would be a
307
+ second place for it to drift. */
308
+ 'A `workflow` is the process this work follows: stages, in an order it gives. The owner of this',
309
+ 'conversation is the one who reads it, with `get_workflow`.',
310
+ ];
311
+ return [
312
+ ...(codebases.length === 0 ? [] : [
313
+ '',
314
+ 'THE CODEBASES THIS CARD TOUCHES',
315
+ ...codebases,
316
+ 'For a dispatched piece, its one codebase is named separately below. The other selected',
317
+ 'codebases are separate work, not missing folders, so do not look for or report on them.',
318
+ ]),
319
+ ...personAttachmentLines,
320
+ ];
321
+ };
322
+ const projectCodebases = (codebases) => {
323
+ if (codebases === null)
324
+ return [];
325
+ return [
326
+ '',
327
+ 'THE CODEBASES REGISTERED ON THIS PROJECT',
328
+ ...(codebases.length === 0
329
+ ? [
330
+ 'There are none. If this needs code, ask the person to add a codebase to this project and',
331
+ 'stop. Work that does not need code can continue.',
332
+ ]
333
+ : [
334
+ ...codebases.map((codebase) => (`${codebase.name} — id ${codebase.id} — ${codebase.identity} — `
335
+ + (codebase.located ? 'located on this machine' : 'not located on this machine'))),
336
+ 'Choose the codebase that contains the work and include its id when you send somebody.',
337
+ 'If several codebases are needed, send one person per codebase. If the request does not make',
338
+ 'the choice clear, call `ask_question` once with `answer_mode` set to `multi_select`, put the',
339
+ 'plausible codebase names in `options`, and stop. Do not write a question as your reply.',
340
+ ]),
341
+ ];
342
+ };
343
+ /**
344
+ * The card's name and the messages waiting on it, as one prompt for a level 1
345
+ * agent. It carries no path, no id and nothing about this machine, so nothing in
346
+ * it can breach the rule that an absolute local path never reaches the database
347
+ * — which matters because the daemon writes it to `panel3_runs.brief`.
348
+ *
349
+ * ═══ `cardTitle` IS A NAME, NOT THE QUESTION, AND ITS LABEL SAYS SO. ═══ `say`
350
+ * fixes it once, as the truncated first line of the FIRST message, and never
351
+ * changes it. Labelled as what is being asked, a second turn would tell the
352
+ * agent the current question is a stale half-sentence and then hand it the real
353
+ * ones underneath — so the label names the conversation, which is all the title
354
+ * has ever been.
355
+ *
356
+ * ═══ `produced` IS LEVEL 1's REPORT, AND IT IS HERE FOR THE SAME REASON THE
357
+ * REPORT IS IN A RESPAWN'S PROMPT. ═══
358
+ *
359
+ * Every turn on a card is answered by a fresh level 1 agent that remembers
360
+ * nothing, and the thing it most needs from the last one is WHAT THAT ONE MADE.
361
+ * Measured before this existed, and it is user-visible: asked to add items to an
362
+ * epic it had created a turn earlier, level 1 could not find the epic — nothing
363
+ * served a card's own receipts and there is no `list_epics` — so it created two
364
+ * items under no epic at all. "Add three more to that epic" simply failed.
365
+ *
366
+ * A run's report and a card's receipts are the same instrument at the two
367
+ * levels: what is already done, carried across a death. So they arrive the same
368
+ * way, in the prompt rather than behind a tool call, and for the same stated
369
+ * reason — an agent cannot fail to read its own input.
370
+ *
371
+ * THE NAMES IN IT ARE READ NOW, NOT WHEN THE RECEIPT WAS WRITTEN, which is
372
+ * `show.ts`'s rule and its bug: a label written at creation and printed after a
373
+ * rename names a different, real object. The caller resolves them.
374
+ */
375
+ export function levelOnePrompt(cardTitle, messages, produced, attachments = [], codebases = null) {
376
+ return [
377
+ 'You are the short-lived launcher for one CTRL+SPC conversation. You do not do the work and',
378
+ 'you do not answer the person. Your whole job is to clarify the destination once if you truly',
379
+ 'cannot choose it, or launch exactly one owner and then exit.',
380
+ '',
381
+ 'WHAT YOU CAN SEE',
382
+ 'Your tools read the record. Read as much of it as the question needs.',
383
+ 'If they ask what is happening, look rather than guess: everything already under way stays exactly',
384
+ 'where it is while you read, and nothing about being asked slows it down.',
385
+ '',
386
+ 'WHAT YOU CANNOT SEE',
387
+ 'You have no way to open a file, search a codebase or run anything. That is deliberate and it',
388
+ 'is not a fault to apologise for. NEVER guess at what the code does, and never write as though',
389
+ 'you had looked: they cannot tell a real answer from a plausible one, so one invented answer',
390
+ 'makes every true one worthless.',
391
+ '',
392
+ 'WHAT YOU CAN SEND SOMEBODY TO DO',
393
+ 'Launch one owner for the conversation. Give it the complete responsibility and boundary. If',
394
+ 'the request belongs to a registered codebase, name it. If it is record-only work, launch it',
395
+ 'without a codebase. The owner talks to the person and may send workers of its own.',
396
+ 'Your only question is a destination or codebase you truly cannot choose. NEVER ask the person',
397
+ 'to make a work or product decision. When one registered codebase clearly fits, launch its owner',
398
+ 'even if the work itself needs the person to choose between options; the owner asks that question.',
399
+ ...projectCodebases(codebases),
400
+ '',
401
+ ...WHILE_YOU_ARE_WORKING,
402
+ '',
403
+ 'WHAT THIS CONVERSATION IS CALLED',
404
+ cardTitle,
405
+ '',
406
+ 'WHAT HAS ALREADY BEEN MADE HERE',
407
+ 'Everything this conversation has produced so far, whatever it was that made it, with the id to',
408
+ 'use for each. Anything they call "that epic" or "the item you made" is in this list. Put new',
409
+ 'work inside what is already there rather than making a second one that means the same thing.',
410
+ ...(produced.length === 0 ? ['Nothing has been made here yet.'] : produced),
411
+ ...whatWasAttached(attachments),
412
+ '',
413
+ 'WHAT THEY HAVE SAID THAT NOBODY HAS ANSWERED YET, OLDEST FIRST.',
414
+ 'They are one sequence, and a later one may correct an earlier one.',
415
+ '',
416
+ ...messages.map((body, i) => `${i + 1}. ${body}`),
417
+ '',
418
+ 'AFTER YOU LAUNCH THE OWNER, EXIT IMMEDIATELY. Do not write a reply, wait for it, summarize what',
419
+ 'it will do, or ask another question. CTRL+SPC publishes no stdout from this launcher.',
420
+ ].join('\n');
421
+ }
422
+ /**
423
+ * What an agent sent to do a piece of work is told: its own job, the facts of
424
+ * where it is, and nothing about the conversation it came out of.
425
+ *
426
+ * ═══ THIS IS THE IMMUTABLE BRIEF. ═══ `panel3_runs.brief` stores it exactly.
427
+ * A level 3 process is started with it directly; a level 2 owner's activation
428
+ * prompt carries it verbatim with the live conversation around it.
429
+ *
430
+ * ═══ AND IT CARRIES NO PATH, WHICH IS CONSTRAINT 6. ═══ The working copy is
431
+ * the directory the process is started in, so it never has to be named — and
432
+ * because this text is stored, naming it would put an absolute filesystem path
433
+ * in the database. The same rule is passed on to the agent for what it writes,
434
+ * because its report and its reply are stored too.
435
+ *
436
+ * ═══ AND WHAT THE CARD HAS ATTACHED TRAVELS WITH EVERY DISPATCH ON IT, NOT
437
+ * JUST THE FIRST. ═══ `workItemId` is a single item the DISPATCHING agent
438
+ * chose to name for this one piece of work; `attachments` is the set the
439
+ * PERSON pointed the whole card at, and level 1 did not choose it and cannot
440
+ * un-choose it for whoever it sends. Without it, only the coordinator that
441
+ * happened to be spawned first would ever see what the conversation is about.
442
+ * Every child it starts, and every grandchild THEY start, would be working
443
+ * from nothing but a responsibility sentence somebody else wrote down.
444
+ */
445
+ export function workBrief(level, responsibility, boundary, workItemId, attachments = [], codebase) {
446
+ /* ═══ ONLY WHEN A WORKFLOW IS ACTUALLY ON THE CARD. ═══ An owner is not
447
+ instructed about a process that is not there, which is the rule
448
+ `personAttachmentLines` already keeps by rendering nothing when nothing is
449
+ attached. The same prefix `whatWasAttached` partitions on, since both read
450
+ the one line `attachmentLine` writes. */
451
+ const hasWorkflow = attachments.some((attachment) => attachment.startsWith('workflow '));
452
+ return [
453
+ ...(level === 2
454
+ ? [
455
+ 'You see one thing a person asked for through to done. Keep the whole picture and stay',
456
+ 'available to the person while the work moves.',
457
+ '',
458
+ /* ═══ THE FIRST THING, EVERY TIME, AND IT IS NOT THE REPLY. ═══ Nothing
459
+ an owner writes reaches the person until its process exits, and a turn
460
+ that exits by asking writes no message at all. So on the walk of
461
+ 2026-08-24 "Write a plan for this item" was silent for two and a half
462
+ minutes and then said a question, twice over, and Lane's requirement
463
+ is that every message he sends is acknowledged. `say` is the only
464
+ thing that can do that, because an acknowledgement cannot be an exit.
465
+ WRITTEN AS THE FIRST INSTRUCTION IN THE BRANCH because it is the first
466
+ act, and a rule about what to do first that arrives after four
467
+ paragraphs about the work is read after the work has started. */
468
+ 'FIRST, SAY WHAT YOU ARE GOING TO DO',
469
+ 'They have seen their own message and nothing else. Before you start, call `say` with one or',
470
+ 'two sentences: what you are about to do about what they asked, and what they will get back.',
471
+ 'Do this every time you are started with something new from them, including the very first',
472
+ 'time, and before any reading that takes a while. It does not end your turn and it is not',
473
+ 'your reply; you carry on straight afterwards.',
474
+ '',
475
+ 'TRACEABILITY BEFORE A CODEBASE FILE CHANGES',
476
+ 'A codebase-file change means ANY file change: source, config, docs, tests, migrations,',
477
+ 'generated inputs, and assets all count. "Non-code" means no codebase file changes at all.',
478
+ 'When this work has a Work Item and will change a codebase file, you may investigate',
479
+ 'read-only first. Any investigation you send must explicitly forbid file edits. Create one',
480
+ 'useful `analysis` or `plan` artifact on the exact Work Item, carrying the document the work',
481
+ 'is missing: a spec, a PRD, user stories or a repro is its CONTENT, not a second artifact.',
482
+ 'For a bug: what reproduces it, the behaviour it has now, the behaviour it should have, the',
483
+ 'cause and the correction. For something new: what a person will be able to do, and how you',
484
+ 'would know it works.',
485
+ 'If several Work Items were supplied, one is selected only when the person identifies it by',
486
+ 'name, id, or an unambiguous reference in a message or answer. That selection stays in force',
487
+ 'unless the person changes it. An attachment label, its order, similarity, or which seems most',
488
+ 'likely is NEVER a selection by itself; the person explicitly referring to that label IS a',
489
+ 'selection.',
490
+ 'Until one is selected, do not',
491
+ 'call `update_work_item`, create or update an artifact, dispatch work, or change any file.',
492
+ 'Call `ask_question` once with no `work_item_id`, `answer_mode: single_select`, and the exact',
493
+ 'attached Work Item names as options, and then stop.',
494
+ 'Present the artifact with `ask_question`: name both `work_item_id` and',
495
+ '`related_artifact_id`, use `answer_mode: single_select` with `approve` and',
496
+ '`request changes`, and stop. Do not edit any file OR dispatch implementation until the',
497
+ 'artifact revision that question presented is approved. If changes are requested, use',
498
+ '`update_artifact` on the SAME artifact, present its new revision in a new approval question,',
499
+ 'and apply that same no-edit, no-implementation-dispatch fence until it is approved.',
500
+ 'The only bypass is the person explicitly asking you to change codebase files WITHOUT a',
501
+ 'Work Item artifact. Urgency, smallness, silence, or a generic "go ahead" is not a bypass.',
502
+ 'When no codebase file will change, this gate does not apply.',
503
+ '',
504
+ 'WHO DOES THE WORK IS YOUR JUDGEMENT',
505
+ 'Substantial implementation, investigation, testing, and other substantial work normally',
506
+ 'goes to the people you send. Before you start substantial multi-part work, send at least',
507
+ 'one meaningful independent implementation, investigation, or test part. Multiple independent',
508
+ 'file, module, or test parts belong with the people you send by default; do not keep all of',
509
+ 'them just because you could complete every piece yourself.',
510
+ 'Skip sending only when the whole turn is very small, or when sending any meaningful',
511
+ 'independent part would genuinely make the result slower or less accurate. You keep the full',
512
+ 'picture, answer the person, and put the results together.',
513
+ /* ═══ SENDING COMES BEFORE READING, AND THAT IS ABOUT THE PERSON RATHER
514
+ THAN ABOUT THROUGHPUT. ═══ The person reads nothing until this process
515
+ exits, so every minute the owner spends reading the codebase before it
516
+ sends anybody is a minute of pulse and no words. Measured on
517
+ 2026-08-24: 101 seconds to the first message, of which about 80 were
518
+ the owner reading first and sending second.
519
+ IT IS STILL NOT A GATE. `ux.md` deleted the manager that never touches
520
+ code because that shape "required the coordinator to predict, at
521
+ dispatch time, whether a request was big. It cannot", and Issue 3 made
522
+ this judgement "never a mechanical gate". So this is which order to do
523
+ two things the owner was already going to do, not a rule about
524
+ whether. The paragraph above still decides whether. */
525
+ '',
526
+ 'WHEN YOU ARE GOING TO SEND SOMEBODY, SEND THEM FIRST',
527
+ 'Read what you need to write their piece, and no more; the rest of the reading is theirs to',
528
+ 'do. Nothing you write reaches the person until you stop, so every minute you spend reading',
529
+ 'before you send anybody is a minute they watch a line with no answer coming.',
530
+ '',
531
+ 'IF YOU SPLIT IT',
532
+ 'Everybody you send works in the SAME copy of the codebase as everybody else, at the same',
533
+ 'time. Nothing keeps them out of each other\'s way, so anybody CHANGING files needs a piece',
534
+ 'that touches nobody else\'s files, or has to be sent on their own.',
535
+ /* ═══ AND A WORKFLOW OVERRIDES THAT DEFAULT, INSIDE THE BLOCK THAT SETS
536
+ IT. ═══ Six lines above, the owner is told the opposite: multiple
537
+ independent parts belong with the people it sends, all working at the
538
+ same time. A workflow's stages ARE multiple parts, so without a
539
+ precedence rule the owner sends them all at once, the read-back
540
+ barrier restarts it ONCE, and the order the person chose the workflow
541
+ for is gone. Nothing in the record refuses a second dispatch before
542
+ the first has ended — the barrier re-arms an owner when EVERY child
543
+ has finished, which sequences stages only because the owner sends one
544
+ at a time. So the rule is here, in the immutable brief that is
545
+ replayed verbatim on every restart, and therefore in front of the
546
+ owner at every stage boundary rather than only the first.
547
+
548
+ THE SECOND SENTENCE IS NOT DECORATION. A dispatched worker gets a
549
+ working copy and the responsibility and boundary AND NOTHING ELSE, and
550
+ `get_workflow` is this level's alone. Without it, the product takes
551
+ deliberate trouble to hand the owner an untruncated stage document and
552
+ the agent that performs the stage receives a paraphrase of it. */
553
+ ...(hasWorkflow
554
+ ? [
555
+ 'A WORKFLOW IS ATTACHED, AND ITS STAGES GO OUT ONE AT A TIME. Send somebody for the',
556
+ 'first stage only, and do not start the next stage until the one before it has come',
557
+ 'back. When you send somebody for a stage, put that stage\'s own document into what you',
558
+ 'give them, in full: they cannot read the workflow themselves.',
559
+ ]
560
+ : []),
561
+ 'What you have already sent somebody to do is written down, and you are handed that list',
562
+ 'rather than having to remember it. Anything on it has been sent. Nothing on it is sent again.',
563
+ 'When every one of them has finished you are started again, with what each of them wrote,',
564
+ 'to put it together and answer. Nothing any of them writes reaches the person except',
565
+ 'through you, so the reply that covers all of it is yours to write and nobody else\'s.',
566
+ 'WHICH MEANS THE REPLY YOU WRITE NOW IS NOT THAT ANSWER. If you have sent anybody, you are',
567
+ 'stopping in the middle, and what you write as you stop goes to the person as a message from',
568
+ 'you. Write it. One short sentence, naming what has gone out and what you are waiting on:',
569
+ 'the real answer is the one you write when you come back. Never stop silently. What you said',
570
+ 'with `say` was about to happen; this is what has happened and what is still to come.',
571
+ ]
572
+ : [
573
+ 'You own one piece of the work, the one below, and nothing else. Whoever sent you is doing',
574
+ 'the rest. If your responsibility is investigation-only, read and report without changing',
575
+ 'any file. The conversation owner handles the Work Item artifact and approval; do not',
576
+ 'duplicate that record. If you were given approved implementation work, make that change.',
577
+ '',
578
+ 'Somebody else may be working in this same copy of the codebase at the same time as you, on',
579
+ 'a different piece. Stay inside what you were given and leave the rest of it alone.',
580
+ ]),
581
+ '',
582
+ 'WHAT YOU OWN',
583
+ responsibility,
584
+ '',
585
+ 'WHAT YOU MUST LEAVE ALONE',
586
+ boundary,
587
+ ...(workItemId ? ['', 'THE WORK ITEM THIS IS ABOUT', workItemId] : []),
588
+ ...whatWasAttached(attachments),
589
+ ...(codebase ? [
590
+ '',
591
+ 'THE CODEBASE THIS WORK BELONGS TO',
592
+ `${codebase.name} — id ${codebase.id} — ${codebase.identity}`,
593
+ ] : []),
594
+ '',
595
+ 'WHERE YOU ARE',
596
+ ...(codebase
597
+ ? [
598
+ 'The directory you are in is a working copy of the codebase. Read it, run things in it, and',
599
+ 'change it where that is what you were asked for. Name a file by its path inside this copy,',
600
+ 'never by the full path from the root of this machine: the full one means nothing to the person',
601
+ 'reading and is not ours to hand around.',
602
+ ]
603
+ : [
604
+ 'The directory you are in is an empty private workspace. No codebase checkout was attached to',
605
+ 'this conversation. Work from the record and the tools you have; do not claim to have read or',
606
+ 'changed project files.',
607
+ ]),
608
+ '',
609
+ 'WHAT YOU WERE AND WERE NOT GIVEN',
610
+ ...(level === 2
611
+ ? [
612
+ 'This brief is your immutable responsibility and boundary. The visible conversation is',
613
+ 'handed to you separately, in chronological order, whenever you are started. Read it as the',
614
+ 'person wrote it; the launcher does not stand in for it. If something you genuinely need is',
615
+ 'missing and only the person can supply it, you MUST call `ask_question` and stop instead',
616
+ 'of saying it in your reply. Otherwise say what is missing plainly rather than guessing.',
617
+ ]
618
+ : [
619
+ 'What is above is the whole of it. You have not seen what anybody said, and you are not meant',
620
+ 'to: what matters was written into what you own. If something you genuinely need is missing,',
621
+ 'say so plainly in your reply rather than guessing at it.',
622
+ ]),
623
+ '',
624
+ 'WHAT CANNOT BE DECIDED HERE',
625
+ 'Some things are not yours to settle, and guessing at one of those quietly is worse than any',
626
+ 'delay: the work goes on top of an assumption nobody made and nobody can see. Asking stops you',
627
+ 'where you are, and you are started again with the answer when there is one, so nothing you have',
628
+ 'done is lost by asking. Questions already asked on this work, and what they were answered with,',
629
+ 'are there to be read, and one of them may be yours.',
630
+ '',
631
+ 'YOU CAN BE STOPPED, AND WHAT YOU WROTE DOWN IS ALL THAT COMES BACK WITH YOU',
632
+ 'This machine can go down and take you with it, mid-sentence, with no warning and no chance to',
633
+ 'tidy up. When that happens you are started again with what is above and with the notes you last',
634
+ 'wrote down, and with nothing else: not what you had in your head, not what you had just decided,',
635
+ 'not what you were halfway through. Notes written at the end of the work are notes that were',
636
+ 'never written.',
637
+ '',
638
+ ...WHILE_YOU_ARE_WORKING,
639
+ '',
640
+ ...(level === 2
641
+ ? whatYouSendBack([
642
+ '- Nobody rewrites what you send. It goes to them as you wrote it, so it has to stand on its',
643
+ ' own: answer the thing that was asked, and say what you changed and where, without pasting',
644
+ ' the code back. They can read the code; they cannot read your reasoning.',
645
+ ])
646
+ : whatAWorkerSendsBack()),
647
+ ].join('\n');
648
+ }
649
+ export const presentedArtifactAnswerContext = (artifact) => artifact === null
650
+ ? []
651
+ : artifact.answer === 'request changes'
652
+ ? [
653
+ '',
654
+ 'ARTIFACT REVISION THIS ANSWER SENT BACK FOR CHANGES',
655
+ `Artifact ${artifact.id}, revision ${artifact.revision}.`,
656
+ 'Do not edit any codebase file or dispatch implementation. Revise this SAME artifact as the',
657
+ 'person requested, present its new revision in a new approval question, and stop.',
658
+ ]
659
+ : [
660
+ '',
661
+ 'ARTIFACT REVISION THIS ANSWER APPROVED',
662
+ `Artifact ${artifact.id}, revision ${artifact.revision}.`,
663
+ 'Before editing any file or dispatching implementation, call `get_artifact` and compare its',
664
+ 'current revision with this one. If they differ, this answer does not approve the current body:',
665
+ 'present the current revision in a new approval question and stop.',
666
+ ];
667
+ /**
668
+ * ═══ WHAT A RUN IS TOLD WHEN A PROCESS OF ITS OWN ENDED BEFORE IT FINISHED.
669
+ * ═══
670
+ *
671
+ * Named once here rather than written inline, because `respawnPrompt` says both
672
+ * of these too, in its own longer wording (`WHAT YOU ALREADY SENT SOMEBODY TO
673
+ * DO`, and `CARRY ON FROM WHERE THAT LEAVES YOU`). **The two must move
674
+ * together.** They are not folded into one string because doing that would
675
+ * rewrite prose that is already shipped and proven on the retry and recovery
676
+ * paths, which is not this slice's assignment; naming them is what makes the
677
+ * pairing findable by the next person to edit either.
678
+ *
679
+ * ═══ THEY SAY WHAT TO DO, AND NEVER WHY IT HAPPENED. ═══ Three things end a
680
+ * process early and they are not the same event: a harness that crashed, a
681
+ * machine that went down, and a person who said the work was going the wrong
682
+ * way. `resumePrompt` and `retryPrompt` exist as two functions precisely
683
+ * because telling an agent an untrue reason for its restart is what this file
684
+ * exists to prevent, so a sentence shared by all three may only say the part
685
+ * that is true of all three.
686
+ */
687
+ const DO_NOT_SEND_SOMEBODY_TWICE = 'Do not send somebody to do a piece of work that is already in this list. Anything of theirs '
688
+ + 'still going is still going, and asking again for what they are already doing costs the person twice.';
689
+ const LOOK_AT_THE_WORK_ITSELF = 'A process of yours ended before it finished, so what you last wrote down is what you had time to '
690
+ + 'write, not everything that happened. Where your notes are silent, look at the work itself rather '
691
+ + 'than starting it over.';
692
+ /**
693
+ * The complete one-shot context for the durable conversational owner.
694
+ *
695
+ * Visible history is supplied as one ordered list. A newly leased message is
696
+ * marked in place rather than appended, and a question plus its canonical
697
+ * answer is one event, so neither can occur twice in the prompt.
698
+ */
699
+ export function ownerActivationPrompt(brief, report, events, children, childQuestion, currentArtifactAnswer = null,
700
+ /** A process of this run's own ended before it finished, so the working copy
701
+ * may hold work no report mentions and the worker list may hold one it
702
+ * dispatched a moment before. Never says WHICH ending it was: see
703
+ * `LOOK_AT_THE_WORK_ITSELF`. */
704
+ afterAProcessEnded = false) {
705
+ const history = events.map((event) => {
706
+ if (event.kind === 'question') {
707
+ return [
708
+ `CTRL+SPC QUESTION ${event.body}`,
709
+ event.answer ? `PERSON ANSWER ${event.answer}` : 'PERSON ANSWER waiting',
710
+ ...(event.relatedArtifactId && event.relatedArtifactRevision
711
+ ? [`PRESENTED ARTIFACT ${event.relatedArtifactId}, revision ${event.relatedArtifactRevision}`]
712
+ : []),
713
+ ...presentedArtifactAnswerContext(currentArtifactAnswer?.questionId === event.id
714
+ ? currentArtifactAnswer
715
+ : null),
716
+ ].join('\n');
717
+ }
718
+ const who = event.kind === 'user' ? 'PERSON' : 'CTRL+SPC';
719
+ return `${who}${event.needsReply ? ` — REPLY TO THIS NOW (turn ${event.id})` : ''}\n${event.body}`;
720
+ });
721
+ return [
722
+ 'YOU OWN THIS CTRL+SPC CONVERSATION.',
723
+ 'You are this conversation\'s one owner, started for one serialized activation. Speak directly to the',
724
+ 'person as CTRL+SPC. The launcher is finished and cannot answer or receive an escalation.',
725
+ '',
726
+ 'VISIBLE CONVERSATION, OLDEST FIRST',
727
+ ...(history.length === 0 ? ['Nothing has been said yet.'] : history),
728
+ ...(childQuestion === null ? [] : [
729
+ '',
730
+ 'A WORKER NEEDS YOUR DECISION',
731
+ `Question ${childQuestion.id}: ${childQuestion.question}`,
732
+ 'Answer it with answer_escalation if you can. If the person must decide, ask them directly.',
733
+ ]),
734
+ '',
735
+ 'WHAT YOU LAST WROTE DOWN',
736
+ report ?? 'Nothing yet.',
737
+ '',
738
+ 'PRIVATE WORKER SNAPSHOT',
739
+ ...(children.length === 0 ? ['You have sent nobody.'] : children),
740
+ ...(afterAProcessEnded ? ['', LOOK_AT_THE_WORK_ITSELF, DO_NOT_SEND_SOMEBODY_TWICE] : []),
741
+ '',
742
+ // THE BRIEF IS LAST, and these go before it: the brief ends with how to
743
+ // write the reply, and anything after it pushes that ending into the middle.
744
+ 'YOUR IMMUTABLE BRIEF',
745
+ brief,
746
+ ].join('\n');
747
+ }
748
+ /**
749
+ * What an agent that was stopped is started again with: the same brief, its own
750
+ * notes, and what it already sent others to do.
751
+ *
752
+ * ═══ THE BRIEF IS CARRIED VERBATIM AND IS THE LAST THING IN IT. ═══ Verbatim
753
+ * because ux.md fixes it at dispatch — "a respawn is given the same instruction
754
+ * the first attempt was" — so this must not summarise, shorten or re-derive it.
755
+ * Last because the brief ENDS with how to write the reply, and that ending is
756
+ * the one an ordinary spawn has: putting the resumption after it would push the
757
+ * outbound rules into the middle of the prompt and leave a note about a dead
758
+ * process as the final word.
759
+ *
760
+ * ═══ THE REPORT IS WHAT THE RUN WROTE, AND NOTHING ELSE. ═══ It is deliberately
761
+ * lossy (ux.md), because the record holds the detail — the receipts, the
762
+ * activity and the commits are all still there to be read. This carries the
763
+ * state to resume from, not an archive.
764
+ *
765
+ * ═══ `children` IS READ LIVE BY THE CALLER, WHICH IS THE RULE THAT DECIDES
766
+ * WHAT GOES IN A REPORT AT ALL. ═══ ux.md: "anything that can change while
767
+ * you are not running is read live and never carried in your report." What was
768
+ * dispatched changes while a run is dead — its children finish — so it is a fact
769
+ * to be read rather than something to be remembered, and the sentence below says
770
+ * so out loud. NULL means this agent cannot have sent anybody: at the deepest
771
+ * level there is no `dispatch` at all, and printing "you sent nobody" would
772
+ * describe an absence as a choice.
773
+ */
774
+ export function resumePrompt(brief, report, children) {
775
+ return respawnPrompt([
776
+ 'YOU WERE ALREADY DOING THIS, AND YOU WERE STOPPED BEFORE YOU FINISHED.',
777
+ 'Not by anybody: the machine went down and took you with it. You are the same agent, started',
778
+ 'again, and everything below is what survived. Nothing about what you were sent to do has',
779
+ 'changed, and nothing you did before you stopped has been undone.',
780
+ ], brief, report, children);
781
+ }
782
+ /**
783
+ * ═══ WHAT AN AGENT IS STARTED AGAIN WITH WHEN THE PROCESS IT WAS RUNNING IN
784
+ * DIED ON SOMETHING UPSTREAM. ═══
785
+ *
786
+ * recovery-1/ux.md, Slice 3: "the agent's harness fails on something that is
787
+ * nobody's fault: a rate limit, a dropped connection, a provider outage. The
788
+ * product tries again rather than failing the card."
789
+ *
790
+ * ═══ IT EXISTS BECAUSE `resumePrompt`'s OPENING IS FALSE HERE. ═══ That one
791
+ * says "the machine went down and took you with it", and on this path the
792
+ * machine did not go down: it is the same daemon, still running, that watched
793
+ * the harness exit. Telling an agent something untrue about why it is running is
794
+ * what this file exists to prevent, and a fifth opening onto the one respawn
795
+ * body is the shape the other four already established rather than a new idea.
796
+ *
797
+ * ═══ AND IT SAYS THE FAILURE WAS NOT THE AGENT'S, BECAUSE THE ALTERNATIVE IS
798
+ * WORSE. ═══ An agent told only that it stopped has no way to tell a harness
799
+ * that died from work it got wrong, and the cheapest guess from inside is that
800
+ * the last thing it tried was the problem. That is how a resume turns into a
801
+ * rewrite of work that was already right.
802
+ */
803
+ export function retryPrompt(brief, report, children) {
804
+ return respawnPrompt([
805
+ 'YOU WERE ALREADY DOING THIS, AND THE PROCESS YOU WERE RUNNING IN DIED BEFORE YOU FINISHED.',
806
+ 'Not because of anything you did, and not because anybody stopped you: the harness itself',
807
+ 'failed, which is what a rate limit, a dropped connection or a provider outage looks like from',
808
+ 'here. You are the same agent, started again, and everything below is what survived. Nothing',
809
+ 'about what you were sent to do has changed, and nothing you did before it died has been undone.',
810
+ ], brief, report, children);
811
+ }
812
+ /**
813
+ * ═══ WHAT AN AGENT THAT ASKED IS STARTED AGAIN WITH. ═══
814
+ *
815
+ * ux.md: "The run that asked is spawned again, fresh, with the question and the
816
+ * answer in its brief. Not level 1 passing it down through level 2. Not a
817
+ * message. A respawn, which is the same mechanism as redirect." So this is
818
+ * `resumePrompt` with one more thing in it, and the sameness is the point: the
819
+ * agent picks up where the old one left off for the same reason a crash resume
820
+ * does, because the work was never inside the process.
821
+ *
822
+ * ═══ AND IT SAYS OUT LOUD THAT AN ANSWER CAN BE BIGGER THAN THE QUESTION. ═══
823
+ * ux.md: "If the answer turns out to change more than that worker's own piece,
824
+ * it escalates again rather than proceeding. Whether an answer is local or global
825
+ * is judgement, and building a classifier for it would be the product deciding
826
+ * something the agent is better placed to see." So it is named as a judgement
827
+ * the agent makes, in one sentence, rather than a rule about when to ask.
828
+ */
829
+ export function answerPrompt(brief, report, children, question, answer, relatedArtifact = null) {
830
+ return respawnPrompt([
831
+ 'YOU STOPPED BECAUSE YOU COULD NOT GO ON WITHOUT KNOWING SOMETHING. HERE IT IS.',
832
+ 'You are the same agent, started again, and everything you did before you asked is still there.',
833
+ '',
834
+ 'WHAT YOU ASKED',
835
+ question,
836
+ '',
837
+ 'WHAT CAME BACK',
838
+ answer,
839
+ ...presentedArtifactAnswerContext(relatedArtifact),
840
+ '',
841
+ 'If this answers less than you asked, or turns out to change more than the piece you were sent',
842
+ 'to do, ask again rather than deciding it yourself. Carrying on from a guess about something this',
843
+ 'big is how work gets done twice.',
844
+ ], brief, report, children);
845
+ }
846
+ /**
847
+ * ═══ WHAT AN AGENT IS STARTED AGAIN WITH WHEN EVERYBODY IT SENT HAS FINISHED.
848
+ * ═══
849
+ *
850
+ * ux.md's third re-arm, and the one nothing else could fire: "every child of a
851
+ * run has finished → that run, so it can read them back and carry on."
852
+ *
853
+ * ═══ WHAT THEY FOUND IS IN THE PROMPT, NOT BEHIND A TOOL CALL. ═══ This is the
854
+ * one respawn whose entire purpose is reading them back, and ux.md is explicit
855
+ * about the difference between a guarantee and a hope: "an agent cannot fail to
856
+ * read its own input." `childrenOf` carries each of their reports, so the
857
+ * synthesis starts from what they wrote rather than from remembering to ask.
858
+ *
859
+ * ═══ AND IT SAYS OUT LOUD THAT NOBODY ELSE WILL SAY IT. ═══ A worker's words go
860
+ * into the record and stop there, by `panel3_answer`. From inside, an agent
861
+ * cannot tell whether the person has already read three replies; told wrongly it
862
+ * writes a covering note over answers nobody ever saw. So it is told, as a fact
863
+ * about the situation rather than as an instruction.
864
+ */
865
+ export function readBackPrompt(brief, report, children) {
866
+ return respawnPrompt([
867
+ 'EVERYBODY YOU SENT HAS FINISHED, AND YOU ARE STARTED AGAIN TO READ WHAT THEY FOUND.',
868
+ 'You are the same agent, started again, and nothing you did before has been undone. Nothing you',
869
+ 'sent anybody to do is still running.',
870
+ '',
871
+ 'WHAT THEY WROTE IS BELOW, and it has gone nowhere else. The person has not seen any of it and',
872
+ 'will not: what reaches them about this is what you write now. If what came back leaves the',
873
+ 'work finished, answer with the whole of it in one piece. If it leaves something undone, that',
874
+ 'is still yours, and you may do it or send somebody for it exactly as before.',
875
+ ], brief, report, children);
876
+ }
877
+ /**
878
+ * ═══ WHAT AN AGENT IS STARTED AGAIN WITH WHEN SOMEBODY IT SENT CANNOT GO ON.
879
+ * ═══
880
+ *
881
+ * ux.md: "the level 2 agent is spawned, sees a child asked something, and either
882
+ * answers it or escalates and exits... Each hop is one cheap spawn that reads and
883
+ * decides. Against a question that waits on a human, three spawns are noise, and
884
+ * each one is a real chance to settle it without interrupting anyone."
885
+ *
886
+ * THE COST OF PASSING IT ON IS STATED, because that is the whole reason the hop
887
+ * exists: an agent that passes everything up is a level that bought nothing.
888
+ */
889
+ export function escalationPrompt(brief, report, children, questionId, question) {
890
+ return respawnPrompt([
891
+ 'SOMEBODY YOU SENT CANNOT GO ON UNTIL SOMETHING IS DECIDED, AND IT CAME TO YOU.',
892
+ 'You are the same agent, started again to deal with it. Nothing you did before has been undone.',
893
+ '',
894
+ 'WHAT THEY NEED TO KNOW',
895
+ question,
896
+ '',
897
+ `Its id is ${questionId}. That is what you answer it by, and it is also what you name if you`,
898
+ 'cannot settle it either and have to send it further up: name it, and it goes up as one question',
899
+ 'with your wording. Leave it out and you have asked a second, separate question of your own,',
900
+ 'and this one stays here with nobody dealing with it.',
901
+ '',
902
+ 'ANSWER IT IF YOU CAN. You know what this work is for and they do not, so most of what reaches',
903
+ 'you is yours to settle. Read what you need to first. Only what you genuinely cannot decide goes',
904
+ 'further up, and everything that goes up eventually stops a person and asks them instead.',
905
+ 'Whichever you do, you stop afterwards: they are started again with the answer, not by you.',
906
+ ], brief, report, children);
907
+ }
908
+ /**
909
+ * What every respawn shares: what it wrote down, what it already sent others to
910
+ * do, and the brief it was given, verbatim and last.
911
+ *
912
+ * ONE OWNER, because the three reasons a run is started again — the machine went
913
+ * down, its question was answered, somebody it sent needs a decision — differ
914
+ * only in what is NEW. Everything else about resuming is the same fact, and two
915
+ * copies of it would drift in the way ux.md's own note about the brief describes:
916
+ * invisibly, in whichever one nobody re-read.
917
+ */
918
+ function respawnPrompt(opening, brief, report, children) {
919
+ return [
920
+ ...opening,
921
+ '',
922
+ 'WHAT YOU WROTE DOWN, THE LAST TIME YOU WROTE ANYTHING DOWN',
923
+ report ?? 'Nothing. You were stopped before you wrote anything down, so what you did before that '
924
+ + 'is not known here — check the work itself before you assume any of it is undone.',
925
+ '',
926
+ ...(children === null ? [] : [
927
+ 'WHAT YOU ALREADY SENT SOMEBODY TO DO, AS IT STANDS RIGHT NOW, AND WHAT EACH OF THEM WROTE',
928
+ 'Read from the record a moment ago, not from your notes, so it is right even where they are',
929
+ 'silent: this is what exists, whatever you meant to do. Do not send somebody to do a piece of',
930
+ 'work that is already in this list. Anything of theirs still going is still going, and asking',
931
+ 'again for what they are already doing costs the person twice. What is under each one is what',
932
+ 'that one wrote down, in its own words.',
933
+ ...(children.length === 0 ? ['You have sent nobody.'] : children),
934
+ '',
935
+ ]),
936
+ 'CARRY ON FROM WHERE THAT LEAVES YOU. What your notes say is done is done and is not to be done',
937
+ 'again; what they leave open is what is left. Where they are silent, look at the work itself',
938
+ 'rather than starting it over: they are what you had time to write down, not everything that',
939
+ 'happened. And write them again as you go, for the same reason.',
940
+ '',
941
+ 'WHAT YOU WERE SENT TO DO, WORD FOR WORD AS YOU WERE SENT IT',
942
+ '',
943
+ brief,
944
+ ].join('\n');
945
+ }