codebyplan 1.13.38 → 1.13.40

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 (54) hide show
  1. package/dist/cli.js +25142 -425
  2. package/package.json +4 -2
  3. package/templates/agents/cbp-cc-executor.md +4 -4
  4. package/templates/agents/cbp-map-architecture.md +90 -0
  5. package/templates/agents/cbp-round-executor.md +2 -0
  6. package/templates/agents/cbp-task-check.md +2 -0
  7. package/templates/agents/cbp-task-planner.md +2 -0
  8. package/templates/context/architecture/arch-map-spec.md +204 -0
  9. package/templates/context/architecture-map.md +117 -0
  10. package/templates/hooks/README.md +14 -2
  11. package/templates/hooks/cbp-session-start-hook.sh +32 -0
  12. package/templates/hooks/cbp-test-coverage-gate.sh +20 -6
  13. package/templates/hooks/cbp-test-hooks.sh +72 -0
  14. package/templates/hooks/hooks.json +11 -0
  15. package/templates/hooks/validate-structure.sh +3 -2
  16. package/templates/rules/architecture-map.md +30 -0
  17. package/templates/rules/context-file-loading.md +3 -0
  18. package/templates/rules/supabase-branch-lifecycle.md +1 -1
  19. package/templates/settings.project.base.json +15 -1
  20. package/templates/skills/cbp-checkpoint-check/SKILL.md +10 -10
  21. package/templates/skills/cbp-checkpoint-complete/SKILL.md +7 -7
  22. package/templates/skills/cbp-checkpoint-create/SKILL.md +11 -9
  23. package/templates/skills/cbp-checkpoint-end/SKILL.md +4 -4
  24. package/templates/skills/cbp-checkpoint-plan/SKILL.md +10 -10
  25. package/templates/skills/cbp-checkpoint-start/SKILL.md +6 -6
  26. package/templates/skills/cbp-checkpoint-update/SKILL.md +9 -9
  27. package/templates/skills/cbp-git-commit/SKILL.md +8 -4
  28. package/templates/skills/cbp-git-worktree-remove/SKILL.md +3 -2
  29. package/templates/skills/cbp-map-architecture/SKILL.md +170 -0
  30. package/templates/skills/cbp-merge-main/SKILL.md +2 -5
  31. package/templates/skills/cbp-refresh-arch-map/SKILL.md +191 -0
  32. package/templates/skills/cbp-round-check/SKILL.md +12 -8
  33. package/templates/skills/cbp-round-complete/SKILL.md +16 -10
  34. package/templates/skills/cbp-round-end/SKILL.md +9 -10
  35. package/templates/skills/cbp-round-execute/SKILL.md +7 -6
  36. package/templates/skills/cbp-round-input/SKILL.md +24 -12
  37. package/templates/skills/cbp-round-start/SKILL.md +36 -16
  38. package/templates/skills/cbp-round-update/SKILL.md +14 -10
  39. package/templates/skills/cbp-session-end/SKILL.md +22 -12
  40. package/templates/skills/cbp-session-start/SKILL.md +19 -15
  41. package/templates/skills/cbp-ship/SKILL.md +4 -4
  42. package/templates/skills/cbp-ship/reference/surface-supabase.md +3 -3
  43. package/templates/skills/cbp-ship-configure/SKILL.md +1 -1
  44. package/templates/skills/cbp-ship-configure/reference/railway-backend.md +2 -2
  45. package/templates/skills/cbp-ship-configure/reference/vercel.md +1 -1
  46. package/templates/skills/cbp-ship-main/SKILL.md +2 -2
  47. package/templates/skills/cbp-standalone-task-complete/SKILL.md +3 -2
  48. package/templates/skills/cbp-supabase-migrate/SKILL.md +6 -7
  49. package/templates/skills/cbp-task-check/SKILL.md +10 -10
  50. package/templates/skills/cbp-task-complete/SKILL.md +11 -9
  51. package/templates/skills/cbp-task-create/SKILL.md +7 -5
  52. package/templates/skills/cbp-task-start/SKILL.md +15 -17
  53. package/templates/skills/cbp-task-testing/SKILL.md +18 -18
  54. package/templates/skills/cbp-todo/SKILL.md +21 -21
@@ -14,14 +14,14 @@ Inspect the resolved identifier from argument parsing to determine the task kind
14
14
  |-----------------|------|
15
15
  | `{task}-{round}` (2-segment, e.g. `45-2`) | `standalone` |
16
16
  | `{chk}-{task}-{round}` (3-segment, e.g. `141-3-1`) | `checkpoint` |
17
- | _(empty / free-text)_ | Check `get_current_standalone_task` first; if found → `standalone`. Else → `checkpoint` via `get_current_task`. |
17
+ | _(empty / free-text)_ | Check `get_current_standalone_task` first; if found → `standalone`. Else → `checkpoint` via `get_current_task`. (Kind-detection is MCP-unavoidable — no identifier yet means no local path to probe; subsequent operations are local-first per the rows below.) |
18
18
 
19
19
  Set `KIND` for the rest of this skill. MCP tool names vary by KIND:
20
20
 
21
21
  | Operation | `checkpoint` KIND | `standalone` KIND |
22
22
  |-----------|------------------|-------------------|
23
- | Get task | `get_current_task(repo_id)` | `get_current_standalone_task(repo_id)` |
24
- | Get rounds | `get_rounds(task_id)` | `get_standalone_rounds(standalone_task_id)` |
23
+ | Get task | local state (break-glass: `get_current_task`) | `get_current_standalone_task(repo_id)` |
24
+ | Get rounds | local state (break-glass: `get_rounds`) | `get_standalone_rounds(standalone_task_id)` |
25
25
  | Add round | `add_round(task_id, ...)` | `add_standalone_round(standalone_task_id, ...)` |
26
26
  | Update round | `update_round(round_id, ...)` | `update_standalone_round(standalone_round_id, ...)` |
27
27
  | Update task | `update_task(task_id, ...)` | `update_standalone_task(standalone_task_id, ...)` |
@@ -64,9 +64,13 @@ If the argument matches the numeric regex, resolve the target task/round from DB
64
64
 
65
65
  ### Step 2: Deep Analysis (MANDATORY — always runs)
66
66
 
67
- **2a:** Load task via KIND-appropriate MCP tool (`get_current_task` or `get_current_standalone_task`) — get `files_changed`, `requirements`, `context`, `qa`
67
+ **2a:** Load task:
68
+ - **checkpoint KIND** — Read `.codebyplan/state/checkpoints/<checkpointId>/tasks/<taskId>.json` (local-first). If missing/stale, run `npx codebyplan sync` once and re-read. Break-glass fallback: MCP `get_current_task(repo_id)` when state dir is absent and sync fails. Get `files_changed`, `requirements`, `context`, `qa`.
69
+ - **standalone KIND** — MCP `get_current_standalone_task(repo_id)`. (Standalone KIND still uses MCP until a later task.)
68
70
 
69
- **2b:** Load all rounds via MCP `get_rounds(task_id)` (checkpoint KIND) or `get_standalone_rounds(standalone_task_id)` (standalone KIND) — get previous round context, testing-qa output
71
+ **2b:** Load all rounds:
72
+ - **checkpoint KIND** — Read `.codebyplan/state/checkpoints/<checkpointId>/tasks/<taskId>/rounds/*.json` (local-first; break-glass: MCP `get_rounds(task_id)`). Get previous round context, testing-qa output.
73
+ - **standalone KIND** — MCP `get_standalone_rounds(standalone_task_id)`.
70
74
 
71
75
  **2c:** Identify unapproved files from `task.files_changed` where `user_approved === false`
72
76
 
@@ -144,10 +148,12 @@ Based on the analysis + user input, create detailed requirements that:
144
148
 
145
149
  If the new round requirements change the task direction:
146
150
 
