@haaaiawd/loom 2.0.0 → 2.0.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.
@@ -1,367 +1,411 @@
1
- export const AGENT_CORE = `# LOOM collaboration core
2
-
3
- Work toward the result the human wants in the world. Treat the human as the owner of consequential
4
- choices, but do not make them decide professional details you can responsibly resolve. Separate
5
- confirmed fact, inference, assumption, and unknown. Inspect discoverable reality before asking about
6
- it. Challenge contradictions, preserve corrections, and prefer the smallest complete system that can
7
- be verified.
8
-
9
- Ask only questions whose answers could materially change the result, boundary, risk, design, or proof.
10
- Group the useful current questions into one coherent round; do not follow a fixed questionnaire. After
11
- answers, update the emerging whole and ask again only where important uncertainty remains. When the
12
- human delegates a reversible decision, make and record a project-specific judgment. When they insist
13
- on skipping clarification, state the concrete risk once, record the assumption, and continue.`;
14
-
15
- export const RUNTIME_PROTOCOL = `# LOOM runtime protocol
16
-
17
- LOOM is invisible continuity infrastructure for the Agent. The human talks naturally to you; use the
18
- CLI silently and never make the human maintain LOOM files or state.
19
-
20
- ## Shape the whole before material execution
21
-
22
- Maintain four distinct layers:
23
-
24
- 1. \`.loom/PROJECT.md\` is the concise entry point and map of the current whole.
25
- 2. \`.loom/design/\` contains the actual project/product/system/contract/verification documents. Split
26
- a document when a consequential subsystem, experience, interface, or operational concern needs to
27
- be understood and verified independently. Small projects may need few documents; large projects may
28
- need many. Do not compress a complex product into PROJECT.md merely to keep the file count low.
29
- 3. \`.loom/capabilities/\` contains project-specific professional-domain dossiers. One dossier represents
30
- one recognizable field such as UI/UX design, visual art direction, game design, psychology, biology,
31
- pharmacology, security, or distributed systems. Do not merge fields into a clever hybrid title and
32
- do not mistake a task technique such as ranking, triage, parsing, or caching for the project's entire
33
- capability surface. Cross-domain synthesis belongs in the design document whose decision it changes.
34
- 4. \`.loom/tasks.json\` is a restartable Work Map. Every Task names the exact design documents,
35
- capability dossiers, source files, fixtures, and contracts it must read.
36
-
37
- Start from the desired result, inspect the workspace when relevant, describe the emerging whole
38
- naturally, and identify the current uncertainty frontier. After every answer round, update project
39
- truth, the document map, and the capability map. Continue until a new Agent can understand the whole,
40
- why each important design decision exists, which professional lenses shaped it, and how success will
41
- be observed.
42
-
43
- ## Compile professional capability
44
-
45
- Identify capabilities at the level of established professional fields. Create separate dossiers when
46
- different fields use different evidence, make different judgments, or could disagree. A dossier is not
47
- a textbook summary or a costume labelled "expert". It must show a distinctive project-specific stance,
48
- opened sources when research was used, rejected generic defaults, concrete consequences for design and
49
- implementation, characteristic failure modes, and observable verification signals.
50
-
51
- Do not force every conceivable field into the project. Include a field only when its knowledge changes
52
- questions, a design decision, implementation, risk handling, or verification. If the work needs several
53
- fields, preserve each field's identity and synthesize them explicitly in the affected design docs.
54
-
55
- ## Build a restartable Work Map
56
-
57
- Plan the whole delivery at milestone resolution, then keep the active horizon detailed. A Task records
58
- an outcome, observable done conditions, boundaries, dependencies, exact reads, expected touches,
59
- progress, next action, and evidence. A long project may have many Tasks, but do not pre-write thousands
60
- of speculative micro-steps. Split and revise the map as reality becomes clearer.
61
-
62
- Before engineering or another material operation begins, tell the human what is about to happen and
63
- which consequential assumptions remain. Ordinary reversible work needs no extra ceremony; irreversible,
64
- high-risk, or materially costly action still requires authority.
65
-
66
- ## Close the loops
67
-
68
- Understanding loop: describe the whole -> locate consequential uncertainty -> ask in a batch -> record
69
- answers and decisions -> update design and capability maps -> repeat while material uncertainty remains.
70
-
71
- Keeper loop: prepare a frozen digest -> fresh Keeper attempts to start from disk -> on
72
- \`needs_revision\` or \`blocked\`, absorb every concrete gap into project truth, design docs, capability
73
- dossiers, or Tasks -> prepare a changed digest -> use another fresh Keeper. Keeper passes only once the
74
- handoff is genuinely buildable; it does not reappear for every Task.
75
-
76
- Delivery loop: select an executable Task -> load exactly referenced context -> implement and verify ->
77
- map every done condition to concrete evidence -> complete, block with recovery conditions, or reopen a
78
- blocked or disproven completion after upstream correction ->
79
- continue. When the human changes a consequential prior answer, preserve the superseding decision and
80
- repair affected documents and Tasks before continuing.`;
81
-
1
+ export const AGENT_CORE = `# LOOM collaboration core
2
+
3
+ Work toward the result the human wants in the world. Treat the human as the owner of consequential
4
+ choices, but do not make them decide professional details you can responsibly resolve. Separate
5
+ confirmed fact, inference, assumption, and unknown. Inspect discoverable reality before asking about
6
+ it. Challenge contradictions, preserve corrections, and prefer the smallest complete system that can
7
+ be verified.
8
+
9
+ Ask only questions whose answers could materially change the result, boundary, risk, design, or proof.
10
+ Group the useful current questions into one coherent round; do not follow a fixed questionnaire. After
11
+ answers, update the emerging whole and ask again only where important uncertainty remains. When the
12
+ human delegates a reversible decision, make and record a project-specific judgment. When they insist
13
+ on skipping clarification, state the concrete risk once, record the assumption, and continue.`;
14
+
15
+ export const RUNTIME_PROTOCOL = `# LOOM runtime protocol
16
+
17
+ LOOM is invisible continuity infrastructure for the Agent. The human talks naturally to you; use the
18
+ CLI silently and never make the human maintain LOOM files or state.
19
+
20
+ ## Shape the whole before material execution
21
+
22
+ Maintain four distinct layers:
23
+
24
+ 1. \`.loom/PROJECT.md\` is the concise entry point and map of the current whole.
25
+ 2. \`.loom/design/\` contains the actual project/product/system/contract/verification documents. Split
26
+ a document when a consequential subsystem, experience, interface, or operational concern needs to
27
+ be understood and verified independently. Small projects may need few documents; large projects may
28
+ need many. Do not compress a complex product into PROJECT.md merely to keep the file count low.
29
+ 3. \`.loom/capabilities/\` contains project-specific professional-domain dossiers. One dossier represents
30
+ one recognizable field such as UI/UX design, visual art direction, game design, psychology, biology,
31
+ pharmacology, security, or distributed systems. Do not merge fields into a clever hybrid title and
32
+ do not mistake a task technique such as ranking, triage, parsing, or caching for the project's entire
33
+ capability surface. Cross-domain synthesis belongs in the design document whose decision it changes.
34
+ 4. \`.loom/tasks.json\` is a restartable Work Map. Every Task names the exact design documents,
35
+ capability dossiers, source files, fixtures, and contracts it must read.
36
+
37
+ Start from the desired result, inspect the workspace when relevant, describe the emerging whole
38
+ naturally, and identify the current uncertainty frontier. After every answer round, update project
39
+ truth, the document map, and the capability map. Continue until a new Agent can understand the whole,
40
+ why each important design decision exists, which professional lenses shaped it, and how success will
41
+ be observed.
42
+
43
+ ## Compile professional capability
44
+
45
+ Identify capabilities at the level of established professional fields. Create separate dossiers when
46
+ different fields use different evidence, make different judgments, or could disagree. A dossier is not
47
+ a textbook summary or a costume labelled "expert". It must show a distinctive project-specific stance,
48
+ opened sources when research was used, rejected generic defaults, concrete consequences for design and
49
+ implementation, characteristic failure modes, and observable verification signals.
50
+
51
+ Do not force every conceivable field into the project. Include a field only when its knowledge changes
52
+ questions, a design decision, implementation, risk handling, or verification. If the work needs several
53
+ fields, preserve each field's identity and synthesize them explicitly in the affected design docs.
54
+
55
+ ## Build a restartable Work Map
56
+
57
+ Plan the whole delivery at milestone resolution, then keep the active horizon detailed. A Task records
58
+ an outcome, observable done conditions, boundaries, dependencies, exact reads, expected touches,
59
+ progress, next action, and evidence. A long project may have many Tasks, but do not pre-write thousands
60
+ of speculative micro-steps. Split and revise the map as reality becomes clearer.
61
+
62
+ Before engineering or another material operation begins, tell the human what is about to happen and
63
+ which consequential assumptions remain. Ordinary reversible work needs no extra ceremony; irreversible,
64
+ high-risk, or materially costly action still requires authority.
65
+
66
+ ## Close the loops
67
+
68
+ Understanding loop: describe the whole -> locate consequential uncertainty -> ask in a batch -> record
69
+ answers and decisions -> update design and capability maps -> repeat while material uncertainty remains.
70
+
71
+ Keeper loop: prepare a frozen digest -> fresh Keeper attempts to start from disk -> on
72
+ \`needs_revision\` or \`blocked\`, absorb every concrete gap into project truth, design docs, capability
73
+ dossiers, or Tasks -> prepare a changed digest -> use another fresh Keeper. Keeper passes only once the
74
+ handoff is genuinely buildable; it does not reappear for every Task.
75
+
76
+ Delivery loop: select an executable Task -> load exactly referenced context -> implement and verify ->
77
+ map every done condition to concrete evidence -> complete, block with recovery conditions, or reopen a
78
+ blocked or disproven completion after upstream correction ->
79
+ continue. When the human changes a consequential prior answer, preserve the superseding decision and
80
+ repair affected documents and Tasks before continuing.`;
81
+
82
82
  export const AGENT_PROTOCOL = `${AGENT_CORE}\n\n${RUNTIME_PROTOCOL}`;
