@caddis/cli 0.4.52 → 0.4.53

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 (100) hide show
  1. package/bundles/antigravity-plugin/CADDIS-GLOSSARY.md +1 -0
  2. package/bundles/antigravity-plugin/plugin.json +1 -1
  3. package/bundles/antigravity-plugin/repo_freshness.py +132 -5
  4. package/bundles/antigravity-plugin/scripts/caddis_checkout_guard.py +223 -0
  5. package/bundles/antigravity-plugin/scripts/caddis_docs_pr.py +284 -0
  6. package/bundles/antigravity-plugin/scripts/caddis_exit.py +2 -0
  7. package/bundles/antigravity-plugin/scripts/caddis_frontmatter.py +1 -0
  8. package/bundles/antigravity-plugin/scripts/caddis_gate.py +226 -195
  9. package/bundles/antigravity-plugin/scripts/caddis_glossary.py +3 -3
  10. package/bundles/antigravity-plugin/scripts/caddis_governor.py +48 -4
  11. package/bundles/antigravity-plugin/scripts/caddis_inventory.py +38 -0
  12. package/bundles/antigravity-plugin/scripts/caddis_lanes.py +294 -127
  13. package/bundles/antigravity-plugin/scripts/caddis_lineage_publish.py +458 -0
  14. package/bundles/antigravity-plugin/scripts/caddis_merge_chain.py +237 -0
  15. package/bundles/antigravity-plugin/scripts/caddis_notify.py +121 -0
  16. package/bundles/antigravity-plugin/scripts/caddis_prod_check.py +380 -0
  17. package/bundles/antigravity-plugin/scripts/caddis_redact.py +99 -0
  18. package/bundles/antigravity-plugin/scripts/caddis_relay_git.py +2 -2
  19. package/bundles/antigravity-plugin/scripts/caddis_review.py +1309 -0
  20. package/bundles/antigravity-plugin/scripts/caddis_roadmap.py +2056 -0
  21. package/bundles/antigravity-plugin/scripts/caddis_roadmap_run.py +2572 -0
  22. package/bundles/antigravity-plugin/scripts/caddis_routing.py +3 -2
  23. package/bundles/antigravity-plugin/scripts/caddis_rows.py +476 -0
  24. package/bundles/antigravity-plugin/scripts/caddis_spawn.py +8 -9
  25. package/bundles/antigravity-plugin/scripts/caddis_spend.py +415 -0
  26. package/bundles/antigravity-plugin/scripts/caddis_tidy.py +357 -20
  27. package/bundles/antigravity-plugin/scripts/caddis_todo.py +55 -0
  28. package/bundles/antigravity-plugin/scripts/caddis_workstreams.py +178 -19
  29. package/bundles/antigravity-plugin/scripts/caddis_worktree_close.py +349 -0
  30. package/bundles/antigravity-plugin/scripts/check_doc_coverage.py +0 -56
  31. package/bundles/antigravity-plugin/scripts/claudster_doctor.py +1 -1
  32. package/bundles/antigravity-plugin/scripts/enforcement_inventory.py +0 -1
  33. package/bundles/antigravity-plugin/scripts/oss_review.py +2 -2
  34. package/bundles/antigravity-plugin/scripts/roadmap-recheck.ps1 +89 -0
  35. package/bundles/antigravity-plugin/scripts/roadmap-run.ps1 +88 -0
  36. package/bundles/antigravity-plugin/scripts/setup_project_ai.py +43 -1
  37. package/bundles/antigravity-plugin/session_end_agy.py +3 -3
  38. package/bundles/antigravity-plugin/skills/_registry.md +2 -6
  39. package/bundles/antigravity-plugin/skills/best-practices/agents/best-practices-referencer.md +1 -1
  40. package/bundles/antigravity-plugin/skills/best-practices/agents/codebase-context-builder.md +1 -1
  41. package/bundles/antigravity-plugin/skills/best-practices/agents/task-intent-analyzer.md +1 -1
  42. package/bundles/antigravity-plugin/skills/catchup/SKILL.md +7 -0
  43. package/bundles/antigravity-plugin/skills/cloud-phases/SKILL.md +1 -1
  44. package/bundles/antigravity-plugin/skills/cross-review/SKILL.md +5 -2
  45. package/bundles/antigravity-plugin/skills/feature-plan/SKILL.md +29 -83
  46. package/bundles/antigravity-plugin/skills/handoff/SKILL.md +77 -48
  47. package/bundles/antigravity-plugin/skills/implement/SKILL.md +87 -147
  48. package/bundles/antigravity-plugin/skills/migrate-dir/SKILL.md +1 -1
  49. package/bundles/antigravity-plugin/skills/mmr/SKILL.md +5 -2
  50. package/bundles/antigravity-plugin/skills/office-documents-official/SKILL.md +24 -0
  51. package/bundles/antigravity-plugin/skills/park/SKILL.md +0 -1
  52. package/bundles/antigravity-plugin/skills/pr-merge/SKILL.md +8 -14
  53. package/bundles/antigravity-plugin/skills/prd/SKILL.md +2 -10
  54. package/bundles/antigravity-plugin/skills/roadmap/SKILL.md +259 -0
  55. package/bundles/antigravity-plugin/skills/roadmap/assets/plan-resume-prompt.md +77 -0
  56. package/bundles/antigravity-plugin/skills/roadmap/assets/render-check.template.mjs +68 -0
  57. package/bundles/antigravity-plugin/skills/roadmap/assets/review-protocol.md +78 -0
  58. package/bundles/antigravity-plugin/skills/roadmap/assets/roadmap.template.md +32 -0
  59. package/bundles/antigravity-plugin/skills/roadmap/assets/value-check.template.py +161 -0
  60. package/bundles/antigravity-plugin/skills/ship/SKILL.md +14 -14
  61. package/bundles/antigravity-plugin/skills/ship-merge/SKILL.md +6 -0
  62. package/bundles/antigravity-plugin/skills/ship-pr/SKILL.md +33 -14
  63. package/bundles/antigravity-plugin/skills/spawn-session/SKILL.md +4 -8
  64. package/bundles/antigravity-plugin/warm_start_agy.py +1 -3
  65. package/bundles/antigravity-plugin-extras/plugin.json +1 -1
  66. package/bundles/antigravity-plugin-extras/skills/_registry.md +1 -2
  67. package/bundles/antigravity-plugin-extras/skills/agent-orchestration/SKILL.md +5 -5
  68. package/bundles/antigravity-plugin-extras/skills/cross-review/SKILL.md +5 -2
  69. package/bundles/antigravity-plugin-extras/skills/runner-move/SKILL.md +214 -0
  70. package/bundles/codex/.codex/skills/docs/office-documents-official/SKILL.md +24 -0
  71. package/bundles/codex/.codex/skills/workflow/best-practices/agents/best-practices-referencer.md +1 -1
  72. package/bundles/codex/.codex/skills/workflow/best-practices/agents/codebase-context-builder.md +1 -1
  73. package/bundles/codex/.codex/skills/workflow/best-practices/agents/task-intent-analyzer.md +1 -1
  74. package/bundles/codex/.codex/skills/workflow/roadmap/SKILL.md +259 -0
  75. package/bundles/codex/.codex/skills/workflow/roadmap/assets/plan-resume-prompt.md +77 -0
  76. package/bundles/codex/.codex/skills/workflow/roadmap/assets/render-check.template.mjs +68 -0
  77. package/bundles/codex/.codex/skills/workflow/roadmap/assets/review-protocol.md +78 -0
  78. package/bundles/codex/.codex/skills/workflow/roadmap/assets/roadmap.template.md +32 -0
  79. package/bundles/codex/.codex/skills/workflow/roadmap/assets/value-check.template.py +161 -0
  80. package/bundles/codex/AGENTS.md +5 -4
  81. package/bundles/manifest.json +3 -3
  82. package/package.json +1 -1
  83. package/bundles/antigravity-plugin/skills/advisory-hub/SKILL.md +0 -233
  84. package/bundles/antigravity-plugin/skills/advisory-hub/reference/context-template.md +0 -214
  85. package/bundles/antigravity-plugin/skills/advisory-hub/reference/hub-handbook.md +0 -233
  86. package/bundles/antigravity-plugin/skills/advisory-hub/reference/report-contract.md +0 -94
  87. package/bundles/antigravity-plugin/skills/advisory-hub/reference/succession.md +0 -118
  88. package/bundles/antigravity-plugin/skills/resume/SKILL.md +0 -6
  89. package/bundles/antigravity-plugin/skills/review/SKILL.md +0 -6
  90. package/bundles/antigravity-plugin/skills/spawn-hub/SKILL.md +0 -341
  91. package/bundles/antigravity-plugin/skills/statusline/SKILL.md +0 -6
  92. package/bundles/antigravity-plugin/skills/validate-phase/SKILL.md +0 -143
  93. package/bundles/antigravity-plugin-extras/skills/data-lineage/SKILL.md +0 -158
  94. package/bundles/antigravity-plugin-extras/skills/data-lineage/scripts/convert_doc_to_confluence.py +0 -1430
  95. package/bundles/antigravity-plugin-extras/skills/golden-plan/SKILL.md +0 -586
  96. package/bundles/codex/.codex/skills/workflow/advisory-hub/SKILL.md +0 -233
  97. package/bundles/codex/.codex/skills/workflow/advisory-hub/reference/context-template.md +0 -214
  98. package/bundles/codex/.codex/skills/workflow/advisory-hub/reference/hub-handbook.md +0 -233
  99. package/bundles/codex/.codex/skills/workflow/advisory-hub/reference/report-contract.md +0 -94
  100. package/bundles/codex/.codex/skills/workflow/advisory-hub/reference/succession.md +0 -118
