codebyplan 1.13.44 → 1.13.45

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 (41) hide show
  1. package/dist/cli.js +5038 -1551
  2. package/package.json +1 -1
  3. package/templates/agents/cbp-task-check.md +1 -3
  4. package/templates/agents/cbp-task-planner.md +8 -6
  5. package/templates/hooks/cbp-auto-test-hooks.sh +1 -0
  6. package/templates/hooks/cbp-e2e-spec-patterns.sh +100 -0
  7. package/templates/hooks/cbp-lint-format-on-edit.sh +1 -0
  8. package/templates/hooks/cbp-maestro-yaml-validate.sh +1 -0
  9. package/templates/hooks/cbp-pre-commit-quality-gate.sh +1 -0
  10. package/templates/hooks/cbp-statusline.sh +0 -0
  11. package/templates/hooks/cbp-subagent-statusline.sh +0 -0
  12. package/templates/hooks/cbp-test-coverage-gate.sh +1 -0
  13. package/templates/hooks/cbp-test-hooks.sh +1 -0
  14. package/templates/hooks/hooks.json +4 -0
  15. package/templates/hooks/verify-parity.sh +20 -0
  16. package/templates/rules/parallel-waves.md +8 -3
  17. package/templates/rules/scope-vocabulary.md +4 -3
  18. package/templates/settings.project.base.json +22 -0
  19. package/templates/skills/cbp-build-cc-claude-file/SKILL.md +11 -1
  20. package/templates/skills/cbp-build-cc-claude-file/scripts/validate-claude-file.sh +72 -0
  21. package/templates/skills/cbp-build-cc-mode/SKILL.md +12 -16
  22. package/templates/skills/cbp-build-cc-rule/SKILL.md +11 -1
  23. package/templates/skills/cbp-build-cc-rule/scripts/validate-rule.sh +69 -0
  24. package/templates/skills/cbp-build-cc-settings/SKILL.md +2 -2
  25. package/templates/skills/cbp-build-cc-settings/scripts/validate-settings.sh +67 -0
  26. package/templates/skills/cbp-checkpoint-create/SKILL.md +12 -4
  27. package/templates/skills/cbp-checkpoint-end/SKILL.md +19 -11
  28. package/templates/skills/cbp-git-commit/SKILL.md +10 -12
  29. package/templates/skills/cbp-git-worktree-create/SKILL.md +7 -48
  30. package/templates/skills/cbp-git-worktree-remove/SKILL.md +23 -40
  31. package/templates/skills/cbp-map-architecture/SKILL.md +1 -0
  32. package/templates/skills/cbp-merge-main/SKILL.md +21 -26
  33. package/templates/skills/cbp-refresh-arch-map/SKILL.md +1 -0
  34. package/templates/skills/cbp-round-check/SKILL.md +37 -36
  35. package/templates/skills/cbp-round-execute/SKILL.md +9 -3
  36. package/templates/skills/cbp-session-end/SKILL.md +27 -47
  37. package/templates/skills/cbp-session-start/SKILL.md +35 -51
  38. package/templates/skills/cbp-standalone-task-start/SKILL.md +10 -19
  39. package/templates/skills/cbp-supabase-migrate/SKILL.md +24 -27
  40. package/templates/skills/cbp-task-start/SKILL.md +9 -21
  41. package/templates/skills/cbp-task-testing/SKILL.md +18 -10
@@ -56,15 +56,12 @@ Continuing Step 1:
56
56
 
57
57
  Same rule as `/cbp-session-start` Step 5.7 — only commit files that are **not** part of an unfinished task.
58
58
 
