orbitmap 0.4.6 → 0.6.0

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.
Files changed (94) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +73 -10
  3. package/dist/adapters/cloud.d.ts +85 -10
  4. package/dist/adapters/cloud.js +118 -17
  5. package/dist/adapters/cloud.js.map +1 -1
  6. package/dist/adapters/factory.js +7 -0
  7. package/dist/adapters/factory.js.map +1 -1
  8. package/dist/adapters/local/adapter.d.ts +47 -8
  9. package/dist/adapters/local/adapter.js +37 -17
  10. package/dist/adapters/local/adapter.js.map +1 -1
  11. package/dist/adapters/local/context.d.ts +13 -1
  12. package/dist/adapters/local/context.js +7 -2
  13. package/dist/adapters/local/context.js.map +1 -1
  14. package/dist/adapters/local/entities/documents.d.ts +18 -4
  15. package/dist/adapters/local/entities/documents.js +46 -7
  16. package/dist/adapters/local/entities/documents.js.map +1 -1
  17. package/dist/adapters/local/entities/planning.d.ts +36 -7
  18. package/dist/adapters/local/entities/planning.js +245 -39
  19. package/dist/adapters/local/entities/planning.js.map +1 -1
  20. package/dist/adapters/local/entities/tasks.d.ts +16 -7
  21. package/dist/adapters/local/entities/tasks.js +55 -42
  22. package/dist/adapters/local/entities/tasks.js.map +1 -1
  23. package/dist/adapters/local/entities/work-items.d.ts +28 -7
  24. package/dist/adapters/local/entities/work-items.js +111 -39
  25. package/dist/adapters/local/entities/work-items.js.map +1 -1
  26. package/dist/adapters/local/lists.d.ts +139 -0
  27. package/dist/adapters/local/lists.js +230 -0
  28. package/dist/adapters/local/lists.js.map +1 -0
  29. package/dist/adapters/local/rules.d.ts +1 -1
  30. package/dist/adapters/local/rules.js +23 -0
  31. package/dist/adapters/local/rules.js.map +1 -1
  32. package/dist/adapters/local/shapes.d.ts +165 -22
  33. package/dist/adapters/local/shapes.js +338 -50
  34. package/dist/adapters/local/shapes.js.map +1 -1
  35. package/dist/adapters/local/types.d.ts +6 -1
  36. package/dist/adapters/local/types.js.map +1 -1
  37. package/dist/adapters/types.d.ts +72 -9
  38. package/dist/agent-instructions.d.ts +41 -11
  39. package/dist/agent-instructions.js +329 -128
  40. package/dist/agent-instructions.js.map +1 -1
  41. package/dist/commands/context.d.ts +62 -37
  42. package/dist/commands/context.js +105 -36
  43. package/dist/commands/context.js.map +1 -1
  44. package/dist/commands/docs.d.ts +4 -0
  45. package/dist/commands/docs.js +12 -5
  46. package/dist/commands/docs.js.map +1 -1
  47. package/dist/commands/emit-instructions.d.ts +26 -0
  48. package/dist/commands/emit-instructions.js +68 -0
  49. package/dist/commands/emit-instructions.js.map +1 -0
  50. package/dist/commands/ideas.d.ts +3 -0
  51. package/dist/commands/ideas.js +14 -7
  52. package/dist/commands/ideas.js.map +1 -1
  53. package/dist/commands/intent.d.ts +26 -0
  54. package/dist/commands/intent.js +117 -8
  55. package/dist/commands/intent.js.map +1 -1
  56. package/dist/commands/issues.d.ts +4 -0
  57. package/dist/commands/issues.js +15 -7
  58. package/dist/commands/issues.js.map +1 -1
  59. package/dist/commands/mission.d.ts +2 -0
  60. package/dist/commands/mission.js +9 -5
  61. package/dist/commands/mission.js.map +1 -1
  62. package/dist/commands/projects.d.ts +3 -0
  63. package/dist/commands/projects.js +28 -0
  64. package/dist/commands/projects.js.map +1 -0
  65. package/dist/commands/setup-agent.d.ts +101 -13
  66. package/dist/commands/setup-agent.js +377 -31
  67. package/dist/commands/setup-agent.js.map +1 -1
  68. package/dist/commands/start.d.ts +13 -0
  69. package/dist/commands/start.js +126 -13
  70. package/dist/commands/start.js.map +1 -1
  71. package/dist/commands/tasks.d.ts +23 -5
  72. package/dist/commands/tasks.js +46 -23
  73. package/dist/commands/tasks.js.map +1 -1
  74. package/dist/commands/vibes.d.ts +3 -0
  75. package/dist/commands/vibes.js +11 -5
  76. package/dist/commands/vibes.js.map +1 -1
  77. package/dist/errors.d.ts +23 -2
  78. package/dist/errors.js +31 -3
  79. package/dist/errors.js.map +1 -1
  80. package/dist/index.js +118 -38
  81. package/dist/index.js.map +1 -1
  82. package/dist/list-meta.d.ts +117 -0
  83. package/dist/list-meta.js +160 -0
  84. package/dist/list-meta.js.map +1 -0
  85. package/dist/list-options.d.ts +33 -0
  86. package/dist/list-options.js +70 -0
  87. package/dist/list-options.js.map +1 -0
  88. package/dist/workspace-resolve.d.ts +47 -1
  89. package/dist/workspace-resolve.js +74 -11
  90. package/dist/workspace-resolve.js.map +1 -1
  91. package/dist/write-target.d.ts +9 -0
  92. package/dist/write-target.js +11 -2
  93. package/dist/write-target.js.map +1 -1
  94. package/package.json +1 -1
@@ -45,10 +45,131 @@
45
45
  // CLI translation of the MCP oracle (`orbitmap-mcp/.../instructions.py`). The skills
46
46
  // have since evolved past that spec — worklog wiring, the keep/drop test, and the v2
47
47
  // whole-intent execute flow — so THIS FILE is now normative, not the spec.
48
- export const MARKER_START = '<!-- ORBITMAP_START -->';
48
+ import { createRequire } from 'node:module';
49
+ /**
50
+ * The version of this CLI, read from package.json exactly the way `--version` does in
51
+ * `src/index.ts`: `../package.json` resolves to the repo root from both `src/` and
52
+ * `dist/`, and npm always ships package.json in the tarball.
53
+ */
54
+ export const CLI_VERSION = createRequire(import.meta.url)('../package.json').version;
55
+ /**
56
+ * Stable prefix of the start marker, shared by every generation of installed block.
57
+ *
58
+ * In-place rewrite logic MUST match on this prefix (never on the full
59
+ * {@link MARKER_START}): pre-versioning installs wrote `<!-- ORBITMAP_START -->` with no
60
+ * version stamp, and a refresh has to find and upgrade those too (IS-bej5d8).
61
+ */
62
+ export const MARKER_START_PREFIX = '<!-- ORBITMAP_START';
63
+ /**
64
+ * The start marker as written by THIS binary. Carries the CLI version so drift between
65
+ * an installed block and the shipped instructions is detectable (IS-bej5d8).
66
+ */
67
+ export const MARKER_START = `${MARKER_START_PREFIX} v${CLI_VERSION} -->`;
68
+ /** Unversioned deliberately — the version lives only in the START marker. */
49
69
  export const MARKER_END = '<!-- ORBITMAP_END -->';
70
+ /**
71
+ * Read the version stamp out of an installed instruction block.
72
+ *
73
+ * Returns the version string (`"0.4.6"`) when the start marker carries one, `null` for a
74
+ * pre-versioning `<!-- ORBITMAP_START -->` marker, and `undefined` when `content` holds
75
+ * no OrbitMap block at all.
76
+ */
77
+ export function parseInstalledMarkerVersion(content) {
78
+ const match = content.match(/<!-- ORBITMAP_START(?:\s+v(\S+?))?\s*-->/);
79
+ if (!match)
80
+ return undefined;
81
+ return match[1] ?? null;
82
+ }
50
83
  /** The core skill name (entry point). Kept for backwards compatibility. */