147
- 1. Update task context via MCP `update_task(task_id, context: { ... })` / `update_standalone_task(standalone_task_id, context: { ... })` per KIND:
151
+ 1. Update task context per KIND:
152
+ - **checkpoint KIND**: `codebyplan task update --id <task_id> --checkpoint-id <checkpoint_id> --context '<json>'` (CLI write-through: local state file + REST). Break-glass fallback: MCP `update_task(task_id, context: { ... })` when the CLI is unavailable.
153
+ - **standalone KIND**: MCP `update_standalone_task(standalone_task_id, context: { ... })`. (Standalone KIND still uses MCP until a later task.)
148
154
  - Add new decisions to `context.decisions[]`
149
155
  - Update `context.discoveries[]` if applicable
150
- 2. If checkpoint-level changes needed (checkpoint KIND only), update checkpoint context via MCP `update_checkpoint`
156
+ 2. If checkpoint-level changes needed (checkpoint KIND only): `codebyplan checkpoint update --id <checkpoint_id> --context '<json>'` (CLI write-through). Break-glass fallback: MCP `update_checkpoint`.
151
157
 
152
158
  ### Step 7: Auto-trigger Round Start
153
159
 
@@ -166,14 +172,18 @@ Trigger `/cbp-round-start` with the round requirements as arguments.
166
172
  If this command is triggered **directly** (not via `/cbp-todo`) and no context is available in the session:
167
173
 
168
174
  1. Read `.codebyplan/repo.json` for `repo_id`
169
- 2. Use Kind Detection to determine KIND, then use the appropriate MCP tool to load checkpoint + task
170
- 3. Use MCP `get_rounds(task_id)` / `get_standalone_rounds(standalone_task_id)` per KIND to load round history
175
+ 2. Use Kind Detection to determine KIND, then:
176
+ - **checkpoint KIND**: Read local `.codebyplan/state/` files for checkpoint + task (break-glass: MCP `get_current_task`).
177
+ - **standalone KIND**: MCP `get_current_standalone_task`.
178
+ 3. Load round history:
179
+ - **checkpoint KIND**: Read `.codebyplan/state/checkpoints/<id>/tasks/<id>/rounds/*.json` (break-glass: MCP `get_rounds(task_id)`).
180
+ - **standalone KIND**: MCP `get_standalone_rounds(standalone_task_id)`.
171
181
  4. Continue from Step 2 (deep analysis handles all context loading)
172
182
 
173
183
  ## Key Rules
174
184
 
175
185
  - **Deep analysis is MANDATORY** — always runs, even if arguments provided (for context)
176
- - **Analysis reads from DB (MCP)**, not conversation history
186
+ - **Analysis reads from local state first**, falling back to MCP only when state files are absent and sync fails
177
187
  - **Follow-up rounds get same depth as round 1** — no quick-fix behavior
178
188
  - **Never ask to git add** — user file approval (git staging) is reconciled by `/cbp-round-complete`
179
189
  - **Update all context locations** — task, checkpoint, and round should all have consistent information
@@ -181,6 +191,8 @@ If this command is triggered **directly** (not via `/cbp-todo`) and no context i
181
191
  ## Integration
182
192
 
183
193
  - **Triggered by**: `/cbp-round-update` (auto, not-clean triage), `/cbp-round-complete` (auto, files left unapproved after completing the round), `/cbp-round-execute` (auto, on hard-fail after retry exhausted), `/cbp-todo` (after /clear), user manually
184
- - **Reads**: MCP `get_current_task` / `get_current_standalone_task`, `get_rounds` / `get_standalone_rounds` (per KIND), file contents (Read tool)
185
- - **Writes**: MCP `update_task` / `update_standalone_task` (context), `update_checkpoint` (context, if checkpoint KIND and needed)
194
+ - **Reads (checkpoint KIND)**: `.codebyplan/state/checkpoints/<id>.json`, `checkpoints/<id>/tasks/<id>.json`, `checkpoints/<id>/tasks/<id>/rounds/*.json` (local-first; break-glass: MCP `get_current_task` / `get_rounds`), file contents (Read tool)
195
+ - **Reads (standalone KIND)**: MCP `get_current_standalone_task` / `get_standalone_rounds` (standalone KIND still uses MCP until a later task)
196
+ - **Writes (checkpoint KIND)**: `codebyplan task update` (context), `codebyplan checkpoint update` (context, if needed). Break-glass: MCP `update_task` / `update_checkpoint`.
197
+ - **Writes (standalone KIND)**: MCP `update_standalone_task` / (checkpoint via MCP `update_checkpoint` if needed). (Standalone KIND still uses MCP until a later task.)
186
198
  - **Triggers**: `/cbp-round-start` (auto)
@@ -17,16 +17,18 @@ Inspect the resolved identifier from argument parsing to determine the task kind
17
17
  | `{chk}-{task}-{round}` (3-segment, e.g. `141-3-1`) | `checkpoint` |
18
18
  | _(empty / free-text)_ | Check `get_current_standalone_task` first; if found → `standalone`. Else → `checkpoint` via `get_current_task`. |
19
19
 
20
- Set `KIND` for the rest of this skill. MCP tool names vary by KIND:
20
+ Set `KIND` for the rest of this skill. Read/write sources vary by KIND:
21
21
 
22
22
  | Operation | `checkpoint` KIND | `standalone` KIND |
23
23
  |-----------|------------------|-------------------|
24
- | Get task | `get_current_task(repo_id)` | `get_current_standalone_task(repo_id)` |
25
- | Get rounds | `get_rounds(task_id)` | `get_standalone_rounds(standalone_task_id)` |
26
- | Add round | `add_round(task_id, ...)` | `add_standalone_round(standalone_task_id, ...)` |
27
- | Update round | `update_round(round_id, ...)` | `update_standalone_round(standalone_round_id, ...)` |
24
+ | Get task | local state (break-glass: `get_current_task`) | `get_current_standalone_task(repo_id)` |
25
+ | Get rounds | local state (break-glass: `get_rounds`) | `get_standalone_rounds(standalone_task_id)` |
26
+ | Add round | `codebyplan round add` (break-glass: `add_round`) | `add_standalone_round(standalone_task_id, ...)` |
27
+ | Update round | `codebyplan round update` (break-glass: `update_round`) | `update_standalone_round(standalone_round_id, ...)` |
28
28
  | Complete round | `complete_round(round_id, duration_minutes?)` | `complete_standalone_round(standalone_round_id, duration_minutes?, caller_worktree_id)` ⚠️ `caller_worktree_id` is REQUIRED for standalone |
29
- | Update task | `update_task(task_id, ...)` | `update_standalone_task(standalone_task_id, ...)` |
29
+ | Update task | `codebyplan task update` (break-glass: `update_task`) | `update_standalone_task(standalone_task_id, ...)` |
30
+
31
+ > **Note**: The `standalone` KIND column uses MCP tools unchanged — standalone local-first migration is out of scope for this task and will be addressed in a later task.
30
32
 
31
33
  # Round Start Command
32
34
 
@@ -94,17 +96,23 @@ round-start: invalid argument `{value}`. Expected:
94
96
 
95
97
  ### Step 1: Get Current Task
96
98
 
97
- If Step 0 produced an identifier (`target_task` set): resolve directly per the identifier (bound or standalone) — use KIND-appropriate MCP tools per the Kind Detection table above.
99
+ If Step 0 produced an identifier (`target_task` set): resolve directly per the identifier (bound or standalone) — use KIND-appropriate sources per the Kind Detection table above.
98
100
 
