codebyplan 1.13.39 → 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 (39) hide show
  1. package/dist/cli.js +24631 -354
  2. package/package.json +4 -2
  3. package/templates/agents/cbp-cc-executor.md +4 -4
  4. package/templates/agents/cbp-round-executor.md +2 -10
  5. package/templates/agents/cbp-task-check.md +2 -0
  6. package/templates/agents/cbp-task-planner.md +2 -5
  7. package/templates/hooks/README.md +14 -2
  8. package/templates/hooks/cbp-session-start-hook.sh +32 -0
  9. package/templates/hooks/cbp-test-coverage-gate.sh +20 -6
  10. package/templates/hooks/cbp-test-hooks.sh +72 -0
  11. package/templates/hooks/hooks.json +11 -0
  12. package/templates/settings.project.base.json +10 -0
  13. package/templates/skills/cbp-checkpoint-check/SKILL.md +10 -10
  14. package/templates/skills/cbp-checkpoint-complete/SKILL.md +7 -7
  15. package/templates/skills/cbp-checkpoint-create/SKILL.md +11 -9
  16. package/templates/skills/cbp-checkpoint-end/SKILL.md +7 -10
  17. package/templates/skills/cbp-checkpoint-plan/SKILL.md +10 -10
  18. package/templates/skills/cbp-checkpoint-start/SKILL.md +6 -6
  19. package/templates/skills/cbp-checkpoint-update/SKILL.md +9 -9
  20. package/templates/skills/cbp-git-commit/SKILL.md +8 -4
  21. package/templates/skills/cbp-merge-main/SKILL.md +2 -5
  22. package/templates/skills/cbp-round-check/SKILL.md +12 -8
  23. package/templates/skills/cbp-round-complete/SKILL.md +16 -10
  24. package/templates/skills/cbp-round-end/SKILL.md +9 -10
  25. package/templates/skills/cbp-round-execute/SKILL.md +7 -6
  26. package/templates/skills/cbp-round-input/SKILL.md +24 -12
  27. package/templates/skills/cbp-round-start/SKILL.md +36 -16
  28. package/templates/skills/cbp-round-update/SKILL.md +14 -10
  29. package/templates/skills/cbp-session-end/SKILL.md +22 -12
  30. package/templates/skills/cbp-session-start/SKILL.md +20 -47
  31. package/templates/skills/cbp-ship/SKILL.md +4 -4
  32. package/templates/skills/cbp-ship-main/SKILL.md +4 -5
  33. package/templates/skills/cbp-supabase-migrate/SKILL.md +12 -9
  34. package/templates/skills/cbp-task-check/SKILL.md +10 -10
  35. package/templates/skills/cbp-task-complete/SKILL.md +11 -9
  36. package/templates/skills/cbp-task-create/SKILL.md +7 -5
  37. package/templates/skills/cbp-task-start/SKILL.md +15 -17
  38. package/templates/skills/cbp-task-testing/SKILL.md +18 -18
  39. package/templates/skills/cbp-todo/SKILL.md +21 -21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codebyplan",
3
- "version": "1.13.39",
3
+ "version": "1.13.40",
4
4
  "description": "CLI for CodeByPlan — AI-powered development planning and tracking",
5
5
  "type": "module",
6
6
  "bin": {
@@ -45,7 +45,9 @@
45
45
  "node": ">=18"
46
46
  },
47
47
  "dependencies": {
48
- "@napi-rs/keyring": "^1.1.6"
48
+ "@napi-rs/keyring": "^1.1.6",
49
+ "@supabase/supabase-js": "^2.106.0",
50
+ "ws": ">=8.20.1"
49
51
  },