@@ -8,6 +8,42 @@ description: End-of-session handoff — capture exact state so the next session
8
8
  You are ending a work session. Produce/refresh this workstream's resume doc (`.caddis/relay/<name>.md`) so the next session
9
9
  (you, a future you, or another agent on any tool) can resume immediately. This is the anti-context-rot checkpoint.
10
10
 
11
+ ## Step 0 — is this a shared checkout?
12
+ Another session may have uncommitted edits in this checkout. A handoff that commits here can carry
13
+ them into its commit, so check first, before Step 1.
14
+
15
+ 1. Write this session's own files to a temp file: copy the list under `## Files changed this session`
16
+ in `.caddis/session-state/<session-id>.md` (the `` - `path` `` lines can be copied as they are).
17
+ No state file or no list means an empty file.
18
+ 2. Run:
19
+ ```
20
+ python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_checkout_guard.py" shared --root . --own-files <temp-file>
21
+ ```
22
+ It prints `SHARED: yes <reason>` or `SHARED: no` and exits 0. It says yes when the root `AGENTS.md`
23
+ has a line `Shared checkout: yes`, or when `git status` lists a path this session did not change.
24
+ 3. **On `SHARED: no`,** do the steps below as written.
25
+ 4. **On `SHARED: yes`,** write NO tracked file in this checkout. Run:
26
+ ```
27
+ python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_docs_pr.py" start --repo .
28
+ ```
29
+ It makes a new worktree from `origin/<default>` on a `docs/handoff-<utc>` branch and prints
30
+ `WORKTREE: <path>`. That worktree is this session's only; no other session's edits can enter it.
31
+ Then, in the steps below:
32
+ - Step 1: tell the `knowledge-transfer` subagent to edit files ONLY under the `WORKTREE:` path.
33
+ - Step 3, point 4: run `caddis_rows.py set --file <worktree>/.caddis/open-work.md ...`, and make the
34
+ plan's Tracker edit in `<worktree>/.caddis/plans/<feature>.md`, not in this checkout.
35
+ - Step 4: skip `caddis_tidy.py --apply` (report `skipped: shared checkout`).
36
+ - Step 6b: skip `session_state.py prune` (report `skipped: shared checkout`).
37
+ - The relay stays in this checkout: `.caddis/relay/` is local and gitignored.
38
+ After Step 6b, run:
39
+ ```
40
+ python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_docs_pr.py" finish --worktree <path> --title "docs(handoff): <name> session notes" --body "Handoff doc edits from a shared checkout."
41
+ ```
42
+ It commits only the worktree's changed files, pushes, opens a PR, and prints `PR: <url>` and one
43
+ `FILE: <path>` line per file (or `PR: none` when nothing changed). It always removes the worktree, and
44
+ it never merges. On a failure it prints `PATCH: <path>` with the edits; report that path. Put the
45
+ `PR:` line and the file list in your final report, under `Docs PR needed:`.
46
+
11
47
  ## Step 1 — capture learnings FIRST (knowledge-transfer)
12
48
  **Before** gathering git signals or writing relay.md, decide on `knowledge-transfer` — and the default
13
49
  is to run it.
@@ -36,7 +72,7 @@ committed before its generator last changed. Paste the parts a next session need
36
72
  them from memory.
37
73
 
38
74
  **Why this step is mechanical.** A handover used to be composed from what the outgoing session
39
- remembered, so it was only ever as complete as that memory. Bringing one Hub to a usable state took
75
+ remembered, so it was only ever as complete as that memory. Bringing one successor session to a usable state took
40
76
  nine corrective round trips and the user caught six of them — including *"the handover listed no
41
77
  reports, documents, KB notes or scripts"*. None of those are judgement calls; every one is a
42
78
  directory listing. An agent recalls **what it did**; a generator enumerates **what exists**, and
@@ -53,39 +89,7 @@ clean phase boundary and lose or double-do the work.
53
89
  tracker shows plan A in progress, but the work moved to plan B), suggest the user run `/digress` to park
54
90
  plan A on the workstream stack — so its exact resume point survives and `/catchup [name]` can pop it back later.
55
91
 