83
83
 
84
- export const AGENT_ANCHOR = `<!-- loom:v2 -->
85
- ## LOOM
86
-
87
- This project uses LOOM as Agent-only continuity infrastructure. Run \`loom context\` before substantial
88
- work, keep project truth, design documents, professional capability dossiers, and Tasks current through
89
- the CLI, and never ask the human to operate LOOM.`;
90
-
91
- function renderKeeperGap(item) {
92
- if (typeof item === 'string') return ` - ${item}`;
93
- if (!item || typeof item !== 'object') return ` - ${String(item)}`;
94
- const title = item.gap || item.title || '<unnamed gap>';
95
- const why = item.why_it_blocks_start || item.why || '';
96
- const proof = item.evidence_to_close || item.close_when || '';
97
- return [` - gap: ${title}`, why ? ` why: ${why}` : '', proof ? ` evidence to close: ${proof}` : ''].filter(Boolean).join('\n');
98
- }
99
-
100
- export function shapingContext({ state, taskSummary, capabilityNames, designNames, forKeeper = false }) {
101
- const open = state.understanding.unresolved.filter((item) => item.status === 'open');
102
- const assumptions = state.understanding.assumptions.filter((item) => item.status === 'active');
103
- const latestKeeper = state.keeper.attempts.at(-1);
104
- const keeperFeedback = ['needs_revision', 'blocked'].includes(state.keeper.status) && latestKeeper
105
- ? `### ${forKeeper ? 'Prior Keeper feedback this prepared revision claims to close' : 'Keeper feedback that must enter the next iteration'}
106
-
107
- - verdict: ${latestKeeper.verdict}
108
- - run: ${latestKeeper.run_id}
109
- - summary: ${latestKeeper.summary}
110
- - gaps:
111
- ${latestKeeper.gaps.length ? latestKeeper.gaps.map(renderKeeperGap).join('\n') : ' - none recorded'}
112
- - evidence:
113
- ${latestKeeper.evidence.map((item) => ` - ${item}`).join('\n')}
114
-
115
- ${forKeeper
116
- ? 'Audit every claimed closure against the current files and Task context. Do not repair it yourself; pass only if the new digest actually closes the gaps without creating new ones.'
117
- : 'Trace each gap to the project index, a design document, a professional capability dossier, or a Task.\nRepair the source of truth rather than answering the review in prose. Ask the human only when the gap\ndepends on their consequential choice. Then run `loom project ready`; an unchanged digest is invalid,\nand the next check must use a different fresh Keeper run.'}`
118
- : '';
119
- return `## Current LOOM state
120
-
121
- - project status: ${state.project.status}
122
- - confirmed facts: ${state.understanding.confirmed.length}
123
- - active assumptions: ${assumptions.length}
124
- - open questions: ${open.length}
125
- - design documents: ${designNames.length ? designNames.join(', ') : 'none yet'}
126
- - professional capability dossiers: ${capabilityNames.length ? capabilityNames.join(', ') : 'none yet'}
127
- - work map: ${taskSummary.total} tasks (${taskSummary.done} done, ${taskSummary.open} open, ${taskSummary.blocked} blocked)
128
- - active task: ${taskSummary.active || 'none'}
129
-
130
- ${open.length ? `### Open uncertainty\n\n${open.map((item) => `- ${item.id} [${item.impact}]: ${item.question}`).join('\n')}` : 'No open uncertainty is recorded.'}
131
-
132
- ${assumptions.length ? `### Active assumptions\n\n${assumptions.map((item) => `- ${item.id}: ${item.text}`).join('\n')}` : ''}
133
-
134
- ${keeperFeedback}`;
135
- }
136
-
137
- export function keeperProtocol({ attemptNumber, preparedDigest } = {}) {
138
- return `# LOOM independent Keeper handoff
139
-
140
- You are a fresh Agent with no access to the shaping conversation. Do not repair the project and do not
141
- edit implementation. Use only this workspace and the LOOM CLI. Run \`loom context --keeper\`, inspect
142
- the referenced files, and attempt a real handoff from disk.
143
-
144
- Judge buildability, not document polish or document count. Demonstrate whether you can:
145
-
146
- 1. Explain the intended result, people or operating reality, boundaries, and observable completion.
147
- 2. Navigate PROJECT.md into the necessary product, experience, system, contract, operations, and
148
- verification documents without prior chat memory.
149
- 3. Identify every professional field that materially shapes the project, keep those fields distinct,
150
- and explain the project-specific stance each contributes.
151
- 4. Select the first executable Task, justify its dependencies, load every file it names, and state the
152
- concrete first edit or command.
153
- 5. State the exact artifact and reproducible evidence that would prove that Task complete.
154
- 6. Expose contradictions, missing systems, absent capability domains, generic expertise, inaccessible
155
- context, invented certainty, or any point where a new Agent would have to guess.
156
-
157
- This is Keeper attempt ${attemptNumber || '<unknown>'}. The frozen prepared digest is
158
- \`${preparedDigest || '<run loom project ready>'}\`. Generate a unique run_id for this fresh Agent and
159
- include both run_id and prepared_digest in the result.
160
-
161
- Use this result shape. Keep \`gaps\` empty on pass; otherwise prefer structured gaps so the next Agent
162
- receives the reason and closure evidence without interpretation loss:
163
-
164
- \`\`\`json
165
- {
166
- "run_id": "<unique-id>",
167
- "prepared_digest": "<digest-above>",
168
- "verdict": "passed | needs_revision | blocked",
169
- "summary": "<concise handoff judgment>",
170
- "gaps": [
171
- {
172
- "gap": "<missing or contradictory truth>",
173
- "why_it_blocks_start": "<concrete consequence for a fresh Agent>",
174
- "evidence_to_close": "<observable condition that would close it>"
175
- }
176
- ],
177
- "evidence": ["<file, command, or observation supporting the verdict>"]
178
- }
179
- \`\`\`
180
-
181
- Record the result with \`loom keeper record --json-file <result.json>\`. Use \`passed\` only when you
182
- could responsibly begin the first Task. Otherwise use \`needs_revision\` with concrete gaps and the
183
- observable evidence that would close each one, or \`blocked\` when progress requires unavailable
184
- authority or external state. A failed attempt returns the project to shaping; revision requires a
185
- changed digest and another fresh Keeper.`;
186
- }
187
-
188
- export const PROJECT_TEMPLATE = `# Project Whole and Document Map
189
-
190
- > This is the concise entry point, not the container for every design decision. Describe the whole and
191
- > link the documents that make it buildable. Add or remove documents according to project complexity.
192
-
193
- ## Intended result
194
-
195
- What should exist or become possible when this project succeeds?
196
-
197
- ## People and operating reality
198
-
199
- Who or what experiences the result, and in what real situation?
200
-
201
- ## Whole experience or behavior
202
-
203
- Describe the coherent end-to-end result rather than a feature inventory.
204
-
205
- ## Boundaries and consequential assumptions
206
-
207
- What must not be changed, lost, invented, or expanded without authority?
208
-
209
- ## Design document map
210
-
211
- Link every product, experience, system, contract, verification, or operations document and state the
212
- decision surface it owns. Complex subsystems should have their own files under \`.loom/design/\`.
213
-
214
- ## Professional capability map
215
-
216
- Link each separate field dossier under \`.loom/capabilities/\` and state which design decisions it
217
- changes. Do not merge distinct fields into one dossier.
218
-
219
- ## Completion and failure
220
-
221
- What observable evidence means the project worked? What could look complete while actually failing?
222
-
223
- ## Work map
224
-
225
- Explain the delivery shape and point to \`.loom/tasks.json\`; do not duplicate volatile Task state here.
226
- `;
227
-
228
- const DESIGN_SECTIONS = {
229
- product: ['Outcome and users', 'Problem and operating reality', 'Product principles', 'Scope and non-goals', 'End-to-end behavior', 'Success and failure signals', 'Decisions and open questions', 'Related documents and capabilities'],
230
- experience: ['Experience intent', 'Users and contexts', 'Journey and information architecture', 'Interaction states and transitions', 'Content, visual, and accessibility direction', 'Errors, empty states, and recovery', 'Usability verification', 'Related documents and capabilities'],
231
- system: ['Responsibility in the whole', 'Inputs, outputs, and boundaries', 'Components and control flow', 'Data and state', 'Interfaces and dependencies', 'Failure, safety, and recovery', 'Implementation constraints', 'Verification strategy', 'Related documents and capabilities'],
232
- contract: ['Consumers and purpose', 'Schema or command surface', 'Invariants and permissions', 'Errors and compatibility', 'Examples and fixtures', 'Contract tests', 'Related documents and capabilities'],
233
- verification: ['Claims under test', 'Environments and fixtures', 'Acceptance matrix', 'Commands and evidence', 'Negative and failure tests', 'Known blind spots', 'Related documents and capabilities'],
234
- operations: ['Operational outcome', 'Preconditions and authority', 'Procedure and commands', 'Safety boundaries', 'Failure detection and recovery', 'Evidence and audit trail', 'Related documents and capabilities'],
235
- research: ['Decision to inform', 'Current evidence and unknowns', 'Method and sources', 'Findings', 'Conflicts and limitations', 'Project consequences', 'Follow-up verification', 'Related documents and capabilities'],
236
- };
237
-
238
- export const DESIGN_KINDS = Object.freeze(Object.keys(DESIGN_SECTIONS));
239
-
240
- export function designTemplate({ title, kind }) {
241
- const sections = DESIGN_SECTIONS[kind];
242
- if (!sections) throw new Error(`Unknown design kind: ${kind}`);
243
- return `# ${title}\n\n- Kind: ${kind}\n- Status: shaping\n\n${sections.map((section) => `## ${section}\n\nDescribe the project-specific decision, mechanism, boundary, or evidence owned by this section.`).join('\n\n')}\n`;
244
- }
245
-
246
- export const CAPABILITY_TEMPLATE = ({ title }) => `# ${title}
247
-
248
- > One dossier covers one recognizable professional field. Keep UI/UX, visual art direction, game
249
- > design, psychology, biology, security, and other fields separate when their evidence and judgments
250
- > differ. Put cross-field synthesis in the affected design document, not in a hybrid capability title.
251
-
252
- ## Field identity and boundary
253
-
254
- Name the established field, what expertise it contributes, and what belongs to another dossier.
255
-
256
- ## Project decisions this field changes
257
-
258
- Identify the consequential questions, design choices, risks, or verification methods that would be
259
- weaker without this field.
260
-
261
- ## Project-specific diagnosis
262
-
263
- Interpret this project's users, constraints, existing evidence, and tensions through this field. Show
264
- authored judgment rather than a generic overview.
265
-
266
- ## Principles, evidence, and sources
267
-
268
- Record specialist principles and opened sources when research is used. State what each source changed,
269
- where sources disagree, and what remains uncertain.
270
-
271
- ## Distinctive stance and rejected defaults
272
-
273
- State what this project will do, why, the important tradeoffs, and which common or generic approaches it
274
- will deliberately refuse.
275
-
276
- ## Consequences for design, implementation, and verification
277
-
278
- Translate the field's stance into concrete requirements and link the design documents it affects.
279
-
280
- ## Questions that could change the stance
281
-
282
- Keep only unresolved questions whose answers would materially alter this field's contribution.
283
-
284
- ## Failure modes and proof signals
285
-
286
- Describe characteristic weak, generic, or harmful outcomes and the observable evidence that distinguishes
287
- a strong result.
288
-
289
- ## Relationships without merger
290
-
291
- Link adjacent capability dossiers and explain the tension or handoff. Do not absorb their expertise here.
292
- `;
293
-
294
- export function evalConditionPrompt({ brief, loom }) {
295
- return loom
296
- ? `# Evaluation condition\n\n${brief}\n\nWork with all ordinary Agent capabilities and tools. Use LOOM as invisible continuity infrastructure: run \`loom context\`, maintain its disk state, and never ask the human to operate it. This condition has no extra authority or information.`
297
- : `# Evaluation condition\n\n${brief}\n\nWork as a normal capable Agent with all ordinary capabilities and tools. LOOM and its files are unavailable in this condition. Use any normal planning or documentation you judge useful.`;
298
- }
299
-
300
- export function evalJudgePrompt() {
301
- return `# Blind Evil Eval judge
302
-
303
- You receive two anonymized runs in randomized order. Do not infer framework identity. Judge observable
304
- work, not framework-shaped filenames or document volume. Cite evidence for every score. Compare intent
305
- fidelity, question value, whole-project coverage, professional capability depth, buildability, continuity
306
- after forced resets, implementation evidence, user burden, and cost/time. Penalize unnecessary ceremony,
307
- questions that do not change decisions, and documentation that a fresh Agent cannot use. Swap order and
308
- judge again; mark order-sensitive conclusions unstable. Attribute missing files or path failures to a run
309
- only after the anonymized packet passed its relative-layout and declared-test preflight. A system wins only if its benefit survives equal
310
- model, tools, workspace, user facts, reset points, and budget.`;
311
- }
312
-
313
- export function promptCatalog() {
314
- const placeholderState = {
315
- project: { status: '<project-status>' },
316
- understanding: {
317
- confirmed: [],
318
- assumptions: [{ id: '<assumption-id>', text: '<assumption>', status: 'active' }],
319
- unresolved: [{ id: '<question-id>', question: '<material uncertainty>', impact: 'high', status: 'open' }],
320
- },
321
- keeper: { status: 'not_run', attempts: [] },
322
- };
323
- const revisionState = {
324
- ...placeholderState,
325
- keeper: {
326
- status: 'needs_revision',
327
- attempts: [{
328
- verdict: 'needs_revision',
329
- run_id: '<fresh-run-id>',
330
- summary: '<why the handoff cannot start>',
331
- gaps: ['<concrete gap>'],
332
- evidence: ['<observable evidence>'],
333
- }],
334
- },
335
- };
336
- return {
337
- purpose: 'Complete inventory of LOOM cognitive messages. Validation errors and JSON status payloads enforce state but are not Agent prompts.',
84
+ export const EXECUTION_PROTOCOL = `# LOOM active Task execution protocol
85
+
86
+ This block applies only when a Task is active or explicitly loaded. Treat the disk state below as the
87
+ recovery source; conversation memory may be incomplete.
88
+
89
+ ## Recover before changing anything
90
+
91
+ 1. Re-read the Task outcome, exact done_when criteria, boundaries, dependencies, reads, expected
92
+ touches, progress, next action, and existing evidence. Read every injected Task context file.
93
+ 2. Inspect the current workspace and version-control state plus the relevant implementation and tests.
94
+ Preserve user changes. If the Task conflicts with discoverable reality, update or block the Task instead
95
+ of silently following stale context or inventing missing facts.
96
+ 3. Resume from progress.next when it remains valid. Otherwise choose the smallest complete next action
97
+ that advances the outcome and can be checked against a done condition.
98
+
99
+ ## Build and prove the smallest complete change
100
+
101
+ - Stay inside the outcome and boundaries. If implementation requires a wider system, authority, risk, or
102
+ file surface than the Task describes, repair the Task or upstream design first.
103
+ - Inspect the relevant existing tests before editing. When observable behavior changes and a stable test
104
+ seam exists, add or update the smallest test that can fail for the missing behavior, then implement and
105
+ run it. Documentation, research, configuration, and operational Tasks use the verification appropriate
106
+ to their claim; do not manufacture a ceremonial unit test.
107
+ - Iterate on local failures while the Task remains active. If the failure exposes an upstream design gap,
108
+ unavailable authority, or external dependency, block with concrete recovery conditions rather than
109
+ broadening scope invisibly.
110
+
111
+ ## Leave a restartable handoff
112
+
113
+ - After a material checkpoint, before an expected context reset, or when handing work to another Agent,
114
+ persist concise completed, current, and executable next progress with loom task update.
115
+ Record evidence only after the referenced command, artifact, or observation actually exists.
116
+ - Complete through loom task done only after every exact done_when criterion has reproducible
117
+ evidence. Report known blind spots and unverified boundaries honestly.
118
+ - A branch, commit, or pull request is a delivery mechanism, not a universal Task requirement. Create one
119
+ when the human or repository workflow asks for it, map it to the Task outcome, and include the verification
120
+ evidence; do not use a PR to disguise an incomplete Task.
121
+
122
+ Do not narrate this protocol to the human unless it helps them understand a decision, risk, or handoff.`;
123
+
124
+ export const AGENT_ANCHOR = `<!-- loom:v2 -->
125
+ ## LOOM
126
+
127
+ This project uses LOOM as Agent-only continuity infrastructure. Run \`loom context\` when entering the
128
+ project, after a context reset, and before substantial work. When a Task is active, the command restores
129
+ its execution protocol, exact state, and declared context; rerun it before editing after any interruption.
130
+ Keep project truth, design documents, professional capability dossiers, and Tasks current through the CLI,
131
+ and never ask the human to operate LOOM. Do not rerun LOOM before every tool call: persist and restore at
132
+ meaningful work boundaries.`;
133
+
134
+ function renderKeeperGap(item) {
135
+ if (typeof item === 'string') return ` - ${item}`;
136
+ if (!item || typeof item !== 'object') return ` - ${String(item)}`;
137
+ const title = item.gap || item.title || '<unnamed gap>';
138
+ const why = item.why_it_blocks_start || item.why || '';
139
+ const proof = item.evidence_to_close || item.close_when || '';
140
+ return [` - gap: ${title}`, why ? ` why: ${why}` : '', proof ? ` evidence to close: ${proof}` : ''].filter(Boolean).join('\n');
141
+ }
142
+
143
+ export function shapingContext({ state, taskSummary, capabilityNames, designNames, forKeeper = false }) {
144
+ const open = state.understanding.unresolved.filter((item) => item.status === 'open');
145
+ const assumptions = state.understanding.assumptions.filter((item) => item.status === 'active');
146
+ const latestKeeper = state.keeper.attempts.at(-1);
147
+ const keeperFeedback = ['needs_revision', 'blocked'].includes(state.keeper.status) && latestKeeper
148
+ ? `### ${forKeeper ? 'Prior Keeper feedback this prepared revision claims to close' : 'Keeper feedback that must enter the next iteration'}
149
+
150
+ - verdict: ${latestKeeper.verdict}
151
+ - run: ${latestKeeper.run_id}
152
+ - summary: ${latestKeeper.summary}
153
+ - gaps:
154
+ ${latestKeeper.gaps.length ? latestKeeper.gaps.map(renderKeeperGap).join('\n') : ' - none recorded'}
155
+ - evidence:
156
+ ${latestKeeper.evidence.map((item) => ` - ${item}`).join('\n')}
157
+
158
+ ${forKeeper
159
+ ? 'Audit every claimed closure against the current files and Task context. Do not repair it yourself; pass only if the new digest actually closes the gaps without creating new ones.'
160
+ : 'Trace each gap to the project index, a design document, a professional capability dossier, or a Task.\nRepair the source of truth rather than answering the review in prose. Ask the human only when the gap\ndepends on their consequential choice. Then run `loom project ready`; an unchanged digest is invalid,\nand the next check must use a different fresh Keeper run.'}`
161
+ : '';
162
+ return `## Current LOOM state
163
+
164
+ - project status: ${state.project.status}
165
+ - confirmed facts: ${state.understanding.confirmed.length}
166
+ - active assumptions: ${assumptions.length}
167
+ - open questions: ${open.length}
168
+ - design documents: ${designNames.length ? designNames.join(', ') : 'none yet'}
169
+ - professional capability dossiers: ${capabilityNames.length ? capabilityNames.join(', ') : 'none yet'}
170
+ - work map: ${taskSummary.total} tasks (${taskSummary.done} done, ${taskSummary.open} open, ${taskSummary.blocked} blocked)
171
+ - active task: ${taskSummary.active || 'none'}
172
+
173
+ ${open.length ? `### Open uncertainty\n\n${open.map((item) => `- ${item.id} [${item.impact}]: ${item.question}`).join('\n')}` : 'No open uncertainty is recorded.'}
174
+
175
+ ${assumptions.length ? `### Active assumptions\n\n${assumptions.map((item) => `- ${item.id}: ${item.text}`).join('\n')}` : ''}
176
+
177
+ ${keeperFeedback}`;
178
+ }
179
+
180
+ export function keeperProtocol({ attemptNumber, preparedDigest } = {}) {
181
+ return `# LOOM independent Keeper handoff
182
+
183
+ You are a fresh Agent with no access to the shaping conversation. Do not repair the project and do not
184
+ edit implementation. Use only this workspace and the LOOM CLI. Run \`loom context --keeper\`, inspect
185
+ the referenced files, and attempt a real handoff from disk.
186
+
187
+ Judge buildability, not document polish or document count. Demonstrate whether you can:
188
+
189
+ 1. Explain the intended result, people or operating reality, boundaries, and observable completion.
190
+ 2. Navigate PROJECT.md into the necessary product, experience, system, contract, operations, and
191
+ verification documents without prior chat memory.
192
+ 3. Identify every professional field that materially shapes the project, keep those fields distinct,
193
+ and explain the project-specific stance each contributes.
194
+ 4. Select the first executable Task, justify its dependencies, load every file it names, and state the
195
+ concrete first edit or command.
196
+ 5. State the exact artifact and reproducible evidence that would prove that Task complete.
197
+ 6. Expose contradictions, missing systems, absent capability domains, generic expertise, inaccessible
198
+ context, invented certainty, or any point where a new Agent would have to guess.
199
+
200
+ This is Keeper attempt ${attemptNumber || '<unknown>'}. The frozen prepared digest is
201
+ \`${preparedDigest || '<run loom project ready>'}\`. Generate a unique run_id for this fresh Agent and
202
+ include both run_id and prepared_digest in the result.
203
+
204
+ Use this result shape. Keep \`gaps\` empty on pass; otherwise prefer structured gaps so the next Agent
205
+ receives the reason and closure evidence without interpretation loss:
206
+
207
+ \`\`\`json
208
+ {
209
+ "run_id": "<unique-id>",
210
+ "prepared_digest": "<digest-above>",
211
+ "verdict": "passed | needs_revision | blocked",
212
+ "summary": "<concise handoff judgment>",
213
+ "gaps": [
214
+ {
215
+ "gap": "<missing or contradictory truth>",
216
+ "why_it_blocks_start": "<concrete consequence for a fresh Agent>",
217
+ "evidence_to_close": "<observable condition that would close it>"
218
+ }
219
+ ],
220
+ "evidence": ["<file, command, or observation supporting the verdict>"]
221
+ }
222
+ \`\`\`
223
+
224
+ Record the result with \`loom keeper record --json-file <result.json>\`. Use \`passed\` only when you
225
+ could responsibly begin the first Task. Otherwise use \`needs_revision\` with concrete gaps and the
226
+ observable evidence that would close each one, or \`blocked\` when progress requires unavailable
227
+ authority or external state. A failed attempt returns the project to shaping; revision requires a
228
+ changed digest and another fresh Keeper.`;
229
+ }
230
+
231
+ export const PROJECT_TEMPLATE = `# Project Whole and Document Map
232
+
233
+ > This is the concise entry point, not the container for every design decision. Describe the whole and
234
+ > link the documents that make it buildable. Add or remove documents according to project complexity.
235
+
236
+ ## Intended result
237
+
238
+ What should exist or become possible when this project succeeds?
239
+
240
+ ## People and operating reality
241
+
242
+ Who or what experiences the result, and in what real situation?
243
+
244
+ ## Whole experience or behavior
245
+
246
+ Describe the coherent end-to-end result rather than a feature inventory.
247
+
248
+ ## Boundaries and consequential assumptions
249
+
250
+ What must not be changed, lost, invented, or expanded without authority?
251
+
252
+ ## Design document map
253
+
254
+ Link every product, experience, system, contract, verification, or operations document and state the
255
+ decision surface it owns. Complex subsystems should have their own files under \`.loom/design/\`.
256
+
257
+ ## Professional capability map
258
+
259
+ Link each separate field dossier under \`.loom/capabilities/\` and state which design decisions it
260
+ changes. Do not merge distinct fields into one dossier.
261
+
262
+ ## Completion and failure
263
+
264
+ What observable evidence means the project worked? What could look complete while actually failing?
265
+
266
+ ## Work map
267
+
268
+ Explain the delivery shape and point to \`.loom/tasks.json\`; do not duplicate volatile Task state here.
269
+ `;
270
+
271
+ const DESIGN_SECTIONS = {
272
+ product: ['Outcome and users', 'Problem and operating reality', 'Product principles', 'Scope and non-goals', 'End-to-end behavior', 'Success and failure signals', 'Decisions and open questions', 'Related documents and capabilities'],
273
+ experience: ['Experience intent', 'Users and contexts', 'Journey and information architecture', 'Interaction states and transitions', 'Content, visual, and accessibility direction', 'Errors, empty states, and recovery', 'Usability verification', 'Related documents and capabilities'],
274
+ system: ['Responsibility in the whole', 'Inputs, outputs, and boundaries', 'Components and control flow', 'Data and state', 'Interfaces and dependencies', 'Failure, safety, and recovery', 'Implementation constraints', 'Verification strategy', 'Related documents and capabilities'],
275
+ contract: ['Consumers and purpose', 'Schema or command surface', 'Invariants and permissions', 'Errors and compatibility', 'Examples and fixtures', 'Contract tests', 'Related documents and capabilities'],
276
+ verification: ['Claims under test', 'Environments and fixtures', 'Acceptance matrix', 'Commands and evidence', 'Negative and failure tests', 'Known blind spots', 'Related documents and capabilities'],
277
+ operations: ['Operational outcome', 'Preconditions and authority', 'Procedure and commands', 'Safety boundaries', 'Failure detection and recovery', 'Evidence and audit trail', 'Related documents and capabilities'],
278
+ research: ['Decision to inform', 'Current evidence and unknowns', 'Method and sources', 'Findings', 'Conflicts and limitations', 'Project consequences', 'Follow-up verification', 'Related documents and capabilities'],
279
+ };
280
+
281
+ export const DESIGN_KINDS = Object.freeze(Object.keys(DESIGN_SECTIONS));
282
+
283
+ export function designTemplate({ title, kind }) {
284
+ const sections = DESIGN_SECTIONS[kind];
285
+ if (!sections) throw new Error(`Unknown design kind: ${kind}`);
286
+ return `# ${title}\n\n- Kind: ${kind}\n- Status: shaping\n\n${sections.map((section) => `## ${section}\n\nDescribe the project-specific decision, mechanism, boundary, or evidence owned by this section.`).join('\n\n')}\n`;
287
+ }
288
+
289
+ export const CAPABILITY_TEMPLATE = ({ title }) => `# ${title}
290
+
291
+ > One dossier covers one recognizable professional field. Keep UI/UX, visual art direction, game
292
+ > design, psychology, biology, security, and other fields separate when their evidence and judgments
293
+ > differ. Put cross-field synthesis in the affected design document, not in a hybrid capability title.
294
+
295
+ ## Field identity and boundary
296
+
297
+ Name the established field, what expertise it contributes, and what belongs to another dossier.
298
+
299
+ ## Project decisions this field changes
300
+
301
+ Identify the consequential questions, design choices, risks, or verification methods that would be
302
+ weaker without this field.
303
+
304
+ ## Project-specific diagnosis
305
+
306
+ Interpret this project's users, constraints, existing evidence, and tensions through this field. Show
307
+ authored judgment rather than a generic overview.
308
+
309
+ ## Principles, evidence, and sources
310
+
311
+ Record specialist principles and opened sources when research is used. State what each source changed,
312
+ where sources disagree, and what remains uncertain.
313
+
314
+ ## Distinctive stance and rejected defaults
315
+
316
+ State what this project will do, why, the important tradeoffs, and which common or generic approaches it
317
+ will deliberately refuse.
318
+
319
+ ## Consequences for design, implementation, and verification
320
+
321
+ Translate the field's stance into concrete requirements and link the design documents it affects.
322
+
323
+ ## Questions that could change the stance
324
+
325
+ Keep only unresolved questions whose answers would materially alter this field's contribution.
326
+
327
+ ## Failure modes and proof signals
328
+
329
+ Describe characteristic weak, generic, or harmful outcomes and the observable evidence that distinguishes
330
+ a strong result.
331
+
332
+ ## Relationships without merger
333
+
334
+ Link adjacent capability dossiers and explain the tension or handoff. Do not absorb their expertise here.
335
+ `;
336
+
337
+ export function evalConditionPrompt({ brief, loom }) {
338
+ return loom
339
+ ? `# Evaluation condition\n\n${brief}\n\nWork with all ordinary Agent capabilities and tools. Use LOOM as invisible continuity infrastructure: run \`loom context\`, maintain its disk state, and never ask the human to operate it. This condition has no extra authority or information.`
340
+ : `# Evaluation condition\n\n${brief}\n\nWork as a normal capable Agent with all ordinary capabilities and tools. LOOM and its files are unavailable in this condition. Use any normal planning or documentation you judge useful.`;
341
+ }
342
+
343
+ export function evalJudgePrompt() {
344
+ return `# Blind Evil Eval judge
345
+
346
+ You receive two anonymized runs in randomized order. Do not infer framework identity. Judge observable
347
+ work, not framework-shaped filenames or document volume. Cite evidence for every score. Compare intent
348
+ fidelity, question value, whole-project coverage, professional capability depth, buildability, continuity
349
+ after forced resets, implementation evidence, user burden, and cost/time. Penalize unnecessary ceremony,
350
+ questions that do not change decisions, and documentation that a fresh Agent cannot use. Swap order and
351
+ judge again; mark order-sensitive conclusions unstable. Attribute missing files or path failures to a run
352
+ only after the anonymized packet passed its relative-layout and declared-test preflight. A system wins only if its benefit survives equal
353
+ model, tools, workspace, user facts, reset points, and budget.`;
354
+ }
355
+
356
+ export function promptCatalog() {
357
+ const placeholderState = {
358
+ project: { status: '<project-status>' },
359
+ understanding: {
360
+ confirmed: [],
361
+ assumptions: [{ id: '<assumption-id>', text: '<assumption>', status: 'active' }],
362
+ unresolved: [{ id: '<question-id>', question: '<material uncertainty>', impact: 'high', status: 'open' }],
363
+ },
364
+ keeper: { status: 'not_run', attempts: [] },
365
+ };
366
+ const revisionState = {
367
+ ...placeholderState,
368
+ keeper: {
369
+ status: 'needs_revision',
370
+ attempts: [{
371
+ verdict: 'needs_revision',
372
+ run_id: '<fresh-run-id>',
373
+ summary: '<why the handoff cannot start>',
374
+ gaps: ['<concrete gap>'],
375
+ evidence: ['<observable evidence>'],
376
+ }],
377
+ },
378
+ };
379
+ return {
380
+ purpose: 'Complete inventory of LOOM cognitive messages. Validation errors and JSON status payloads enforce state but are not Agent prompts.',
338
381
  layers: {
339
382
  stable_core: AGENT_CORE,
340
383
  runtime_protocol: RUNTIME_PROTOCOL,
341
- project_state: shapingContext({ state: placeholderState, taskSummary: { total: 0, done: 0, open: 0, blocked: 0, active: null }, capabilityNames: [], designNames: [] }),
342
- project_state_after_keeper_failure: shapingContext({ state: revisionState, taskSummary: { total: 1, done: 0, open: 1, blocked: 0, active: null }, capabilityNames: ['<field>.md'], designNames: ['<system>.md'] }),
343
- keeper_review_of_prior_failure: shapingContext({ state: revisionState, taskSummary: { total: 1, done: 0, open: 1, blocked: 0, active: null }, capabilityNames: ['<field>.md'], designNames: ['<system>.md'], forKeeper: true }),
344
- current_task: '## Active Task\n\n<exact Task JSON>\n\n---\n\n## Task context: <path from Task.reads>\n\n<exact file content>\n\n(repeated for every read path)',
345
- on_demand_map: '## On-demand project context\n\n- Decision history: .loom/DECISIONS.md (read when correction or lineage matters)\n- Design: .loom/design/<document>.md\n- Professional capability: .loom/capabilities/<field>.md',
346
- keeper_context: '## Decision history (...)\n\n<exact DECISIONS.md>\n\n---\n\n## Work map summary\n\n<summary and first executable Task>\n\n---\n\n## Design document: <name>\n\n<exact content>\n\n---\n\n## Capability dossier: <name>\n\n<exact content>',
347
- },
348
- workspace_anchor: AGENT_ANCHOR,
349
- templates: {
350
- project_index: PROJECT_TEMPLATE,
351
- design_documents: Object.fromEntries(DESIGN_KINDS.map((kind) => [kind, designTemplate({ title: `<${kind}-title>`, kind })])),
352
- professional_capability: CAPABILITY_TEMPLATE({ title: '<recognizable-professional-field>' }),
353
- decision_history: '# Decision History\n\nCurrent truth belongs in PROJECT.md and linked design documents. This file preserves consequential superseding decisions.',
354
- },
355
- keeper: keeperProtocol({ attemptNumber: '<attempt-number>', preparedDigest: '<prepared-digest>' }),
356
- evaluation: {
357
- baseline_condition: evalConditionPrompt({ brief: '<identical-raw-brief>', loom: false }),
358
- loom_condition: evalConditionPrompt({ brief: '<identical-raw-brief>', loom: true }),
359
- blind_judge: evalJudgePrompt(),
360
- },
384
+ execution_protocol: EXECUTION_PROTOCOL,
385
+ project_state: shapingContext({ state: placeholderState, taskSummary: { total: 0, done: 0, open: 0, blocked: 0, active: null }, capabilityNames: [], designNames: [] }),
386
+ project_state_after_keeper_failure: shapingContext({ state: revisionState, taskSummary: { total: 1, done: 0, open: 1, blocked: 0, active: null }, capabilityNames: ['<field>.md'], designNames: ['<system>.md'] }),
387
+ keeper_review_of_prior_failure: shapingContext({ state: revisionState, taskSummary: { total: 1, done: 0, open: 1, blocked: 0, active: null }, capabilityNames: ['<field>.md'], designNames: ['<system>.md'], forKeeper: true }),
388
+ current_task: '## Active Task\n\n<exact Task JSON>\n\n---\n\n## Task context: <path from Task.reads>\n\n<exact file content>\n\n(repeated for every read path)',
389
+ on_demand_map: '## On-demand project context\n\n- Decision history: .loom/DECISIONS.md (read when correction or lineage matters)\n- Design: .loom/design/<document>.md\n- Professional capability: .loom/capabilities/<field>.md',
390
+ keeper_context: '## Decision history (...)\n\n<exact DECISIONS.md>\n\n---\n\n## Work map summary\n\n<summary and first executable Task>\n\n---\n\n## Design document: <name>\n\n<exact content>\n\n---\n\n## Capability dossier: <name>\n\n<exact content>',
391
+ },
392
+ workspace_anchor: AGENT_ANCHOR,
393
+ templates: {
394
+ project_index: PROJECT_TEMPLATE,
395
+ design_documents: Object.fromEntries(DESIGN_KINDS.map((kind) => [kind, designTemplate({ title: `<${kind}-title>`, kind })])),
396
+ professional_capability: CAPABILITY_TEMPLATE({ title: '<recognizable-professional-field>' }),
397
+ decision_history: '# Decision History\n\nCurrent truth belongs in PROJECT.md and linked design documents. This file preserves consequential superseding decisions.',
398
+ },
399
+ keeper: keeperProtocol({ attemptNumber: '<attempt-number>', preparedDigest: '<prepared-digest>' }),
400
+ evaluation: {
401
+ baseline_condition: evalConditionPrompt({ brief: '<identical-raw-brief>', loom: false }),
402
+ loom_condition: evalConditionPrompt({ brief: '<identical-raw-brief>', loom: true }),
403
+ blind_judge: evalJudgePrompt(),
404
+ },
361
405
  composition: {
362
406
  normal_resume: ['stable_core', 'runtime_protocol', 'project_state', 'PROJECT.md', 'on-demand document and capability map'],
363
- active_task: ['normal_resume', 'active Task JSON', 'exact files in Task.reads'],
364
- keeper_handoff: ['keeper', 'normal_resume', 'DECISIONS.md', 'Work Map summary and first executable Task', 'all design documents', 'all professional capability dossiers'],
365
- },
366
- };
367
- }
407
+ active_task: ['normal_resume', 'execution_protocol', 'active Task JSON', 'exact files in Task.reads'],
408
+ keeper_handoff: ['keeper', 'normal_resume', 'DECISIONS.md', 'Work Map summary and first executable Task', 'all design documents', 'all professional capability dossiers'],
409
+ },
410
+ };
411
+ }