51
84
  export const SKILL_NAME = 'orbitmap';
85
+ // ── Shared section: SESSION FOCUS ──────────────────────────────────────────────
86
+ //
87
+ // LOCKED COPY from IN-vnz6fs's design ("Skill bodies" block), plus the amendment-2
88
+ // semantics (soft cap, transient references, file-as-optimization). Consumed verbatim —
89
+ // do not paraphrase it away. The full section ships ONCE, inside the core `orbitmap`
90
+ // skill body; every other gate body carries a compact ensure rule that points here.
91
+ //
92
+ // Decision #11 (IN-nahetc) compatibility: session focus is CLIENT-SIDE state only —
93
+ // nothing on the wire narrows a list to an intent on the agent's behalf. Every task
94
+ // query the skills emit still carries `--intent` explicitly; the locked copy below
95
+ // restates that rule ("Never narrow silently").
96
+ export const SESSION_FOCUS_SECTION = `## Session focus
97
+
98
+ SESSION FOCUS — Ensure, don't call. A session focus file ({mission, intents (≤3 typical —
99
+ a SOFT cap: focus holds what the session is actively advancing), areas, agent_id,
100
+ matched_at}) lives in your session temp directory. If present and the agent identity
101
+ matches: do NOT call context. If missing or invalid — an identity or area mismatch
102
+ invalidates it — call \`orbitmap context\` once, match the conversation against its
103
+ handles, write the file, and STATE the match in one line — the intent's NAME, its number
104
+ only at first mention. Never narrow silently: every task query you send still carries
105
+ \`--intent\` explicitly. An intent you just created or fetched joins the focus by its
106
+ handle — no context call. If a write fails INTENT_CLOSED: your focus is stale — re-derive
107
+ and say so. Before creating a new intent or declaring none exists: fetch the 1–3 nearest
108
+ candidates with \`intent show --no-logs\` and judge from their bodies, not TL;DRs — a rule
109
+ for creation/dedup decision points only. If nothing matches: offer to frame an intent
110
+ (brainstorm gate) — never create a bare shell; if declined, work from the fetched missions
111
+ and intents ("look wider").
112
+
113
+ TRANSIENT references never enter focus: an intent fetched for a dedup check or a
114
+ cross-comparison is read and used, not focused; a real focus switch is stated aloud
115
+ ("focus now X, parking Y"). The file is an optimization with graceful failure — the
116
+ conversation is the primary carrier, the file only compaction insurance: no file → the
117
+ ensure rule above triggers one context call. Agent memory directories are the WRONG store
118
+ for focus (a cross-session lifetime means stale focus).`;
119
+ // ── Shared section: FRESHNESS (API 10.1.0, IN-qqqna5) ──────────────────────────
120
+ //
121
+ // The two UNIVERSAL rules plus the intent freshness-probe flow. Ships ONCE, inside the
122
+ // core `orbitmap` skill body (same pattern as SESSION_FOCUS_SECTION); other gate bodies
123
+ // carry a compact rule that points here.
124
+ export const FRESHNESS_SECTION = `## Freshness
125
+
126
+ Two universal rules — they apply to EVERY OrbitMap object, in every flow:
127
+ - TRUST THE WRITE'S ECHO. A successful write already returns the updated object — the
128
+ echo IS the current state. Never re-fetch an object just to verify a write you made.
129
+ - COMPARE THE HELD MARKER BEFORE RE-FETCHING ANYTHING BIG. Every full fetch hands you a
130
+ change marker — the \`updated_at\` + \`last_log_id\` pair on intents (tasks and missions
131
+ carry the pair too), \`version\` on documents. Hold it; re-fetch only on a mismatch.
132
+
133
+ PROBE FLOW (intents): the session focus file remembers each focused intent's
134
+ \`updated_at\` + \`last_log_id\` pair from the last FULL fetch. To check whether an
135
+ intent moved, run \`orbitmap intent show IN-x --slim\` — a ~150-token probe (handle,
136
+ TL;DRs, areas, mission, task counts, the pair). Pair unchanged → the intent has not
137
+ moved: SAY SO in one line and keep working from what you hold — no full fetch. Pair
138
+ changed → re-fetch (\`intent show IN-x\`, with \`--no-logs\` when the log tail is not
139
+ needed) and remember the new pair in the focus file.`;
140
+ // ── Shared block: the KEEP/DROP TEST (IS-vw765j) ───────────────────────────────
141
+ //
142
+ // ONE definition rendered into all four gate skills. It used to be four byte-identical
143
+ // copies, which is why the contradiction below survived so long: `code_change` is a
144
+ // caller-authorable type, yet the drop list forbade exactly what such an entry is — a
145
+ // fact git already holds. Six worker-built tasks on IN-5pdqkq produced 1 blocker, 8
146
+ // decisions, 12 notes and ZERO code_change entries, every worker obeying the rules
147
+ // correctly. The exemption below resolves it; keeping the block in one place is what
148
+ // makes the next correction a one-line change.
149
+ //
150
+ // The bullet indent differs between skills (execute uses `- `, the three gate skills
151
+ // ` - `), so the caller passes it in; continuation lines sit two spaces further in.
152
+ export function worklogKeepDropTest(indent = '') {
153
+ const c = `${indent} `;
154
+ return `${indent}- KEEP/DROP TEST — log a \`decision\` when ANY of these is true: an alternative was
155
+ ${c}considered and REJECTED (record which, and why it lost); a non-obvious assumption or
156
+ ${c}constraint was LOCKED IN; a choice was made that a later reader would otherwise
157
+ ${c}re-litigate. Do NOT log: restating the outcome, design or plan (they are already
158
+ ${c}fields on the intent); confirming something already written down elsewhere; mechanical
159
+ ${c}facts recoverable from git, CI or the tracker (test counts, file lists, commit hashes);
160
+ ${c}progress narration ("started X", "working on Y").
161
+ ${c}KEEP → "Parallelised the build across four subagents; the Laravel slices were split by
162
+ ${c}file ownership to avoid collisions in one working tree." — records the rejected
163
+ ${c}alternative (one agent per repo) and why it lost.
164
+ ${c}DROP → "make verify green at 2415 passed after merging all four agents." — a mechanical
165
+ ${c}fact already in the commit message and the CI output.
166
+ ${c}EXEMPTION — \`code_change\` is the one type the "mechanical facts" rule does NOT
167
+ ${c}forbid. Work that ships closes with ONE entry naming WHAT shipped and where: the
168
+ ${c}shape of the change, never a file listing, which the \`[TS-x]\` commit already
169
+ ${c}carries. Use it too for changes git CANNOT see — a config flipped in a dashboard, a
170
+ ${c}migration run against a live database, an external system mutated. Without this a
171
+ ${c}task records why every decision was made and never what was built.`;
172
+ }
52
173
  // ── Skill: orbitmap (core) — §8.3 ──────────────────────────────────────────────