56
- ## Step 2b — Advisory-Hub handoff audit (conditional — skip silently if not applicable)
57
-
58
- **Trigger:** the active plan found in Step 2 has a sibling `<slug>-advisory-context.md`. **No such file
59
- → skip this step entirely and silently** — no extra work on an ordinary handoff.
60
-
61
- > **First, say which command the user actually wants.** A context doc means a Hub is running, and
62
- > handing over a Hub is `/caddis:spawn-hub`, not this command. The two look interchangeable from
63
- > outside and are not: `/handoff` writes a resume doc for the same workstream, while `spawn-hub`
64
- > ends the Hub's tenure, runs the mechanical audit, conserves the carried-open ledger, and files
65
- > `hub-NN.spawn.md` in `.caddis/advisory-hub-reports/`. Tell the user plainly, then continue only if
66
- > they still want a plain handoff.
67
-
68
- **Why it is a distinct step:** a context doc is written *before* the work happens, so it is **always
69
- stale by the time it is needed**. The outgoing Hub's instinct is always "yes, this doc is designed for
70
- exactly this" — **that instinct has been measured and found wrong**: a real audit found seven gaps in a
71
- context file the outgoing Hub believed was current, including the single highest-value technique the Hub
72
- had developed by then.
73
-
74
- **Do not ask "are there gaps?" Assume there are, and find them mechanically** (full detail: the
75
- `advisory-hub` skill's §G):
76
- 1. **List every technique, decision, and correction you actually used this session** — from your own
77
- actions in this transcript, not by re-reading the context doc.
78
- 2. **For each, check whether the context doc's instruction itself already covers it** — not whether the
79
- word appears. Would a fresh Hub, reading only that file, be told to do the same thing?
80
- 3. **The caveat that will burn you:** a literal-string grep over prose produces **false MISSINGs**. A
81
- `0 matches` result means "this exact string isn't here," not "this isn't covered." **Read the section
82
- before believing a 0-match grep.**
83
- 4. **Land every real gap as a durable rule** in the right section of the advisory-context, carrying the
84
- specific failure that earned it — a note left for later is not a fix.
85
-
86
- Record the outcome in relay.md's `## Learnings captured` line (below).
87
-
88
- ## Step 2c — was any of it the harness?
92
+ ## Step 2b — was any of it the harness?
89
93
 
90
94
  <!-- shared:harness-friction-question — keep byte-identical across commands; a test pins it -->
91
95
  **One question, asked here because here is where you are already reflecting.** The observations
@@ -111,7 +115,7 @@ Nothing to say is the normal answer. Say nothing and move on — this must not b
111
115
  > `session_id` and `--session-id`. Never guess one: a wrong id disables session matching.
112
116
  >
113
117
  > 1. **Name the workstream** (active plan's `feature`, else the branch; the script prints nothing
114
- > on the default branch with no plan — then ask the user for a short name):
118
+ > on the default branch with no plan — run `caddis_workstreams.py list` (`python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_workstreams.py" list`) to show existing workstreams, then ask the user which one to use or for a short name):
115
119
  > `python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_workstreams.py" resolve --plan <feature> --branch <branch> --default-branch <main>`
116
120
  > 2. **Legacy repo:** if `.caddis/relay.md` exists and does not start with
117
121
  > `<!-- caddis-workstream-index-v1 -->`, or an old `/digress` stack `.caddis/workstreams.json`
@@ -120,11 +124,21 @@ Nothing to say is the normal answer. Say nothing and move on — this must not b
120
124
  > to the user and stop.
121
125
  > 3. **Read the stored version's hash** before you compose: `caddis_workstreams.py hash <name>`
122
126
  > (prints `none` for a new workstream).
123
- > 4. **Write** the relay below to a temp file, then
124
- > `caddis_workstreams.py write <name> <temp-file> --expected-hash <hash>`. Exit 1 means another
125
- > session changed the relay since step 3: it prints the diff and writes nothing. Show the diff,
126
- > merge by hand, and retry with the new hash. Never force it.
127
- > 5. **Refresh the index:** `caddis_workstreams.py render-index --session-id <id> --branch <branch>`.
127
+ > 4. **Open-work rows** (only when `.caddis/open-work.md` exists and its frontmatter says
128
+ > `type: open-work`): first set each row this session
129
+ > finished, by id and column name, never by hand:
130
+ > `python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_rows.py" set --file .caddis/open-work.md --id <row id> --col Status=done --col Evidence=<evidence>`.
131
+ > In a shared checkout (Step 0), use `--file <worktree>/.caddis/open-work.md` instead.
132
+ > **Order of work:** when the repo has a roadmap (`caddis_roadmap.py list` prints a slug), the
133
+ > roadmap on origin is the order of work. Write the relay's "Next step (exact)" as
134
+ > `next: top open item of roadmap <slug> (caddis_roadmap.py status --roadmap <slug>)`. Never copy a
135
+ > list of open items into the relay.
136
+ > 5. **Write** the relay below to a temp file, then
137
+ > `python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_workstreams.py" put <name> <temp-file> --require-status --expected-hash <hash>`.
138
+ > It refuses a relay whose last line is not a valid status line (see "Programme triggers" below).
139
+ > Exit 1 also means another session changed the relay since step 3: it prints the diff and writes
140
+ > nothing. Show the diff, merge by hand, and retry with the new hash. Never force it.
141
+ > 6. **Refresh the index:** `caddis_workstreams.py render-index --session-id <id> --branch <branch>`.
128
142
  >
129
143
  > (Source checkout: `scripts/caddis_workstreams.py`.) A repo still on the pre-rename `.claudster/`
130
144
  > won't see this relay until it's converted — `/caddis:migrate-dir` does that.
@@ -154,6 +168,7 @@ generated:
154
168
  <The single next action. Include the command/phase. Add a fallback if blocked.>
155
169
 
156
170
  ## Read first on resume
171
+ Paths are relative to the repo root.
157
172
  - `<path>` — why it matters
158
173
  - `.caddis/plans/<feature>.md` — the plan + tracker
159
174
 
@@ -165,18 +180,26 @@ generated:
165
180
 
166
181
  ## Learnings captured
167
182
  knowledge-transfer: <✓ ran → files written | ✗ skipped → reason>
168
- advisory-context audit: <N candidates → M gaps → landed in <path>> | n/a (no advisory-context for this plan)
169
183
 
170
184
  ## Resume prompt
171
185
  \`\`\`
172
186
  Read .caddis/relay/<name>.md, then the plan it points to. Continue from <phase/step>. Next action: <exact>.
173
187
  \`\`\`
188
+
189
+ STATUS: <CONTINUE | OWNER-GATE <P>-OG<n> | BLOCKED <owner> | FAILED <reason>>
174
190
  ```
175
191
 
192
+ ## Programme triggers
193
+
194
+ Small work that does not meet a trigger skips its block.
195
+
196
+ **Trigger: Always.** The relay ends with a status line, the last non-empty line, and it is exactly one of `STATUS: CONTINUE`, `STATUS: OWNER-GATE <P>-OG<n>`, `STATUS: BLOCKED <owner>` or `STATUS: FAILED <reason>`. In Step 3, point 5, write the relay with `python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_workstreams.py" put <name> <temp-file> --require-status --expected-hash <hash>` instead of `write` (in short: put --require-status), with the same hash Step 3 read, so a peer's newer relay is never overwritten. It rejects a relay with no valid status line, and renders the index. When the repo has `.caddis/open-work.md` with `type: open-work` in its frontmatter, also set each open-work row's status with `python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_rows.py" set --file <open-work.md> --id <row id> --col Status=<status>` (in a shared checkout, the copy in the Step 0 worktree). When the status is `done`, also pass `--col Evidence=<commit, PR or test>`: caddis_rows.py refuses `done` with no Evidence.
197
+
176
198
  ## Step 4 — tidy finished artifacts