99
- Otherwise: use Kind Detection to determine KIND, then use MCP `get_current_task` (checkpoint KIND) or `get_current_standalone_task` (standalone KIND) with repo_id to find the active task.
101
+ Otherwise: use Kind Detection to determine KIND, then:
102
+ - **checkpoint KIND**: read `.codebyplan/state/checkpoints/<checkpointId>/tasks/<taskId>.json` (local-first). If missing/stale, run `npx codebyplan sync` once and re-read. Break-glass fallback: MCP `get_current_task` when the state dir is absent and sync fails (daemon-dead + CLI-unavailable).
103
+ - **standalone KIND**: MCP `get_current_standalone_task(repo_id)` — standalone tools are NOT migrated this task; standalone KIND still uses MCP until a later task.
100
104
 
101
105
  If no in-progress task and Step 0 produced no identifier, show error: `No active task. Run /cbp-task-start first.`
102
106
 
103
107
  ### Step 2: Determine Round Number
104
108
 
105
- If Step 0 produced `target_round`: use that as the round number directly (may target an existing round for resume, or N+1 for a new round — disambiguate by checking MCP `get_rounds` / `get_standalone_rounds` per KIND).
109
+ If Step 0 produced `target_round`: use that as the round number directly (may target an existing round for resume, or N+1 for a new round — disambiguate by reading local round files or MCP per KIND below).
110
+
111
+ Otherwise:
112
+ - **checkpoint KIND**: list `.codebyplan/state/checkpoints/<checkpointId>/tasks/<taskId>/rounds/` (local-first). If missing/stale, run `npx codebyplan sync` once and re-read. Break-glass fallback: MCP `get_rounds` when the state dir is absent and sync fails.
113
+ - **standalone KIND**: MCP `get_standalone_rounds(standalone_task_id)` — standalone still uses MCP.
106
114
 
107
- Otherwise: use MCP `get_rounds` (checkpoint KIND) or `get_standalone_rounds` (standalone KIND) for the task; count existing rounds; next is N+1.
115
+ Count existing rounds; next is N+1.
108
116
 
109
117
  ### Step 3: Gather Round Requirements
110
118
 