53
174
  export const SKILL_ORBITMAP_FRONTMATTER = `---
54
175
  name: orbitmap
@@ -65,9 +186,9 @@ identically in cloud mode and local-files mode — never assume which one is act
65
186
  never read or write the workspace's data files directly. The CLI is the only interface.
66
187
 
67
188
  ## Goal
68
- Operate OrbitMap correctly: always start from \`orbitmap context\`, act on the active mission
69
- and open intents, write every item to the area the work belongs to, and go through the CLI
70
- only — never the data files.
189
+ Operate OrbitMap correctly: ensure session focus (below) instead of ritually calling
190
+ context, act on the mission and intents the session is about, write every item to the area
191
+ the work belongs to, and go through the CLI only — never the data files.
71
192
 
72
193
  **Interface:** every action below is an OrbitMap operation — run the \`orbitmap\` CLI command
73
194
  shown, or its equivalent MCP tool when this session uses MCP; \`orbitmap <cmd> --help\` and the
@@ -89,10 +210,17 @@ MCP tool schemas are the authority. Never edit the workspace data files directly
89
210
  outside a task. Task (TS-) = unit of work.
90
211
  - Entity numbers (TS-xxxxxx etc.) are accepted by every command that takes an id.
91
212
 
213
+ ${SESSION_FOCUS_SECTION}
214
+
215
+ ${FRESHNESS_SECTION}
216
+
92
217
  ## Context
93
- - START HERE, always: \`orbitmap context\`. \`orbitmap context\` is authoritative and returns
94
- in ONE call everything a session needs the agent, the workspace, the areas you work in,
95
- the active mission, open intents, your tasks and the documents. Never list areas and never
218
+ - Ensure session focus (above) at most ONE \`orbitmap context\` call per session, and none
219
+ while a valid focus file is held. \`orbitmap context\` is authoritative MATCHING MATERIAL:
220
+ your agent identity, the missions and intents as handles with TL;DR summaries, standalone
221
+ mission workitems, the areas you work in, and document metadata. It carries no task
222
+ lists and no bodies — fetch deeper on demand (\`orbitmap intent show IN-x\`,
223
+ \`orbitmap tasks --intent IN-x\`, \`orbitmap doc <slug>\`). Never list areas and never
96
224
  ask the user "which area?" before you have read it.
97
225
  - You work in a WORKSPACE, not inside a single area. Missions, intents
98
226
  and documents are workspace-level and take no area — a document is exactly ONE copy,
@@ -120,15 +248,38 @@ MCP tool schemas are the authority. Never edit the workspace data files directly
120
248
  \`source\` of \`global ~/.orbitmap/config.json\` is a machine-wide leftover that nothing
121
249
  here chose — treat it as unconfirmed and pass \`--area\` explicitly.
122
250
 
251
+ ## Task or intent?
252
+
253
+ An intent earns its gates when the work carries knowledge someone would otherwise
254
+ re-derive or re-litigate: a decision with a rejected alternative, a design that outlives
255
+ the change, a constraint worth recording. Work with none of that — a typo, a copy tweak,
256
+ an obvious one-file fix — is a task: create it, do it, log it, done. The same test the
257
+ work log uses for what to write down. If a "small" fix turns out to hide a real decision,
258
+ stop and frame it; discovering that mid-change is normal, not a failure.
259
+
123
260
  ## Task statuses
124
261
  backlog, todo, in_progress, in_review, review_changes, done, blocked.
125
262
  \`orbitmap tasks\` defaults to todo,in_progress. Ask for others explicitly, e.g.
126
263
  \`orbitmap tasks --status backlog\` when the user asks about the backlog.
127
264
 
265
+ ## Listing tasks
266
+ - A list spans EVERY area you can reach and EVERY assignee — nothing narrows it to the
267
+ current directory or to you. It is capped at 30 rows with the totals behind the cap
268
+ printed, and every list states the filters that produced it. Read that line before you
269
+ answer from a list.
270
+ - While you are executing an intent, EVERY task query carries \`--intent IN-x\`. Nothing
271
+ narrows a list to an intent on your behalf: a bare \`orbitmap tasks\` is you having
272
+ deliberately left the intent to look at the whole workspace.
273
+ - \`orbitmap intent show IN-x\` already carries the intent's own tasks, so intent lifecycle
274
+ work needs no filter at all. \`orbitmap tasks --intent IN-x\` is the escape hatch for the
275
+ times you want the task-list shape — statuses, assignees, the filter line — instead.
276
+
128
277
  ## Command reference (all commands accept --json)
129
- - Context: \`orbitmap context\` (start here), \`orbitmap overview\`, \`orbitmap areas\`
278
+ - Context: \`orbitmap context\` (once per session at most — see Session focus),
279
+ \`orbitmap overview\`, \`orbitmap areas\`
130
280
  (rarely needed — context already lists the areas you work in)
131
- - Tasks: \`orbitmap tasks [--status s1,s2]\`, \`orbitmap task TS-x\`, \`orbitmap get <ID>\`,
281
+ - Tasks: \`orbitmap tasks [--status s1,s2] [--intent IN-x]\`, \`orbitmap task TS-x\`,
282
+ \`orbitmap get <ID>\`,
132
283
  \`orbitmap start [TS-x]\`, \`orbitmap status TS-x <status> [--delivery <d>]\`,
133
284
  \`orbitmap create "title" [--intent IN-x|--mission MS-x] [--priority p]\`,
134
285
  \`orbitmap subtask TS-parent "title"\`, \`orbitmap assign TS-x [agent]\`,
@@ -138,6 +289,8 @@ backlog, todo, in_progress, in_review, review_changes, done, blocked.
138
289
  - Vibes: \`orbitmap vibe log|list|show\`
139
290
  - Missions: \`orbitmap mission list|show|create|update|status|link|unlink\`
140
291
  - Intents: \`orbitmap intent list|show|create|update|link|unlink\`
292
+ (\`show\` embeds the context bundle — \`--no-bundle\` strips it, \`--slim\` is the
293
+ freshness probe, \`--no-logs\` skips the log tail)
141
294
  - Documents: \`orbitmap docs\`, \`orbitmap doc <slug> [--section "## H"|--full]\`,
142
295
  \`orbitmap doc-import\`, \`orbitmap doc-update\`
143
296
 
@@ -194,16 +347,29 @@ MCP tool schemas are the authority. Never edit the workspace data files directly
194
347
  - **Distrust and verify.** Instructions age; the tree is the truth. Re-grep any claim a
195
348
  task's instructions make about the code ("X lives in Y", "verified list of call sites")
196
349
  before relying on it.
197
- - **The orchestrator owns shared state.** Workers never run git, never write OrbitMap,
198
- never use the shared test DB, never format, never change dependencies commits, logs,
199
- statuses, formatting and test gates all happen at fold time, in the orchestrator.
350
+ - **Every task query names the intent.** While executing IN-x, EVERY task query carries
351
+ \`--intent IN-x\`. A list otherwise spans every area you can reach and every assignee,
352
+ capped at 30 rows with the totals printed and the filters that produced it stated on
353
+ the list — so a bare \`orbitmap tasks\` is you deliberately stepping OUTSIDE the intent,
354
+ never a shortcut to it. \`orbitmap intent show IN-x\` already carries the intent's own
355
+ tasks, so the intent lifecycle steps below need no filter at all; \`--intent\` is the
356
+ escape hatch for the times you want the task-list shape instead.
357
+ - **The orchestrator owns shared state.** Workers never run git, never use the shared
358
+ test DB, never format, never change dependencies, and never write OrbitMap beyond
359
+ appending to their OWN task's work log — commits, statuses, formatting and test gates
360
+ all happen at fold time, in the orchestrator.
361
+ - **Freshness** (see Freshness in the \`orbitmap\` skill): trust each write's echo — never
362
+ re-fetch to verify your own write; before any big re-fetch compare the held
363
+ \`updated_at\`/\`last_log_id\` pair, probing with \`orbitmap intent show IN-x --slim\`.
200
364
  - **Never end the run to wait.** Shared gates QUEUE safely: run them in the foreground
201
365
  and wait on the command (generous timeout); an overrun that gets backgrounded resumes
202
366
  you on completion. Ending your turn is only for: run COMPLETE, or hard-blocked and
203
367
  logged — a background run that yields to "wait for a signal" is a dead run.
204
368
 
205
369
  ## Flow A — execute IN-x (whole intent)
206
- 1. **Premise check.** \`orbitmap intent show IN-x\`: it must exist, be at status \`build\`,
370
+ 1. **Premise check.** IN-x joins your session focus by its handle — no context call
371
+ (see Session focus in the \`orbitmap\` skill). \`orbitmap intent show IN-x\`: it must
372
+ exist, be at status \`build\`,
207
373
  and have tasks with agent_instructions. Anything missing → refuse politely and point at
208
374
  the missing gate (\`orbitmap-brainstorm\` for no outcome, \`orbitmap-design\` for no
209
375
  design, \`orbitmap-plan\` for no tasks). Read the outcome, design, plan field and work
@@ -229,18 +395,22 @@ MCP tool schemas are the authority. Never edit the workspace data files directly
229
395
  - Size the wave by GATE CONTENTION, not a constant: tasks needing the shared test DB
230
396
  ≤4 concurrent (the gate serialises anyway); light, file-disjoint tasks (docs,
231
397
  separate repos) as wide as the ready-set — 10+ is fine.
232
- - Dispatch one worker (subagent) per task. Prompt = the task number, its
233
- agent_instructions PASTED VERBATIM (workers get no CLI credentials never make one
234
- fetch its own spec), the repo path, the exact files it owns, and one line: "Follow
398
+ - Dispatch one worker (subagent) per task, writing \`orbitmap status TS-x in_progress\`
399
+ at dispatch. Pass ORBITMAP_API_KEY + ORBITMAP_API_URL into the worker's env the
400
+ worker logs its OWN task as it builds, per the contract. Prompt = the task number,
401
+ its agent_instructions PASTED VERBATIM (never make a worker fetch its own spec),
402
+ the repo path, the exact files it owns, and one line: "Follow
235
403
  references/worker-contract.md of the orbitmap-execute skill." Worktree isolation
236
404
  ONLY when same-repo tasks in the wave overlap on files; otherwise slice the wave
237
405
  file-disjoint in one tree; cross-repo needs nothing.
238
406
  - FOLD the workers' results sequentially in dependency order, a gate between folds:
239
407
  integrate one task → scoped tests → formatter → commit \`[TS-x] …\` (one commit may
240
- carry several tasks that verify as one unit) → log per the keep/drop test →
408
+ carry several tasks that verify as one unit) → log ONLY what the fold itself
409
+ learns (keep/drop test) — the worker wrote its own narrative; do not re-write it →
241
410
  \`orbitmap status TS-x in_review --delivery on_branch\`.
242
411
  - A task neither the worker nor the fold can save → \`orbitmap log TS-x "Blocked: …"
243
- --type blocker\` + \`orbitmap status TS-x blocked\` the run CONTINUES without it.
412
+ --type blocker\` + \`orbitmap status TS-x blocked\` THE MOMENT the worker reports it,
413
+ not at fold — the run CONTINUES without it.
244
414
  Its dependents leave the ready-set with their own logged blocker but KEEP their
245
415
  status (backlog): they are waiting, not failed.
246
416
  - Recompute the ready-set; next wave.
@@ -256,13 +426,15 @@ MCP tool schemas are the authority. Never edit the workspace data files directly
256
426
  delivered or honestly blocked and the gates are green vs baseline. An unfixable intent
257
427
  test or a design contradiction → STOP and ask the user: that is intent-level risk, the
258
428
  one thing that interrupts.
259
- 8. **Report + resume note.** Leave every repo checked out on its BASE branch — the
260
- intent branch is named in the report, not left underfoot. Report in chat: what
261
- shipped, what was decided, what is blocked and why, deviations from the plan, gate
262
- results vs baseline. Write ONE resume
263
- point: \`orbitmap log IN-x "Resume point: …" --type note\`. The intent STAYS \`build\`;
264
- merging and closing are the USER'S. The merge EVENT whoever performs it — is what
265
- later flips the tasks to \`--delivery merged\`.
429
+ 8. **Report + move the intent to in_review.** Leave every repo checked out on its BASE
430
+ branch — the intent branch is named in the report, not left underfoot. Report in
431
+ chat: what shipped, what was decided, what is blocked and why, deviations from the
432
+ plan, gate results vs baseline. Write ONE resume
433
+ point: \`orbitmap log IN-x "Resume point: …" --type note\`. Then end the run:
434
+ \`orbitmap intent update IN-x --status in_review --log <entries>\`the transition's
435
+ response carries an Instructions section (it will ask for release notes); FOLLOW it.
436
+ Merging and closing to \`done\` are the USER'S. The merge EVENT — whoever performs
437
+ it — is what later flips the tasks to \`--delivery merged\`.
266
438
 
267
439
  **No subagent runtime?** Same flow, serial: do steps 4–7 yourself, task by task, with the
268
440
  worker contract as your own build rules. The contract is the outcome, not the parallelism.
@@ -284,7 +456,7 @@ digraph orbitmap_execute {
284
456
  "Regressions or intent-test failures?" [shape=diamond];
285
457
  "Fix findings, scoped tests per fix" [shape=box];
286
458
  "Intent-level risk: stop and ask the user" [shape=box];
287
- "Report + resume note; intent stays build; user merges" [shape=doublecircle];
459
+ "Report + resume note; intent update --status in_review; user merges" [shape=doublecircle];
288
460
 
289
461
  "Premise: intent at build, tasks with instructions?" -> "Refuse politely; point at the missing gate" [label="no"];
290
462
  "Premise: intent at build, tasks with instructions?" -> "Baseline: full gate per touched repo, results recorded" [label="yes"];
@@ -302,15 +474,18 @@ digraph orbitmap_execute {
302
474
  "Regressions or intent-test failures?" -> "Fix findings, scoped tests per fix" [label="yes"];
303
475
  "Fix findings, scoped tests per fix" -> "Impact pass: full gate per repo, diff vs baseline (+contract steps)" [label="re-run"];
304
476
  "Fix findings, scoped tests per fix" -> "Intent-level risk: stop and ask the user" [label="unfixable / contradiction"];
305
- "Regressions or intent-test failures?" -> "Report + resume note; intent stays build; user merges" [label="no"];
477
+ "Regressions or intent-test failures?" -> "Report + resume note; intent update --status in_review; user merges" [label="no"];
306
478
  }
307
479
  \`\`\`
308
480
 
309
481
  ## Flow B — work on TS-x (single task)
310
- 1. \`orbitmap context\` workspace, areas, active mission, open intents and your tasks in
311
- one call. Never ask which area; never list areas first.
312
- 2. Unfinished work in context (or \`orbitmap tasks --status in_progress\`)
313
- \`orbitmap task TS-x\` read the work log resume from the resume point.
482
+ 1. Ensure session focus (see Session focus in the \`orbitmap\` skill): a valid focus file
483
+ means NO context call; missing or invalid one \`orbitmap context\` call, match the
484
+ conversation against its handles, and state the match in one line. A directly named
485
+ TS-x needs no matching at all fetch it. Never ask which area; never list areas first.
486
+ 2. Unfinished work (\`orbitmap tasks --status in_progress\`, with \`--intent IN-x\` while
487
+ focused on an intent) → \`orbitmap task TS-x\` → read the work log → resume from the
488
+ resume point.
314
489
  3. Otherwise pick work serving the active mission / open intents, or \`orbitmap start\` —
315
490
  auto-picks the first todo task, sets it in_progress and prints full context.
316
491
  \`orbitmap start TS-x\` begins a specific task; \`orbitmap task TS-x\` only inspects.
@@ -322,6 +497,13 @@ digraph orbitmap_execute {
322
497
 
323
498
  ## Logging (both flows)
324
499
  - \`orbitmap log TS-x "…" --type note|code_change|decision|blocker\` — work WITHIN a task.
500
+ - CADENCE IS A TEST, not a schedule: log when knowledge arises that git cannot
501
+ reconstruct — a spec claim that failed verification, a decision with a rejected
502
+ alternative, a blocker the moment it blocks, a discovery or risk outside the task's
503
+ boundary, what a failing gate revealed. NOT file lists, test counts or progress
504
+ narration. 1–3 entries on a normal task — losing nothing is the goal, volume is not.
505
+ A long task whose whole log lands at the end is refused (WORK_LOG_RECONSTRUCTED) —
506
+ log during, not after.
325
507
  - \`orbitmap vibe log "…" --type discovery|exploration|fix\` — ad-hoc work outside a task.
326
508
  - \`orbitmap idea add\` — future possibilities, NOT problems (problems →
327
509
  \`orbitmap issue register\`).
@@ -329,18 +511,7 @@ digraph orbitmap_execute {
329
511
  \`blocker\` goes in as \`note\`, with \`--meta\` carrying any unusual structure. There is
330
512
  deliberately NO \`other\` type. NEVER write \`status_change\` — the server authors it on
331
513
  every transition and the API rejects it from clients.
332
- - KEEP/DROP TEST — log a \`decision\` when ANY of these is true: an alternative was
333
- considered and REJECTED (record which, and why it lost); a non-obvious assumption or
334
- constraint was LOCKED IN; a choice was made that a later reader would otherwise
335
- re-litigate. Do NOT log: restating the outcome, design or plan (they are already
336
- fields on the intent); confirming something already written down elsewhere; mechanical
337
- facts recoverable from git, CI or the tracker (test counts, file lists, commit hashes);
338
- progress narration ("started X", "working on Y").
339
- KEEP → "Parallelised the build across four subagents; the Laravel slices were split by
340
- file ownership to avoid collisions in one working tree." — records the rejected
341
- alternative (one agent per repo) and why it lost.
342
- DROP → "make verify green at 2415 passed after merging all four agents." — a mechanical
343
- fact already in the commit message and the CI output.
514
+ ${worklogKeepDropTest()}
344
515
  - Promote to the parent intent — TWO filters, BOTH must pass: the entry is a \`decision\` or
345
516
  \`blocker\` (never \`note\`/\`code_change\`), AND it passes the keep/drop test. Then ALSO
346
517
  write a SECOND, separately-worded entry for a reader who never saw the task:
@@ -358,7 +529,8 @@ digraph orbitmap_execute {
358
529
  --type blocker\` then \`orbitmap status TS-x blocked\`.
359
530
  - Session ending, task unfinished but NOT blocked → \`orbitmap log TS-x "Resume point: …"
360
531
  --type note\` — leave status in_progress.
361
- - NEVER leave a task without a final log entry.
532
+ - NEVER leave a task without a final log entry — the final entry closes a record that
533
+ already exists; it is never the record.
362
534
  - Closing the intent (ONLY when the user explicitly asks — Flow A never does) → the
363
535
  transition must carry the build phase's entries (\`--log <type>:<content>\` is
364
536
  repeatable): \`orbitmap intent update IN-x --status done --log code_change:"<what was
@@ -385,22 +557,26 @@ digraph orbitmap_execute {
385
557
 
386
558
  ## Rules
387
559
  - Flow A never merges, never pushes to the default branch, never closes tasks or the
388
- intent as \`done\` — the run ends at \`in_review\` on the intent branch, intent at \`build\`.
560
+ intent as \`done\` — the run ends with \`orbitmap intent update IN-x --status in_review
561
+ --log …\` (follow the Instructions the transition returns); merging and \`done\` are
562
+ the user's.
389
563
  - Baseline before any change; "no new bugs" = no failure absent from the baseline.
390
564
  - The fix loop is goal-based — no round cap; termination is delivered-or-blocked plus
391
565
  green gates, never a retry budget.
392
566
  - Decide-and-log within the design; \`blocked\` + continue for a stuck task; interrupt the
393
567
  user only for intent-level risk. Never a silent skip.
394
- - Workers follow \`references/worker-contract.md\`: no git, no OrbitMap writes, no shared
395
- test DB, no formatter, no dependency changes the orchestrator owns all of those.
568
+ - Workers follow \`references/worker-contract.md\`: no git, no shared test DB, no
569
+ formatter, no dependency changes, no OrbitMap writes beyond their own task's log
570
+ the orchestrator owns all of those.
396
571
  - Flow B works on ONE task at a time.
397
572
  - Always read agent_instructions before implementing, then re-verify their claims against
398
573
  the tree (distrust-and-verify).
399
574
  - Agents with a plan mode: an implementation plan for a tracked task MUST include the
400
575
  lifecycle as explicit steps — first the task number/title, last the final \`orbitmap log\`
401
576
  + \`orbitmap status\` per the status decision guide.
402
- - NEVER leave a task without a final log entry; never author \`status_change\`; an intent
403
- transition without \`--log\` entries is refused (422).`;
577
+ - NEVER leave a task without a final log entry it closes a record that already exists,
578
+ never IS the record; never author \`status_change\`; an intent transition without
579
+ \`--log\` entries is refused (422).`;
404
580
  // Reference files shipped WITH the orbitmap-execute skill (the worker contract that