177
199
  Flip any plan/prompt's frontmatter `status:` to `done` (or `superseded`) if this session actually
178
200
  finished it — that is your judgment call; the script below never makes it and never auto-flips
179
- status. Then run:
201
+ status. In a shared checkout (Step 0), make the `status:` flip in the Step 0 worktree copy of the plan,
202
+ never in this checkout. Then run (skip it in a shared checkout, Step 0: it moves tracked files):
180
203
  ```
181
204
  python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_tidy.py" --apply
182
205
  ```
@@ -184,7 +207,13 @@ python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_tidy.py" --apply
184
207
  skip this step** — it degrades open, same as the other machine gates; an older install must not
185
208
  be blocked by a script it does not have. Include its report in your output. A **collision**
186
209
  (`done/<name>` already exists) is reported by the script, not fatal — surface it, do not fail the
187
- handoff over it.
210
+ handoff over it. Exit 2 means a plan is held because its Tracker still has open rows (`held (open Tracker rows): ...` lines, from Phase 3): show those lines; finish, park (`.caddis/parking-lot/<file>.md` in the row) or mark the rows `dropped: <reason>`, or set the plan status back. Do not fail the handoff over it.
211
+
212
+ After step 4, for each item this session closed (a phase `<plan>#<n>`, a plan slug, or an open-work row id), run `mentions` to check whether another relay's Next step still names it:
213
+ ```
214
+ python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_workstreams.py" mentions --item "<item>" --except <name>
215
+ ```
216
+ Print a `WARNING:` line per hit (`WARNING: relay <other> still names closed item <item> in its Next step`). Never edit another workstream's relay (`caddis_workstreams.py mentions` only reads).
188
217
 
189
218
  ## Step 5 — check the handover you just wrote
190
219
 
@@ -197,7 +226,7 @@ report that repo's paths as missing, which is the tool being right about the wro
197
226
 
198
227
  It fails when the handover names a file that does not exist. The incoming session has **no other
199
228
  source** for those paths, so it cannot tell a typo from a real file: one live handover sent an
200
- incoming Hub looking for a prompt that was never written. Fix what it lists, then re-run.
229
+ incoming session looking for a prompt that was never written. Fix what it lists, then re-run.
201
230
 
202
231
  It also notes any generated artefact committed before its generator last changed. That is advisory,
203
232
  not blocking — but do not quote a report the note names without rebuilding it first.
@@ -219,7 +248,8 @@ python "${CLAUDE_PLUGIN_ROOT}/scripts/session_state.py" prune
219
248
  `usage` finds this session's transcript by its id and appends one token-and-skill record to
220
249
  `.caddis/usage-log.jsonl`, which `/usage-review` reads. Pass `--transcript <path>` if you know the
221
250
  path and it is not under the Claude config folder. `prune` keeps the newest 8 files in
222
- `.caddis/session-state/`; run it after Step 6, which reads this session's file. Include the
251
+ `.caddis/session-state/`; run it after Step 6, which reads this session's file. Skip `prune` in a
252
+ shared checkout (Step 0). Include the
223
253
  `[USAGE]` line in your output. Both always exit 0; if the script is missing, skip this step.
224
254
 
225
255
  Then list old local state (falls back to `scripts/caddis_tidy.py`; skip if missing):
@@ -247,10 +277,9 @@ On the other machine, `/catchup <name>` fetches it.
247
277
  order: (1) interrupted mid-phase work → finish + commit it; else (2) the active plan's next not-started
248
278
  phase; else (3) the top open question/decision. Everything else is context, not the next step.
249
279
  - Only verified facts and real paths. Mark anything unconfirmed as `Unknown`.
250
- - Update the plan's tracker rows too (status + last commit) — relay and tracker must agree.
280
+ - Update the plan's tracker rows too (status + last commit) — relay and tracker must agree. In a shared
281
+ checkout, edit the Tracker in the Step 0 worktree, never in this checkout.
251
282
  - Don't commit unless asked. Report which `.caddis/relay/<name>.md` was written and the one next action.
252
- - **Never hand off a Hub session on the strength of "the context doc is designed for this."** That is the
253
- one instinct that has been measured and found wrong. Run Step 2b's audit instead.
254
283
  - **Prune the Done section — two rules, both apply:**
255
284
  1. **Merge-based:** Phases already merged to `main` (confirmed by a tag or commit) must be compressed
256
285
  to a single line: `- **RW-N**: merged to main as vYYYY.MM.DD.N (<commit>) ✅`. Only the current
@@ -5,10 +5,10 @@ description: Headless plan executor — implement an approved plan phase-by-phas
5
5
 
6
6
  # /caddis:implement — execute an approved plan (headless driver)
7
7
 
8
- Implement the plan at **$ARGUMENTS** (falls back to the `DOCKET_PLAN` env var if `$ARGUMENTS` is empty).
8
+ Implement the plan at **$ARGUMENTS**.
9
9
 
10
- **Which plan.** An explicit plan always wins: `$ARGUMENTS` first, then the `DOCKET_PLAN` env var
11
- (it counts as an explicit argument). Only when both are empty, find the active plan:
10
+ **Which plan.** An explicit plan always wins: the plan path comes only from `$ARGUMENTS`. Only when
11
+ it is empty, find the active plan:
12
12
 