59
- 1. `git status --porcelain` list all modified/untracked files. If empty → skip this step.
60
- 2. Resolve **task-related files** (leave these uncommitted):
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
- - Collect `files[]` from those rounds `task_files` set
64
- - If no active task exists, `task_files` is empty
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 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
- 5. If `infra_files` is empty → skip. Otherwise present once:
59
+ 1. Resolve the active task's round files (local-first):
60
+ - Read `.codebyplan/state/todos.json` (local-first; reuse the Step 1.3 result 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.
61
+ - If active task exists: read `.codebyplan/state/checkpoints/<checkpoint_id>/tasks/<task_id>/rounds/` and filter to rounds with status not in `completed` / `cancelled`; collect their `files[]` → `task_files` set. Break-glass fallback: MCP `get_rounds(task_id)`.
62
+ - If no active task exists, `task_files` is empty.
63
+ 2. Run `codebyplan session infra-files --json --task-files "<csv>"` where `<csv>` is the comma-separated task files from step 1. Parse the JSON response (`{ infra_files: string[], task_files: string[], note?: string }`). The CLI re-runs `git status --porcelain` internally and applies the set-math deterministically — the race-safe recompute, reading the index after Steps 1–1.3 round-trips complete.
64
+ 3. If `infra_files` is empty skip. Otherwise present once:
68
65
 
69
66
  ```
70
67
  Commit these non-task files before ending session?
@@ -73,7 +70,7 @@ Same rule as `/cbp-session-start` Step 5.7 — only commit files that are **not*
73
70
  Reply: yes | no | select
74
71
  ```
75
72
 
76
- 6. On `yes`: `git add` the listed files, then trigger `/cbp-git-commit`.
73
+ 4. On `yes`: `git add` the listed files, then trigger `/cbp-git-commit`.
77
74
  On `no`: skip. On `select`: ask which subset.
78
75
 
79
76
  Non-blocking — session end proceeds either way.
@@ -84,22 +81,11 @@ Keep this worktree's **home branch** rooted at the freshest production tip — n
84
81
 
85
82
  Runs after Step 1.5 so any infra commits land first, and before Step 1.7 so the freshness gate's asset update operates on the freshest tree.
86
83
 
87
- Resolve the production branch: read `.codebyplan/git.json` and take `branch_config.production` (fall back to `main` if the file or field is absent). Call this `$PRODUCTION`. Then compare the current branch against the worktree's folder name:
84
+ Run `codebyplan session home-ff` and parse the JSON output (`{ result: 'skipped'|'warn'|'fast_forwarded', reason?, warn? }`):
88
85
 
89
- ```bash
90
- FOLDER="$(basename "$(git rev-parse --show-toplevel)")"
91
- CURRENT="$(git rev-parse --abbrev-ref HEAD)"
92
- ```
93
-
94
- - **`$CURRENT` != `$FOLDER`** (a `feat/*` or any non-home branch): skip silently — no fetch, no output.
95
- - **`$CURRENT` == `$FOLDER`** (home branch): fast-forward to `origin/$PRODUCTION`, warning once per failure and continuing:
96
-
97
- ```bash
98
- git fetch origin "$PRODUCTION" 2>/dev/null \
99
- || echo "⚠ home-branch ff: fetch failed — staying on local $CURRENT"
100
- git merge --ff-only "origin/$PRODUCTION" 2>/dev/null \
101
- || echo "⚠ home-branch ff: $CURRENT not fast-forwardable (ahead/diverged) — left untouched"
102
- ```
86
+ - **`result === 'skipped'`** (non-home branch or production mismatch): proceed silently.
87
+ - **`result === 'warn'`** (fast-forward attempt failed): surface the `warn` field as one line, then proceed silently.
88
+ - **`result === 'fast_forwarded'`** (home branch updated): proceed silently.
103
89
 
104
90
  Never rebase, reset, force-push, or stash. A non-fast-forwardable home branch is a signal to reconcile manually, not to overwrite.
105
91
 
@@ -107,31 +93,25 @@ Never rebase, reset, force-push, or stash. A non-fast-forwardable home branch is
107
93
 
108
94
  Check whether a newer `codebyplan` is published and safe to auto-install on this worktree's current branch, then run the local install + asset update. Runs after the Step 1.6 home-branch fast-forward (so any update lands on the freshest tree) and before Step 2. Fully non-blocking — the guard and skip branches proceed silently; any failure in the install/update commands warns once and continues to Step 2. session-end never halts.
109
95
 
110
- ```bash
111
- VERSION_JSON=$(npx codebyplan version-status 2>/dev/null)
112
- ```
113
-
114
- Parse `$VERSION_JSON` as JSON and branch on the result:
96
+ Run `codebyplan session freshness-gate` (WITHOUT `--halt-on-update`; session-end is continue-only) and parse the JSON output (`{ result: 'skipped'|'guarded'|'up_to_date'|'updated'|'error', ... }`):
115
97
 
116
- - **Probe failed / unparseable** — the command errored, produced no output, or the output cannot be parsed as JSON carrying the required keys (`newer`, `guarded`, `installCommand`). This includes an installed `codebyplan` too old to have the `version-status` subcommand (which prints `Unknown command`). → **FAIL-SAFE SKIP**: proceed silently to Step 2. A best-effort freshness probe must never disrupt session-end.
117
- - **`guarded: true`** (protected/main branch OR the canonical `codebyplan` source monorepo — any `guardReason`) → skip silently, proceed to Step 2. Gate on the `guarded` boolean only; never branch on the specific `guardReason` string. This is the guard that prevents clobbering the canonical monorepo's ahead-of-published `.claude/` and blocks any update or commit on a protected branch.
118
- - **`newer: false`** (already up to date) → skip silently, proceed to Step 2.
119
- - **`newer: true` AND `guarded: false`** → run the update path:
120
- 1. Run the JSON's `installCommand` (e.g. `pnpm add codebyplan@latest`) to LOCALLY install `codebyplan@latest` via the repo's package manager. Never a global `-g` install.
121
- 2. Run `npx codebyplan claude update` to refresh the worktree's `.claude/` assets on the current branch. If `installCommand` (step 1) or this command exits non-zero, warn once and skip to Step 2 — this path is non-blocking.
122
- 3. Detect changes across BOTH asset directories in one pass: `git status --porcelain -- .claude/ .codebyplan/`. If non-empty, present a single combined offer (same pattern as Step 1.5):
98
+ - **Probe failed** — the command errored or output cannot be parsed as JSON. → **FAIL-SAFE SKIP**: proceed silently to Step 2. A best-effort freshness probe must never disrupt session-end.
99
+ - **`result === 'skipped'` / `'guarded'` / `'up_to_date'`** → skip silently, proceed to Step 2. Gate on the `result` field only. This guard prevents clobbering the canonical monorepo's ahead-of-published `.claude/` and blocks any update or commit on a protected branch.
100
+ - **`result === 'error'`** fail-safe skip, proceed to Step 2.
101
+ - **`result === 'updated'`** → the CLI already ran the install + `npx codebyplan claude update`. Parse the JSON response:
102
+ - If `changed_files[]` is present and non-empty, present a single combined offer (same pattern as Step 1.5):
123
103
 
124
- ```
125
- codebyplan updated. Commit these changes before ending the session?
126
- [list of changed paths under .claude/ and .codebyplan/]
104
+ ```
105
+ codebyplan updated. Commit these changes before ending the session?
106
+ [list of changed paths under .claude/ and .codebyplan/]
127
107
 
128
- Reply: yes | no | select
129
- ```
108
+ Reply: yes | no | select
109
+ ```
130
110
 
131
- On `yes`: `git add` the listed paths only (not the whole directories), then trigger `/cbp-git-commit`. On `no`: skip. On `select`: ask which subset.
132
- 4. Continue to Step 2 — session-end does NOT halt. The update lands in the current worktree on its current branch; main/protected branches and the canonical source repo are already excluded by the `guarded` check above.
111
+ On `yes`: `git add` the listed paths only (not the whole directories), then trigger `/cbp-git-commit`. On `no`: skip. On `select`: ask which subset.
112
+ - Continue to Step 2 — session-end does NOT halt. The update lands in the current worktree on its current branch; main/protected branches and the canonical source repo are already excluded by the `result !== 'guarded'` check above.
133
113
 
134
- **Home branches are intentionally not guarded.** A worktree's folder-named home branch (e.g. `codebyplan-web`) is neither protected/main nor the canonical source, so `version-status` returns `guarded:false` there and this gate runs the update exactly as on a feat branch — landing it on whichever branch the worktree currently rests on (the deliberate "update the branch they're on, except main/canonical" behavior).
114
+ **Home branches are intentionally not guarded.** A worktree's folder-named home branch (e.g. `codebyplan-web`) is neither protected/main nor the canonical source, so the freshness gate returns `result !== 'guarded'` there and this gate runs the update exactly as on a feat branch — landing it on whichever branch the worktree currently rests on (the deliberate "update the branch they're on, except main/canonical" behavior).
135
115
 
136
116
  Non-blocking — session end proceeds regardless of outcome.
137
117
 
@@ -170,9 +150,9 @@ You can close this window.
170
150
  ## Integration
171
151
 
172
152
  - **Triggered by**: user invocation (prompted by `/cbp-todo` when no work remains)
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)
153
+ - **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); `codebyplan session home-ff` (Step 1.6 home-branch fast-forward); `codebyplan session freshness-gate` (Step 1.7 package-freshness gate, without --halt-on-update); `codebyplan session infra-files --json --task-files <csv>` (Step 1.5 infra-file set math)
174
154
  - **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`)
175
155
  - **Spawns**: none
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).
156
+ - **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 `result === 'updated'` path (committing changed `.claude/` and `.codebyplan/` paths).
177
157
  - **Paired with**: `/cbp-session-start`
178
158
  - **Pairs with**: `/cbp-session-start` Step 4.5 (handoff payload shape + freshness-gate contract; specified inline — no separate rule file)
@@ -55,22 +55,11 @@ Pass `WORKTREE_ID` to MCP tools that support it. Null `WORKTREE_ID` means the (d
55
55
 
56
56
  Keep this worktree's **home branch** rooted at the freshest production tip — no prompt, fully non-blocking. Home branches are the folder-named placeholder branches each worktree rests on (e.g. `codebyplan-web`); `feat/*` branches are deliberately skipped — they integrate via `/cbp-merge-main` with QA, never an auto fast-forward.
57
57
 
58
- Resolve the production branch: read `.codebyplan/git.json` and take `branch_config.production` (fall back to `main` if the file or field is absent). Call this `$PRODUCTION`. Then compare the current branch against the worktree's folder name:
58
+ Run `codebyplan session home-ff` and parse the JSON output (`{ result: 'skipped'|'warn'|'fast_forwarded', reason?, warn? }`):
59
59
 
60
- ```bash
61
- FOLDER="$(basename "$(git rev-parse --show-toplevel)")"
62
- CURRENT="$(git rev-parse --abbrev-ref HEAD)"
63
- ```
64
-
65
- - **`$CURRENT` != `$FOLDER`** (a `feat/*` or any non-home branch): skip silently — no fetch, no output.
66
- - **`$CURRENT` == `$FOLDER`** (home branch): fast-forward to `origin/$PRODUCTION`, warning once per failure and continuing:
67
-
68
- ```bash
69
- git fetch origin "$PRODUCTION" 2>/dev/null \
70
- || echo "⚠ home-branch ff: fetch failed — staying on local $CURRENT"
71
- git merge --ff-only "origin/$PRODUCTION" 2>/dev/null \
72
- || echo "⚠ home-branch ff: $CURRENT not fast-forwardable (ahead/diverged) — left untouched"
73
- ```
60
+ - **`result === 'skipped'`** (non-home branch or production mismatch): proceed silently.
61
+ - **`result === 'warn'`** (fast-forward attempt failed): surface the `warn` field as one line, then proceed silently.
62
+ - **`result === 'fast_forwarded'`** (home branch updated): proceed silently.
74
63
 
75
64
  Never rebase, reset, force-push, or stash. A non-fast-forwardable home branch is a signal to reconcile manually, not to overwrite.
76
65
 
@@ -123,40 +112,38 @@ binary simply yields a zero count and no line.
123
112
 
124
113
  Check whether a newer `codebyplan` is published and safe to auto-install on this worktree's current branch. Runs AFTER the architecture-map drift check (Step 1.55) and BEFORE session activation (Step 3).
125
114
 
126
- ```bash
127
- VERSION_JSON=$(npx codebyplan version-status 2>/dev/null)
128
- # Populate the claude-status cache best-effort (pure cache population never gates session-start).
129
- npx codebyplan claude status --write-cache --quiet 2>/dev/null || true
130
- ```
115
+ Run `codebyplan session freshness-gate --halt-on-update` and parse the JSON output (`{ result: 'skipped'|'guarded'|'up_to_date'|'updated'|'error', ... }`):
116
+
117
+ - **Probe failed** — the command errored or output cannot be parsed as JSON. → **FAIL-SAFE SKIP**: proceed silently to Step 3. Never disrupt a session over a best-effort freshness probe — the MCP gate (Step 0) is the only vital gate.
118
+ - **`result === 'skipped'` / `'guarded'` / `'up_to_date'`** → skip silently, proceed to Step 3. Gate on the `result` field only.
119
+ - **`result === 'error'`** → fail-safe skip, proceed to Step 3.
120
+ - **`result === 'updated'`** → the CLI already ran the install + `npx codebyplan claude update`. Parse the JSON response:
121
+ - If `changed_files[]` is present and non-empty, offer the same commit gate as Step 5.7:
131
122
 
132
- Parse `$VERSION_JSON` as JSON and branch on the result:
123
+ ```
124
+ codebyplan updated. Commit the resulting .claude/ and .codebyplan/ changes before exiting?
125
+ [list of changed paths under .claude/ and .codebyplan/]
133
126
 
134
- - **Probe failed / unparseable** — the command errored, produced no output, or the output cannot be parsed as JSON carrying the required keys (`newer`, `guarded`, `installCommand`). This includes an installed `codebyplan` too old to have the `version-status` subcommand (which prints `Unknown command`). → **FAIL-SAFE SKIP**: proceed silently to Step 3. Never disrupt a session over a best-effort freshness probe — the MCP gate (Step 0) is the only vital gate.
135
- - **`guarded: true`** (protected/main branch OR the canonical `codebyplan` source monorepo — any `guardReason`) → skip silently, proceed to Step 3. Gate on the `guarded` boolean only; never branch on the specific `guardReason` string.
136
- - **`newer: false`** (already up to date) → skip silently, proceed to Step 3.
137
- - **`newer: true` AND `guarded: false`** → run the update path:
138
- 1. Run the JSON's `installCommand` (e.g. `pnpm add codebyplan@latest`) to LOCALLY install `codebyplan@latest` via the repo's package manager. Never a global `-g` install.
139
- 2. Run `npx codebyplan claude update` to refresh the worktree's `.claude/` assets on the current branch.
140
- 3. Detect changes across BOTH asset directories in one pass: `git status --porcelain -- .claude/ .codebyplan/`. If non-empty, offer the same commit gate as Step 5.7:
127
+ Reply: yes | no | select
128
+ ```
141
129
 
142
- ```
143
- codebyplan updated. Commit the resulting .claude/ and .codebyplan/ changes before exiting?
144
- [list of changed paths under .claude/ and .codebyplan/]
130
+ On `yes`: `git add` the listed paths only, then trigger `/cbp-git-commit`. On `no`: skip. On `select`: ask which subset.
131
+ - **HALT** do NOT proceed to Step 3. Print:
145
132
 
146
- Reply: yes | no | select
147
- ```
133
+ ```
134
+ ✓ codebyplan updated. Start a FRESH Claude Code session
135
+ (run /clear or open a new window) so the updated .claude/ takes effect.
136
+ ```
148
137
 
149
- On `yes`: `git add` the listed paths only, then trigger `/cbp-git-commit`. On `no`: skip. On `select`: ask which subset.
150
- 4. **HALT** — do NOT proceed to Step 3. Print:
138
+ On this update-and-halt path the session is NOT continued: `update_session_state(activate)` is NOT called, `create_session_log` is NOT called, and `/cbp-todo` is NOT triggered.
151
139
 
152
- ```
153
- ✓ codebyplan updated to {latest}. Start a FRESH Claude Code session
154
- (run /clear or open a new window) so the updated .claude/ takes effect.
155
- ```
140
+ **Home branches are intentionally not guarded.** A worktree's folder-named home branch (e.g. `codebyplan-web`) is neither protected/main nor the canonical source, so the freshness gate returns `result !== 'guarded'` there and this gate fires exactly as on a feat branch. That is deliberate — the update lands on whatever branch the worktree is currently resting on (the "update the branch they're on, except main/canonical" decision), not an accidental halt.
156
141
 
157
- On this update-and-halt path the session is NOT continued: `update_session_state(activate)` is NOT called, `create_session_log` is NOT called, and `/cbp-todo` is NOT triggered.
142
+ Populate the claude-status cache best-effort (pure cache population never gates session-start):
158
143
 
159
- **Home branches are intentionally not guarded.** A worktree's folder-named home branch (e.g. `codebyplan-web`) is neither protected/main nor the canonical source, so `version-status` returns `guarded:false` there and this gate fires exactly as on a feat branch. That is deliberate — the update lands on whatever branch the worktree is currently resting on (the "update the branch they're on, except main/canonical" decision), not an accidental halt.
144
+ ```bash
145
+ npx codebyplan claude status --write-cache --quiet 2>/dev/null || true
146
+ ```
160
147
 
161
148
  ### Step 1.7: LSP Binary Nudge
162
149
 
@@ -221,15 +208,12 @@ Probe the most-recent closed session log for a structured handoff payload (the h
221
208
 
222
209
  Clean the working tree of leftover infra before the session begins. Only commit files that are **not** part of an unfinished task.
223
210
 
224
- 1. `git status --porcelain` list all modified/untracked files. If empty → skip this step.
225
- 2. Resolve **task-related files** (leave these uncommitted):
211
+ 1. Resolve the active task's round files (local-first):
226
212
  - 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.
227
- - 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)`.
228
- - Collect `files[]` from those rounds `task_files` set
229
- - If no active task exists, `task_files` is empty
230
- 3. `infra_files = changed_files task_files`
231
- 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.
232
- 5. If `infra_files` is empty → skip. Otherwise present once:
213
+ - If active task exists: read `.codebyplan/state/checkpoints/<checkpoint_id>/tasks/<task_id>/rounds/` and filter to rounds with status not in `completed` / `cancelled`; collect their `files[]` → `task_files` set. Break-glass fallback: MCP `get_rounds(task_id)`.
214
+ - If no active task exists, `task_files` is empty.
215
+ 2. Run `codebyplan session infra-files --json --task-files "<csv>"` where `<csv>` is the comma-separated task files from step 1. Parse the JSON response (`{ infra_files: string[], task_files: string[], note?: string }`). The CLI re-runs `git status --porcelain` internally and applies the set-math deterministically — the race-safe recompute, reading the index after Steps 0–5 round-trips complete.
216
+ 3. If `infra_files` is empty skip. Otherwise present once:
233
217
 
234
218
  ```
235
219
  Commit these non-task files before starting session?
@@ -238,7 +222,7 @@ Clean the working tree of leftover infra before the session begins. Only commit
238
222
  Reply: yes | no | select
239
223
  ```
240
224
 
241
- 6. On `yes`: `git add` the listed files, then trigger `/cbp-git-commit` (it handles conventional message + commit).
225
+ 4. On `yes`: `git add` the listed files, then trigger `/cbp-git-commit` (it handles conventional message + commit).
242
226
  On `no`: skip. On `select`: ask which subset.
243
227
 
244
228
  Non-blocking — session start proceeds either way.
@@ -288,7 +272,7 @@ Three-branch gate using `owned_count` and `total_count` from Step 5.8:
288
272
 
289
273
  - **Triggered by**: user invocation, `/clear` recovery
290
274
  - **Resolves**: `npx codebyplan resolve-worktree --json` (worktree id + distress signal; non-tuple-miss distress is non-blocking at session-start)
291
- - **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 arch-map drift` + `.codebyplan/architecture.json` presence (Step 1.55 architecture-map drift nudge, non-blocking); `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
275
+ - **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 arch-map drift` + `.codebyplan/architecture.json` presence (Step 1.55 architecture-map drift nudge, non-blocking); `codebyplan session home-ff` (Step 1.4 home-branch fast-forward); `codebyplan session freshness-gate --halt-on-update` (Step 1.6 package-freshness gate); `codebyplan session infra-files --json --task-files <csv>` (Step 5.7 infra-file set math); `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
292
276
  - **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
293
277
  - **Spawns**: none
294
278
  - **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)
@@ -66,9 +66,7 @@ Compute `TARGET`:
66
66
  | Task type | TARGET |
67
67
  |-----------|--------|
68
68
  | Standalone, `task.branch_name` set | `task.branch_name` |
69
- | Standalone, `branch_name` null | `feat/standalone-TASK-{N}-{kebab-slug-from-task-title}` |
70
-
71
- Slug rules: lowercase, words joined by `-`, drop punctuation, truncate to 40 chars.
69
+ | Standalone, `branch_name` null | `feat/standalone-TASK-{N}-{slug}` where slug is computed via `codebyplan slug "{task title}"` |
72
70
 
73
71
  #### 3.2 — Compare current branch
74
72
 
@@ -76,26 +74,19 @@ Run `git branch --show-current`. If `current == TARGET` → continue to Step 3b.
76
74
 
77
75
  #### 3.3 — Switch automatically (no AskUserQuestion, no blocking)
78
76
 
77
+ Run the branch checkout via the deterministic CLI:
78
+
79
79
  ```bash
80
- # (a) target exists locally
81
- if git rev-parse --verify "$TARGET" >/dev/null 2>&1; then
82
- git checkout "$TARGET"
83
-
84
- # (b) target exists on origin (track it)
85
- elif git rev-parse --verify "origin/$TARGET" >/dev/null 2>&1; then
86
- git checkout -t "origin/$TARGET"
87
-
88
- # (c) target doesn't exist — create from production branch
89
- else
90
- git fetch origin "$PRODUCTION" 2>/dev/null || true
91
- git checkout -b "$TARGET" "origin/$PRODUCTION" 2>/dev/null \
92
- || git checkout -b "$TARGET" "$PRODUCTION"
93
- fi
80
+ RESULT=$(codebyplan branch checkout --target "$TARGET" --production "$PRODUCTION")
81
+ # Parse JSON: { action: "checked_out_local" | "checked_out_tracking" | "created_from_production" | "error", branch, previous?, error? }
82
+ ACTION=$(echo "$RESULT" | jq -r '.action')
94
83
  ```
95
84
 
96
- No `git stash`, ever (per `git-safety.md`). No `git add`, ever (per `git-workflow.md`).
85
+ **Interpreting the result:**
86
+ - `action === "error"`: surface the raw `error` field verbatim and stop.
87
+ - Otherwise (all success actions): branch is now `TARGET`. Continue to Step 3.4.
97
88
 
98
- If `git checkout` exits non-zero (would clobber), surface the raw git error verbatim and stop.
89
+ No `git stash`, ever (per `git-safety.md`). No `git add`, ever (per `git-workflow.md`).
99
90
 
100
91
  #### 3.4 — Persist + verify
101
92
 
@@ -3,7 +3,7 @@ scope: org-shared
3
3
  name: cbp-supabase-migrate
4
4
  description: Scaffold or adopt a Supabase migration for the current PR branch, apply to the branch's preview DB, run advisor checks, regenerate TypeScript types. Includes a fresh-branch dry-run pre-flight that uses one persistent dry-run ephemeral branch per feature branch.
5
5
  argument-hint: "[--new <name> | <path-to-sql>]"
6
- allowed-tools: Read, Edit, Write, Bash(git *), Bash(supabase *), Bash(jq *), Bash(date *), Bash(which *), Bash(cp *), Bash(mv *), Bash(test *), Bash(ls *), Bash(npx codebyplan checkpoint update *), Bash(npx codebyplan task update *), mcp__supabase__apply_migration, mcp__supabase__list_migrations, mcp__supabase__get_advisors, mcp__supabase__generate_typescript_types, mcp__supabase__reset_branch, mcp__supabase__list_branches, mcp__supabase__create_branch, mcp__supabase__get_cost, mcp__supabase__confirm_cost
6
+ allowed-tools: Read, Edit, Write, Bash(codebyplan supabase *), Bash(npx codebyplan supabase *), Bash(npx codebyplan checkpoint update *), Bash(npx codebyplan task update *), Bash(git *), Bash(supabase *), Bash(jq *), Bash(date *), Bash(which *), Bash(cp *), Bash(mv *), Bash(test *), Bash(ls *), mcp__supabase__apply_migration, mcp__supabase__list_migrations, mcp__supabase__get_advisors, mcp__supabase__generate_typescript_types, mcp__supabase__reset_branch, mcp__supabase__list_branches, mcp__supabase__create_branch, mcp__supabase__get_cost, mcp__supabase__confirm_cost, mcp__codebyplan__update_checkpoint, mcp__codebyplan__update_task
7
7
  effort: xhigh
8
8
  ---
9
9
 
@@ -99,16 +99,21 @@ skip.
99
99
 
100
100
  ### Guard 2 — DB-path / migration intent
101
101
 
102
- Reuse the db_paths detection so the step proceeds only when this invocation actually touches
103
- the database. Read the globs (default `supabase/**`, `apps/backend/**`, `packages/**/db/**`):
102
+ Delegate the db_paths config + branch diff to the CLI (replaces the former `db_paths` jq +
103
+ `git diff` bash), and capture the parent project ref for the MCP calls below:
104
104
 
105
105
  ```bash
106
- DB_PATHS=$(jq -r '.shipment.surfaces.supabase.db_paths[]? // empty' .codebyplan/shipment.json 2>/dev/null)
107
- [ -z "$DB_PATHS" ] && DB_PATHS=$(printf '%s\n' 'supabase/**' 'apps/backend/**' 'packages/**/db/**')
106
+ codebyplan supabase resolve-preview
108
107
  ```
109
108
 
109
+ Parse its JSON `{ parent_ref, project_ref, db_changed, base }`. Capture `PARENT_REF=parent_ref`
110
+ (read from `.codebyplan/shipment.json` `.shipment.surfaces.supabase.project_ref` — used by the
111
+ list/create calls below, never a hardcoded literal). `db_changed` reflects the branch diff
112
+ against `origin/<base>` matched against the configured db_paths globs (default `supabase/**`,
113
+ `apps/backend/**`, `packages/**/db/**`).
114
+
110
115
  Proceed when **either**:
111
- - the branch diff against `origin/$PRODUCTION` touches any `DB_PATHS` glob, **or**
116
+ - `db_changed === true`, **or**
112
117
  - this invocation will create/adopt a migration — `$ARGUMENTS` is `--new <name>` or a `.sql`
113
118
  path (the migration file may not exist on disk yet, so explicit migrate intent counts as a
114
119
  DB change). The bare-picker case (Step 5 Case C) is treated as migrate intent.
@@ -125,11 +130,12 @@ already provisioned the branch. Capture it as `PREVIEW_PROJECT_REF` and jump str
125
130
 
126
131
  ### Idempotency check (list before create)
127
132
 
128
- Call `mcp__supabase__list_branches` with the parent `project_id` `rrvtrumtkhrsbhcyrwvf`. The
129
- parent `project_id` for MCP calls is the same ref string stored in `.codebyplan/shipment.json`
130
- `surfaces.supabase.project_ref` — Supabase uses that one ref as both the project identifier
131
- and the branch target. Scan the returned list for an entry whose `name` exactly equals
132
- `$BRANCH` (slashes included — `feat/CHK-144-...` is a valid Supabase branch name).
133
+ Call `mcp__supabase__list_branches` with the parent `project_id` `$PARENT_REF` (resolved by
134
+ `codebyplan supabase resolve-preview` in Guard 2 from `.codebyplan/shipment.json`
135
+ `.shipment.surfaces.supabase.project_ref` — never a hardcoded literal). Supabase uses that one
136
+ ref as both the project identifier and the branch target. Scan the returned list for an entry
137
+ whose `name` exactly equals `$BRANCH` (slashes included — `feat/CHK-144-...` is a valid
138
+ Supabase branch name).
133
139
 
134
140
  - **Match found**: capture its `project_ref` as `PREVIEW_PROJECT_REF`. Skip creation; proceed
135
141
  to "Record connection". This is the idempotent reuse path (covers a branch the GitHub
@@ -148,7 +154,7 @@ Cost confirmation is mandatory before creating a branch — never bypass it:
148
154
  stays empty.
149
155
 
150
156
  After cost is confirmed, call `mcp__supabase__create_branch`:
151
- - `project_id`: `rrvtrumtkhrsbhcyrwvf` (parent project ref)
157
+ - `project_id`: `$PARENT_REF` (parent project ref from `codebyplan supabase resolve-preview`)
152
158
  - `name`: `$BRANCH` (verbatim — slashes included)
153
159
  - `confirm_cost_id`: the same id from the `get_cost` response that was passed to `confirm_cost`
154
160
 
@@ -276,25 +282,16 @@ Parse `$ARGUMENTS`:
276
282
 
277
283
  ### Case A: `--new <name>`
278
284
 
279
- Generate a timestamp strictly greater than the latest filename in `supabase/migrations/`:
280
-
281
- ```bash
282
- ls supabase/migrations/ | sort | tail -1
283
- ```
284
-
285
- Extract the numeric prefix from the `tail -1` output (e.g. `20260520000003` from `20260520000003_chk116_security_and_logging_fixes.sql`). Your `date -u +%Y%m%d%H%M%S` output must be strictly greater than that prefix. If two scaffolds happen in the same UTC second, append `_01`, `_02` to maintain monotonicity. Use the current wall-clock UTC time
286
- via:
285
+ Scaffold the migration file with a guaranteed-monotonic timestamp via the CLI (replaces the
286
+ former `ls | tail` + `date` + `touch` bash):
287
287
 
288
288
  ```bash
289
- date -u +%Y%m%d%H%M%S
289
+ codebyplan supabase new-migration "<name>"
290
290
  ```
291
291
 
292
- Create the file:
293
-
294
- ```bash
295
- TIMESTAMP=$(date -u +%Y%m%d%H%M%S)
296
- touch "supabase/migrations/${TIMESTAMP}_<name>.sql"
297
- ```
292
+ Parse its JSON `{ path }`. The CLI creates an empty `supabase/migrations/<timestamp>_<slug>.sql`
293
+ whose timestamp is strictly greater than the latest existing migration's, appending `_01`/`_02`
294
+ on a same-second collision. Record the returned path as `MIGRATION_PATH`.
298
295
 
299
296
  Open the file for editing — write the migration SQL now. Include both the intended change
300
297
  and a comment block at the top:
@@ -93,9 +93,7 @@ Compute `TARGET`:
93
93
  | Task type | TARGET |
94
94
  |-----------|--------|
95
95
  | Checkpoint-bound, `checkpoint.branch_name` set | `checkpoint.branch_name` (e.g. `feat/CHK-095-pricing-page`) |
96
- | Checkpoint-bound, `branch_name` null (legacy) | `feat/CHK-{NNN}-{kebab-slug-from-checkpoint-title}` |
97
-
98
- Slug rules: lowercase, words joined by `-`, drop punctuation, truncate to 40 chars.
96
+ | Checkpoint-bound, `branch_name` null (legacy) | `feat/CHK-{NNN}-{slug}` where slug is computed via `codebyplan slug "{checkpoint title}"` |
99
97
 
100
98
  #### 3.2 — Compare current branch
101
99
 
@@ -103,29 +101,19 @@ Run `git branch --show-current`. If `current == TARGET` → continue to Step 3b.
103
101
 
104
102
  #### 3.3 — Switch automatically (no AskUserQuestion, no blocking)
105
103
 
106
- Run the switch directly. Three sub-cases, in order:
104
+ Run the branch checkout via the deterministic CLI:
107
105
 
108
106
  ```bash
109
- # (a) target exists locally
110
- if git rev-parse --verify "$TARGET" >/dev/null 2>&1; then
111
- git checkout "$TARGET"
112
-
113
- # (b) target exists on origin (track it)
114
- elif git rev-parse --verify "origin/$TARGET" >/dev/null 2>&1; then
115
- git checkout -t "origin/$TARGET"
116
-
117
- # (c) target doesn't exist — create from production branch (main)
118
- else
119
- # First make sure production is up to date
120
- git fetch origin "$PRODUCTION" 2>/dev/null || true
121
- git checkout -b "$TARGET" "origin/$PRODUCTION" 2>/dev/null \
122
- || git checkout -b "$TARGET" "$PRODUCTION"
123
- fi
107
+ RESULT=$(codebyplan branch checkout --target "$TARGET" --production "$PRODUCTION")
108
+ # Parse JSON: { action: "checked_out_local" | "checked_out_tracking" | "created_from_production" | "error", branch, previous?, error? }
109
+ ACTION=$(echo "$RESULT" | jq -r '.action')
124
110
  ```
125
111
 
126
- **Carrying uncommitted work** — `git checkout` carries clean (non-conflicting) working-tree changes to the new branch automatically. This is intended: changes made on `main` while preparing the task move with the user to the new feat branch. No `git stash`, ever (per `git-safety.md`). No `git add`, ever (per `git-workflow.md`).
112
+ **Interpreting the result:**
113
+ - `action === "error"`: surface the raw `error` field verbatim, stop, do NOT attempt recovery. The user resolves git state and re-invokes. This is the only case where `/cbp-task-start` halts on branch state.
114
+ - Otherwise (all success actions): branch is now `TARGET`. Continue to Step 3.4.
127
115
 
128
- **If `git checkout` exits non-zero** (typically "would clobber" because a tracked file has unstaged changes that conflict with target's version): surface the raw git error verbatim, stop, do NOT attempt recovery. The user resolves and re-invokes. This is the only case where `/cbp-task-start` halts on branch state.
116
+ **Carrying uncommitted work** the CLI respects git's automatic carrying of clean (non-conflicting) working-tree changes. Changes made while preparing the task move with the user to the new feat branch. No `git stash`, ever (per `git-safety.md`). No `git add`, ever (per `git-workflow.md`).
129
117
 
130
118
  **Note — Supabase preview branch**: no Supabase branch is created at this point. Creation is lazy — it happens on the first DB change when `/cbp-supabase-migrate` runs on the feat branch, which provisions a Supabase branch named identically to the git branch. See `cbp-supabase-migrate` Step 2.3 for the creation protocol.
131
119
 
@@ -9,7 +9,7 @@ effort: xhigh
9
9
 
10
10
  # Task Testing Command
11
11
 
12
- Comprehensive task-level testing — the **cross-round double-check** run once after all rounds complete. Per-round QA (per-app build/lint/types, the `console.log`/debug scan, the OWASP/secret grep, `pnpm audit`) is owned by each round's `testing-qa-agent`; this skill does NOT re-run it. Instead it tests the **entire delivered feature holistically** across the full task diff — catching cross-package and cross-round problems no single round can see. Runs inline — no sub-agent.
12
+ Comprehensive task-level testing — runs all automated tests and walks the user through manual testing one-by-one. Distinct from round-level testing (`testing-qa-agent`): this tests the **entire delivered feature holistically** after all rounds are complete. Runs inline — no sub-agent.
13
13
 
14
14
  ## When Used
15
15
 
@@ -19,13 +19,13 @@ Comprehensive task-level testing — the **cross-round double-check** run once a
19
19
 
20
20
  ## Scope vs Round-Level Validation
21
21
 
22
- Per-wave `testing-qa-agent` runs inside `/cbp-round-execute` Step 5 and **owns per-round QA**: per-app build/lint/types, the `console.log`/debug scan, the OWASP/secret full-diff grep, and `pnpm audit`. This skill does NOT repeat them. It adds only the cross-round layer invisible within a single round: workspace-wide lint, workspace tsc, and the full test suite (which catch cross-package breakage), plus the cross-round code review (Step 6.5), the autonomous sim screenshot loop (Step 6.x), and the user manual walkthrough (Step 8).
22
+ Per-wave `testing-qa-agent` runs inside `/cbp-round-execute` Step 5. This skill adds the cross-cutting layer that is only visible across the full task diff: whole-repo lint, whole-repo typecheck, full test suite, `pnpm audit` (via `codebyplan check --scope task --json`), and full-diff security scan each run once here, not per-round.
23
23
 
24
24
  ## Instructions
25
25
 
26
26
  ### Step 1: Parse `$ARGUMENTS`
27
27
 
28
- Parse the argument using the canonical chk-task-round notation (see `cbp-round-start` Step 0 "CHK / TASK / ROUND Identifier Notation Vocabulary"):
28
+ Parse the argument using the canonical chk-task-round notation (see `.claude/rules/notation-consistency.md`):
29
29
 
30
30
  | Shape | Regex | Resolves to |
31
31
  |-------|-------|-------------|
@@ -104,14 +104,24 @@ Capture stdout and stderr for each check.
104
104
 
105
105
  **Hard-fail tests** (block completion):
106
106
 
107
+ Run the unified check matrix:
108
+
109
+ ```bash
110
+ codebyplan check --scope task --json
111
+ ```
112
+
113
+ Capture the JSON result. The runner is **whole-repo + baseline**: it runs `turbo run lint|typecheck|test` across every package and diffs each per-package result against the committed `.check-baseline.json`, so only NEW per-package failures fail a check. Five checks run for `--scope task`: `gate6` (sibling-identity parity — ALWAYS hard-fail, never baselined), `lint`, `typecheck`, `tests`, and `audit` (`audit.new_failures` lists new GHSA advisory ids not in the allowlist). A baselined check's `status` is `pass` when its `new_failures` array is empty even if the underlying command exited non-zero. If `any_failed === true` (or `hard_fail_checks` is non-empty), this is a hard fail — surface each failing result's `stdout`/`stderr`/`new_failures` and stop.
114
+
115
+ For each result entry, record: `category` (from `result.check`), `status` (from `result.status`), `details`, `stdout` (from `result.stdout`), `stderr` (from `result.stderr`), and `new_failures` (from `result.new_failures` — the newly-failing packages / new GHSA ids; the field is omitted/`undefined` for `gate6`, not `null`).
116
+
117
+ Additional hard-fail checks (not part of the runner):
118
+
107
119
  | Category | Command | Condition |
108
120
  | ----------------------- | ------------------------------- | -------------------------------- |
109
- | Full-repo lint | `pnpm -w lint` | Always |
110
- | Full-repo types | `pnpm exec tsc --noEmit` | Source files changed |
111
- | Full-repo unit tests | `pnpm test --run` | Source files in aggregated_files |
112
121
  | Per-package E2E | `pnpm --filter <pkg> e2e:test` | UI files in aggregated_files |
122
+ | Full-diff security scan | inline grep or `security-agent` | Always |
113
123
 
114
- These are the workspace-wide / cross-package checks only — per-app build/lint/types, the `console.log`/debug scan, the OWASP/secret grep, and `pnpm audit` already ran per-round inside `testing-qa-agent` and are NOT repeated here. Per-file lint + format are enforced by `lint-format-on-edit.sh` per edit. This step catches cross-package issues invisible to per-wave checks.
124
+ Per-file lint + format are enforced by `lint-format-on-edit.sh` hook per edit. This step catches cross-package issues invisible to per-wave checks.
115
125
 
116
126
  **Soft tests** (report, don't block):
117
127
 
@@ -120,8 +130,6 @@ These are the workspace-wide / cross-package checks only — per-app build/lint/
120
130
  | Visual | Screenshot compare via `e2e:visual-check` | UI work + dev server running |
121
131
  | API Health | `curl` health endpoint | API routes changed |
122
132
 
123
- For each test, record: `category, status (pass|fail|skipped), details, stdout, stderr`.
124
-
125
133
  #### Step 6.x: Autonomous Sim Screenshot Validation (mobile / on-device)
126
134
 
127
135
  For mobile rounds (Maestro / XCUITest / Tauri-mobile) where unit tests passed but the round touched component-mount code paths (custom hooks, prop signatures, conditional renders, navigation tabs), unit-test green is NOT sufficient evidence that the screen mounts at runtime. Use the autonomous sim screenshot loop to catch runtime crashes invisible to mocked unit tests.
@@ -168,7 +176,7 @@ For each finding, record: `{category, file, description, severity: 'low'|'medium
168
176
 
169
177
  Findings with severity `medium` or `high` feed the Step 9 problem classification. `low` findings are recorded in `task_testing_output` for the record but do not block.
170
178
 
171
- If any finding points to a need that exceeds task scope (e.g. a utility worth extracting for the wider codebase, a convention the repo should adopt globally), route per `cbp-task-create` Step 3.5 "Immediate Issue Capture Contract — How to Capture" — default to a NEW TASK in the current checkpoint, not a standalone task. Standalone routing applies only when the finding is genuinely off-axis from every active checkpoint AND the user has confirmed standalone routing.
179
+ If any finding points to a need that exceeds task scope (e.g. a utility worth extracting for the wider codebase, a convention the repo should adopt globally), route per `immediate-issue-capture.md` "How to Capture" — default to a NEW TASK in the current checkpoint, not a standalone task. Standalone routing applies only when the finding is genuinely off-axis from every active checkpoint AND the user has confirmed standalone routing.
172
180
 
173
181
  ### Step 7: Separate Claude-Testable vs User-Testable
174
182