405
581
  // dispatched subagents read instead of the whole skill). See SkillDef.references for
406
582
  // the shape the installer consumes.
@@ -423,8 +599,13 @@ state, formatting, the test gates. Your job is the code and an honest report.
423
599
  - Own ONLY the files named in your dispatch prompt. A change needed elsewhere is a
424
600
  finding to report, never an edit to make.
425
601
  - NEVER run git — no commit, branch, stash, checkout. The orchestrator commits.
426
- - NEVER write OrbitMap stateno \`orbitmap log\` / \`status\` / \`create\` / \`update\`.
427
- Reading (\`orbitmap task\`, \`orbitmap doc\`) is fine.
602
+ - OrbitMap writesone carve-out. You MAY append work-log entries to YOUR ONE
603
+ dispatched task (\`orbitmap log TS-x "…" --type note|code_change|decision|blocker\`),
604
+ as knowledge arises, never batched at the end. This is safe because append-only
605
+ writes to a single task cannot collide between parallel workers. Everything else is
606
+ still NEVER — \`orbitmap status\` / \`create\` / \`update\`, and any write to any OTHER
607
+ task: those operations share state the orchestrator owns. Reading (\`orbitmap task\`,
608
+ \`orbitmap doc\`) is fine.
428
609
  - NEVER use the shared test DB or its Docker gate — parallel workers would collide on it.
429
610
  The orchestrator runs those tests at fold time.
430
611
  - NEVER run the repo formatter (it rewrites files you do not own) and NEVER change
@@ -437,6 +618,19 @@ state, formatting, the test gates. Your job is the code and an honest report.
437
618
  - Syntax-check everything you touch with cheap, isolated checks (\`php -l\`, \`tsc --noEmit\`,
438
619
  \`python -m py_compile\`, a scoped non-shared test run) — never the shared gates.
439
620
 
621
+ ## Log as you build — the cadence is a test
622
+ Write a work-log entry when knowledge arises that git cannot reconstruct: a spec claim
623
+ that failed verification, a decision with a rejected alternative, a blocker the moment
624
+ it blocks, a discovery or risk outside your boundary, what a failing check revealed.
625
+ NOT file lists, test counts, or progress narration. 1–3 entries on a normal task —
626
+ losing nothing is the goal, volume is not.
627
+
628
+ Close with ONE \`code_change\` entry naming WHAT you shipped and where — the shape of the
629
+ change, never a file listing, which the \`[TS-x]\` commit already carries. It is the one
630
+ type the "not mechanical facts" rule above does not forbid: without it your task records
631
+ why every decision was made and never what was built. Use it too for anything git cannot
632
+ see — a config flipped in a dashboard, a migration run against a live database.
633
+
440
634
  ## Report — your final text goes to the orchestrator, not to a user
441
635
  Structure it as:
442
636
  - **Files changed** — every file, one line each on what changed and why.
@@ -546,26 +740,22 @@ task/issue that has an intent; the CLI enforces this.
546
740
  edge — wire it even though the tasks live in different areas.
547
741
 
548
742
  ## Flow
549
- 1. Gather context. Read the intent's \`outcome\` + \`design\` + \`plan\` field
743
+ 1. Gather context. Ensure session focus (see Session focus in the \`orbitmap\` skill) —
744
+ the intent you are planning joins the focus by its handle, no context call while the
745
+ focus file is valid. Read the intent's \`outcome\` + \`design\` + \`plan\` field
550
746
  (\`orbitmap intent show IN-x\`) — if the plan field holds seed notes, absorb them as
551
- highest-priority input (see above); \`orbitmap context\`; the relevant doc BODIES (\`orbitmap doc <slug>\` — the design flagged
747
+ highest-priority input (see above); the relevant doc BODIES (\`orbitmap doc <slug>\` — the design flagged
552
748
  which); the neighbourhood (mission, sibling intents, and the intent's EXISTING tasks —
553
749
  do not re-decompose them). Verify against the repo before decomposing.
554
750
  2. Decompose the design into a FLAT list of concrete tasks, each placed in the CORRECT
555
751
  area — \`orbitmap create "title" --intent IN-x --area <slug> [--priority p]\`. No
556
752
  subtasks.
557
- - KEEP/DROP TEST log a \`decision\` when ANY of these is true: an alternative was
558
- considered and REJECTED (record which, and why it lost); a non-obvious assumption or
559
- constraint was LOCKED IN; a choice was made that a later reader would otherwise
560
- re-litigate. Do NOT log: restating the outcome, design or plan (they are already
561
- fields on the intent); confirming something already written down elsewhere; mechanical
562
- facts recoverable from git, CI or the tracker (test counts, file lists, commit hashes);
563
- progress narration ("started X", "working on Y").
564
- KEEP → "Parallelised the build across four subagents; the Laravel slices were split by
565
- file ownership to avoid collisions in one working tree." — records the rejected
566
- alternative (one agent per repo) and why it lost.
567
- DROP → "make verify green at 2415 passed after merging all four agents." — a mechanical
568
- fact already in the commit message and the CI output.
753
+ - DECLARE THE INTENT'S AREAS as part of decomposition: your task placement decisions
754
+ ARE the intent's area list write it with
755
+ \`orbitmap intent update IN-x --areas <slug>,<slug>\` (the distinct areas of the
756
+ tasks you are creating). Declared areas feed session-focus matching for every later
757
+ session.
758
+ ${worklogKeepDropTest(' ')}
569
759
  - LOG IT THE MOMENT IT IS AGREED, not batched at the end:
570
760
  \`orbitmap log IN-x "<the decision and why — task shape, sequencing, area>" --type decision\`.
571
761
  An abandoned session must still leave its decisions recorded.
@@ -664,7 +854,8 @@ digraph orbitmap_plan {
664
854
  - **Self-contained?** Every task's instructions carry summary + Orb context + doc pointers
665
855
  + acceptance + any depends-on line — runnable by a zero-context agent.
666
856
  - **No placeholders?** Self-review done; no vague/TBD instructions remain.
667
- - **Areas?** Each task in the right area.
857
+ - **Areas?** Each task in the right area, and the intent's areas declared
858
+ (\`intent update --areas\`) to match the placements.
668
859
  - **Dependencies?** Orb dep edges wired AND named in the dependent tasks' instructions.
669
860
  - **Plan field?** Cross-task notes + a summary written to the intent \`plan\` field.
670
861
  - **Doc-update?** A doc-update-after-green task is in the plan.
@@ -702,6 +893,8 @@ triaging issues):
702
893
  Orb context + doc pointers + acceptance + any depends-on line). No placeholders.
703
894
  - Wire dependencies as Orb edges AND name them in the dependent tasks' instructions.
704
895
  - Place each task in the correct area; derive it from the work, not the current directory.
896
+ - Declare the intent's areas during decomposition (\`orbitmap intent update IN-x --areas\`) —
897
+ task placement decisions are the area list.
705
898
  - Self-review the plan before presenting; fix placeholders/coverage/consistency inline.
706
899
  - Write cross-task notes + a summary to the intent \`plan\` field.
707
900
  - Log \`decision\` entries that pass the keep/drop test (Flow step 2) as they are agreed, never
@@ -753,9 +946,11 @@ you hand to \`orbitmap-design\` (and, through the plan field, to \`orbitmap-plan
753
946
  do not interrogate. The ONE thing you must reach is an AGREED OUTCOME; everything else
754
947
  useful gets captured for later, never blocked on.
755
948
  - **Gate before build.** No feature, component, or behavior change starts before the
756
- outcome is agreed and written to OrbitMap. "Too simple to frame" is exactly where
757
- unexamined assumptions cost the most — every idea gets an outcome, even a one-sentence
758
- one.
949
+ outcome is agreed and written to OrbitMap. For anything that changes behaviour, "too
950
+ simple to frame" is exactly where unexamined assumptions cost the most — a one-sentence
951
+ outcome is still an outcome. Genuinely small self-contained work (a typo, a copy tweak,
952
+ an obvious one-file fix) is a task, not an intent; see the \`orbitmap\` skill's
953
+ task-or-intent test.
759
954
  - **The outcome is an agreement, not your guess.** It is the user's, in the user's words.
760
955
  Never advance on an assumed or half-agreed outcome.
761
956
  - **One question at a time.** Refine by dialogue, never a questionnaire dump.
@@ -793,9 +988,11 @@ you hand to \`orbitmap-design\` (and, through the plan field, to \`orbitmap-plan
793
988
 
794
989
  ## Flow
795
990
  1. Gather context.
796
- - \`orbitmap context\` and \`orbitmap intent show IN-x\` already carry the workspace,
797
- mission, recently-used and open intents, and the target intent; read any referenced
798
- idea (ID-) too.
991
+ - Ensure session focus (see Session focus in the \`orbitmap\` skill): a valid focus
992
+ file means NO context call; missing or invalid one \`orbitmap context\` call
993
+ supplies the matching material. The focus plus \`orbitmap intent show IN-x\` already
994
+ carry the workspace, mission, the nearby recently-used and open intents, and the
995
+ target intent; read any referenced idea (ID-) too.
799
996
  - Check the repo itself — relevant files, docs, recent commits — when the outcome
800
997
  touches existing code and to get all the context.
801
998
  - Skim the available knowledge — the doc lists (\`available_docs\` across areas,
@@ -806,7 +1003,9 @@ you hand to \`orbitmap-design\` (and, through the plan field, to \`orbitmap-plan
806
1003
  intent serve a still-active mission?) and the SIBLING intents under that mission/orbit
807
1004
  with their outcomes + statuses — from the intent context if present, else
808
1005
  \`orbitmap mission show MS-x\` / \`orbitmap intents\`. Reconcile or link rather than frame
809
- a duplicate/conflicting outcome; ignore siblings that are \`done\`/\`cancelled\`.
1006
+ a duplicate/conflicting outcome and never declare "no duplicate" from TL;DRs alone:
1007
+ fetch the 1–3 nearest candidates' bodies (\`orbitmap intent show IN-x --no-logs\`)
1008
+ first. Ignore siblings that are \`done\`/\`cancelled\`.
810
1009
  - Verify the premise before framing: is this already built or partially shipped, is any
811
1010
  prerequisite phase actually complete, do the named entities exist? Grep migrations /
812
1011
  commits / the tracker — frame on what is true NOW, not on the plan doc's claim.
@@ -814,18 +1013,7 @@ you hand to \`orbitmap-design\` (and, through the plan field, to \`orbitmap-plan
814
1013
  and for whom, what success looks like, the constraints. As you go, capture the user's
815
1014
  opinions, preferences and context as notes; these outrank your own ideas in the design
816
1015
  stage, so record them faithfully.
817
- - KEEP/DROP TEST — log a \`decision\` when ANY of these is true: an alternative was
818
- considered and REJECTED (record which, and why it lost); a non-obvious assumption or
819
- constraint was LOCKED IN; a choice was made that a later reader would otherwise
820
- re-litigate. Do NOT log: restating the outcome, design or plan (they are already
821
- fields on the intent); confirming something already written down elsewhere; mechanical
822
- facts recoverable from git, CI or the tracker (test counts, file lists, commit hashes);
823
- progress narration ("started X", "working on Y").
824
- KEEP → "Parallelised the build across four subagents; the Laravel slices were split by
825
- file ownership to avoid collisions in one working tree." — records the rejected
826
- alternative (one agent per repo) and why it lost.
827
- DROP → "make verify green at 2415 passed after merging all four agents." — a mechanical
828
- fact already in the commit message and the CI output.
1016
+ ${worklogKeepDropTest(' ')}
829
1017
  - LOG IT THE MOMENT IT PASSES, not batched at the end: \`orbitmap log IN-x "<what was
830
1018
  decided and why>" --type decision\`. An abandoned session must still leave its decisions
831
1019
  recorded. If the intent does not exist yet, create it (step 4) at the first passing
@@ -847,6 +1035,10 @@ you hand to \`orbitmap-design\` (and, through the plan field, to \`orbitmap-plan
847
1035
  as the user's in both fields; you may add your own, kept separate. The design gate reads
848
1036
  the design notes and the plan gate reads the plan notes, each as its highest-priority
849
1037
  input.
1038
+ - A freshly created intent joins your session focus by its handle — no context call.
1039
+ - OPTIONALLY declare the intent's areas when the conversation already made the touched
1040
+ repos obvious — \`orbitmap intent update IN-x --areas <slug>,<slug>\`; otherwise leave
1041
+ the declaration to the design and plan gates, which own it.
850
1042
  - If you promoted an OrbitMap idea, mark it used: \`orbitmap idea status ID-x used\`.
851
1043
  5. Advance the lifecycle, carrying this gate's entries — \`--log <type>:<content>\` is
852
1044
  REPEATABLE and \`new → design\` is decision-heavy (why this outcome, what is out of scope):
@@ -921,7 +1113,8 @@ Then write it (Flow step 4), advance \`new → design\`, and hand the baton to
921
1113
  export const SKILL_DESIGN_FRONTMATTER = `---