13
13
  ```bash
14
14
  python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_todo.py" active-plan
@@ -20,8 +20,9 @@ python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_todo.py" active-plan
20
20
  candidates it printed on stderr (or "none") in the review file, and end with the
21
21
  `"implemented":false` JSON block from step 6.
22
22
 
23
- This command is the **docket Implement lane's driver**. It is spawned autonomously by the docket runner —
24
- **no human is present**. It does not design or re-plan: the plan is the intelligence, you are the executor.
23
+ This command is the **headless Implement driver**. It is spawned autonomously by a runner or a lane
24
+ launcher (they set `CADDIS_HEADLESS`) — **no human is present**. It does not design or re-plan: the plan
25
+ is the intelligence, you are the executor.
25
26
  The runner independently re-runs the tests and a fresh code-review after you finish and decides success
26
27
  itself — so your job is to implement faithfully, commit cleanly, and report honestly. Overstating success
27
28
  does not help you; the runner will catch it.
@@ -30,11 +31,15 @@ does not help you; the runner will catch it.
30
31
  These override everything below. They exist because branch isolation and the runner's post-run backstops
31
32
  depend on them:
32
33
 
33
- - **Work ONLY on the current branch.** You are already on the feature branch (`DOCKET_BRANCH`, e.g.
34
- `agent/<slug>`). **NEVER** run `git checkout`, `git switch`, `git branch`, `git switch -c`, or any
35
- command that changes, creates, or leaves the current branch. If you somehow find yourself on the default
36
- branch (`DOCKET_DEFAULT_BRANCH`), **stop immediately, do not commit**, and emit the failure JSON below —
37
- a commit on the default branch fails the run.
34
+ - **Work ONLY on the current branch.** You are already on the feature branch (the current branch,
35
+ `git branch --show-current`; that read is the only `git branch` form allowed). **NEVER** run
36
+ `git checkout`, `git switch`, `git branch <name>`, `git switch -c`, or any command that changes,
37
+ creates, or leaves the current branch. Read the default branch with
38
+ `git symbolic-ref --short refs/remotes/origin/HEAD`, which prints `origin/<default>`: remove the
39
+ `origin/` prefix before you compare. If that command fails (origin/HEAD is not set), the default
40
+ branch is `main` or `master`. **Stop immediately, do not commit**, and emit the failure JSON below when
41
+ `git branch --show-current` prints nothing (a detached HEAD) or prints the default branch — a commit
42
+ there is lost or fails the run.
38
43
  - **NEVER touch git remotes.** No `git push`, `git pull`, `git fetch`, `git remote`, no PR, no merge. The
39
44
  runner never pushes; neither do you.
40
45
  - **NEVER edit your own success criteria.** Do not modify `.caddis/PROJECT-FACTS.md`, and do not change
@@ -51,16 +56,36 @@ depend on them:
51
56
  ## Three rules: one attempt, one review
52
57
  1. **Think before you send.** Before a task goes to any coder, write its edge cases and check the facts it depends on (one query or one file read).
53
58
  2. **Run it before review.** The coder runs the same checks as CI (name the exact commands in the task). Then run the change once on real data.
54
- 3. **Review once.** Use whatever reviewer is available. Stop at the first CLEAN. After two blocking reviews, ask the owner.
59
+ 3. **Review by tier.** Run `python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_gate.py" review-tier --range <base>...HEAD` (add `--plan <plan> --phase <N>` inside a plan; no `TIER:` line means tier 2).
60
+ Tier 0: gates only. Tier 1-small: your self-check only. Tier 1: one review by another vendor; stop at
61
+ the first CLEAN. Tier 2: two reviewers of two other vendors, in one round. Fix blocking findings only;
62
+ park the rest. Re-review only the fix diff, and only when the fix changed logic. After 3 rounds, ask the owner.
55
63
 
56
- This run is headless, so "ask the owner" means: stop the phase, do not commit it, and record the
57
- two blocking reviews in the review file.
64
+ **Author self-check** (tier 1-small, and before any review). It is not a model review. Answer all five:
65
+ 1. The CI gates named in the phase passed, with the literal output.
66
+ 2. Every changed function has a test that fails without the change.
67
+ 3. No TODO, placeholder or debug print is left.
68
+ 4. Error paths return or raise. None is swallowed.
69
+ 5. The diff touches only the phase's files.
70
+
71
+ This run is headless, so "ask the owner" (after 3 rounds) means: stop the phase, do not commit it, and record the
72
+ blocking findings of the 3 rounds in the review file.
73
+
74
+ ## Programme triggers
75
+
76
+ Small work that does not meet a trigger skips its block.
77
+
78
+ **Trigger: Always.** Mutation proof: for each gate the phase adds, break the code under test once with a recorded mutation and see the gate fail. Write the mutation and the failing test line in the review file.
79
+
80
+ **Trigger: The phase computes or shows a number.** Value check: the computed figure must equal an independent source for a fixed past window, never today. Start from the `roadmap` skill's `assets/value-check.template.py`. Run it once with `--prove-it-can-fail` and see it exit 1.
81
+
82
+ **Trigger: The phase changes UI.** Render check: the changed page must render at 1440 and 400 px wide with 0 console errors, after the network is idle plus the settle time (default 3 s). Start from the `roadmap` skill's `assets/render-check.template.mjs`. Run it once with `--prove-it-can-fail`.
58
83
 
59
84
  ## What to do
60
85
 
61
- **1. Read the plan.** Load the plan file (`$ARGUMENTS` / `DOCKET_PLAN`). Read its `## Phases`, `## Affected
62
- files`, `## Constraints & decisions`, and `## Tracker`. Read the `AGENTS.md` at the repo root and in each
63
- folder you will touch (the canonical rules; `CLAUDE.md` is an `@AGENTS.md` shim), and
86
+ **1. Read the plan.** Load the plan file (`$ARGUMENTS`, or the active plan found above). Read its
87
+ `## Phases`, `## Affected files`, `## Constraints & decisions`, and `## Tracker`. Read the `AGENTS.md`
88
+ at the repo root and in each folder you will touch (the canonical rules; `CLAUDE.md` is an `@AGENTS.md` shim), and
64
89
  `.caddis/PROJECT-FACTS.md` if present (for the real run/test commands) —
65
90
  **read it, never edit it**. Identify the test command the plan/facts specify so you can run it yourself.
66
91
 
@@ -68,12 +93,11 @@ folder you will touch (the canonical rules; `CLAUDE.md` is an `@AGENTS.md` shim)
68
93
 
69
94
  ```bash
70
95
  python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_gate.py" lane-check --plan <plan> --phase <N>
71
- python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_gate.py" verdict-gate --plan <plan> --phase <N>
72
96
  python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_gate.py" tracker-vs-git --plan <plan>
73
97
  ```
74
98
 
75
99
  Use the shared scale in `caddis_exit.py`: 0 clean, 1 blocked, 2 advisory, 3 could not run,
76
- 4 error or bad usage. For `caddis_gate.py`, obey the exit code: **0** proceed · **1** STOP and report
100
+ 4 error or bad usage, 5 round limit (`caddis_review.py --plan` only: stop, the owner decides). For `caddis_gate.py`, obey the exit code: **0** proceed · **1** STOP and report
77
101
  why · **2** proceed but record the note it
78
102
  printed · **3** wrong lane — the launch command is on stdout, spawn it · **4** the launch command is
79
103
  malformed, do not run it.
@@ -92,7 +116,7 @@ You cannot always prove your own lane, but you can detect a known mismatch — a
92
116
  looking at `Lane: glm-headless`. Apply this **asymmetrically: act on a known mismatch, proceed when
93
117
  unsure.** On a known mismatch:
94
118
 
95
- - **Interactive session (no `CADDIS_HEADLESS`, no `DOCKET_PLAN`/`DOCKET_BRANCH` in the environment)
119
+ - **Interactive session (no `CADDIS_HEADLESS` in the environment)
96
120
  → spawn the assigned lane.** Run the phase's literal launch command yourself — e.g.
97
121
  `claude-glm -p "/caddis:implement <plan> — Phase N only"` — wait for it, then verify it (below).
98
122
  On Windows `claude-glm` is `claude-glm.ps1` and resolves only on the **PowerShell** PATH; a