@@ -122,7 +130,11 @@ Otherwise: use MCP `get_rounds` (checkpoint KIND) or `get_standalone_rounds` (st
122
130
 
123
131
  ### Step 4: Create Round in DB
124
132
 
125
- Use MCP `add_round` (checkpoint KIND) or `add_standalone_round` (standalone KIND):
133
+ **checkpoint KIND**: `codebyplan round add --task-id <uuid> --checkpoint-id <uuid> --number <N> --status in_progress --started-at <ISO> --triggered-by <user|claude|auto_loop> [--requirements <text>] [--context <json>]` (CLI write-through: writes local state at `.codebyplan/state/checkpoints/<checkpointId>/tasks/<taskId>/rounds/<roundId>.json` + REST). Break-glass fallback: MCP `add_round` when the CLI is unavailable.
134
+
135
+ **standalone KIND**: MCP `add_standalone_round(standalone_task_id, ...)` — standalone still uses MCP.
136
+
137
+ Fields to supply:
126
138
  - `task_id` (checkpoint) / `standalone_task_id` (standalone): current task ID
127
139
  - `number`: next round number
128
140
  - `status`: "in_progress"
@@ -138,7 +150,9 @@ Load from checkpoint and task:
138
150
  - Task context and requirements
139
151
  - Resources from checkpoint and task (documentation links, API docs, guides)
140
152
  - Previous round results (files_changed, QA results)
141
- - For round 2+: load the latest completed round's `context.testing_qa_output` and `context.executor_output` via `get_rounds` / `get_standalone_rounds` per KIND
153
+ - For round 2+: load the latest completed round's `context.testing_qa_output` and `context.executor_output`:
154
+ - **checkpoint KIND**: read `.codebyplan/state/checkpoints/<checkpointId>/tasks/<taskId>/rounds/<roundId>.json` (local-first). If missing/stale, run `npx codebyplan sync` once and re-read. Break-glass fallback: MCP `get_rounds` when the state dir is absent and sync fails.
155
+ - **standalone KIND**: MCP `get_standalone_rounds(standalone_task_id)` — standalone still uses MCP.
142
156
  - Identify unapproved files from task.files_changed (where user_approved === false)
143
157
 
144
158
  ### Step 6: First Round Analysis (Round 1 only)
@@ -149,7 +163,8 @@ For the first round only:
149
163
  2. Identify any ambiguities or gaps
150
164
  3. If questions are needed, ask user via AskUserQuestion (max 4 per batch)
151
165
  4. If task context changes from Q&A answers:
152
- - Update task context via MCP `update_task(task_id, context: {...})` / `update_standalone_task(standalone_task_id, context: {...})` per KIND
166
+ - **checkpoint KIND**: `codebyplan task update --id <task-id> --checkpoint-id <uuid> --context <json>` (CLI write-through: local state at `.codebyplan/state/checkpoints/<checkpointId>/tasks/<taskId>.json` + REST). Break-glass fallback: MCP `update_task` when the CLI is unavailable.
167
+ - **standalone KIND**: MCP `update_standalone_task(standalone_task_id, context: {...})` — standalone still uses MCP.
153
168
  - Save Q&A decisions as `context.decisions[]`
154
169
 
155
170
  Skip this step for round 2+ (context already established via `/cbp-round-input`).
@@ -219,7 +234,10 @@ Single-wave plans present the existing flat plan view (no wave table) — backwa
219
234
 
220
235
  ### Step 9: Auto-trigger Round Execute
221
236
 
222
- Save planner output to round context via MCP `update_round` / `update_standalone_round` per KIND, then trigger `/cbp-round-execute`. The `ask`-tier permission prompt on `/cbp-round-execute` is the user's plan approval (see Step 8).
237
+ Save planner output to round context, then trigger `/cbp-round-execute`. The `ask`-tier permission prompt on `/cbp-round-execute` is the user's plan approval (see Step 8).
238
+
239
+ - **checkpoint KIND**: `codebyplan round update --id <round-id> --task-id <uuid> --checkpoint-id <uuid> --context <json>` (CLI write-through: local state at `.codebyplan/state/checkpoints/<checkpointId>/tasks/<taskId>/rounds/<roundId>.json` + REST). Break-glass fallback: MCP `update_round` when the CLI is unavailable.
240
+ - **standalone KIND**: MCP `update_standalone_round(standalone_round_id, ...)` — standalone still uses MCP.
223
241
 
224
242
  ```
225
243
  Starting execution phase...
@@ -235,8 +253,10 @@ Starting execution phase...
235
253
 
236
254
  ## Integration
237
255
 
238
- - **Reads**: MCP `get_current_task` / `get_current_standalone_task`, `get_rounds` / `get_standalone_rounds` (per KIND)
239
- - **Writes**: MCP `add_round` / `add_standalone_round`, `update_round` / `update_standalone_round`, `update_task` / `update_standalone_task` (context only) — per KIND
256
+ - **Reads (checkpoint KIND)**: `.codebyplan/state/checkpoints/<id>.json`, `checkpoints/<id>/tasks/<id>.json`, `checkpoints/<id>/tasks/<id>/rounds/<id>.json` (local-first; `npx codebyplan sync` on miss; MCP `get_current_task` / `get_rounds` as break-glass)
257
+ - **Reads (standalone KIND)**: MCP `get_current_standalone_task`, `get_standalone_rounds` standalone still uses MCP
258
+ - **Writes (checkpoint KIND)**: `codebyplan round add` (Step 4), `codebyplan round update` (Step 9), `codebyplan task update` (Step 6 context only) — break-glass: MCP `add_round` / `update_round` / `update_task`
259
+ - **Writes (standalone KIND)**: MCP `add_standalone_round`, `update_standalone_round`, `update_standalone_task` — standalone still uses MCP
240
260
  - **Spawns**: `cbp-task-planner`
241
261
  - **Triggers**: `/cbp-round-execute` (auto, on plan approval)
242
262
  - **Triggered by**: `/cbp-task-start` (round 1), `/cbp-round-input` (round 2+)
@@ -17,13 +17,15 @@ Inspect the resolved identifier from argument parsing to determine the task kind
17
17
  | `{chk}-{task}-{round}` (3-segment, e.g. `141-3-1`) | `checkpoint` |
18
18
  | _(empty / free-text)_ | Check `get_current_standalone_task` first; if found → `standalone`. Else → `checkpoint` via `get_current_task`. |
19
19
 
20
- Set `KIND` for the rest of this skill. round-update is **read + triage only** — it reads round state and routes; it never completes the round or writes file approvals. MCP read/audit tool names vary by KIND:
20
+ Set `KIND` for the rest of this skill. round-update is **read + triage only** — it reads round state and routes; it never completes the round or writes file approvals. Read/write sources vary by KIND:
21
21
 
22
22
  | Operation | `checkpoint` KIND | `standalone` KIND |
23
23
  |-----------|------------------|-------------------|
24
- | Get task | `get_current_task(repo_id)` | `get_current_standalone_task(repo_id)` |
25
- | Get rounds | `get_rounds(task_id)` | `get_standalone_rounds(standalone_task_id)` |
26
- | Update round (audit only) | `update_round(round_id, ...)` | `update_standalone_round(standalone_round_id, ...)` |
24
+ | Get task | local state (break-glass: `get_current_task`) | `get_current_standalone_task(repo_id)` |
25
+ | Get rounds | local state (break-glass: `get_rounds`) | `get_standalone_rounds(standalone_task_id)` |
26
+ | Update round (audit only) | `codebyplan round update` (break-glass: `update_round`) | `update_standalone_round(standalone_round_id, ...)` |
27
+
28
+ > **Note**: The `standalone` KIND column uses MCP tools unchanged — standalone local-first migration is out of scope for this task and will be addressed in a later task.
27
29
 
28
30
  The completion + file-approval reconcile (`sync-approvals`, `complete_round` / `complete_standalone_round`) now lives in `/cbp-round-complete`.
29
31
 
@@ -72,9 +74,9 @@ Given the parse from Step 1:
72
74
 
73
75
  | Parse | Resolution path |
74
76
  |-------|-----------------|
75
- | `{chk}-{task}-{round}` | MCP `get_checkpoints(repo_id)` filter `number === {chk}`. MCP `get_tasks(checkpoint_id)` filter `number === {task}`. MCP `get_rounds(task_id)` filter `number === {round}`. |
76
- | `{task}-{round}` | MCP `get_standalone_rounds` via `get_current_standalone_task` or direct task lookup → filter `number === {round}`. |
77
- | _(empty)_ | Use Kind Detection: checkpoint KIND → MCP `get_current_task(repo_id)` + `get_rounds(task_id)`; standalone KIND → MCP `get_current_standalone_task(repo_id)` + `get_standalone_rounds(standalone_task_id)`. |
77
+ | `{chk}-{task}-{round}` | Read `.codebyplan/state/checkpoints/` to find the checkpoint where `number === {chk}` (local-first; `npx codebyplan sync` on miss; break-glass: MCP `get_checkpoints(repo_id)`). Read `checkpoints/<id>/tasks/<taskId>.json` to find task where `number === {task}` (break-glass: MCP `get_tasks`). Read `checkpoints/<id>/tasks/<id>/rounds/<roundId>.json` to find round where `number === {round}` (break-glass: MCP `get_rounds`). |
78
+ | `{task}-{round}` | MCP `get_standalone_rounds` via `get_current_standalone_task` or direct task lookup → filter `number === {round}`. Standalone still uses MCP. |
79
+ | _(empty)_ | checkpoint KIND → read `.codebyplan/state/checkpoints/<id>/tasks/<id>.json` (local-first; sync on miss; break-glass: MCP `get_current_task` + `get_rounds`); standalone KIND → MCP `get_current_standalone_task(repo_id)` + `get_standalone_rounds(standalone_task_id)` — standalone still uses MCP. |
78
80
 
79
81
  If no task found: `No active task. Nothing to update.`
80
82
 
@@ -97,7 +99,7 @@ Display a one-line triage summary, e.g. `"ROUND-N triage: clean"` or `"ROUND-N t
97
99
 
98
100
  - **Auto-loop** (`round.context.auto_loop_mode === true`): compute `next_index = (round.context.auto_loop_index ?? 0) + 1`.
99
101
  - If `next_index > (round.context.auto_loop_cap ?? 5)`: surface the cap-exhausted prompt via AskUserQuestion (a genuine multi-option user decision — keep it). Options: extend cap, stop loop / drop into round-input, close task as-is. Persist `round.context.auto_loop_cap_exhausted = { user_choice, decided_at }` and route per choice.
100
- - Otherwise: persist `round.context.auto_loop_decision = { spawned_next: true, next_index, decided_at }` on the current round via `update_round` / `update_standalone_round` (audit trail), then auto-trigger `/cbp-round-input` with NO prompt. Pass `auto_loop_mode: true`, `auto_loop_index: next_index`, `auto_loop_cap: (prior cap ?? 5)` forward — round-start Step 4 persists them on the new round.
102
+ - Otherwise: persist `round.context.auto_loop_decision = { spawned_next: true, next_index, decided_at }` on the current round (audit trail) — **checkpoint KIND**: `codebyplan round update --id <round-id> --task-id <uuid> --checkpoint-id <uuid> --context <json>` (break-glass: MCP `update_round`); **standalone KIND**: MCP `update_standalone_round(standalone_round_id, ...)` standalone still uses MCP. Then auto-trigger `/cbp-round-input` with NO prompt. Pass `auto_loop_mode: true`, `auto_loop_index: next_index`, `auto_loop_cap: (prior cap ?? 5)` forward — round-start Step 4 persists them on the new round.
101
103
  - **Manual round**: auto-trigger `/cbp-round-input` directly (no prompt).
102
104
 
103
105
  ## Key Rules
@@ -111,6 +113,8 @@ Display a one-line triage summary, e.g. `"ROUND-N triage: clean"` or `"ROUND-N t
111
113
  ## Integration
112
114
 
113
115
  - **Triggered by**: `/cbp-round-end` (auto), or user manually
114
- - **Reads**: MCP `get_current_task` / `get_current_standalone_task`, `get_rounds` / `get_standalone_rounds` (per KIND); round context (`testing_qa_output`, `improve_round_findings`, `round_type`, `files_changed[].claude_approved`)
115
- - **Writes**: MCP `update_round` / `update_standalone_round` — audit only (`auto_loop_decision` / `auto_loop_cap_exhausted`). No completion, no file-approval writes.
116
+ - **Reads (checkpoint KIND)**: `.codebyplan/state/checkpoints/<id>.json`, `checkpoints/<id>/tasks/<id>.json`, `checkpoints/<id>/tasks/<id>/rounds/<id>.json` (local-first; `npx codebyplan sync` on miss; MCP `get_current_task` / `get_checkpoints` / `get_tasks` / `get_rounds` as break-glass)
117
+ - **Reads (standalone KIND)**: MCP `get_current_standalone_task`, `get_standalone_rounds` — standalone still uses MCP
118
+ - **Writes (checkpoint KIND)**: `codebyplan round update` — audit only (`auto_loop_decision` / `auto_loop_cap_exhausted`; break-glass: MCP `update_round`). No completion, no file-approval writes.
119
+ - **Writes (standalone KIND)**: MCP `update_standalone_round` — audit only — standalone still uses MCP
116
120
  - **Triggers**: `/cbp-round-complete` (clean triage — `ask`-tier permission prompt is the user confirmation), `/cbp-round-input` (not-clean triage: outstanding findings, hard-fail, or unapproved Claude checks — fires independent of git staging; also the auto-loop dirty spawn), cap-exhausted prompt routes from Step 3b (any of the three options)
@@ -17,17 +17,17 @@ Always write a session log for this session — **even if empty**. `/cbp-session
17
17
 
18
18
  1. Resolve the current session log:
19
19
  - Preferred: use the log ID held in context from `/cbp-session-start`.
20
- - Fallback: MCP `get_session_logs` (limit 1, most recent open log for this `repo_id`).
21
- - If still none found (e.g. session-start was skipped), create one now with MCP `create_session_log`.
22
- 2. Pull facts from the DB rather than narrating from memory:
23
- - Rounds added/completed, tasks advanced/completed during this session
20
+ - Fallback: read `.codebyplan/state/session/current.json` (local-first). If missing/stale, run `npx codebyplan sync` once and re-read. Break-glass fallback: MCP `get_session_logs` (limit 1, most recent open log for this `repo_id`) when the state dir is absent and sync fails.
21
+ - If still none found (e.g. session-start was skipped), create one now with `codebyplan session create-log` (break-glass: MCP `create_session_log`).
22
+ 2. Pull facts from local state files rather than narrating from memory:
23
+ - Rounds added/completed, tasks advanced/completed during this session (read from `.codebyplan/state/checkpoints/` subtree)
24
24
  - Decisions, blockers, or discoveries recorded in checkpoint/task context
25
25
 
26
26
  ### Step 1.3: Capture Handoff Snapshot
27
27
 
28
28
  Snapshot the current next-action so the next `/cbp-session-start` (Step 4.5) can auto-resume. The handoff write-path + payload shape are specified inline here and in `/cbp-session-start` Step 4.5 (freshness gate).
29
29
 
30
- 1. Call MCP `get_todos({ repo_id, worktree_id })` and take the queue head `rows[0]` (rows are ordered by `sort_order`; `rows[0]` is the current next-action). The worker stamps `command`, `instructions`, `state`, and the entity ids `checkpoint_id` / `task_id` / `round_id` on every row.
30
+ 1. Read `.codebyplan/state/todos.json` (local-first) and take the queue head `rows[0]` (rows are ordered by `sort_order`; `rows[0]` is the current next-action). If missing/stale, run `npx codebyplan sync` once and re-read. Break-glass fallback: MCP `get_todos({ repo_id, worktree_id })` when the state dir is absent and sync fails. The worker stamps `command`, `instructions`, `state`, and the entity ids `checkpoint_id` / `task_id` / `round_id` on every row.
31
31
  2. If `rows[0]` exists and its `command` is non-empty (active work in flight):
32
32
  ```yaml
33
33
  handoff:
@@ -46,7 +46,7 @@ Snapshot the current next-action so the next `/cbp-session-start` (Step 4.5) can
46
46
 
47
47
  Continuing Step 1:
48
48
 
49
- 3. Use MCP `update_session_log` to finalize:
49
+ 3. Run `codebyplan session update-log --id <log-id> --ended-at <now> --summary <text> --pending <text> --handoff <json>` (CLI write-through: updates `.codebyplan/state/session/current.json` + REST). Break-glass fallback: MCP `update_session_log` when the CLI is unavailable. Fields:
50
50
  - `ended_at`: now (maps to the `closed_at` column per TASK-2 alias)
51
51
  - `handoff`: from Step 1.3 (jsonb or `null`; MCP write surface aliases to the `content` column transparently per CHK-111 Migration A — `handoff` wins over `content` when both are passed)
52
52
  - `summary`: concise — may be empty if nothing happened
@@ -58,12 +58,12 @@ Same rule as `/cbp-session-start` Step 5.7 — only commit files that are **not*
58
58
 
59
59
  1. `git status --porcelain` — list all modified/untracked files. If empty → skip this step.
60
60
  2. Resolve **task-related files** (leave these uncommitted):
61
- - MCP `get_current_task(repo_id)` active task
62
- - If active task exists: MCP `get_rounds(task_id)`, filter to rounds with status not in `completed` / `cancelled`
61
+ - Read `.codebyplan/state/todos.json` (local-first; reuse result from Step 1.3 if already fetched) to identify the active task id. Break-glass fallback: MCP `get_current_task(repo_id)` when the state dir is absent and sync fails.
62
+ - If active task exists: read `.codebyplan/state/checkpoints/<checkpoint_id>/tasks/<task_id>/rounds/` directory and filter to rounds with status not in `completed` / `cancelled`. Break-glass fallback: MCP `get_rounds(task_id)`.
63
63
  - Collect `files[]` from those rounds → `task_files` set
64
64
  - If no active task exists, `task_files` is empty
65
65
  3. `infra_files = changed_files − task_files`
66
- 4. Re-run `git status --porcelain` immediately before showing the commit-prompt (after Steps 1–1.3 have completed their MCP round-trips). Recompute `infra_files` from the fresh listing — eliminates the race where files appear in the index only after the network round-trips complete.
66
+ 4. Re-run `git status --porcelain` immediately before showing the commit-prompt (after Steps 1–1.3 have completed their round-trips). Recompute `infra_files` from the fresh listing — eliminates the race where files appear in the index only after network round-trips complete.
67
67
  5. If `infra_files` is empty → skip. Otherwise present once:
68
68
 
69
69
  ```
@@ -145,9 +145,19 @@ Non-blocking — session end proceeds regardless of outcome.
145
145
 
146
146
  Non-blocking — if kill fails, warn and continue. Silent when no process found.
147
147
 
148
+ ### Step 2.5: Stop Watch Daemon
149
+
150
+ Stop this worktree's Realtime watch daemon, non-blocking and non-fatal:
151
+
152
+ ```bash
153
+ npx codebyplan watch stop 2>/dev/null || true
154
+ ```
155
+
156
+ This SIGTERMs the per-worktree pidfile daemon started by `cbp-session-start-hook.sh`. Silently ignored when no daemon is running for this worktree. If there is no daemon to stop (e.g. session-start was skipped), `watch stop` itself exits 0 — the `|| true` guard is defense-in-depth only, so Step 3's session-state write never sees a failure from this step.
157
+
148
158
  ### Step 3: Update Session State
149
159
 
150
- Use MCP `update_session_state` with action `deactivate`.
160
+ Run `codebyplan session update-state --action deactivate` (CLI write-through: writes `.codebyplan/state/session/state.json` + REST). Break-glass fallback: MCP `update_session_state` with action `deactivate` when the CLI is unavailable. Note: the CLI validates `--action` — only `activate`/`deactivate` are accepted; a missing, valueless, or invalid value exits 1 with a usage message.
151
161
 
152
162
  ### Step 4: Output
153
163
 
@@ -160,8 +170,8 @@ You can close this window.
160
170
  ## Integration
161
171
 
162
172
  - **Triggered by**: user invocation (prompted by `/cbp-todo` when no work remains)
163
- - **Reads**: `.codebyplan/repo.json`, `.codebyplan/git.json` (`branch_config.production` for the Step 1.6 home-branch fast-forward), MCP `get_session_logs` (resolve current log), MCP `get_current_task`, MCP `get_rounds`, MCP `get_todos` (Step 1.3 handoff snapshot queue head `rows[0]`); `npx codebyplan version-status` (Step 1.7 package-freshness gate)
164
- - **Writes**: MCP `update_session_log` (with `ended_at` + `handoff` per TASK-2 alias surface; or `create_session_log` fallback), MCP `update_session_state` (deactivate)
173
+ - **Reads**: `.codebyplan/repo.json`, `.codebyplan/git.json` (`branch_config.production` for the Step 1.6 home-branch fast-forward); local-first reads (with `npx codebyplan sync` + MCP break-glass): `.codebyplan/state/session/current.json` (Step 1 resolve log), `.codebyplan/state/todos.json` (Step 1.3 handoff snapshot + Step 1.5 active-task lookup), `.codebyplan/state/checkpoints/<id>/tasks/<id>/rounds/` (Step 1.5 task-file resolution); `npx codebyplan version-status` (Step 1.7 package-freshness gate)
174
+ - **Writes**: `codebyplan session update-log --id <id> ...` (Step 1 finalize — CLI write-through to `.codebyplan/state/session/current.json`; break-glass: MCP `update_session_log`), `codebyplan session create-log` (Step 1 fallback when no log exists; break-glass: MCP `create_session_log`), `codebyplan session update-state --action deactivate` (Step 3 — CLI write-through to `.codebyplan/state/session/state.json`; break-glass: MCP `update_session_state`)
165
175
  - **Spawns**: none
166
176
  - **Triggers**: none at the skill-contract level. Step 1.5 may invoke `/cbp-git-commit` inline on user approval; Step 1.7 may invoke `/cbp-git-commit` on the `newer:true AND guarded:false` update path (committing changed `.claude/` and `.codebyplan/` paths).
167
177
  - **Paired with**: `/cbp-session-start`
@@ -142,18 +142,22 @@ LSP_NUDGE=$(npx codebyplan lsp --check 2>/dev/null || true)
142
142
 
143
143
  ### Step 3: Update Session State
144
144
 
145
- Use MCP `update_session_state` with action `activate`. This deactivates all other repos automatically.
145
+ Run `codebyplan session update-state --action activate` (CLI write-through: writes `.codebyplan/state/session/state.json` + REST). This deactivates all other repos automatically. Break-glass fallback: MCP `update_session_state` with action `activate` when the CLI is unavailable. Note: the CLI validates `--action` — only `activate`/`deactivate` are accepted; a missing, valueless, or invalid value exits 1 with a usage message.
146
+
147
+ Note: Step 0 `health_check` stays MCP unconditionally — it tests MCP connectivity itself and must not be replaced.
146
148
 
147
149
  ### Step 4: Read Last Session Log
148
150
 
149
- Call MCP `get_session_logs({ repo_id, worktree_id, limit: 1 })` same inclusive-worktree call shape used by Step 4.5 below so the previous-session display and the handoff probe agree on which row is "most recent for this worktree". Take the first (and only) row.
151
+ Read `.codebyplan/state/session/current.json` (local-first). If missing/stale, run `npx codebyplan sync` once and re-read. Break-glass fallback: MCP `get_session_logs({ repo_id, worktree_id, limit: 1 })` when the state dir is absent and sync fails (daemon-dead + CLI-unavailable).
152
+
153
+ Take the first row — same inclusive-worktree scope as Step 4.5 so the previous-session display and the handoff probe agree on which row is "most recent for this worktree".
150
154
 
151
155
  - If a previous log exists, hold its title/summary/pending items for the Step 6 output so the user sees where they left off.
152
156
  - If none exists (first session ever for this worktree), skip silently.
153
157
 
154
158
  ### Step 5: Create This Session's Log
155
159
 
156
- Use MCP `create_session_log` to open a new session log for the current session. Create it **even if empty** — this establishes the record for session-end to finalize.
160
+ Run `codebyplan session create-log --started-at <now> --repo-id <repo_id> --worktree-id <WORKTREE_ID>` (CLI write-through: writes `.codebyplan/state/session/current.json` + REST). Create it **even if empty** — this establishes the record for session-end to finalize. Break-glass fallback: MCP `create_session_log` when the CLI is unavailable.
157
161
 
158
162
  Minimal seed content:
159
163
 
@@ -167,7 +171,7 @@ Hold the new log's ID in context so `/cbp-session-end` can update the same recor
167
171
 
168
172
  Probe the most-recent closed session log for a structured handoff payload (the handoff freshness-gate contract is specified inline in this step) and auto-resume directly into the captured command when fresh. Additive — placed BEFORE the existing `/cbp-todo` auto-trigger; ALL failure paths fall through silently to Step 7.
169
173
 
170
- 1. Reuse the row held from Step 4 (same `get_session_logs({ repo_id, worktree_id, limit: 1 })` call shape no extra MCP round-trip).
174
+ 1. Reuse the row held from Step 4 (held from Step 4 in memory — do NOT re-read from disk here; at this point `session/current.json` still holds the previous session row, which Step 5 will overwrite).
171
175
  2. **Defensive gates** (any failure → silent fall-through to Step 7):
172
176
  - No row returned → fall through.
173
177
  - Row missing `closed_at` (orphan / still-open session) → fall through.
@@ -175,12 +179,12 @@ Probe the most-recent closed session log for a structured handoff payload (the h
175
179
  - `row.content` exists but parse throws or shape mismatch (`command` field absent OR is an empty string) → fall through.
176
180
  3. **Freshness gate** — load the row as `handoff = row.content` (per CHK-111 Migration A column alias). Mark stale when ANY of:
177
181
  - `(now - row.closed_at) > freshness_window_hours` (read from `.codebyplan/repo.json`, default 24 hours)
178
- - Referenced entity in `handoff.context` has shifted. For each id present, run the matching MCP read and find the row whose `id` matches:
179
- - `checkpoint_id` → `get_checkpoints({ repo_id })` find entry where `entry.id === handoff.context.checkpoint_id`
180
- - `task_id` → `get_tasks({ checkpoint_id })` if `handoff.context.checkpoint_id` is present, else `get_tasks({ repo_id, standalone: true })` → find entry where `entry.id === handoff.context.task_id`
181
- - `round_id` → `get_rounds({ task_id: handoff.context.task_id })` find entry where `entry.id === handoff.context.round_id`
182
+ - Referenced entity in `handoff.context` has shifted. For each id present, read the matching local state file and check `updated_at`:
183
+ - `checkpoint_id` → read `.codebyplan/state/checkpoints/<checkpoint_id>.json` (local-first; sync + MCP break-glass if missing)
184
+ - `task_id` → read `.codebyplan/state/checkpoints/<checkpoint_id>/tasks/<task_id>.json` (local-first; sync + MCP break-glass if missing)
185
+ - `round_id` → read `.codebyplan/state/checkpoints/<checkpoint_id>/tasks/<task_id>/rounds/<round_id>.json` (local-first; sync + MCP break-glass if missing)
182
186
  Then compare `entry.updated_at > handoff.captured_at` → stale on any inequality.
183
- - Entity lookup fails OR the matching `id` is not present in the returned array → stale (referenced entity gone or moved out of reach).
187
+ - Local file missing after sync attempt → stale (referenced entity gone or moved out of reach).
184
188
  - `handoff.context.checkpoint_id` resolves to a checkpoint whose `worktree_id` is non-null AND (caller `WORKTREE_ID` is `null` OR differs from `checkpoint.worktree_id`) → stale (a fresh handoff for another worktree's work — or for assigned work this caller cannot confirm ownership of — must not auto-resume here). Mirrors the cbp-todo Step 1.5 ownership rule.
185
189
  4. **On stale OR any defensive gate hit**: fall through silently to Step 7 (existing `/cbp-todo` trigger).
186
190
  5. **On fresh hit**: trigger `handoff.command` directly with `handoff.context` / `handoff.state` in the trigger arguments. The downstream skill self-loads its full context — do NOT duplicate `/cbp-todo` Step 2's context-loading matrix here. Skip Step 5.7, Step 6 output, and Step 7.
@@ -191,12 +195,12 @@ Clean the working tree of leftover infra before the session begins. Only commit
191
195
 
192
196
  1. `git status --porcelain` — list all modified/untracked files. If empty → skip this step.
193
197
  2. Resolve **task-related files** (leave these uncommitted):
194
- - MCP `get_current_task(repo_id)` active task
195
- - If active task exists: MCP `get_rounds(task_id)`, filter to rounds with status not in `completed` / `cancelled`
198
+ - Read `.codebyplan/state/todos.json` (local-first) to identify the active task id. If missing/stale, run `npx codebyplan sync` once and re-read. Break-glass fallback: MCP `get_current_task(repo_id)` when the state dir is absent and sync fails.
199
+ - If active task exists: read `.codebyplan/state/checkpoints/<checkpoint_id>/tasks/<task_id>/rounds/` directory and filter to rounds with status not in `completed` / `cancelled`. Break-glass fallback: MCP `get_rounds(task_id)`.
196
200
  - Collect `files[]` from those rounds → `task_files` set
197
201
  - If no active task exists, `task_files` is empty
198
202
  3. `infra_files = changed_files − task_files`
199
- 4. **Re-run `git status --porcelain` immediately before showing the commit-prompt** (after Steps 0–5 have completed all MCP round-trips). Eliminates the race where prior-session staged files appear in the index only after MCP init's network round-trips complete. Recompute `infra_files` from the fresh listing.
203
+ 4. **Re-run `git status --porcelain` immediately before showing the commit-prompt** (after Steps 0–5 have completed all their round-trips). Eliminates the race where prior-session staged files appear in the index only after network round-trips complete. Recompute `infra_files` from the fresh listing.
200
204
  5. If `infra_files` is empty → skip. Otherwise present once:
201
205
 
202
206
  ```
@@ -213,7 +217,7 @@ Non-blocking — session start proceeds either way.
213
217
 
214
218
  ### Step 5.8: Resolve Ownership
215
219
 
216
- Call MCP `get_checkpoints({ repo_id, status: 'active' })`. Partition results into:
220
+ Call MCP `get_checkpoints({ repo_id, status: 'active' })` (MCP only — deliberate: the active-filter query has no local-mirror equivalent). Partition results into:
217
221
 
218
222
  - `owned[]` — entries where `checkpoint.worktree_id === WORKTREE_ID`, OR both are `null`
219
223
  - `cross_worktree[]` — entries where `checkpoint.worktree_id` is non-null AND differs from `WORKTREE_ID` (includes the case where caller `WORKTREE_ID` is `null` but the target has a non-null `worktree_id`)
@@ -253,8 +257,8 @@ Three-branch gate using `owned_count` and `total_count` from Step 5.8:
253
257
 
254
258
  - **Triggered by**: user invocation, `/clear` recovery
255
259
  - **Resolves**: `npx codebyplan resolve-worktree --json` (worktree id + distress signal; non-tuple-miss distress is non-blocking at session-start)
256
- - **Reads**: `.codebyplan/repo.json`, `.codebyplan/git.json` (`branch_config.production` for the Step 1.4 home-branch fast-forward), MCP `get_session_logs` (worktree-filtered, limit 1single call shared by Step 4 and Step 4.5), MCP `health_check` (Step 0 hard gate), MCP `get_current_task`, MCP `get_rounds`, MCP `get_checkpoints` (two calls: `{ repo_id, status: 'active' }` for the Step 5.8 ownership partition; `{ repo_id }` unfiltered for the Step 4.5 freshness probe, which may resolve a non-active checkpoint), MCP `get_tasks` / `get_rounds` for the Step 4.5 freshness probe; `scripts/infra-drift.mjs` + a best-effort `git fetch` (Step 1.5 monorepo drift); `npx codebyplan version-status` (Step 1.6 package-freshness gate); `npx codebyplan lsp --check` (Step 1.7 LSP binary nudge — reads `.codebyplan/lsp.json`, non-blocking). Reads at Step 3 and later (session-state, session logs, checkpoints, tasks/rounds) do NOT fire on a Step 0 MCP hard-fail or the Step 1.6 update-and-halt path
257
- - **Writes**: MCP `create_session_log` (new, possibly empty), MCP `update_session_state` (activate) — both SKIPPED on a Step 0 MCP hard-fail and on the Step 1.6 update-and-halt path
260
+ - **Reads**: `.codebyplan/repo.json`, `.codebyplan/git.json` (`branch_config.production` for the Step 1.4 home-branch fast-forward), MCP `health_check` (Step 0 hard gate stays MCP unconditionally); local-first reads (with `npx codebyplan sync` + MCP break-glass): `.codebyplan/state/session/current.json` (Step 4 previous log + Step 4.5 handoff probe), `.codebyplan/state/checkpoints/<id>.json` / `tasks/<id>.json` / `rounds/<id>.json` (Step 4.5 freshness probe), `.codebyplan/state/todos.json` (Step 5.7 active-task lookup); MCP `get_checkpoints({ repo_id, status: 'active' })` (Step 5.8 ownership partition MCP only, no local mirror for active-filter query); `scripts/infra-drift.mjs` + a best-effort `git fetch` (Step 1.5 monorepo drift); `npx codebyplan version-status` (Step 1.6 package-freshness gate); `npx codebyplan lsp --check` (Step 1.7 LSP binary nudge — reads `.codebyplan/lsp.json`, non-blocking). Reads at Step 3 and later do NOT fire on a Step 0 MCP hard-fail or the Step 1.6 update-and-halt path
261
+ - **Writes**: `codebyplan session create-log` (Step 5 — CLI write-through; break-glass: MCP `create_session_log`), `codebyplan session update-state --action activate` (Step 3 CLI write-through to `.codebyplan/state/session/state.json`; break-glass: MCP `update_session_state`) — both SKIPPED on a Step 0 MCP hard-fail and on the Step 1.6 update-and-halt path
258
262
  - **Spawns**: none
259
263
  - **Triggers**: `/cbp-git-commit` (conditional, on user approval at Step 5.7 or the Step 1.6 update path), `handoff.command` (on fresh handoff hit at Step 4.5), `/cbp-todo` (auto fall-through when owned_count >= 1 or total_count === 0; STOPS with no trigger when total_count >= 1 AND owned_count === 0; NOT triggered on a Step 0 hard-fail or the Step 1.6 update-and-halt path)
260
264
  - **Paired with**: `/cbp-session-end`
@@ -21,7 +21,7 @@ Step 1 of `/cbp-checkpoint-end` handles branch promotion to main via `/cbp-ship-
21
21
 
22
22
  | Source | What's read |
23
23
  | ----------------------------- | ----------------------------------------------------------------------------------------- |
24
- | MCP `get_current_task` | Active checkpoint (for context.shipment write-back) |
24
+ | Local state `.codebyplan/state/checkpoints/<id>.json`; on miss `npx codebyplan sync` once; MCP `get_current_task` break-glass | Active checkpoint (for context.shipment write-back) |
25
25
  | `.codebyplan/git.json` + `.codebyplan/shipment.json` | `branch_config`, `shipment` section if present (per `ship-configure`) |
26
26
  | Repo scan | Detect surfaces from filesystem (vercel.json, eas.json, package.json publishConfig, etc.) |
27
27
  | `checkpoint.context.shipment` | Last shipment record (timestamp, surfaces, results) |
@@ -197,7 +197,7 @@ Verification timeouts are conservative (Vercel: 5min, EAS: 30min, TestFlight pro
197
197
 
198
198
  ### Step 7 — Persist shipment record
199
199
 
200
- Write to `checkpoint.context.shipment` via MCP `update_checkpoint`:
200
+ Write to `checkpoint.context.shipment` via `codebyplan checkpoint update <id> --context '{"shipment": {...}}'` (CLI write-through); use MCP `update_checkpoint` as documented break-glass when the CLI is unavailable:
201
201
 
202
202
  ```json
203
203
  {
@@ -326,7 +326,7 @@ When present, this overrides scan results. `ship-configure` writes here.
326
326
  ## Integration
327
327
 
328
328
  - **Triggered by**: `/cbp-checkpoint-end` (auto, after branch promotion to main via `/cbp-ship-main`); user direct invocation for re-runs
329
- - **Reads**: MCP `get_current_task`, `.codebyplan/git.json` + `.codebyplan/shipment.json` (`branch_config` + `shipment`), filesystem scan
330
- - **Writes**: MCP `update_checkpoint` (context.shipment)
329
+ - **Reads**: Local state `.codebyplan/state/checkpoints/<id>.json`; on miss `npx codebyplan sync` once; MCP `get_current_task` as documented break-glass when the state dir is absent and sync fails. Also reads `.codebyplan/git.json` + `.codebyplan/shipment.json` (`branch_config` + `shipment`), filesystem scan.
330
+ - **Writes**: `codebyplan checkpoint update <id> --context '...'` (CLI write-through) for context.shipment; MCP `update_checkpoint` break-glass.
331
331
  - **Calls**: per-surface deploy via reference files (vercel CLI, eas CLI, supabase CLI, npm, vsce, railway CLI, gh release)
332
332
  - **Triggers**: returns control to caller — does NOT auto-trigger `/cbp-checkpoint-complete` (that's the caller's job)
@@ -35,8 +35,8 @@ This is **always interactive**. The orchestrator does NOT silently apply migrati
35
35
 
36
36
  1. **List pending migrations**:
37
37
  ```bash
38
- PROJECT_REF=$(jq -r '.surfaces.supabase.project_ref' .codebyplan/shipment.json)
39
- LAST_VERSION=$(jq -r '.surfaces.supabase.last_shipped_migration_version // ""' .codebyplan/shipment.json)
38
+ PROJECT_REF=$(jq -r '.shipment.surfaces.supabase.project_ref' .codebyplan/shipment.json)
39
+ LAST_VERSION=$(jq -r '.shipment.surfaces.supabase.last_shipped_migration_version // ""' .codebyplan/shipment.json)
40
40
 
41
41
  PENDING=$(ls supabase/migrations/*.sql | sort)
42
42
  if [ -n "$LAST_VERSION" ]; then
@@ -116,7 +116,7 @@ This is **always interactive**. The orchestrator does NOT silently apply migrati
116
116
  7. **Update the last-shipped marker**:
117
117
  ```bash
118
118
  LAST_APPLIED=$(echo "$PENDING" | tail -1 | xargs basename)
119
- jq --arg v "$LAST_APPLIED" '.surfaces.supabase.last_shipped_migration_version = $v' .codebyplan/shipment.json > .codebyplan/shipment.json.tmp
119
+ jq --arg v "$LAST_APPLIED" '.shipment.surfaces.supabase.last_shipped_migration_version = $v' .codebyplan/shipment.json > .codebyplan/shipment.json.tmp
120
120
  mv .codebyplan/shipment.json.tmp .codebyplan/shipment.json
121
121
  ```
122
122
 
@@ -126,7 +126,7 @@ The skill's job is to verify these credentials EXIST and are valid; never to sto
126
126
  Run the verification step from the surface reference. For Vercel, this is:
127
127
 
128
128
  ```bash
129
- vercel inspect "$(jq -r '.surfaces."vercel-web".project_id' .codebyplan/shipment.json)" 2>&1 | head -20
129
+ vercel inspect "$(jq -r '.shipment.surfaces."vercel-web".project_id' .codebyplan/shipment.json)" 2>&1 | head -20
130
130
  ```
131
131
 
132
132
  If verification passes, mark the surface as configured. If it fails, surface the error and offer to retry the failing step.
@@ -161,7 +161,7 @@ railway domain
161
161
  Verify:
162
162
 
163
163
  ```bash
164
- PROJECT_ID=$(jq -r '.surfaces."railway-backend".project_id' .codebyplan/shipment.json)
164
+ PROJECT_ID=$(jq -r '.shipment.surfaces."railway-backend".project_id' .codebyplan/shipment.json)
165
165
  railway status --json | jq
166
166
  # Expect: project + service info matching saved IDs
167
167
  ```
@@ -171,7 +171,7 @@ Test deploy:
171
171
  ```bash
172
172
  railway up --detach
173
173
  # Wait, then verify URL responds
174
- URL=$(jq -r '.surfaces."railway-backend".url' .codebyplan/shipment.json)
174
+ URL=$(jq -r '.shipment.surfaces."railway-backend".url' .codebyplan/shipment.json)
175
175
  curl -sI "$URL/health" | head -1
176
176
  ```
177
177
 
@@ -98,7 +98,7 @@ Write `.codebyplan/shipment.json`:
98
98
  Verify:
99
99
 
100
100
  ```bash
101
- PROJECT_ID=$(jq -r '.surfaces."vercel-web".project_id' .codebyplan/shipment.json)
101
+ PROJECT_ID=$(jq -r '.shipment.surfaces."vercel-web".project_id' .codebyplan/shipment.json)
102
102
  vercel inspect "$PROJECT_ID" --json | jq -r '.name, .latestDeployments[0].readyState'
103
103
  ```
104
104
 
@@ -13,7 +13,7 @@ Compose a PR body from checkpoint context, then delegate all git/gh mechanics to
13
13
 
14
14
  ### Step 1: Read Checkpoint Context
15
15
 
16
- Use MCP `get_current_task` (repo_id) to get the active checkpoint. Collect `checkpoint.title`, completed task titles (`get_tasks(checkpoint_id)` filtered to `status === 'completed'`), and key decisions from `checkpoint.context.decisions[]`.
16
+ Read local state `.codebyplan/state/checkpoints/<id>.json` to get the active checkpoint; on miss run `npx codebyplan sync` once and re-read. Use MCP `get_current_task` as documented break-glass when the state dir is absent and sync fails. Collect `checkpoint.title`, completed task titles (from `.codebyplan/state/checkpoints/<id>/tasks/*.json` filtered to `status === 'completed'`; MCP `get_tasks` break-glass), and key decisions from `checkpoint.context.decisions[]`.
17
17
 
18
18
  ### Step 2: Compose PR Body
19
19
 
@@ -98,4 +98,4 @@ If `branch_deleted === true`, run a conditional Supabase preview-branch teardown
98
98
 
99
99
  - **Called by**: `/cbp-checkpoint-end`
100
100
  - **Delegates to**: `codebyplan ship` CLI
101
- - **Reads**: MCP `get_current_task`, `get_tasks`
101
+ - **Reads**: Local state `.codebyplan/state/checkpoints/<id>.json` + `.../tasks/<id>.json`; on miss `npx codebyplan sync` once; MCP `get_current_task` / `get_tasks` as documented break-glass when the state dir is absent and sync fails.
@@ -169,12 +169,13 @@ Parse the JSON output and store: `pr_url`, `merge_commit`, `branch_deleted`, `fe
169
169
  When `branch_deleted === true` in the ship JSON:
170
170
 
171
171
  - Read `FEAT_BRANCH` from the `feat_branch` field in the ship JSON — NOT from `git branch --show-current`. By the time Step 7.3 runs, `codebyplan ship` has already checked out the base branch, so the live branch is the base, not the feat branch.
172
- - Call `mcp__supabase__list_branches` with `project_id: rrvtrumtkhrsbhcyrwvf`.
172
+ - Resolve the parent project ref: read `.codebyplan/shipment.json` `.shipment.surfaces.supabase.project_ref`; if absent or empty, read the first line of `supabase/.temp/project-ref`. Use that resolved ref as the `project_id`.
173
+ - Call `mcp__supabase__list_branches` with the resolved `project_id`.
173
174
  - Scan the returned list for an entry whose `name` exactly equals `FEAT_BRANCH`.
174
175
  - If found: call `mcp__supabase__delete_branch` with its `branch_id`. Report the outcome.
175
176
  - If not found: no-op silently — the GitHub integration may have already removed the preview branch on PR close; not-found is success, NOT an error.
176
177
  - If the `list_branches` call itself fails (network, auth, or non-success response): emit a non-blocking warning that the Supabase preview branch for `FEAT_BRANCH` may still exist and should be verified in the dashboard. Never treat an API failure as a not-found success.
177
- - Never delete the parent project `rrvtrumtkhrsbhcyrwvf` itself or any persistent/production branch.
178
+ - Never delete the branch where `is_default` is true in the `list_branches` response (the production/parent project branch) or any other persistent/long-lived branch.
178
179
 
179
180
  ### Step 7.5: Complete Standalone Task
180
181