922
1114
  name: orbitmap-design
923
1115
  description: >
924
- Designing an intent's solution in OrbitMap: turns an agreed outcome into an approach,
1116
+ Designing an intent's solution in OrbitMap the second gate of the product-building
1117
+ flow (after brainstorm): turns an agreed outcome into an approach,
925
1118
  technical spec, and UX (when there's UI), one question at a time, then writes the
926
1119
  result to the intent's design field. Use for "design this intent", "let's design X", or
927
1120
  an intent entering \`design\` status. Use it once the outcome is agreed; if the outcome is
@@ -1001,9 +1194,10 @@ well-bounded units are easier to build, review, and reason about.
1001
1194
 
1002
1195
  ## Flow
1003
1196
  1. Gather context.
1004
- - \`orbitmap intent show IN-x\` the outcome and the design field; \`orbitmap context\`
1005
- for the workspace and mission. If the design field holds framing notes, absorb them
1006
- as highest-priority input (see above).
1197
+ - Ensure session focus (see Session focus in the \`orbitmap\` skill) the intent you
1198
+ are designing joins the focus by its handle; no context call while the focus file is
1199
+ valid. \`orbitmap intent show IN-x\` the outcome and the design field. If the design
1200
+ field holds framing notes, absorb them as highest-priority input (see above).
1007
1201
  - Check the repo — relevant files, existing patterns, docs, recent commits. You design
1008
1202
  against real code, so read it before proposing.
1009
1203
  - Pull the relevant OrbitMap docs: from the doc lists (\`available_docs\` /
@@ -1023,18 +1217,7 @@ well-bounded units are easier to build, review, and reason about.
1023
1217
  cases, data/API shape. Continuously check whether the emerging design actually delivers
1024
1218
  the outcome, and surface any gap where it would not. Capture the user's decisions and
1025
1219
  the reasoning behind them as you go — those decisions are part of the design.
1026
- - KEEP/DROP TEST — log a \`decision\` when ANY of these is true: an alternative was
1027
- considered and REJECTED (record which, and why it lost); a non-obvious assumption or
1028
- constraint was LOCKED IN; a choice was made that a later reader would otherwise
1029
- re-litigate. Do NOT log: restating the outcome, design or plan (they are already
1030
- fields on the intent); confirming something already written down elsewhere; mechanical
1031
- facts recoverable from git, CI or the tracker (test counts, file lists, commit hashes);
1032
- progress narration ("started X", "working on Y").
1033
- KEEP → "Parallelised the build across four subagents; the Laravel slices were split by
1034
- file ownership to avoid collisions in one working tree." — records the rejected
1035
- alternative (one agent per repo) and why it lost.
1036
- DROP → "make verify green at 2415 passed after merging all four agents." — a mechanical
1037
- fact already in the commit message and the CI output.
1220
+ ${worklogKeepDropTest(' ')}
1038
1221
  - LOG IT THE MOMENT IT IS AGREED, not batched at the end: \`orbitmap log IN-x "<the choice
1039
1222
  and why, incl. what it rules out>" --type decision\`. An abandoned session must still
1040
1223
  leave its decisions recorded.
@@ -1066,7 +1249,9 @@ well-bounded units are easier to build, review, and reason about.
1066
1249
  more when nuanced); after each section ask whether it looks right, and get the user's
1067
1250
  approval before writing anything.
1068
1251
  6. Write it: \`orbitmap intent update IN-x --design "<doc>"\`. This REPLACES any framing
1069
- notes that were in the field — you have already absorbed them into the doc.
1252
+ notes that were in the field — you have already absorbed them into the doc. When the
1253
+ spec names the repos the build will touch, declare them on the intent in the same
1254
+ update — \`--areas <slug>,<slug>\` — so session-focus matching works from declared data.
1070
1255
  7. Advance the lifecycle, carrying this gate's entries — \`--log <type>:<content>\` is
1071
1256
  REPEATABLE and \`design → plan\` is decision-heavy (technical choices, rejected
1072
1257
  alternatives):
@@ -1166,7 +1351,9 @@ description: >
1166
1351
  export const SKILL_DOCS_BODY = `# OrbitMap documents
1167
1352
 
1168
1353
  Documents are workspace-level: exactly ONE copy per workspace, never per-area. No document
1169
- command takes an area, and \`orbitmap context\` already lists them.
1354
+ command takes an area, and their metadata (slug, when to use) already rides the context
1355
+ payload your session focus was matched from (see Session focus in the \`orbitmap\` skill —
1356
+ ensure, don't re-call).
1170
1357
 
1171
1358
  ## Goal
1172
1359
  Read and update OrbitMap documents efficiently: pull only the context you need (TOC →
@@ -1196,7 +1383,19 @@ conversation.
1196
1383
  - Update: \`orbitmap doc-update <slug> --file <file.md>\` (replaces content, bumps
1197
1384
  version).
1198
1385
  - To change an OrbitMap document, ALWAYS go through these commands — NEVER edit files
1199
- inside the OrbitMap workspace/cache directories directly.`;
1386
+ inside the OrbitMap workspace/cache directories directly.
1387
+
1388
+ ## Editing safely — documents have NO revert (known server defects: IS-8wwkb9)
1389
+ - Prefer section ops (\`doc-patch --replace-section/--insert-section\`); use line-based
1390
+ ops only when no section op can express the change — line coordinates are shifted
1391
+ server-side assuming ASCENDING order, and blank edges of op content get trimmed.
1392
+ - The section parser is not fence-aware: a line-start \`#\` INSIDE a code block is taken
1393
+ for a heading and becomes a section boundary. Keep code-block comments inline
1394
+ (\`cmd # comment\`), and check target sections for this hazard BEFORE replacing them.
1395
+ - Never read a document between a \`doc-update\` upload and its confirm — a cached read
1396
+ makes the confirm silently re-save the OLD content while still bumping the version.
1397
+ - After ANY write, re-read the changed section (or TOC for structure) and verify the
1398
+ result actually matches what you sent. A bumped version number is not proof.`;
1200
1399
  export const SKILLS = [
1201
1400
  {
1202
1401
  name: 'orbitmap',
@@ -1231,35 +1430,37 @@ export const SKILLS = [
1231
1430
  },
1232
1431
  ];
1233
1432
  // ── The thin always-on hook (CLAUDE.md / AGENTS.md) ────────────────────────────
1234
- // Claude variant — §8.2, verbatim (without the markers, which buildClaudeHook adds).
1433
+ // Claude variant — §8.2, verbatim (without the markers, which buildClaudeBlock adds).
1235
1434
  export const THIN_HOOK_CLAUDE = `## OrbitMap
1236
1435
 
1237
- This project tracks work in OrbitMap via the \`orbitmap\` CLI (cloud or local files alike).
1238
- You work in a WORKSPACE: run \`orbitmap context\` first one call gives the workspace, your
1239
- areas, the active mission, open intents, tasks and documents. Never ask which area — it
1240
- follows from the directory (map in \`.orbitmap/config.json\`); missions, intents and docs
1241
- need none. When the user mentions tasks, backlog, missions, intents, ideas, issues, vibes,
1242
- or design, load the matching skill: \`orbitmap\` (core), \`orbitmap-execute\` (tasks),
1243
- \`orbitmap-plan\` (missions/intents/ideas/issues), \`orbitmap-brainstorm\` (idea outcome),
1244
- \`orbitmap-design\` (intent solutions), \`orbitmap-docs\` (documents).
1245
- Golden rules: ONE task at a time per worker the execute skill orchestrates intents; NEVER
1246
- finish without a final \`orbitmap log\` entry and \`orbitmap status\` update — finished work
1247
- defaults to \`in_review\`, not \`done\`. NEVER edit workspace files directly always use \`orbitmap\`.`;
1436
+ Work is tracked in OrbitMap via the \`orbitmap\` CLI. You work in a WORKSPACE, which can span
1437
+ several repositories: each repo is an AREA, while missions, intents and documents belong to
1438
+ the workspace itself, not to any one repo.
1439
+ Load the OrbitMap skills whenever the user wants to build, add, change or fix something, in
1440
+ whatever words they use do not wait for OrbitMap vocabulary. Load them too when they talk
1441
+ about tracking work (backlog, tasks, missions, intents, ideas, issues, documents, planning).
1442
+ Nothing gets built before it is framed: a feature, component or behaviour change gets an intent
1443
+ — outcome (brainstorm) → design → plan → build (execute), one gate at a time, written to the
1444
+ intent as you go. Small self-contained work (a typo, an obvious one-file fix) is just a task.
1445
+ NEVER finish a task, intent or mission without a final \`orbitmap log\` entry and a status update;
1446
+ the final entry closes a record that already exists. Finished work defaults to \`in_review\`, not \`done\`.
1447
+ OrbitMap tool responses may carry an Instructions section — act on it before continuing.`;
1248
1448
  // Non-Claude variant: same rules, but points at the inlined sections below instead of
1249
1449
  // skills that these agents cannot load.
1250
1450
  export const THIN_HOOK_GENERIC = `## OrbitMap
1251
1451
 
1252
- This project tracks work in OrbitMap via the \`orbitmap\` CLI (cloud or local files alike).
1253
- You work in a WORKSPACE: run \`orbitmap context\` first one call gives the workspace, your
1254
- areas, the active mission, open intents, tasks and documents. Never ask which area — it
1255
- follows from the directory (map in \`.orbitmap/config.json\`); missions, intents and docs
1256
- need none. When the user mentions tasks, backlog, missions, intents, ideas, issues, vibes,
1257
- or design, follow the sections below: core (context & commands), working on tasks,
1258
- planning (missions/intents/ideas/issues), framing an idea into an outcome, designing an
1259
- intent's solution, and documents.
1260
- Golden rules: ONE task at a time per worker intent execution orchestrates its tasks; NEVER
1261
- finish a task session without a final \`orbitmap log\` entry and an \`orbitmap status\` update;
1262
- finished work defaults to \`in_review\`, not \`done\`. NEVER edit workspace files directly — always use \`orbitmap\`.`;
1452
+ Work is tracked in OrbitMap via the \`orbitmap\` CLI. You work in a WORKSPACE, which can span
1453
+ several repositories: each repo is an AREA, while missions, intents and documents belong to
1454
+ the workspace itself, not to any one repo.
1455
+ Follow the sections below whenever the user wants to build, add, change or fix something, in
1456
+ whatever words they use do not wait for OrbitMap vocabulary. Follow them too when they talk
1457
+ about tracking work (backlog, tasks, missions, intents, ideas, issues, documents, planning).
1458
+ Nothing gets built before it is framed: a feature, component or behaviour change gets an intent
1459
+ outcome (brainstorm) → design → plan → build (execute), one gate at a time, written to the
1460
+ intent as you go. Small self-contained work (a typo, an obvious one-file fix) is just a task.
1461
+ NEVER finish a task, intent or mission without a final \`orbitmap log\` entry and a status update;
1462
+ the final entry closes a record that already exists. Finished work defaults to \`in_review\`, not \`done\`.
1463
+ OrbitMap tool responses may carry an Instructions section — act on it before continuing.`;
1263
1464
  // ── Assembly helpers ───────────────────────────────────────────────────────────
1264
1465
  /** Build one SKILL.md file (frontmatter + body) for Claude. */
1265
1466
  export function buildSkillFile(skill) {
@@ -1282,7 +1483,7 @@ export const SKILL_SCOPE_CAVEAT_PROJECT = 'These skills are installed at PROJECT
1282
1483
  * `scope` is where the accompanying skill files were installed — see
1283
1484
  * {@link SKILL_SCOPE_CAVEAT_PROJECT}.
1284
1485
  */
1285
- export function buildClaudeHook(scope = 'user') {
1486
+ export function buildClaudeBlock(scope = 'user') {
1286
1487
  const body = scope === 'project' ? `${THIN_HOOK_CLAUDE}\n${SKILL_SCOPE_CAVEAT_PROJECT}` : THIN_HOOK_CLAUDE;
1287
1488
  return `${MARKER_START}\n${body}\n${MARKER_END}`;
1288
1489
  }