@@ -105,9 +129,9 @@ unsure.** On a known mismatch:
105
129
  > it spawns a session that is not marked headless, which reads this same `Lane:` line and spawns
106
130
  > again — unbounded recursion. Without `-p` the command also opens an interactive session, so the
107
131
  > parent waits forever on a child that is sitting at a prompt.
108
- - **Headless or docket-runner session → never spawn. Implement here and record the deviation.**
132
+ - **Headless session (`CADDIS_HEADLESS` set) → never spawn. Implement here and record the deviation.**
109
133
  You may already *be* the spawned lane, and a session that spawns its own lane on every start is
110
- an infinite loop. The env markers above are the guard: if either is set, someone else placed you.
134
+ an infinite loop. The env marker above is the guard: if it is set, someone else placed you.
111
135
 
112
136
  **After the spawn, verify it — do not assume.** Re-read the plan's Tracker row for that phase and
113
137
  confirm the status and commit hash the child claims to have written. "Wait for it and report" checks
@@ -122,7 +146,7 @@ the bug the lane routing exists to fix.
122
146
 
123
147
  **Record the lane you actually ran on in the Tracker's `Lane` column** — the lane you ran, never the
124
148
  lane the plan planned. A deviation then shows up as a diff between the phase block and the tracker
125
- row, visible to any later reader without an Advisory Hub having to catch it live.
149
+ row, visible to any later reader without anyone having to catch it live.
126
150
 
127
151
  **Multi-lane phases — `caddis_lanes.py`.** Use this procedure when the phase launch command is
128
152
  `python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_lanes.py" run …`.
@@ -179,89 +203,17 @@ row, visible to any later reader without an Advisory Hub having to catch it live
179
203
  or `You're out of extra usage`; the full list is `BUDGET_PATTERNS["claude"]` in
180
204
  `caddis_lanes.py`), run `python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_lanes.py" next-lane --role <the phase's role> --after <the model that ran>`.
181
205
  Re-dispatch the same phase prompt to the printed lane with its direct launch command:
182
- `codex exec ...` or `agy ... -p "..."`, using the same form that `/feature-plan` writes.
206
+ `codex exec ...` or `python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_spend.py" run --caller lane-pN -- agy ... -p "..."`,
207
+ using the same form that `/feature-plan` writes. Never start agy without the `caddis_spend.py run`
208
+ prefix: it is the global spend cap. Its own refusals have their own exit codes, never agy's:
209
+ **75** = over the cap or could not lock (treat like out of budget: switch lane, not an attempt);
210
+ **78** = the cap is not configured (stop and tell the owner to write `~/.caddis/spend-cap.toml`).
211
+ Each refusal also prints a `caddis_spend:` line on stderr. Any other exit code is agy's own.
183
212
  An out-of-budget switch is not an attempt (item 4). Record the fallback in the Tracker
184
213
  `Lane` column, for example `sonnet -> agy (claude out of budget)`.
185
214
  If `next-lane` exits 3, stop and report that no lane is left. As a last resort, the owner can
186
215
  open `caddis-run codex -m gpt-6-astra` and ask it to follow this same subsection.
187
216
 
188
- **Advisory-Hub mode (conditional — OFF by default).** Check whether a companion file
189
- `<plan-dir>/<plan-stem>-advisory-context.md` exists (e.g. plan `.caddis/plans/foo.md` → look for
190
- `.caddis/plans/foo-advisory-context.md`). **If it does not exist — the normal case, including every
191
- docket run — Advisory-Hub mode is OFF and nothing else in this command changes.** If it exists, read it
192
- and set Advisory-Hub mode ON for this run: it names locked decisions you may not change unilaterally,
193
- this project's declared safety conventions, and how to re-derive the plan's anchor numbers. See the
194
- `advisory-hub` skill for the full contract.
195
-
196
- **In Advisory-Hub mode, the previous phase's VERDICT gates this one.** Before starting phase N, require
197
- a verdict in `.caddis/advisory-hub-reports/` that satisfies **all three** of:
198
-
199
- 1. **It covers phase N-1.** Usually `phase-(N-1).verdict.md`, but a **batched** verdict counts: a file
200
- whose `phase:` is a range — `phase-10-11.verdict.md`, `phase: 10-11` — satisfies the gate for every
201
- phase the range **covers**. Batched pairs are normal, not exotic: one live plan alone carries
202
- `phase-05-06`, `08-09`, `10-11` and `13-14`. A literal `phase-(N-1)` lookup sends phase 12 hunting
203
- for a `phase-11.verdict.md` that will never exist, and falsely blocks a properly validated plan.
204
- 2. **It belongs to the plan you are implementing.** The report directory is flat and shared, so with two
205
- hub-mode plans in one repo, plan A's `phase-02.verdict.md` would otherwise satisfy plan B's phase-3
206
- gate. Match the verdict's identity field against the plan. **Accept either `plan:` (a path) or
207
- `feature:` (a slug) — both are in live fleet use** and neither is wrong; one project's verdicts carry
208
- one, another's carry the other. If a verdict carries neither, treat its identity as unproven: say so
209
- and do not let it gate anything.
210
- 3. **It carries `verdict: accept` or `verdict: accept-with-correction`.**
211
-
212
- - **Missing** → the Hub has not validated it yet. **STOP.** Mark the Tracker row
213
- `blocked-pending-hub` and say which verdict you are waiting on.
214
- - **`verdict: reject`** → **STOP.** The phase is to be redone, not built upon.
215
- - **`verdict: accept-degraded`** → the Hub validated it **without an advisory context**, so the
216
- locked-decision and safety-rule re-checks never ran. It is a partial check wearing an accept. Proceed
217
- only if the phase is low-stakes, and **say in your report that you did so on a degraded verdict**.
218
- - Phase 1 (or the first phase of the plan) has no predecessor — proceed.
219
-
220
- This is the Hub's central power and until now it ran on human discipline alone: the verdict recorded
221
- whether the next phase could start, and *nothing read it*. Five lines of check make the claim true by
222
- machine.
223
-
224
- ### Ringing the Hub, and waiting for it (Claude Code only, optional)
225
-
226
- Two moments in Advisory-Hub mode currently cost the user a copy-paste. Both are optional, both
227
- degrade to today's behaviour, and neither replaces a file.
228
-
229
- **After you file `phase-NN.report.md`** — if `ListAgents` is available, look for a peer session whose
230
- name starts with **this repo's directory name**. Sessions are auto-named `<repo-dir>-<hash>`, so a
231
- same-repo peer is the Hub:
232
-
233
- ```
234
- SendMessage({to: "<peer-name>", summary: "phase-05 report filed",
235
- message: "phase-05.report.md is filed and awaiting a verdict."})
236
- ```
237
-
238
- **When you are BLOCKED on a verdict** — instead of stopping dead, subscribe once:
239
-
240
- ```
241
- SendMessage({to: "<peer-name>", notify_when_idle: true,
242
- message: "blocked on phase-05 verdict; ping me when you have written it"})
243
- ```
244
-
245
- `notify_when_idle` is one-shot and costs the Hub nothing extra. **Never poll `ListAgents` in a loop,
246
- and never send "are you done yet?"** — that burns both sessions' context to no purpose.
247
-
248
- **The rules that keep this from becoming a mess:**
249
-
250
- - **The file is the decision; the message is a doorbell.** Never treat a chat message as a verdict.
251
- If a peer says "accepted", still read `phase-NN.verdict.md` — the gate above checks the FILE, and
252
- a message cannot be re-read next week or by a third session.
253
- - **No `ListAgents`, no peer, or more than one same-repo peer → do nothing and carry on.** caddis
254
- also runs on agy and Codex, which have no cross-session messaging at all. Everything above is an
255
- accelerant on one harness; the file protocol is the portable layer and is what actually works.
256
- - **Headless runs never message.** There is no copy-paste to save.
257
- - **Never ask a peer to perform work your own session was denied.** Permission boundaries are
258
- per-session, and routing blocked work through another session launders the user's decision.
259
-
260
- **If a `phase-NN.prompt.md` exists for the phase you are about to run, it is the INSTRUCTION OF
261
- RECORD** — read it, and measure your DEVIATIONS against it, not against the plan alone. The Hub writes
262
- that file before the phase precisely so a deviation is falsifiable; an executor that never reads it
263
- undermines the whole argument.
264
-
265
217
  **2. Determine where to resume.** The `## Tracker` table is the resume signal. Start at the first phase whose
