cclaw-cli 0.32.0 → 0.34.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.
package/README.md CHANGED
@@ -133,7 +133,7 @@ inside `/cc-ops` subcommands.
133
133
  | **`/cc <idea>`** | Classify the task, discover origin docs (`docs/prd/**`, ADRs, root `PRD.md`, …), sniff the stack, recommend a track, then start the first stage of that track. `/cc` without arguments resumes the current flow. |
134
134
  | **`/cc-next`** | The one progression primitive. Reads `flow-state.json`, checks gates + mandatory subagent delegations, and either resumes the current stage or advances to the next. `/cc-next` in a new session is how you **resume**. |
135
135
  | **`/cc-ideate`** | Repository improvement discovery. Scans for TODOs, flaky tests, oversized modules, docs drift, and recurring knowledge-store lessons; returns a ranked backlog before you commit to a specific feature. |
136
- | **`/cc-view`** | Read-only flow visibility. `/cc-view status` (default), `/cc-view tree`, `/cc-view diff` (baseline delta map). Never mutates state. |
136
+ | **`/cc-view`** | Read-only flow visibility. `/cc-view status` (default) shows stage progress, mandatory delegations with their fulfillment mode (isolated / generic-dispatch / role-switch), the ship closeout substate (retro → compound → archive), and the active harness parity row. `/cc-view tree` renders the same picture as a tree with a closeout sub-branch under ship and a per-harness playbook summary. `/cc-view diff` shows stage/gate/closeout/delegation deltas since the last run. Never mutates state (except diff's snapshot baseline). |
137
137
 
138
138
  > Power-user surface: `/cc-ops` is an operational router for manual
139
139
  > overrides (rewind a stale stage, manage parallel features, re-run a
@@ -277,9 +277,8 @@ The `tdd` stage is not prose guidance. It requires:
277
277
  - optional **REFACTOR** pass with coverage preservation
278
278
 
279
279
  `/cc-next` will not advance past `tdd` until the delegation log shows the
280
- subagent as `completed` or explicitly `waived` (for harnesses without
281
- native subagent dispatch, such as Codex — see
282
- [Harness support](#harness-support)).
280
+ subagent as `completed` (or, on Codex / OpenCode, role-switched with
281
+ `evidenceRefs` see [Harness support](#harness-support)).
283
282
 
284
283
  ---
285
284
 
@@ -320,21 +319,50 @@ to: `/cc-next` is the only command.
320
319
 
321
320
  ## Harness support
322
321
 
323
- cclaw is honest about which harnesses give you full automation and which
324
- need small manual bridges. See
325
- [`docs/harnesses.md`](./docs/harnesses.md) for the full matrix.
326
-
327
- | Harness | Subagent dispatch | Hook surface | Structured ask | Status |
328
- |---|---|---|---|---|
329
- | Claude Code | native | full | `AskUserQuestion` | full parity |
330
- | Cursor | partial | full | `AskQuestion` | parity gap: subagent dispatch |
331
- | OpenCode | partial | plugin | plain-text | parity gap: plugin hooks |
332
- | OpenAI Codex | none (waiver) | full | plain-text | parity gap: no subagent |
333
-
334
- Capability gaps are captured in `.cclaw/state/harness-gaps.json`. Where
335
- native dispatch is missing, cclaw emits a **structured waiver** rather
336
- than pretending the delegation happened. Closing these gaps is an
337
- ongoing kinetic effort see the harness tracking doc above.
322
+ cclaw is honest about what each harness can and cannot do, and it
323
+ closes every real gap with a documented fallback — not a silent waiver.
324
+
325
+ | Harness | Dispatch | Fallback | Hook surface | Structured ask | Playbook |
326
+ |---|---|---|---|---|---|
327
+ | Claude Code | full (named subagents) | `native` | full | `AskUserQuestion` | [`claude-playbook.md`](./src/content/harness-playbooks.ts) |
328
+ | Cursor | generic Task dispatcher | `generic-dispatch` | full | `AskQuestion` | `cursor-playbook.md` |
329
+ | OpenCode | plugin / in-session | `role-switch` | plugin | plain-text | `opencode-playbook.md` |
330
+ | OpenAI Codex | in-session only | `role-switch` (evidenceRefs required) | full | plain-text | `codex-playbook.md` |
331
+
332
+ What the fallbacks mean:
333
+
334
+ - `native` Claude runs mandatory delegations in isolated subagent
335
+ workers; cclaw records them with `fulfillmentMode: "isolated"`.
336
+ - `generic-dispatch`Cursor has a real Task tool with a fixed
337
+ vocabulary of `subagent_type`s (`explore`, `generalPurpose`, …).
338
+ cclaw maps each named agent (planner / reviewer / test-author /
339
+ security-reviewer / doc-updater) onto the generic dispatcher with a
340
+ structured role prompt. Per-agent mapping lives in the Cursor
341
+ playbook.
342
+ - `role-switch` — OpenCode and Codex lack an isolated worker primitive.
343
+ The agent announces the role in-session, performs the work, and
344
+ records a delegation row with `fulfillmentMode: "role-switch"` and at
345
+ least one `evidenceRef` pointing at the artifact section that
346
+ captures the output. Under role-switch, a `completed` row **without**
347
+ evidenceRefs is classified as `missingEvidence` by `cclaw doctor` and
348
+ blocks stage completion.
349
+ - `waiver` — reserved. Only fires auto-waivers if every installed
350
+ harness declares it. Currently unused — v0.33 removed the old
351
+ Codex-only auto-waiver path.
352
+
353
+ The full capability matrix lives in
354
+ [`docs/harnesses.md`](./docs/harnesses.md). Per-harness playbooks are
355
+ generated into `.cclaw/references/harnesses/` on every install and
356
+ upgrade; stage skills cite them by path.
357
+
358
+ Runtime state:
359
+
360
+ - `.cclaw/state/harness-gaps.json` (schema v2) — per-harness list of
361
+ missing capabilities, missing hook events, the declared fallback, the
362
+ playbook path, and a `remediation[]` list you can act on.
363
+ - `cclaw doctor` — asserts every installed harness has its playbook on
364
+ disk and surfaces the expected fulfillment mode inside the
365
+ `delegation:mandatory:current_stage` check.
338
366
 
339
367
  ---
340
368
 
@@ -7,12 +7,23 @@ function flowStatePath() {
7
7
  function snapshotPath() {
8
8
  return `${RUNTIME_ROOT}/state/flow-state.snapshot.json`;
9
9
  }
10
+ function delegationLogPath() {
11
+ return `${RUNTIME_ROOT}/state/delegation-log.json`;
12
+ }
13
+ function retroArtifactPath() {
14
+ return `${RUNTIME_ROOT}/artifacts/09-retro.md`;
15
+ }
10
16
  export function diffCommandContract() {
11
17
  return `# /cc-view diff
12
18
 
13
19
  ## Purpose
14
20
 
15
- Show a visual before/after diff map for flow-state progression.
21
+ Show a visual before/after diff map for flow-state progression. Covers the core
22
+ stage/gate transitions plus:
23
+
24
+ - ship **closeout substate** transitions (\`retro_review\` → \`compound_review\` → \`ready_to_archive\`),
25
+ - delegation **fulfillmentMode** transitions per mandatory agent,
26
+ - appearance or removal of the retro artifact \`09-retro.md\`.
16
27
 
17
28
  ## HARD-GATE
18
29
 
@@ -21,16 +32,27 @@ Show a visual before/after diff map for flow-state progression.
21
32
 
22
33
  ## Algorithm
23
34
 
24
- 1. Read current state from \`${flowStatePath()}\`.
25
- 2. Read baseline from \`${snapshotPath()}\` (if missing -> create baseline from current state and stop).
26
- 3. Compute deltas:
27
- - stage transition (\`from -> to\`)
28
- - completed stage additions/removals
29
- - skipped stage additions/removals
30
- - stale stage additions/removals
31
- - current-stage gate \`passed\` and \`blocked\` changes
32
- 4. Render a compact diff map (added \`+\`, removed \`-\`, changed \`->\`).
33
- 5. Persist current state back to \`${snapshotPath()}\` as new baseline with \`capturedAt\`.
35
+ 1. Read current state from \`${flowStatePath()}\` (including \`closeout\`).
36
+ 2. Read current delegation log from \`${delegationLogPath()}\` (if missing treat as empty).
37
+ 3. Read baseline from \`${snapshotPath()}\` (if missing -> create baseline from
38
+ current state **plus** a copy of the current delegation log; report
39
+ \`flow diff baseline created\` and stop).
40
+ 4. Compute deltas:
41
+ - stage transition (\`from -> to\`),
42
+ - completed stage additions/removals,
43
+ - skipped stage additions/removals,
44
+ - stale stage additions/removals,
45
+ - current-stage gate \`passed\` and \`blocked\` changes,
46
+ - \`closeout.shipSubstate\` transition (\`from -> to\`),
47
+ - \`closeout.retroDraftedAt\` / \`retroAcceptedAt\` / \`retroSkipped\` flips,
48
+ - \`closeout.compoundPromoted\` / \`compoundSkipped\` flips,
49
+ - per-agent \`fulfillmentMode\` transitions from the baseline delegation log,
50
+ - appearance (\`+\`) or disappearance (\`-\`) of \`${retroArtifactPath()}\`.
51
+ 5. Render a compact diff map (added \`+\`, removed \`-\`, changed \`->\`).
52
+ 6. Persist current state back to \`${snapshotPath()}\` as new baseline with
53
+ \`capturedAt\` and an embedded \`delegations\` projection
54
+ (\`{ agent, status, fulfillmentMode }[]\`) so fulfillmentMode transitions are
55
+ computable on the next run.
34
56
 
35
57
  ## Diff Map Format
36
58
 
@@ -41,8 +63,18 @@ cclaw flow diff
41
63
  stale: -design
42
64
  gates(spec): +spec_contract_complete -spec_open_questions_closed
43
65
  blocked(spec): +spec_trace_matrix_missing
66
+ closeout: idle -> retro_review
67
+ retro: +drafted (09-retro.md appeared)
68
+ delegations:
69
+ - reviewer: scheduled -> completed (mode=generic-dispatch)
70
+ - test-author: mode=? -> role-switch (evidenceRefs=2)
44
71
  \`\`\`
45
72
 
73
+ - The \`closeout:\` line is omitted when \`shipSubstate\` is unchanged.
74
+ - The \`delegations:\` block is omitted when no agent changed status or mode.
75
+ - The \`retro:\` line is emitted only on artifact appearance/removal or on a
76
+ \`retroAcceptedAt\` / \`retroSkipped\` flip.
77
+
46
78
  ## Primary skill
47
79
 
48
80
  **${RUNTIME_ROOT}/skills/${DIFF_SKILL_FOLDER}/SKILL.md**
@@ -51,7 +83,7 @@ cclaw flow diff
51
83
  export function diffCommandSkillMarkdown() {
52
84
  return `---
53
85
  name: ${DIFF_SKILL_NAME}
54
- description: "Compare current flow-state against saved snapshot and render gate/stage deltas."
86
+ description: "Compare current flow-state against saved snapshot and render gate/stage/closeout/delegation deltas."
55
87
  ---
56
88
 
57
89
  # /cc-view diff
@@ -63,21 +95,35 @@ Never lose baseline visibility: render deltas before writing a new snapshot.
63
95
  ## Protocol
64
96
 
65
97
  1. Read \`${flowStatePath()}\`.
66
- 2. Read \`${snapshotPath()}\`.
67
- 3. If snapshot missing:
68
- - write baseline snapshot from current state,
98
+ 2. Read \`${delegationLogPath()}\` (missing → treat as empty list).
99
+ 3. Read \`${snapshotPath()}\`.
100
+ 4. If snapshot missing:
101
+ - write baseline snapshot from current state **plus** a
102
+ \`delegations\` projection (\`{ agent, status, fulfillmentMode }[]\`),
69
103
  - print \`flow diff baseline created\`,
70
104
  - stop.
71
- 4. Build deltas for stage, completed/skipped/stale sets, and current-stage gate arrays.
72
- 5. Print a compact diff map with explicit \`+\`, \`-\`, and \`->\` markers.
73
- 6. Write updated snapshot with:
74
- - \`capturedAt\` (ISO)
75
- - \`state\` (full current flow-state object)
105
+ 5. Build deltas for:
106
+ - stage, completed/skipped/stale sets,
107
+ - current-stage gate arrays (\`passed\`, \`blocked\`),
108
+ - \`closeout.shipSubstate\` transitions (\`from -> to\`),
109
+ - \`closeout.retroDraftedAt\` / \`retroAcceptedAt\` / \`retroSkipped\` flips,
110
+ - \`closeout.compoundPromoted\` / \`compoundSkipped\` / \`compoundCompletedAt\` flips,
111
+ - per-agent \`fulfillmentMode\` transitions by matching baseline delegations
112
+ against current delegations on \`agent\` + latest entry,
113
+ - appearance or removal of \`${retroArtifactPath()}\` on disk.
114
+ 6. Print a compact diff map with explicit \`+\`, \`-\`, and \`->\` markers.
115
+ 7. Write updated snapshot with:
116
+ - \`capturedAt\` (ISO),
117
+ - \`state\` (full current flow-state object),
118
+ - \`delegations\` projection from the current log.
76
119
 
77
120
  ## Validation
78
121
 
79
122
  - Diff output must be deterministic for identical states ("no changes").
80
123
  - Snapshot file stays valid JSON after every run.
81
124
  - Do not suppress removed values; removals are first-class evidence.
125
+ - Closeout diff lines must use the same \`shipSubstate\` vocabulary as the
126
+ state machine (\`idle\` / \`retro_review\` / \`compound_review\` /
127
+ \`ready_to_archive\` / \`archived\`).
82
128
  `;
83
129
  }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Per-harness parity playbooks.
3
+ *
4
+ * cclaw's subagent contracts (planner / reviewer / security-reviewer /
5
+ * test-author / doc-updater) assume Claude-style isolated workers. On
6
+ * harnesses without that primitive, the agent has to fulfil the role via a
7
+ * documented fallback (generic Task dispatch, role-switch in-session, …).
8
+ *
9
+ * Each playbook is:
10
+ * 1. short (≤ ~150 lines markdown),
11
+ * 2. executable — reproducible by an agent without reading the whole repo,
12
+ * 3. evidence-first — always records a delegation-log entry with
13
+ * `fulfillmentMode` and `evidenceRefs` so `cclaw doctor` can tell the
14
+ * role was actually performed.
15
+ *
16
+ * Playbooks are materialised at
17
+ * `.cclaw/references/harnesses/<harness>-playbook.md` by install/sync/upgrade.
18
+ */
19
+ import type { HarnessId } from "../types.js";
20
+ export declare const HARNESS_PLAYBOOKS_DIR = "references/harnesses";
21
+ export declare function harnessPlaybookRelativePath(harness: HarnessId): string;
22
+ export declare function harnessPlaybookFileName(harness: HarnessId): string;
23
+ export declare function harnessPlaybookMarkdown(harness: HarnessId): string;
24
+ export declare function harnessPlaybooksIndexMarkdown(): string;
@@ -0,0 +1,292 @@
1
+ /**
2
+ * Per-harness parity playbooks.
3
+ *
4
+ * cclaw's subagent contracts (planner / reviewer / security-reviewer /
5
+ * test-author / doc-updater) assume Claude-style isolated workers. On
6
+ * harnesses without that primitive, the agent has to fulfil the role via a
7
+ * documented fallback (generic Task dispatch, role-switch in-session, …).
8
+ *
9
+ * Each playbook is:
10
+ * 1. short (≤ ~150 lines markdown),
11
+ * 2. executable — reproducible by an agent without reading the whole repo,
12
+ * 3. evidence-first — always records a delegation-log entry with
13
+ * `fulfillmentMode` and `evidenceRefs` so `cclaw doctor` can tell the
14
+ * role was actually performed.
15
+ *
16
+ * Playbooks are materialised at
17
+ * `.cclaw/references/harnesses/<harness>-playbook.md` by install/sync/upgrade.
18
+ */
19
+ import { HARNESS_ADAPTERS } from "../harness-adapters.js";
20
+ export const HARNESS_PLAYBOOKS_DIR = "references/harnesses";
21
+ export function harnessPlaybookRelativePath(harness) {
22
+ return `${HARNESS_PLAYBOOKS_DIR}/${harness}-playbook.md`;
23
+ }
24
+ export function harnessPlaybookFileName(harness) {
25
+ return `${harness}-playbook.md`;
26
+ }
27
+ const CLAUDE_PLAYBOOK = `---
28
+ harness: claude
29
+ fallback: native
30
+ description: "Claude Code has real isolated subagent workers with user-defined named types. No fallback required — this playbook is reference-only."
31
+ ---
32
+
33
+ # Claude Code — Parity Playbook
34
+
35
+ **Status: native.** Claude Code supports isolated subagent workers via the
36
+ \`Task\` tool with user-defined \`subagent_type\` (\`planner\`, \`reviewer\`,
37
+ \`security-reviewer\`, \`test-author\`, \`doc-updater\`). Each dispatch runs in
38
+ its own context and produces a return message visible only to the parent
39
+ agent.
40
+
41
+ This playbook exists so the harness matrix has one reference shape; Claude
42
+ itself has no parity gap to close.
43
+
44
+ ## Dispatch pattern
45
+
46
+ 1. Pick the \`subagent_type\` matching the cclaw agent (e.g. \`reviewer\`).
47
+ 2. Provide a specific, self-contained \`prompt\` — the subagent cannot see
48
+ prior assistant turns.
49
+ 3. Record a delegation entry before dispatch:
50
+
51
+ \`\`\`json
52
+ {
53
+ "stage": "review",
54
+ "agent": "reviewer",
55
+ "mode": "mandatory",
56
+ "status": "scheduled",
57
+ "fulfillmentMode": "isolated",
58
+ "spanId": "dspan-..."
59
+ }
60
+ \`\`\`
61
+
62
+ 4. After the subagent returns, update the entry to \`status: "completed"\`
63
+ and attach \`evidenceRefs\` pointing at the artifact section that
64
+ captures the subagent's output.
65
+
66
+ ## Verification
67
+
68
+ \`cclaw doctor\` will pass the \`delegation:mandatory:current_stage\` check
69
+ when each mandatory agent has a \`completed\` row for the active run.
70
+ `;
71
+ const CURSOR_PLAYBOOK = `---
72
+ harness: cursor
73
+ fallback: generic-dispatch
74
+ description: "Cursor has a generic Task dispatcher with subagent_type (generalPurpose, explore, shell, …) but no user-defined named subagents. cclaw maps planner/reviewer/test-author/… onto generic dispatch with a structured role prompt."
75
+ ---
76
+
77
+ # Cursor — Parity Playbook
78
+
79
+ **Fallback: generic-dispatch.** Cursor's \`Task\` tool supports
80
+ \`subagent_type\` from a fixed vocabulary (\`generalPurpose\`, \`explore\`,
81
+ \`shell\`, \`browser-use\`, …). Real isolation, but no user-defined agent
82
+ names. cclaw closes the gap by mapping each named cclaw agent onto the
83
+ generic dispatcher with a strict role prompt.
84
+
85
+ ## Named-agent → Cursor subagent_type map
86
+
87
+ | cclaw agent | Cursor \`subagent_type\` | Readonly? | Rationale |
88
+ |----------------------|-------------------------|-----------|-----------|
89
+ | \`planner\` | \`explore\` | yes | Pure research, no writes. |
90
+ | \`reviewer\` | \`explore\` | yes | Reads diff + context, emits findings. |
91
+ | \`security-reviewer\`| \`explore\` | yes | Reads code, produces report; no fixes. |
92
+ | \`test-author\` | \`generalPurpose\` | no | Writes tests, runs them, iterates. |
93
+ | \`doc-updater\` | \`generalPurpose\` | no | Edits docs, re-runs build. |
94
+
95
+ ## Dispatch pattern
96
+
97
+ 1. Pick the mapped \`subagent_type\` from the table above.
98
+ 2. Build the \`prompt\` from the cclaw agent contract in
99
+ \`.cclaw/agents/<agent>.md\`, prefaced with a single line naming the
100
+ cclaw role (\`You are the cclaw <agent>. Follow the contract below.\`).
101
+ 3. Set \`readonly: true\` when the table says yes — Cursor enforces it.
102
+ 4. Before dispatch, append a delegation row:
103
+
104
+ \`\`\`json
105
+ {
106
+ "stage": "tdd",
107
+ "agent": "test-author",
108
+ "mode": "mandatory",
109
+ "status": "scheduled",
110
+ "fulfillmentMode": "generic-dispatch",
111
+ "spanId": "dspan-..."
112
+ }
113
+ \`\`\`
114
+
115
+ 5. After dispatch returns, transition the row to \`completed\` with
116
+ \`evidenceRefs\` citing the artifact anchor where the result landed.
117
+
118
+ ## Why not upgrade Cursor to a full tier-1?
119
+
120
+ Cursor has dispatch + hooks + \`AskQuestion\`. The missing piece is
121
+ **user-defined named subagents**. Semantically this is the difference
122
+ between Claude's \`test-author\` (a distinct runtime worker registered by
123
+ cclaw) and Cursor's \`generalPurpose\` worker that cclaw *asks* to act as a
124
+ test-author. Good enough for parity; different enough to keep the labels
125
+ honest.
126
+
127
+ ## Verification
128
+
129
+ \`cclaw doctor\` passes when the delegation row exists with
130
+ \`fulfillmentMode: "generic-dispatch"\` (or \`completed\` rows for the
131
+ mandatory agents in general). No evidenceRef requirement applies here —
132
+ Cursor dispatch is real isolation.
133
+ `;
134
+ const OPENCODE_PLAYBOOK = `---
135
+ harness: opencode
136
+ fallback: role-switch
137
+ description: "OpenCode has plugin-based dispatch hooks but no isolated subagent worker primitive. cclaw uses an in-session role-switch with a delegation-log entry + evidenceRefs."
138
+ ---
139
+
140
+ # OpenCode — Parity Playbook
141
+
142
+ **Fallback: role-switch.** OpenCode exposes tool/session event hooks via a
143
+ plugin but does not provide an isolated subagent worker. cclaw closes the
144
+ delegation gate by role-switching inside the same session: the agent
145
+ announces the role, performs the work against the contract, and records
146
+ evidence.
147
+
148
+ ## Role-switch protocol
149
+
150
+ 1. Announce the role explicitly in a single message:
151
+
152
+ > Acting as cclaw **<agent>** per \`.cclaw/agents/<agent>.md\`. No other
153
+ > role may be assumed until the delegation row is closed.
154
+
155
+ 2. Execute the role's contract. Do NOT interleave other roles' work.
156
+ 3. Write the result into the stage artifact (e.g. TDD work lands in
157
+ \`.cclaw/artifacts/06-tdd.md\`).
158
+ 4. Append a delegation row:
159
+
160
+ \`\`\`json
161
+ {
162
+ "stage": "tdd",
163
+ "agent": "test-author",
164
+ "mode": "mandatory",
165
+ "status": "completed",
166
+ "fulfillmentMode": "role-switch",
167
+ "evidenceRefs": [
168
+ ".cclaw/artifacts/06-tdd.md#red-run",
169
+ ".cclaw/artifacts/06-tdd.md#green-run"
170
+ ],
171
+ "spanId": "dspan-..."
172
+ }
173
+ \`\`\`
174
+
175
+ 5. \`evidenceRefs\` **must** point at concrete artifact anchors — not
176
+ placeholder text. \`cclaw doctor\` will report \`missingEvidence\` if
177
+ the array is empty under a role-switch fallback.
178
+
179
+ ## Exception: OpenCode plugin dispatch
180
+
181
+ If the project configures a plugin-based dispatch path (e.g. a tool that
182
+ spawns a worker process), set \`fulfillmentMode: "generic-dispatch"\`
183
+ instead of \`role-switch\` and omit the role-announce step. evidenceRefs
184
+ remain optional but recommended.
185
+
186
+ ## Verification
187
+
188
+ \`cclaw doctor\` passes when every mandatory agent for the active stage
189
+ has either a \`completed\` row with evidenceRefs (role-switch) or a
190
+ \`completed\` row under plugin dispatch.
191
+ `;
192
+ const CODEX_PLAYBOOK = `---
193
+ harness: codex
194
+ fallback: role-switch
195
+ description: "OpenAI Codex has no subagent dispatch primitive. cclaw uses role-switch with evidenceRefs; silent auto-waiver is explicitly disabled."
196
+ ---
197
+
198
+ # OpenAI Codex — Parity Playbook
199
+
200
+ **Fallback: role-switch.** Codex has no subagent dispatch — neither named
201
+ nor generic. cclaw used to silently auto-waive mandatory delegations on
202
+ Codex; v0.33 disables that shortcut. The agent must role-switch in-session
203
+ and record evidence, or the delegation gate blocks stage completion.
204
+
205
+ ## Role-switch protocol
206
+
207
+ Identical to OpenCode. Key requirements:
208
+
209
+ 1. **Explicit announce.** Before performing the role, emit a single
210
+ message naming the role and citing \`.cclaw/agents/<agent>.md\`.
211
+ 2. **No role interleaving.** Do not mix, for example, reviewer and
212
+ test-author work into the same turn — close one delegation before
213
+ opening another.
214
+ 3. **EvidenceRefs are mandatory.** Under Codex's role-switch fallback a
215
+ \`completed\` row without \`evidenceRefs\` is treated as
216
+ \`missingEvidence\` by \`cclaw doctor\` and blocks the gate.
217
+
218
+ ## Stage-specific role maps
219
+
220
+ | Stage | Mandatory roles | Artifact to cite in evidenceRefs |
221
+ |------------|----------------------------------|--------------------------------------|
222
+ | scope | \`planner\` | \`.cclaw/artifacts/02-scope.md\` |
223
+ | design | \`planner\` | \`.cclaw/artifacts/03-design.md\` |
224
+ | plan | \`planner\` | \`.cclaw/artifacts/05-plan.md\` |
225
+ | tdd | \`test-author\` | \`.cclaw/artifacts/06-tdd.md\` |
226
+ | review | \`reviewer\`, \`security-reviewer\` | \`.cclaw/artifacts/07-review.md\` |
227
+ | ship | \`doc-updater\` | \`.cclaw/artifacts/08-ship.md\` |
228
+
229
+ ## Why no auto-waiver anymore?
230
+
231
+ Silent auto-waiver on Codex let entire stages complete without any
232
+ reviewer or test-author work. That defeats cclaw's hard gates. v0.33
233
+ replaces it with an explicit role-switch obligation: the agent still gets
234
+ a path forward, but the path is visible in the delegation log.
235
+
236
+ If a team genuinely wants to skip a delegation on Codex, they must
237
+ manually append a \`status: "waived"\` row with a one-line
238
+ \`waiverReason\` — the same audit trail any Claude/Cursor install would
239
+ need.
240
+
241
+ ## Verification
242
+
243
+ \`cclaw doctor\` passes when every mandatory agent for the active stage
244
+ has a \`completed\` row with \`fulfillmentMode: "role-switch"\` and at
245
+ least one \`evidenceRef\`.
246
+ `;
247
+ const PLAYBOOK_BY_HARNESS = {
248
+ claude: CLAUDE_PLAYBOOK,
249
+ cursor: CURSOR_PLAYBOOK,
250
+ opencode: OPENCODE_PLAYBOOK,
251
+ codex: CODEX_PLAYBOOK
252
+ };
253
+ export function harnessPlaybookMarkdown(harness) {
254
+ const body = PLAYBOOK_BY_HARNESS[harness];
255
+ if (!body) {
256
+ throw new Error(`No playbook defined for harness "${harness}".`);
257
+ }
258
+ return body;
259
+ }
260
+ export function harnessPlaybooksIndexMarkdown() {
261
+ const rows = Object.keys(HARNESS_ADAPTERS)
262
+ .map((h) => {
263
+ const fallback = HARNESS_ADAPTERS[h].capabilities.subagentFallback;
264
+ return `| \`${h}\` | ${fallback} | [\`${harnessPlaybookFileName(h)}\`](./${harnessPlaybookFileName(h)}) |`;
265
+ })
266
+ .join("\n");
267
+ return `# Harness parity playbooks
268
+
269
+ Each playbook describes the concrete pattern cclaw expects when the
270
+ harness does not natively satisfy a mandatory delegation contract.
271
+
272
+ | Harness | Fallback | Playbook |
273
+ |---|---|---|
274
+ ${rows}
275
+
276
+ ## How cclaw uses these files
277
+
278
+ - \`cclaw doctor\` verifies that every installed harness has its playbook
279
+ present under \`.cclaw/references/harnesses/\`.
280
+ - Stage skills (TDD, review, ship) cite the active harness's playbook
281
+ instead of inlining the fallback pattern.
282
+ - The \`delegation:mandatory:current_stage\` check expects
283
+ \`fulfillmentMode\` to match the harness's declared \`subagentFallback\`
284
+ (\`isolated\`, \`generic-dispatch\`, or \`role-switch\`).
285
+
286
+ ## When to edit
287
+
288
+ Playbooks are generated by \`cclaw upgrade\`. Local edits are overwritten.
289
+ To customise the parity pattern for a specific repository, override the
290
+ skill that cites the playbook, not the playbook itself.
291
+ `;
292
+ }
@@ -1,5 +1,6 @@
1
1
  import { HARNESS_ADAPTERS, harnessTier } from "../harness-adapters.js";
2
2
  import { HOOK_EVENTS_BY_HARNESS, HOOK_SEMANTIC_EVENTS } from "./hook-events.js";
3
+ import { HARNESS_PLAYBOOKS_DIR, harnessPlaybookFileName } from "./harness-playbooks.js";
3
4
  function harnessTitle(harness) {
4
5
  switch (harness) {
5
6
  case "claude":
@@ -25,7 +26,9 @@ export function harnessIntegrationDocMarkdown() {
25
26
  .map((harness) => {
26
27
  const adapter = HARNESS_ADAPTERS[harness];
27
28
  const tier = harnessTier(harness);
28
- return `| ${harnessTitle(harness)} | \`${harness}\` | \`${tier}\` (${tierDescription(tier)}) | ${adapter.capabilities.nativeSubagentDispatch} | ${adapter.capabilities.hookSurface} | ${adapter.capabilities.structuredAsk} |`;
29
+ const caps = adapter.capabilities;
30
+ const playbook = `\`${HARNESS_PLAYBOOKS_DIR}/${harnessPlaybookFileName(harness)}\``;
31
+ return `| ${harnessTitle(harness)} | \`${harness}\` | \`${tier}\` (${tierDescription(tier)}) | ${caps.nativeSubagentDispatch} | ${caps.subagentFallback} | ${caps.hookSurface} | ${caps.structuredAsk} | ${playbook} |`;
29
32
  })
30
33
  .join("\n");
31
34
  const hookRows = HOOK_SEMANTIC_EVENTS.map((eventName) => {
@@ -43,10 +46,17 @@ Generated from \`src/harness-adapters.ts\` capabilities and hook event mappings.
43
46
 
44
47
  ## Capability tiers
45
48
 
46
- | Harness | ID | Tier | Native subagent dispatch | Hook surface | Structured ask |
47
- |---|---|---|---|---|---|
49
+ | Harness | ID | Tier | Native dispatch | Fallback | Hook surface | Structured ask | Playbook |
50
+ |---|---|---|---|---|---|---|---|
48
51
  ${capabilityRows}
49
52
 
53
+ Fallback legend:
54
+
55
+ - \`native\` — first-class named subagent dispatch (Claude).
56
+ - \`generic-dispatch\` — generic Task dispatcher mapped to cclaw roles (Cursor).
57
+ - \`role-switch\` — in-session role announce + delegation-log entry with evidenceRefs (OpenCode, Codex).
58
+ - \`waiver\` — no parity path; reserved for harnesses that cannot role-switch (none shipped).
59
+
50
60
  ## Semantic hook event coverage
51
61
 
52
62
  | Event | Claude | Cursor | OpenCode | Codex |