50
52
  "devDependencies": {
51
53
  "@eslint/js": "^9.18.0",
@@ -2,7 +2,7 @@
2
2
  scope: org-shared
3
3
  name: cbp-cc-executor
4
4
  description: Authoring executor for `.claude/` infrastructure. Applies approved changes across rules, skills, agents, context, CLAUDE.md, settings, and hooks — with update-first discipline, scope-marker enforcement, and length-limit awareness. Callable by the main conversation, `/cbp-checkpoint-end`, and `round-executor` (for in-scope `.claude/` infra deliverables).
5
- tools: Read, Write, Edit, Glob, Grep, Skill, Task, AskUserQuestion, mcp__codebyplan__create_task
5
+ tools: Read, Write, Edit, Glob, Grep, Skill, Task, AskUserQuestion, Bash(npx codebyplan task create *)
6
6
  model: sonnet
7
7
  effort: xhigh
8
8
  ---
@@ -134,7 +134,7 @@ Record every applied change with `authored_via` and `status`.
134
134
 
135
135
  - **Downgrade `create` → `update`** — apply silently, note in output.
136
136
  - **Unclear fit between two existing files** — `AskUserQuestion` with the two candidates and their descriptions.
137
- - **Change exceeds this invocation's scope** (e.g. proposal implies a broader refactor) — create a task via MCP `create_task` per `cbp-task-create` Step 3.5 "Immediate Issue Capture Contract", record in `deferred_changes` with `task_id_created`.
137
+ - **Change exceeds this invocation's scope** (e.g. proposal implies a broader refactor) — create a task via CLI write-through `codebyplan task create --checkpoint-id <id> ...` per `cbp-task-create` Step 3.5 "Immediate Issue Capture Contract"; MCP `create_task` as documented break-glass when CLI unavailable. Record in `deferred_changes` with `task_id_created`.
138
138
  - **Hook or settings change with cross-environment implications** — require explicit `scope` field from caller; if missing or ambiguous, ask.
139
139
 
140
140
  ### Phase 5: Post-Apply Sanity
@@ -197,7 +197,7 @@ Block-limit violations are non-negotiable — split before applying.
197
197
  - **Signed creates, edited updates** — creates route through build-cc skills (they embed the signature); updates use direct Edit on already-signed files.
198
198
  - **Never create agents** — only `update`. Agent creation requires a planning-level decision outside the fix pipeline.
199
199
  - **Length limits are enforced pre-apply** — refuse to produce a file that will fail the block limit.
200
- - **Surface, don't silently swallow** — ambiguity → `AskUserQuestion`; out-of-scope → MCP `create_task`.
200
+ - **Surface, don't silently swallow** — ambiguity → `AskUserQuestion`; out-of-scope → CLI `codebyplan task create` (MCP `create_task` as documented break-glass).
201
201
  - **Fresh inventory per invocation** — never reuse a cached inventory from a prior call.
202
202
 
203
203
  ## Integration
@@ -206,5 +206,5 @@ Block-limit violations are non-negotiable — split before applying.
206
206
  - **Reads**: `.claude/` inventory, `validate-structure-lengths.sh`, target files
207
207
  - **Writes**: `.claude/` files (via `/cbp-build-cc-*` skills for creates, direct Edit for updates)
208
208
  - **Calls skills**: `/cbp-build-cc-rule`, `/cbp-build-cc-skill`, `/cbp-build-cc-claude-file`, `/cbp-build-cc-settings`
209
- - **Creates tasks**: via MCP `create_task` when a change exceeds invocation scope
209
+ - **Creates tasks**: via CLI write-through `codebyplan task create` when a change exceeds invocation scope; MCP `create_task` as documented break-glass when CLI unavailable
210
210
  - **Enforced by**: `validate-structure-lengths.sh` (length), `validate-structure-scope.sh` (scope marker), `validate-structure-patterns.sh` (path layout)
@@ -212,16 +212,6 @@ If modifying managed files (`.claude/*`, `.claude/docs/architecture/*`, etc.):
212
212
 
213
213
  **Why:** Routing commands do this automatically. If you bypass routing, you MUST do source consultation manually. Skills contain coding patterns and conventions that must be followed.
214
214
 
215
- ### Step 2.4: Architecture Map Consultation
216
-
217
- For ANY module you are about to edit (app code or managed files), check for a pre-computed architecture map:
218
-
219
- 1. For each path in `files_to_modify`, derive its module and Glob `.claude/architecture/<module-slug>.md`.
220
- 2. If a map exists, read it BEFORE Step 3 — it surfaces the module's boundaries, internal structure, dependencies, and where-things-live landmarks, reducing broad file-system scans.
221
- 3. If `.claude/architecture/` is absent or the module has no map, proceed without it (not a blocker).
222
-
223
- See `.claude/context/architecture-map.md` for the full consultation contract. Unlike Step 2 (managed files only), this step fires for every round regardless of file type.
224
-
225
215
  ### Step 2.5: Search Before Creating
226
216
 
227
217
  For each file with action `create` in `files_to_modify`:
@@ -610,6 +600,8 @@ Which would you prefer?
610
600
  - **Spawned by**: `/cbp-round-execute` Step 3 (single-wave 3-AGENT path or per-wave 3-WAVE path)
611
601
  - **Returns to**: `/cbp-round-execute` which collects output and runs per-wave `cbp-testing-qa-agent`
612
602
  - **Depends on**: `cbp-task-planner` agent (provides approved plan)
603
+ - **Reads**: All task/round context arrives via the Input Contract (approved plan from `/cbp-round-start`). When the executor needs to read additional round or task state, read `.codebyplan/state/checkpoints/<id>/tasks/<id>/rounds/<id>.json` (local-first). If missing/stale, run `npx codebyplan sync` once and re-read. Break-glass fallback: MCP `get_*` tools when the state dir is absent and sync fails.
604
+ - **Writes**: DB-side mutations are surfaced as `improvements_noted` entries for the orchestrator to execute (executor frontmatter excludes MCP DB tools — see Step 0.2 carve-out).
613
605
  - **May spawn**: `cbp-database-agent` (Supabase operations), `general-purpose` (background batch writes), and `cbp-cc-executor` (in-scope `.claude/` infra deliverables, `source: 'round-executor'`) as sub-executors. (NOT any `cbp-e2e-*` specialist — e2e is orchestrator-owned, spawned by `/cbp-round-execute` Step 5 per the Step 0.2 carve-out.)
614
606
 
615
607
  ## Structure Knowledge
@@ -216,3 +216,5 @@ When no divergence is detected, set `scope_divergence_detected: false` and proce
216
216
 
217
217
  - **Spawned by**: `/cbp-task-check` command
218
218
  - **Returns to**: `/cbp-task-check` which routes based on verdict
219
+ - **Reads**: All task, checkpoint, and rounds data arrives via the Input Contract (passed by `/cbp-task-check`). Local `.codebyplan/state/` files are the preferred source when `/cbp-task-check` pre-fetches context — read `.codebyplan/state/checkpoints/<checkpointId>/tasks/<taskId>.json` and `rounds/*.json` (local-first; break-glass: MCP `get_*` tools when state dir is absent and sync fails). The agent itself reads only filesystem content (changed files) via the Read tool — it never calls MCP or CLI directly.
220
+ - **Writes**: None — review only, never edits.
@@ -376,11 +376,6 @@ delegation_hint:
376
376
 
377
377
  Read `.claude/rules/*.md` and relevant architecture docs.
378
378
 
379
- If `.claude/architecture/` contains map file(s) for the target module(s), read them before
380
- finalizing scope — they provide pre-computed structural context (boundaries, dependencies,
381
- landmarks) that reduces the need for broad file-system scans. See
382
- `.claude/context/architecture-map.md` for the consultation contract.
383
-
384
379
  ### Phase 4: Clarify Requirements (Context-First)
385
380
 
386
381
  Before any AskUserQuestion call, check (1) `checkpoint.context`, (2) `task.context`, (3) codebase via Grep/Glob/Read. Only ask if all three fail. When asking, prefix with `Checked: [sources]. Not found. Asking: [question]`. If a question IS answered in context, use that answer directly — do not re-ask.
@@ -590,3 +585,5 @@ Use TaskCreate for plan step visibility.
590
585
 
591
586
  - **Spawned by**: `/cbp-round-start` (Step 5)
592
587
  - **Returns to**: `/cbp-round-start` for user approval
588
+ - **Reads**: All DB state arrives via the Input Contract (pre-fetched by `/cbp-round-start`). Local `.codebyplan/state/` files are the preferred source when `/cbp-round-start` reads context before passing it in. Break-glass: MCP `get_*` tools when the state dir is absent and sync fails (daemon-dead + CLI-unavailable). The planner itself never calls MCP or the CLI directly (frontmatter excludes those tools).
589
+ - **Writes**: None — planner never mutates DB state.
@@ -2,7 +2,7 @@
2
2
 
3
3
  The `codebyplan` npm package ships a small, portable set of Claude Code hooks. They run in your project, use only generic primitives (`git rev-parse`, `${CLAUDE_PROJECT_DIR}`, `${CLAUDE_PLUGIN_ROOT}`), and degrade gracefully (exit 0) when their preconditions aren't met.
4
4
 
5
- Hook registration lives in [`hooks/hooks.json`](./hooks.json) — PreToolUse, PostToolUse, and UserPromptSubmit events are wired. (`Notification`, `SessionStart`, `SessionEnd`, `Stop`, and `SubagentStop` are also schema-permitted but unused here.)
5
+ Hook registration lives in [`hooks/hooks.json`](./hooks.json) — PreToolUse, PostToolUse, UserPromptSubmit, and SessionStart events are wired. (`Notification`, `SessionEnd`, `Stop`, and `SubagentStop` are also schema-permitted but unused here.)
6
6
 
7
7
  **`cbp-statusline.sh` is auto-wired via `settings.project.base.json`.** The `statusLine` block is shipped inside `templates/settings.project.base.json` and merged into the consumer's `.claude/settings.json` automatically by `codebyplan claude install` (and on every `codebyplan claude update`). No manual copy-paste is required.
8
8
 
@@ -243,13 +243,25 @@ drops below threshold (e.g. after `/compact` or `/clear`), so the notice re-fire
243
243
 
244
244
  ---
245
245
 
246
+ ### `cbp-session-start-hook.sh` — SessionStart
247
+
248
+ Hydrates the local-first state mirror at session start: runs `codebyplan sync` (full hydrate when cold, delta pull otherwise) and `codebyplan watch start` (idempotent — pidfile + process-alive check) so the per-worktree Realtime down-sync daemon is running for the session.
249
+
250
+ **Blocks vs warns**: never blocks — exit 0 always. All command errors are swallowed.
251
+
252
+ **Skips when**: no `.codebyplan/repo.json` in the project directory (not a CodeByPlan repo), or the CLI is unauthenticated/offline (both subcommands self-guard and the hook ignores their failures).
253
+
254
+ **Opt out**: settings.json override removing the `SessionStart` entry, or plugin disable.
255
+
256
+ ---
257
+
246
258
  ## Supporting (not registered)
247
259
 
248
260
  ### `test-hooks.sh` — invoked by `auto-test-hooks.sh`
249
261
 
250
262
  Test suite for the plugin's 9 registered hooks. Runs two passes:
251
263
 
252
- 1. **Header check** — every registered hook (`lint-format-on-edit`, `test-coverage-gate`, `pre-commit-quality-gate`, `maestro-yaml-validate`, `auto-test-hooks`, `mcp-migration-guard`, `validate-git-stash-deny`, `cbp-mcp-round-sync`, `cbp-context-window-notify`) carries the required `# Hook:` and `# Purpose:` header comments. `statusline` uses its own `# Claude Code Status Line` marker.
264
+ 1. **Header check** — every registered hook (`lint-format-on-edit`, `test-coverage-gate`, `pre-commit-quality-gate`, `maestro-yaml-validate`, `auto-test-hooks`, `mcp-migration-guard`, `validate-git-stash-deny`, `cbp-mcp-round-sync`, `cbp-context-window-notify`, `cbp-session-start-hook`) carries the required `# Hook:` and `# Purpose:` header comments. `statusline` uses its own `# Claude Code Status Line` marker.
253
265
  2. **Functional smoke tests** — each hook is invoked with synthetic stdin matching its fast-path / graceful-degrade input; all must exit 0.
254
266
 
255
267
  Not in `hooks.json` — invoked indirectly via `auto-test-hooks.sh` on hook edits, or directly via `bash ${CLAUDE_PLUGIN_ROOT}/hooks/test-hooks.sh`.
@@ -0,0 +1,32 @@
1
+ #!/bin/bash
2
+ # @scope: org-shared
3
+ # Hook: SessionStart
4
+ # Purpose: Hydrate .codebyplan/state/ via `codebyplan sync` and ensure the
5
+ # per-worktree watch daemon is running. Hook-safe: all errors
6
+ # swallowed, always exits 0. No-op when unauthenticated/offline.
7
+ #
8
+ # Runtime bound: the registered settings entry carries "timeout": 30 so the
9
+ # Claude Code hook runtime kills a hung sync/start — never shell-wrap with
10
+ # `timeout` (absent on macOS). `codebyplan sync` self-bounds its HTTP calls;
11
+ # `watch start` returns immediately after the detached spawn.
12
+ #
13
+ # Concurrency: `codebyplan watch start` is atomically idempotent — it takes an
14
+ # exclusive-create .pid.lock (O_EXCL) around the pidfile check + spawn, so two
15
+ # SessionStart hooks firing together in the same worktree start at most one
16
+ # daemon (the loser exits 0 with "start already in progress").
17
+
18
+ # Resolve the project dir: Claude Code sets CLAUDE_PROJECT_DIR; fall back to pwd.
19
+ PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
20
+
21
+ # No-op when not inside a codebyplan repo (sentinel file absent).
22
+ if [ ! -f "$PROJECT_DIR/.codebyplan/repo.json" ]; then
23
+ exit 0
24
+ fi
25
+
26
+ # Hydrate state cache from backend (no-op offline / unauthenticated).
27
+ npx codebyplan sync >/dev/null 2>&1 || true
28
+
29
+ # Ensure per-worktree watch daemon is running (no-op when already up).
30
+ npx codebyplan watch start >/dev/null 2>&1 || true
31
+
32
+ exit 0
@@ -59,15 +59,20 @@ CHECKED=0
59
59
  SKIPPED=0
60
60
 
61
61
  while IFS= read -r FILE; do
62
- # Skip test files themselves
63
- if echo "$FILE" | grep -qE '\.(test|spec)\.(ts|tsx|js|jsx)$'; then
62
+ # Skip test files themselves. The leading [.-] class also matches framework
63
+ # spec conventions that suffix the marker with a dash — e.g. NestJS
64
+ # `*.e2e-spec.ts` (dot-form `.spec.ts` plus dash-form `-spec.ts`/`-test.ts`).
65
+ if echo "$FILE" | grep -qE '[.-](test|spec)\.(ts|tsx|js|jsx)$'; then
64
66
  continue
65
67
  fi
66
68
 
67
- # Skip files under a __tests__/ or __mocks__/ directory — fixtures, helpers,
68
- # setup, manual mocks, and other test infrastructure are imported by the test
69
- # files that exercise them; requiring a dedicated .test.ts is nonsensical.
70
- if echo "$FILE" | grep -qE '/__tests__/|/__mocks__/'; then
69
+ # Skip files under a __tests__/, __mocks__/, or top-level test/ directory —
70
+ # fixtures, helpers, setup (seed.ts, load-env.ts), manual mocks, and other
71
+ # test infrastructure are imported by the test files that exercise them;
72
+ # requiring a dedicated .test.ts for a fixture is nonsensical. `/test/` covers
73
+ # the NestJS e2e convention (apps/<app>/test/*.e2e-spec.ts) alongside the
74
+ # __tests__/ and __mocks__/ layouts.
75
+ if echo "$FILE" | grep -qE '/__tests__/|/__mocks__/|/test/'; then
71
76
  SKIPPED=$((SKIPPED + 1))
72
77
  continue
73
78
  fi
@@ -88,6 +93,15 @@ while IFS= read -r FILE; do
88
93
  continue
89
94
  fi
90
95
 
96
+ # Skip NestJS framework wrappers — *.module.ts are dependency-injection wiring
97
+ # barrels and *.decorator.ts are metadata-only; behavior lives in the
98
+ # providers/handlers they wire, which carry their own specs. Same category as
99
+ # the index barrel skip above.
100
+ if echo "$FILE" | grep -qE '\.(module|decorator)\.(ts|js)$'; then
101
+ SKIPPED=$((SKIPPED + 1))
102
+ continue
103
+ fi
104
+
91
105
  # Skip Next.js App Router framework files — page/layout/loading/error/route/
92
106
  # etc. are framework-convention wrappers, not logic-bearing modules. Same
93
107
  # category as the barrel/index skip above: behavior lives in the components
@@ -455,6 +455,78 @@ fi
455
455
 
456
456
  echo ""
457
457
 
458
+ # ===== HOOK SMOKE TESTS — cbp-session-start-hook =====
459
+ echo "## Hook Smoke Tests — cbp-session-start-hook (CHK-178)"
460
+
461
+ SESSION_START_HOOK="$HOOKS_DIR/cbp-session-start-hook.sh"
462
+
463
+ if [ ! -f "$SESSION_START_HOOK" ]; then
464
+ test_result "cbp-session-start-hook.sh present" "passed" "missing"
465
+ else
466
+ test_result "cbp-session-start-hook.sh present" "passed" "passed"
467
+
468
+ # Header/@scope check
469
+ FIRST_LINE=$(head -1 "$SESSION_START_HOOK")
470
+ if echo "$FIRST_LINE" | grep -q '^#!/'; then
471
+ test_result "cbp-session-start-hook.sh has shebang" "passed" "passed"
472
+ else
473
+ test_result "cbp-session-start-hook.sh has shebang" "passed" "missing"
474
+ fi
475
+
476
+ if grep -q '@scope: org-shared' "$SESSION_START_HOOK"; then
477
+ test_result "cbp-session-start-hook.sh has @scope: org-shared" "passed" "passed"
478
+ else
479
+ test_result "cbp-session-start-hook.sh has @scope: org-shared" "passed" "missing"
480
+ fi
481
+
482
+ # Syntax check
483
+ if bash -n "$SESSION_START_HOOK" 2>/dev/null; then
484
+ test_result "cbp-session-start-hook.sh bash -n syntax ok" "passed" "passed"
485
+ else
486
+ test_result "cbp-session-start-hook.sh bash -n syntax ok" "passed" "failed"
487
+ fi
488
+
489
+ # Graceful-degrade: run in a temp dir without .codebyplan/repo.json — hook
490
+ # must exit 0 (no-op) without invoking npx (stub npx as a no-op in PATH).
491
+ ISO=$(mktemp -d)
492
+ # Create a stub npx in a temp bin dir so npx invocations are harmless no-ops.
493
+ STUB_BIN=$(mktemp -d)
494
+ printf '#!/bin/bash\nexit 0\n' > "$STUB_BIN/npx"
495
+ chmod +x "$STUB_BIN/npx"
496
+ ACTUAL_EXIT=$(CLAUDE_PROJECT_DIR="$ISO" PATH="$STUB_BIN:$PATH" bash "$SESSION_START_HOOK" >/dev/null 2>&1; echo $?)
497
+ # In the no-repo.json path npx must NOT be invoked at all — use a recording
498
+ # stub marker dir to assert zero invocations.
499
+ rm -rf "$ISO" "$STUB_BIN"
500
+ if [ "$ACTUAL_EXIT" = "0" ]; then
501
+ test_result "cbp-session-start-hook.sh graceful-degrade (no repo.json) exits 0" "passed" "passed"
502
+ else
503
+ test_result "cbp-session-start-hook.sh graceful-degrade (no repo.json) exits 0" "passed" "failed (exit=$ACTUAL_EXIT)"
504
+ fi
505
+
506
+ # Positive path: with .codebyplan/repo.json present, the hook must invoke
507
+ # `npx codebyplan sync` AND `npx codebyplan watch start` (recording stub
508
+ # writes each invocation's args to a marker file), and still exit 0.
509
+ ISO=$(mktemp -d)
510
+ STUB_BIN=$(mktemp -d)
511
+ MARKER="$STUB_BIN/invocations.log"
512
+ mkdir -p "$ISO/.codebyplan"
513
+ printf '{}' > "$ISO/.codebyplan/repo.json"
514
+ printf '#!/bin/bash
515
+ echo "$@" >> "%s"
516
+ exit 0
517
+ ' "$MARKER" > "$STUB_BIN/npx"
518
+ chmod +x "$STUB_BIN/npx"
519
+ ACTUAL_EXIT=$(CLAUDE_PROJECT_DIR="$ISO" PATH="$STUB_BIN:$PATH" bash "$SESSION_START_HOOK" >/dev/null 2>&1; echo $?)
520
+ if [ "$ACTUAL_EXIT" = "0" ] && grep -q "codebyplan sync" "$MARKER" 2>/dev/null && grep -q "codebyplan watch start" "$MARKER" 2>/dev/null; then
521
+ test_result "cbp-session-start-hook.sh positive path invokes sync + watch start, exits 0" "passed" "passed"
522
+ else
523
+ test_result "cbp-session-start-hook.sh positive path invokes sync + watch start, exits 0" "passed" "failed (exit=$ACTUAL_EXIT)"
524
+ fi
525
+ rm -rf "$ISO" "$STUB_BIN"
526
+ fi
527
+
528
+ echo ""
529
+
458
530
  # ===== SUMMARY =====
459
531
  echo "=== TEST SUMMARY ==="
460
532
  echo -e "Passed: ${GREEN}$PASSED${NC}"
@@ -1,5 +1,16 @@
1
1
  {
2
2
  "hooks": {
3
+ "SessionStart": [
4
+ {
5
+ "hooks": [
6
+ {
7
+ "type": "command",
8
+ "command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/cbp-session-start-hook.sh",
9
+ "timeout": 30
10
+ }
11
+ ]
12
+ }
13
+ ],
3
14
  "UserPromptSubmit": [
4
15
  {
5
16
  "hooks": [
@@ -194,6 +194,16 @@
194
194
  "Bash(npx codebyplan lsp:*)",
195
195
  "Bash(codebyplan round:*)",
196
196
  "Bash(npx codebyplan round:*)",
197
+ "Bash(codebyplan sync:*)",
198
+ "Bash(npx codebyplan sync:*)",
199
+ "Bash(codebyplan watch:*)",
200
+ "Bash(npx codebyplan watch:*)",
201
+ "Bash(codebyplan checkpoint:*)",
202
+ "Bash(npx codebyplan checkpoint:*)",
203
+ "Bash(codebyplan task:*)",
204
+ "Bash(npx codebyplan task:*)",
205
+ "Bash(codebyplan session:*)",
206
+ "Bash(npx codebyplan session:*)",
197
207
  "Bash(codebyplan help:*)",
198
208
  "Bash(npx codebyplan help:*)",
199
209
  "Bash(codebyplan --version:*)",
@@ -14,17 +14,17 @@ Full re-evaluation: compares initial ideas vs delivered work, aggregates files a
14
14
 
15
15
  ### Step 1: Identify Checkpoint
16
16
 
17
- **If arguments provided:** Parse `$ARGUMENTS` for CHK-NNN format, extract number. Use MCP `get_checkpoints` to find by number.
17
+ **If arguments provided:** Parse `$ARGUMENTS` for CHK-NNN format, extract number. Scan `.codebyplan/state/checkpoints/*.json` to find by `number` field (local-first; if missing/stale run `npx codebyplan sync` once; break-glass: MCP `get_checkpoints`).
18
18
 
19
- **If NO arguments:** Use MCP `get_current_task` to get the active checkpoint.
19
+ **If NO arguments:** Read `.codebyplan/state/session/current.json` to get the active checkpoint (fallback: MCP `get_current_task`).
20
20
 
21
21
  If no checkpoint found, show error and stop.
22
22
 
23
23
  ### Step 2: Load All Data
24
24
 
25
- 1. Get checkpoint details (context, research, qa, ideas, goal, user_context)
26
- 2. Use MCP `get_tasks` for the checkpoint
27
- 3. For each task, use MCP `get_rounds` to get all rounds
25
+ 1. Read `.codebyplan/state/checkpoints/<id>.json` for checkpoint details (context, research, qa, ideas, goal, user_context). Break-glass: MCP `get_checkpoints`.
26
+ 2. Read task files under `.codebyplan/state/checkpoints/<id>/tasks/*.json` (fallback: MCP `get_tasks`).
27
+ 3. For each task, read round files under `.codebyplan/state/checkpoints/<id>/tasks/<taskId>/rounds/*.json` (fallback: MCP `get_rounds`).
28
28
 
29
29
  ### Step 3: Before/After Comparison
30
30
 
@@ -109,7 +109,7 @@ Aggregate the files touched across all tasks (reusing Step 4's deduplicated tabl
109
109
  credential_vars: [from e2e.json — env var names only, never secrets]
110
110
  ```
111
111
 
112
- Hold each specialist's output keyed by framework (an `e2e_outputs[framework]` map) for this skill's aggregation — checkpoint-check has no MCP round, so this lives in-memory during the run (persist to `checkpoint.context` via `update_checkpoint` at Step 7 if a durable record is needed). `test_strategy` is intentionally omitted — the agent resolves it from `.codebyplan/e2e.json` and the DB tech-stack record.
112
+ Hold each specialist's output keyed by framework (an `e2e_outputs[framework]` map) for this skill's aggregation — checkpoint-check has no MCP round, so this lives in-memory during the run (persist to `checkpoint.context` via the Step 7 CLI write-through — `codebyplan checkpoint update` — if a durable record is needed). `test_strategy` is intentionally omitted — the agent resolves it from `.codebyplan/e2e.json` and the DB tech-stack record.
113
113
 
114
114
  3. **Wait for all specialists to complete.** Each agent's output carries `whole_checkpoint_aggregated: true` confirming whole-checkpoint formatting.
115
115
 
@@ -120,7 +120,7 @@ Aggregate the files touched across all tasks (reusing Step 4's deduplicated tabl
120
120
  Continue to Step 6.
121
121
 
122
122
  5. **On fail** (any framework `f`: `e2e_outputs[f].status === 'failed'` OR `e2e_outputs[f].test_results.failed > 0`): build a failure summary from `e2e_outputs[*].test_results.failures[]` aggregated and grouped by `category`. Surface via `AskUserQuestion`:
123
- - **(a) Create fix-task in CHK-{NNN} (recommended)** — invoke MCP `create_task` with `checkpoint_id=current_checkpoint_id`, `title="Fix checkpoint-level e2e failures (CHK-{NNN})"`, `requirements` containing the detailed failure breakdown (category counts, files involved, pages broken, screenshot paths from `e2e_outputs[*].screenshots[]`), AND `context: { source_checkpoint_id, e2e_failure_summary: { category_counts, pages_broken, screenshot_paths }, fix_type: "checkpoint_e2e" }` so downstream `cbp-task-planner` can verify failure premises. Per `cbp-round-end` reference `findings-presentation.md` "Infra Issue Absorption Contract — Resolve-in-Current-Scope by Default", checkpoint-level e2e failures absorb into the active checkpoint — not standalone.
123
+ - **(a) Create fix-task in CHK-{NNN} (recommended)** — run `codebyplan task create` (CLI write-through; break-glass: MCP `create_task`) with `checkpoint_id=current_checkpoint_id`, `title="Fix checkpoint-level e2e failures (CHK-{NNN})"`, `requirements` containing the detailed failure breakdown (category counts, files involved, pages broken, screenshot paths from `e2e_outputs[*].screenshots[]`), AND `context: { source_checkpoint_id, e2e_failure_summary: { category_counts, pages_broken, screenshot_paths }, fix_type: "checkpoint_e2e" }` so downstream `cbp-task-planner` can verify failure premises. Per `cbp-round-end` reference `findings-presentation.md` "Infra Issue Absorption Contract — Resolve-in-Current-Scope by Default", checkpoint-level e2e failures absorb into the active checkpoint — not standalone.
124
124
  - **(b) Surface as warning only — proceed to checkpoint-end** — append `| Checkpoint E2E | warning | N failures (deferred) |` to Step 5 QA Summary; continue to Step 6.
125
125
  - **(c) Halt — review manually** — STOP and wait for the user.
126
126
 
@@ -145,7 +145,7 @@ If unapproved files exist:
145
145
 
146
146
  ### Step 7: Save Results
147
147
 
148
- Update checkpoint via MCP `update_checkpoint`:
148
+ Update checkpoint via `codebyplan checkpoint update --id <id> --qa <json> --context <json>` (CLI write-through; break-glass: MCP `update_checkpoint`):
149
149
  - `qa`: aggregated QA results
150
150
  - `context`: add `check_results` with before/after, file summary, assessment
151
151
 
@@ -155,6 +155,6 @@ If all clear, auto-trigger `/cbp-checkpoint-end`.
155
155
 
156
156
  ## Integration
157
157
 
158
- - **Reads**: MCP `get_checkpoints`, `get_tasks`, `get_rounds`, `get_current_task`
159
- - **Writes**: MCP `update_checkpoint` (qa, context)
158
+ - **Reads**: `.codebyplan/state/checkpoints/<id>.json`, `checkpoints/<id>/tasks/*.json`, `checkpoints/<id>/tasks/<taskId>/rounds/*.json`, `session/current.json` (local-first; `npx codebyplan sync` if stale; break-glass: MCP `get_checkpoints`, `get_tasks`, `get_rounds`, `get_current_task`)
159
+ - **Writes**: `codebyplan checkpoint update --qa ... --context ...` (CLI write-through; break-glass: MCP `update_checkpoint`)
160
160
  - **Triggers**: `/cbp-checkpoint-end` (auto, if ready) or STOPS for `/cbp-task-create` (if issues)
@@ -19,7 +19,7 @@ Parse the argument:
19
19
  | Shape | Regex | Resolves to |
20
20
  |-------|-------|-------------|
21
21
  | `{chk}` (e.g. `108`) | `^[0-9]+$` | Target CHK-{chk} |
22
- | _(empty)_ | — | Use MCP `get_current_task` to find the active checkpoint |
22
+ | _(empty)_ | — | Resolve from local state per Step 1.5/2 (MCP `get_current_task` break-glass) the active checkpoint |
23
23
 
24
24
  Anything else is malformed — surface this error and stop:
25
25
 
@@ -42,8 +42,8 @@ Given the parse from Step 0.5:
42
42
 
43
43
  | Parse | Resolution path |
44
44
  |-------|-----------------|
45
- | `{chk}` | MCP `get_checkpoints(repo_id)` filter `number === {chk}` (must exist). |
46
- | _(empty)_ | MCP `get_current_task` with repo_id. Get the active checkpoint. If no active checkpoint, show error and stop. |
45
+ | `{chk}` | Scan `.codebyplan/state/checkpoints/*.json` for `number === {chk}` (local-first; if missing/stale run `npx codebyplan sync` once; break-glass: MCP `get_checkpoints`). |
46
+ | _(empty)_ | Read `.codebyplan/state/session/current.json` for the active checkpoint (fallback: MCP `get_current_task`). If no active checkpoint, show error and stop. |
47
47
 
48
48
  ### Step 2: Verify Checkpoint End Has Run
49
49
 
@@ -59,7 +59,7 @@ Stop here.
59
59
 
60
60
  ### Step 2.5: Verify All Tasks Complete
61
61
 
62
- Use MCP `get_tasks` for the checkpoint. Verify all tasks have status `completed`.
62
+ Read task files under `.codebyplan/state/checkpoints/<id>/tasks/*.json` (fallback: MCP `get_tasks`). Verify all tasks have status `completed`.
63
63
 
64
64
  If incomplete tasks remain:
65
65
  ```
@@ -82,7 +82,7 @@ If any critical failures, warn the user but don't block.
82
82
 
83
83
  ### Step 4: Complete Checkpoint
84
84
 
85
- Use MCP `complete_checkpoint(checkpoint_id)`.
85
+ Run `codebyplan checkpoint complete --id <checkpoint-id>` (CLI write-through: updates `.codebyplan/state/checkpoints/<id>.json` + REST; break-glass: MCP `complete_checkpoint`).
86
86
 
87
87
  This automatically:
88
88
  - Sets status to `completed`
@@ -105,5 +105,5 @@ This automatically:
105
105
  ## Integration
106
106
 
107
107
  - **Triggered by**: `/cbp-checkpoint-end` (auto, after successful shipment)
108
- - **Reads**: MCP `get_current_task`, `get_tasks`, `get_rounds`
109
- - **Writes**: MCP `complete_checkpoint`
108
+ - **Reads**: `.codebyplan/state/session/current.json`, `checkpoints/<id>.json`, `checkpoints/<id>/tasks/*.json` (local-first; `npx codebyplan sync` if stale; break-glass: MCP `get_current_task`, `get_tasks`, `get_rounds`)
109
+ - **Writes**: `codebyplan checkpoint complete --id <id>` (CLI write-through; break-glass: MCP `complete_checkpoint`)
@@ -20,7 +20,7 @@ Runs INLINE. This is the **mechanical** stage only: capture raw user input, infe
20
20
 
21
21
  ### Step 1: Check for Existing Checkpoint Data
22
22
 
23
- Source `repo_id` from `.codebyplan/repo.json`. If `$ARGUMENTS` contains a checkpoint number, load it via MCP `get_checkpoints`. If the checkpoint already has `ideas[]` with descriptions, reuse `ideas[].description` (do not re-ask) and skip Step 2.
23
+ Source `repo_id` from `.codebyplan/repo.json`. If `$ARGUMENTS` contains a checkpoint number, read `.codebyplan/state/checkpoints/` to find the matching file by `number` field (local-first). If missing/stale, run `npx codebyplan sync` once and re-read. Break-glass fallback: MCP `get_checkpoints` when the state dir is absent and sync fails. If the checkpoint already has `ideas[]` with descriptions, reuse `ideas[].description` (do not re-ask) and skip Step 2.
24
24
 
25
25
  ### Step 2: Get Checkpoint Description
26
26
 
@@ -71,14 +71,16 @@ Record the choice; it drives both the create call (Step 8) and the plan→start
71
71
 
72
72
  ### Step 7: Determine Next Checkpoint Number
73
73
 
74
- MCP `get_checkpoints` for the repo; highest `number` + 1.
74
+ Scan `.codebyplan/state/checkpoints/*.json` for the highest `number` field + 1. If state dir is absent, run `npx codebyplan sync` once. Break-glass fallback: MCP `get_checkpoints` when sync fails.
75
75
 
76
76
  ### Step 8: Create Checkpoint Row
77
77
 
78
- MCP `create_checkpoint`:
79
- - `repo_id` (from `.codebyplan/repo.json`), `number`, `title`, `goal`, `deadline`, `status: "pending"`
80
- - `ideas`: `[{ description: <raw user text> }]`
81
- - `worktree_id`: the resolved worktree from Step 6 **only if the user chose "claim"**; omit when "leave open"
78
+ `codebyplan checkpoint create` (CLI write-through: writes `.codebyplan/state/checkpoints/<id>.json` + REST). Pass flags:
79
+ - `--repo-id` (from `.codebyplan/repo.json`), `--number`, `--title`, `--goal`, `--deadline`, `--status pending`
80
+ - `--ideas` JSON `[{ description: <raw user text> }]`
81
+ - `--worktree-id` the resolved worktree **only if the user chose "claim"**; omit when "leave open"
82
+
83
+ Break-glass fallback: MCP `create_checkpoint` when the CLI is unavailable.
82
84
 
83
85
  This is the first identity-stamping point — when claiming, passing `worktree_id` here engages the CHK-104 hard-lock from birth. No `context`, `research`, `plan`, or tasks are written here.
84
86
 
@@ -93,7 +95,7 @@ git checkout -b "feat/CHK-{NNN}-{slug}" "origin/$BASE" 2>/dev/null \
93
95
  git push -u origin "feat/CHK-{NNN}-{slug}"
94
96
  ```
95
97
 
96
- Slug: lowercase, dash-joined, punctuation dropped, ≤40 chars. Persist the branch via MCP `update_checkpoint(checkpoint_id, branch_name: "feat/CHK-{NNN}-{slug}")`. (The dedicated `/cbp-git-branch-feat-create` skill is the canonical config-driven helper if you prefer to delegate.)
98
+ Slug: lowercase, dash-joined, punctuation dropped, ≤40 chars. Persist the branch via `codebyplan checkpoint update --id <checkpoint-id> --branch-name "feat/CHK-{NNN}-{slug}"` (CLI write-through; break-glass: MCP `update_checkpoint`). (The dedicated `/cbp-git-branch-feat-create` skill is the canonical config-driven helper if you prefer to delegate.)
97
99
 
98
100
  **Note — Supabase preview branch**: no Supabase branch is created here. Creation is lazy — it happens on the first DB change when `/cbp-supabase-migrate` runs on this feat branch, which provisions a Supabase branch named identically to the git branch. See `cbp-supabase-migrate` Step 2.3 for the creation protocol.
99
101
 
@@ -113,6 +115,6 @@ Auto-trigger `/cbp-checkpoint-plan {NNN}` in the same context. This skill create
113
115
  ## Integration
114
116
 
115
117
  - **Runs inline**: mechanical setup only — no assessment, research, Q&A, plan, or tasks
116
- - **Reads**: MCP `get_checkpoints`; `.codebyplan/repo.json`, `.codebyplan/git.json`; `npx codebyplan resolve-worktree`
117
- - **Writes**: MCP `create_checkpoint` (description-only ideas + deadline + optional worktree_id), `update_checkpoint` (branch_name)
118
+ - **Reads**: `.codebyplan/state/checkpoints/*.json` (local-first; `npx codebyplan sync` if stale; MCP `get_checkpoints` break-glass); `.codebyplan/repo.json`, `.codebyplan/git.json`; `npx codebyplan resolve-worktree`
119
+ - **Writes**: `codebyplan checkpoint create` (description-only ideas + deadline + optional worktree_id), `codebyplan checkpoint update --branch-name` (break-glass: MCP `create_checkpoint` / `update_checkpoint`)
118
120
  - **Triggers**: `/cbp-checkpoint-plan` (auto)
@@ -34,7 +34,7 @@ Before any shipment logic, ensure the feat branch is current against main. Shipm
34
34
 
35
35
  ### Step 1: Get Active Checkpoint
36
36
 
37
- Use MCP `get_current_task` with repo_id. Get the active checkpoint.
37
+ 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.
38
38
 
39
39
  If no active checkpoint, show error and stop.
40
40
 
@@ -166,13 +166,12 @@ Only after both the local and remote git delete above succeed, run a conditional
166
166
 
167
167
  > Lifecycle contract: see [[supabase-branch-lifecycle]].
168
168
 
169
- - 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`.
170
- - Call `mcp__supabase__list_branches` with the resolved `project_id`.
169
+ - Call `mcp__supabase__list_branches` with `project_id: rrvtrumtkhrsbhcyrwvf`.
171
170
  - Scan the returned list for an entry whose `name` exactly equals `$BRANCH`.
172
171
  - If found: call `mcp__supabase__delete_branch` with its `branch_id`. Record the branch name in `SUPABASE_BRANCHES_DELETED[]`.
173
172
  - If not found: no-op silently — the GitHub integration may have already removed it on PR close; not-found is success, NOT an error.
174
173
  - If the `list_branches` call itself fails (network, auth, or a non-success response — distinct from a successful lookup that returns no match): emit a non-blocking warning that the Supabase preview branch for `$BRANCH` may still exist and should be verified in the dashboard. Do not treat an API failure as a not-found success.
175
- - 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.
174
+ - Never delete the parent project `rrvtrumtkhrsbhcyrwvf` itself or any persistent/production branch.
176
175
 
177
176
  Accumulate all Supabase branch names removed across the loop in `SUPABASE_BRANCHES_DELETED`.
178
177
 
@@ -199,17 +198,15 @@ git push origin --delete "$FEAT_BRANCH"
199
198
 
200
199
  After the feat branch git delete, run the same conditional Supabase teardown for `$FEAT_BRANCH`:
201
200
 
202
- - 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`.
203
- - Call `mcp__supabase__list_branches` with the resolved `project_id`.
201
+ - Call `mcp__supabase__list_branches` with `project_id: rrvtrumtkhrsbhcyrwvf`.
204
202
  - Scan for an entry whose `name` exactly equals `$FEAT_BRANCH`.
205
203
  - If found: call `mcp__supabase__delete_branch` with its `branch_id`. Add `$FEAT_BRANCH` to `SUPABASE_BRANCHES_DELETED[]`.
206
204
  - If not found: no-op silently — idempotent, not-found is success.
207
205
  - If the `list_branches` call itself fails (network, auth, or a non-success response — distinct from a successful lookup that returns no match): emit a non-blocking warning that the Supabase preview branch for `$FEAT_BRANCH` may still exist and should be verified in the dashboard. Do not treat an API failure as a not-found success.
208
- - 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.
209
206
 
210
207
  ### Step 10: Save Shipment Results and Summary
211
208
 
212
- Update checkpoint context via MCP `update_checkpoint`. The `shipment` block contains both branch promotion AND runtime surface results (from `/cbp-ship` Step 7):
209
+ Update checkpoint context via `codebyplan checkpoint update <id> --context '{"shipment": {...}}'` (CLI write-through); use MCP `update_checkpoint` as documented break-glass when the CLI is unavailable. The `shipment` block contains both branch promotion AND runtime surface results (from `/cbp-ship` Step 7):
213
210
 
214
211
  ```
215
212
  context.shipment: {
@@ -284,7 +281,7 @@ Auto-trigger `/cbp-checkpoint-complete`.
284
281
  ## Integration
285
282
 
286
283
  - **Triggered by**: `/cbp-checkpoint-check` (auto, when ready)
287
- - **Reads**: MCP `get_current_task`, `.codebyplan/git.json` (`branch_config`), `.codebyplan/server.json` (`auto_push_enabled`), `.codebyplan/shipment.json` (`shipment`), git branches
288
- - **Writes**: MCP `update_checkpoint` (context.shipment both branch promotion and runtime surface results)
284
+ - **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` (`branch_config`), `.codebyplan/server.json` (`auto_push_enabled`), `.codebyplan/shipment.json` (`shipment`), git branches.
285
+ - **Writes**: `codebyplan checkpoint update <id> --context '...'` (CLI write-through) for context.shipment; MCP `update_checkpoint` break-glass. Note: `mcp__supabase__list_branches` / `mcp__supabase__delete_branch` calls in Steps 8–9 are Supabase MCP (not CodeByPlan MCP) and are unchanged.
289
286
  - **Calls**: `/cbp-merge-main` (Step 0, sync); `/cbp-ship-main` (Step 5, branch promotion to main); `/cbp-ship` (Step 7, runtime surface deploy + verification)
290
287
  - **Triggers**: `/cbp-checkpoint-complete` (auto, after successful shipment)