266
218
  status is not `done`/`✅`. If every phase is already done, verify the tests are green and go straight to the
267
219
  report — do not redo completed work.
@@ -289,33 +241,6 @@ report — do not redo completed work.
289
241
  ACTUALLY ran on (not the planned one — see Step 1), and add a one-line note. This is what lets a
290
242
  future session (or the runner) see progress. Commit the Tracker update with the phase (or as a tiny
291
243
  follow-up commit) — it lives in the plan file, which is fine to commit on this branch.
292
- - **FILE THE PHASE REPORT — Advisory-Hub mode only.** *Skip this bullet entirely if Step 1 found no
293
- `<slug>-advisory-context.md`.* Write `.caddis/advisory-hub-reports/phase-NN.report.md` (zero-padded
294
- phase number; create the directory and add a `README.md` index row if absent — and when you
295
- create `.caddis/advisory-hub-reports/` for the first time, also write an **`AGENTS.md`** there
296
- carrying the naming, frontmatter and role rules from the `advisory-hub` skill, so they bind every
297
- agent that writes to that directory including ones that never loaded the skill. The skill claims
298
- this file ships; nothing ever created it, so it exists only where a Hub hand-wrote one.
299
- **Never overwrite an existing `AGENTS.md`** — the hand-written ones in the fleet are the good
300
- copies) using the
301
- `advisory-hub` skill's report contract. Verbatim means verbatim — paste real terminal output, never
302
- reconstruct it. Report the model/lane you actually ran on. Report every commit, including tooling and
303
- config. `git add` the report file with this phase's commit. **If the report's SURPRISES /
304
- CONTRADICTIONS section is non-empty, stop after this phase** — mark the Tracker row
305
- `blocked-pending-hub`, leave later phases untouched, and let the Hub correct the plan; that is not
306
- your call to make here.
307
-
308
- > **Give it OKF frontmatter — `type` is REQUIRED and its absence is a defect.**
309
- > Keep it flat (scalar `key: value` only; nested maps and lists defeat simple parsers):
310
- > ```yaml
311
- > ---
312
- > type: phase-report
313
- > plan: <path to the plan>
314
- > phase: 12 # or 10-11 for a batched pair
315
- > milestone: M4
316
- > ---
317
- > ```
318
-
319
244
 
320
245
  If a phase cannot be completed (a blocking gap the plan did not resolve, or a rule above would be
321
246
  violated), **stop there**: leave later phases untouched, record the blocker in the review file, mark the
@@ -327,7 +252,11 @@ or a **failed/blocked** phase. A lane change is not one of them: you spawn the l
327
252
 
328
253
  The `risk: high` halt is deliberately *after*, not before. Execute and commit the phase normally; the
329
254
  halt exists to stop the **next** phase building on it before a human has looked, so the blast radius
330
- stays one reviewable, revertable commit.
255
+ stays one reviewable, revertable commit. One exception: when your session prompt itself says the runner
256
+ reviews `risk: high` phases (the runner's `plan-resume-prompt.md` says so), do not halt; end the session
257
+ `STATUS: CONTINUE`. The runner then reviews the phase twice (`caddis_review.py --plan --phase --runs 2`),
258
+ starts one fix session on blocking findings, and stops `BLOCKED review` when findings remain.
259
+ `CADDIS_HEADLESS=1` alone is NOT that instruction: without the prompt line, a `risk: high` phase still halts.
331
260
 
332
261
  **At every halt, PERFORM the handoff yourself, now, before you stop.** Write `relay.md` and update
333
262
  the Tracker in this session — you are the only party holding the context that makes them worth
@@ -358,31 +287,45 @@ more and record the real result. The runner will re-run it independently and tha
358
287
  you run it too so your reported `"tests"` value is truthful, not assumed. Never report `"passed"` on a
359
288
  suite you did not see go green.
360
289
 
361
- **4b. If every phase is now done, tidy the plan into `done/`.** Only when the whole plan is
362
- finished (every `## Tracker` row is `done`, no halt, no blocker) — a mid-plan halt is not this.
363
- Flip the plan's own frontmatter `status:` to `done` (your judgment call: only if the Tracker
364
- genuinely backs it up), commit that with the final phase, then run:
365
- ```
366
- python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_tidy.py" --apply
367
- ```
368
- (falls back to `scripts/caddis_tidy.py` from a source checkout; **skip this step if the script is
369
- missing** — degrades open, same as the gates in Step 1). A **collision**
370
- (`done/<name>` already exists) is reported by the script, not fatal — note it in the review file,
371
- do not fail the run over it.
372
-
373
- **5. Write a concise review file** to the path in the `DOCKET_REVIEW` env var (falls back to
374
- `.caddis/reviews/<slug>.md`, where `<slug>` is `DOCKET_SLUG`). Create `.caddis/reviews/` if needed.
290
+ **4b. If every phase is now done, tidy the plan into `done/` IN THE SAME COMMIT.** Only when the
291
+ whole plan is finished (every `## Tracker` row is `done`, no halt, no blocker) — a mid-plan halt is
292
+ not this. Tidy is part of finishing: the plan closes in the PR that finishes it, so nothing is left
293
+ for a later session to clean up, and nothing is left uncommitted. Order matters:
294
+
295
+ 1. Edit the final phase's `## Tracker` row to `done` (Step 3). **Do not commit it yet.**
296
+ 2. Run tidy on THIS plan only. It reads the Tracker, sets the plan's `status: done` and `git mv`s
297
+ it into `done/`. `--only` keeps it off every other file, so another session's finished plan, a
298
+ shipped prompt or a done parking-lot item is never swept into this PR:
299
+ ```
300
+ python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_tidy.py" --repo-root . --apply --only .caddis/plans/<this plan>.md
301
+ ```
302
+ Read the output before you commit. It must say `moved: .caddis/plans/<this plan>.md` and name
303
+ no other file. **Refuse** if it would touch anything else, or prints `ERROR` or `NOT MOVED`:
304
+ stop, do not commit the move, and report the output in the review file.
305
+ 3. `git add` the moved plan by name (`.caddis/plans/done/<plan>.md`, so the status and Tracker edits
306
+ are staged with the rename), then make the final commit. The move, the status and the last
307
+ Tracker row land in one commit.
308
+
309
+ (Falls back to `scripts/caddis_tidy.py` from a source checkout; **skip this step if the script is
310
+ missing** — degrades open, same as the gates in Step 1.) A **collision** (`done/<name>` already
311
+ exists) is reported by the script, not fatal: it changes nothing, so commit the Tracker row as
312
+ usual and note the collision in the review file; do not fail the run over it. `/caddis:ship-pr`
313
+ runs `caddis_tidy.py --check` on the PR's files and stops on a plan whose Tracker is done but whose
314
+ status is not, so a skipped tidy is caught before the PR opens.
315
+
316
+ **5. Write a concise review file** to `.caddis/reviews/<slug>.md`, where `<slug>` is the plan file's
317
+ name without `.md`. Create `.caddis/reviews/` if needed.
375
318
  Keep it short and scannable — this is what the human reviewer reads before merging the branch:
376
319
 
377
320
  ```markdown
378
321
  ---
379
322
  type: implement-review
380
323
  feature: <slug>
381
- branch: <DOCKET_BRANCH>
324
+ branch: <current branch>
382
325
  ---
383
326
 
384
327
  # Implement review — <feature>
385
- **Branch:** `<DOCKET_BRANCH>` • **Phases done:** <N of M> • **Tests:** passed | failed
328
+ **Branch:** `<current branch>` • **Phases done:** <N of M> • **Tests:** passed | failed
386
329
 
387
330
  ## What changed
388
331
  - <phase 1 — one line: what shipped + commit hash>
@@ -406,9 +349,6 @@ showed; `review` is the review-file path you wrote:
406
349
  {"implemented":true,"phases_done":<int>,"tests":"passed|failed","review":".caddis/reviews/<slug>.md"}
407
350
  ```
408
351
 
409
- (In Advisory-Hub mode, the phase report from Step 3 is a **file**, written per phase — this JSON block
410
- remains the one and only final output of the whole run, in every mode, unchanged.)
411
-
412
352
  If you had to stop before implementing anything (e.g. you were on the default branch, or the plan was
413
353
  unreadable), still end with the block using `"implemented":false,"phases_done":0,"tests":"failed"` and put
414
354
  the reason in the review file. The only acceptable final output is the code + commits + review file + this
@@ -62,7 +62,7 @@ the rename **on its own**, e.g. `chore(caddis): migrate .claudster/ -> .caddis/`
62
62
 
63
63
  ## Notes
64
64
  - Also grep the repo for stale refs the migrator leaves alone on purpose:
65
- `.gitignore`, CI workflows, `.docket/config.json`, and any script hardcoding `.claudster/`.
65
+ `.gitignore`, CI workflows, and any script hardcoding `.claudster/`.
66
66
  Update those by hand in the same commit.
67
67
  - Repos that haven't migrated keep working indefinitely — the `.claudster` read-fallback is removed
68
68
  only after the whole fleet has migrated and soaked.
@@ -18,12 +18,15 @@ anything else is the task for `run`. Pass supported run flags such as `--type` w
18
18
  An unknown flag returns a usage error.
19
19
 
20
20
  The exit codes follow `caddis_exit.py`: 0 clean, 1 blocked, 2 advisory, 3 could not run,
21
- 4 error or bad usage. In particular, `caddis_adhoc.py` returns 4 for bad usage.
21
+ 4 error or bad usage, 5 round limit (`caddis_review.py --plan` only: stop, the owner decides). In particular, `caddis_adhoc.py` returns 4 for bad usage.
22
22
 
23
23
  ## Three rules: one attempt, one review
24
24
  1. **Think before you send.** Before a task goes to any coder, write its edge cases and check the facts it depends on (one query or one file read).
25
25
  2. **Run it before review.** The coder runs the same checks as CI (name the exact commands in the task). Then run the change once on real data.
26
- 3. **Review once.** Use whatever reviewer is available. Stop at the first CLEAN. After two blocking reviews, ask the owner.
26
+ 3. **Review by tier.** Run `python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_gate.py" review-tier --range <base>...HEAD` (add `--plan <plan> --phase <N>` inside a plan; no `TIER:` line means tier 2).
27
+ Tier 0: gates only. Tier 1-small: your self-check only. Tier 1: one review by another vendor; stop at
28
+ the first CLEAN. Tier 2: two reviewers of two other vendors, in one round. Fix blocking findings only;
29
+ park the rest. Re-review only the fix diff, and only when the fix changed logic. After 3 rounds, ask the owner.
27
30
 
28
31
  `/mmr` is for handing a task to another model, not for normal reviews. For a normal review, use
29
32
  `/cross-review`.
@@ -0,0 +1,24 @@
1
+ ---
2
+ name: office-documents-official
3
+ description: Hint for Office and PDF file work. Use when the user asks to create, edit, read or convert a Word .docx, PDF, PowerPoint .pptx or Excel .xlsx file. caddis does not ship these skills; points to Anthropic's official document-skills plugin.
4
+ ---
5
+
6
+ # Office and PDF files: use Anthropic's document-skills
7
+
8
+ caddis does not include skills for Word (.docx), PDF, PowerPoint (.pptx) or Excel (.xlsx) files.
9
+ These skills belong to Anthropic. Anthropic publishes them as the `document-skills` plugin.
10
+
11
+ ## Install (Claude Code)
12
+
13
+ ```
14
+ /plugin marketplace add anthropics/skills
15
+ /plugin install document-skills@anthropic-agent-skills
16
+ ```
17
+
18
+ Source: https://github.com/anthropics/skills (see its README, section "Claude Code").
19
+
20
+ ## What to do
21
+
22
+ 1. If the plugin is installed, use its `docx`, `pdf`, `pptx` or `xlsx` skill for the file type. Do not work from this note.
23
+ 2. If the plugin is not installed, tell the user the two commands above. Then ask if they want to install it first.
24
+ 3. If the user cannot install it, say what you can do without it. For example, write the content as Markdown and let the user convert it.
@@ -66,7 +66,6 @@ Park it only if it is work **we** will do later. Redirect these instead, and say
66
66
  | Being worked on right now | `.caddis/plans/<feature>.md` |
67
67
  | An interrupted task you will come back to this session | `/caddis:digress` |
68
68
  | Blocked on a person outside this repo | `.caddis/comms/` + its `register.md` |
69
- | A card on the docket board | the board. **Never hand-edit `.caddis/backlog/`** — docket writes it |
70
69
  | A fact about the environment, not a task | the KB (`/caddis:kb`) |
71
70
 
72
71
  ### Step 2 — do not duplicate