codebyplan 1.11.2 → 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +590 -405
- package/package.json +1 -1
- package/templates/hooks/README.md +1 -13
- package/templates/hooks/cbp-statusline.mjs +44 -0
- package/templates/hooks/cbp-statusline.py +24 -2
- package/templates/hooks/cbp-statusline.sh +22 -2
- package/templates/hooks/cbp-test-coverage-gate.sh +8 -0
- package/templates/hooks/cbp-test-hooks.sh +0 -42
- package/templates/hooks/hooks.json +0 -9
- package/templates/rules/README.md +8 -1
- package/templates/rules/supabase-branch-lifecycle.md +99 -0
- package/templates/settings.project.base.json +1 -2
- package/templates/skills/cbp-build-cc-settings/reference/cbp-conventions.md +1 -2
- package/templates/skills/cbp-checkpoint-create/SKILL.md +2 -0
- package/templates/skills/cbp-checkpoint-end/SKILL.md +27 -5
- package/templates/skills/cbp-checkpoint-start/SKILL.md +2 -2
- package/templates/skills/cbp-git-worktree-remove/SKILL.md +17 -1
- package/templates/skills/cbp-session-start/SKILL.md +28 -3
- package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/SKILL.md +1 -1
- package/templates/skills/cbp-setup-eslint/SKILL.md +199 -0
- package/templates/skills/cbp-setup-eslint/reference/base.md +82 -0
- package/templates/skills/cbp-setup-eslint/reference/cli.md +56 -0
- package/templates/skills/cbp-setup-eslint/reference/e2e.md +68 -0
- package/templates/skills/cbp-setup-eslint/reference/jest.md +59 -0
- package/templates/skills/cbp-setup-eslint/reference/nestjs.md +69 -0
- package/templates/skills/cbp-setup-eslint/reference/nextjs.md +63 -0
- package/templates/skills/cbp-setup-eslint/reference/node.md +74 -0
- package/templates/skills/cbp-setup-eslint/reference/react-native.md +60 -0
- package/templates/skills/cbp-setup-eslint/reference/react.md +82 -0
- package/templates/skills/cbp-setup-eslint/reference/tailwind.md +64 -0
- package/templates/skills/cbp-setup-eslint/reference/testing-react.md +57 -0
- package/templates/skills/cbp-setup-eslint/reference/vitest.md +62 -0
- package/templates/skills/cbp-ship-main/SKILL.md +13 -0
- package/templates/skills/cbp-supabase-branch-check/SKILL.md +12 -5
- package/templates/skills/cbp-supabase-migrate/SKILL.md +139 -9
- package/templates/skills/cbp-supabase-migrate/reference/preflight-dry-run.md +1 -1
- package/templates/skills/cbp-supabase-setup/SKILL.md +13 -7
- package/templates/skills/cbp-supabase-setup/reference/branching-setup.md +2 -2
- package/templates/skills/cbp-task-complete/SKILL.md +1 -3
- package/templates/skills/cbp-task-start/SKILL.md +5 -3
- package/templates/hooks/cbp-mcp-worktree-inject.sh +0 -76
- /package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/reference/maestro.md +0 -0
- /package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/reference/playwright.md +0 -0
- /package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/reference/tauri.md +0 -0
- /package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/reference/vscode.md +0 -0
- /package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/reference/xcuitest.md +0 -0
package/package.json
CHANGED
|
@@ -228,18 +228,6 @@ Denies any `git stash` command (including `git -C <dir> stash` and `git stash po
|
|
|
228
228
|
|
|
229
229
|
---
|
|
230
230
|
|
|
231
|
-
### `cbp-mcp-worktree-inject.sh` — PreToolUse, matcher `mcp__codebyplan__(update_task|complete_task|complete_round|update_checkpoint)`
|
|
232
|
-
|
|
233
|
-
Auto-injects `caller_worktree_id` into CodeByPlan MCP mutation calls when it's missing, resolving it via `npx codebyplan resolve-worktree` (with `--fallback-from-branch`). Closes the manual worktree-pinning workaround so MCP writes pass the server-side worktree pre-guard without hand-editing every call.
|
|
234
|
-
|
|
235
|
-
**Blocks vs warns**: neither — emits an `updatedInput` to add the field when resolvable, otherwise passes the call through unchanged (graceful passthrough preserves backwards-compat).
|
|
236
|
-
|
|
237
|
-
**Skips when**: the call already carries `caller_worktree_id`, or no worktree can be resolved (both → clean passthrough). A no-op in repos that don't use the CodeByPlan MCP.
|
|
238
|
-
|
|
239
|
-
**Opt out**: settings.json override removing this entry, or plugin disable.
|
|
240
|
-
|
|
241
|
-
---
|
|
242
|
-
|
|
243
231
|
### `cbp-mcp-round-sync.sh` — PostToolUse, matcher `mcp__codebyplan__complete_round`
|
|
244
232
|
|
|
245
233
|
After a `complete_round` MCP call succeeds, reconciles the round's `files_changed[]` against `git status`: new files in the diff are added (unapproved), and approval records no longer in the diff are flagged `removed_from_diff` (never deleted — lifecycle preserved).
|
|
@@ -258,7 +246,7 @@ After a `complete_round` MCP call succeeds, reconciles the round's `files_change
|
|
|
258
246
|
|
|
259
247
|
Test suite for the plugin's 10 registered hooks. Runs two passes:
|
|
260
248
|
|
|
261
|
-
1. **Header check** — every registered hook (`lint-format-on-edit`, `test-coverage-gate`, `pre-commit-quality-gate`, `maestro-yaml-validate`, `notify`, `auto-test-hooks`, `mcp-migration-guard`, `validate-git-stash-deny`, `cbp-mcp-
|
|
249
|
+
1. **Header check** — every registered hook (`lint-format-on-edit`, `test-coverage-gate`, `pre-commit-quality-gate`, `maestro-yaml-validate`, `notify`, `auto-test-hooks`, `mcp-migration-guard`, `validate-git-stash-deny`, `cbp-mcp-round-sync`) carries the required `# Hook:` and `# Purpose:` header comments. `statusline` uses its own `# Claude Code Status Line` marker.
|
|
262
250
|
2. **Functional smoke tests** — each hook is invoked with synthetic stdin matching its fast-path / graceful-degrade input; all must exit 0.
|
|
263
251
|
|
|
264
252
|
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`.
|
|
@@ -118,6 +118,7 @@ function main() {
|
|
|
118
118
|
rate_limits: true,
|
|
119
119
|
repo_pr: true,
|
|
120
120
|
worktree: true,
|
|
121
|
+
infra_drift: true,
|
|
121
122
|
no_color: false,
|
|
122
123
|
};
|
|
123
124
|
try {
|
|
@@ -136,6 +137,7 @@ function main() {
|
|
|
136
137
|
"rate_limits",
|
|
137
138
|
"repo_pr",
|
|
138
139
|
"worktree",
|
|
140
|
+
"infra_drift",
|
|
139
141
|
]) {
|
|
140
142
|
if (typeof parsed.lines[k] === "boolean") cfg[k] = parsed.lines[k];
|
|
141
143
|
}
|
|
@@ -374,6 +376,48 @@ function main() {
|
|
|
374
376
|
}
|
|
375
377
|
}
|
|
376
378
|
|
|
379
|
+
// ============================================================
|
|
380
|
+
// LINE 7 — Infra drift (monorepo feat branches behind main)
|
|
381
|
+
// ============================================================
|
|
382
|
+
// Only the codebyplan monorepo (templates/ present) on a feat branch can carry
|
|
383
|
+
// stale .claude/ infra. No fetch — counts against the cached origin/main only.
|
|
384
|
+
if (shouldShow("INFRA_DRIFT", cfg.infra_drift)) {
|
|
385
|
+
if (
|
|
386
|
+
BRANCH.startsWith("feat/") &&
|
|
387
|
+
fs.existsSync(
|
|
388
|
+
path.join(root, "packages", "codebyplan-package", "templates")
|
|
389
|
+
)
|
|
390
|
+
) {
|
|
391
|
+
let behind = 0;
|
|
392
|
+
try {
|
|
393
|
+
behind = parseInt(
|
|
394
|
+
execFileSync(
|
|
395
|
+
"git",
|
|
396
|
+
[
|
|
397
|
+
"-C",
|
|
398
|
+
root,
|
|
399
|
+
"rev-list",
|
|
400
|
+
"--count",
|
|
401
|
+
"HEAD..origin/main",
|
|
402
|
+
"--",
|
|
403
|
+
".claude",
|
|
404
|
+
"packages/codebyplan-package/templates",
|
|
405
|
+
],
|
|
406
|
+
{ encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }
|
|
407
|
+
).trim(),
|
|
408
|
+
10
|
|
409
|
+
);
|
|
410
|
+
} catch {
|
|
411
|
+
behind = 0;
|
|
412
|
+
}
|
|
413
|
+
if (Number.isFinite(behind) && behind > 0) {
|
|
414
|
+
out.push(
|
|
415
|
+
`${C.YELLOW}⚠ infra ${behind} behind${C.RST} ${C.DIM}→ /cbp-refresh-infra${C.RST}`
|
|
416
|
+
);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
377
421
|
process.stdout.write(out.length ? out.join("\n") + "\n" : "");
|
|
378
422
|
}
|
|
379
423
|
|
|
@@ -80,7 +80,8 @@ def main():
|
|
|
80
80
|
# ---- Config: line toggles + no_color -------------------------------------
|
|
81
81
|
cfg = {
|
|
82
82
|
"identity": True, "context": True, "cost": True,
|
|
83
|
-
"rate_limits": True, "repo_pr": True, "worktree": True,
|
|
83
|
+
"rate_limits": True, "repo_pr": True, "worktree": True,
|
|
84
|
+
"infra_drift": True, "no_color": False,
|
|
84
85
|
}
|
|
85
86
|
try:
|
|
86
87
|
with open(os.path.join(root, ".codebyplan", "statusline.json"), "r", encoding="utf-8") as fh:
|
|
@@ -90,7 +91,7 @@ def main():
|
|
|
90
91
|
cfg["no_color"] = parsed["no_color"]
|
|
91
92
|
lines = parsed.get("lines")
|
|
92
93
|
if isinstance(lines, dict):
|
|
93
|
-
for k in ["identity", "context", "cost", "rate_limits", "repo_pr", "worktree"]:
|
|
94
|
+
for k in ["identity", "context", "cost", "rate_limits", "repo_pr", "worktree", "infra_drift"]:
|
|
94
95
|
if isinstance(lines.get(k), bool):
|
|
95
96
|
cfg[k] = lines[k]
|
|
96
97
|
except Exception:
|
|
@@ -321,6 +322,27 @@ def main():
|
|
|
321
322
|
l6 += " %s%s%s" % (DIM, wt_path_disp, RST)
|
|
322
323
|
out.append(l6)
|
|
323
324
|
|
|
325
|
+
# ===== LINE 7 — Infra drift (monorepo feat branches behind main) =====
|
|
326
|
+
# Only the codebyplan monorepo (templates/ present) on a feat branch can carry
|
|
327
|
+
# stale .claude/ infra. No fetch — counts against the cached origin/main only.
|
|
328
|
+
if should_show("INFRA_DRIFT", cfg["infra_drift"]):
|
|
329
|
+
if branch.startswith("feat/") and os.path.isdir(
|
|
330
|
+
os.path.join(root, "packages", "codebyplan-package", "templates")
|
|
331
|
+
):
|
|
332
|
+
behind = 0
|
|
333
|
+
try:
|
|
334
|
+
res = subprocess.run(
|
|
335
|
+
["git", "-C", root, "rev-list", "--count", "HEAD..origin/main",
|
|
336
|
+
"--", ".claude", "packages/codebyplan-package/templates"],
|
|
337
|
+
stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, text=True,
|
|
338
|
+
)
|
|
339
|
+
if res.returncode == 0:
|
|
340
|
+
behind = int(res.stdout.strip() or "0")
|
|
341
|
+
except Exception:
|
|
342
|
+
behind = 0
|
|
343
|
+
if behind > 0:
|
|
344
|
+
out.append("%s⚠ infra %d behind%s %s→ /cbp-refresh-infra%s" % (YELLOW, behind, RST, DIM, RST))
|
|
345
|
+
|
|
324
346
|
sys.stdout.write(("\n".join(out) + "\n") if out else "")
|
|
325
347
|
|
|
326
348
|
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
#
|
|
16
16
|
# DISPLAY OPTIONS (team-shared, committed)
|
|
17
17
|
# .codebyplan/statusline.json -> { "lines": {identity,context,cost,rate_limits,
|
|
18
|
-
# repo_pr,worktree}, "no_color": bool }
|
|
18
|
+
# repo_pr,worktree,infra_drift}, "no_color": bool }
|
|
19
19
|
#
|
|
20
20
|
# ENV-VAR OVERRIDES (env > config > default)
|
|
21
21
|
# CBP_STATUSLINE_HIDE_IDENTITY=1 suppress line 1 (folder, branch, model, effort, …)
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
# CBP_STATUSLINE_HIDE_RATE_LIMITS=1 suppress line 4 (5h / 7d rate limits)
|
|
25
25
|
# CBP_STATUSLINE_HIDE_REPO_PR=1 suppress line 5 (repo host/owner/name, PR)
|
|
26
26
|
# CBP_STATUSLINE_HIDE_WORKTREE=1 suppress line 6 (worktree name/branch/path)
|
|
27
|
+
# CBP_STATUSLINE_HIDE_INFRA_DRIFT=1 suppress line 7 (.claude infra commits behind main)
|
|
27
28
|
# CBP_STATUSLINE_NO_COLOR=1 strip all ANSI colour codes (also honoured by $NO_COLOR)
|
|
28
29
|
#
|
|
29
30
|
# TEST SEAMS (no effect in normal use)
|
|
@@ -104,7 +105,7 @@ eval "$(echo "$INPUT" | jq -r '
|
|
|
104
105
|
|
|
105
106
|
# ---- Config: line toggles + no_color from .codebyplan/statusline.json --------
|
|
106
107
|
CFG_IDENTITY=true; CFG_CONTEXT=true; CFG_COST=true
|
|
107
|
-
CFG_RATE_LIMITS=true; CFG_REPO_PR=true; CFG_WORKTREE=true; CFG_NO_COLOR=false
|
|
108
|
+
CFG_RATE_LIMITS=true; CFG_REPO_PR=true; CFG_WORKTREE=true; CFG_INFRA_DRIFT=true; CFG_NO_COLOR=false
|
|
108
109
|
CBP_CFG="$CBP_ROOT/.codebyplan/statusline.json"
|
|
109
110
|
if [ -f "$CBP_CFG" ] && command -v jq >/dev/null 2>&1; then
|
|
110
111
|
# Use `!= false` / `== true` (NOT jq `//`): the `//` operator treats an explicit
|
|
@@ -117,6 +118,7 @@ if [ -f "$CBP_CFG" ] && command -v jq >/dev/null 2>&1; then
|
|
|
117
118
|
"CFG_RATE_LIMITS=\(.lines.rate_limits != false)",
|
|
118
119
|
"CFG_REPO_PR=\(.lines.repo_pr != false)",
|
|
119
120
|
"CFG_WORKTREE=\(.lines.worktree != false)",
|
|
121
|
+
"CFG_INFRA_DRIFT=\(.lines.infra_drift != false)",
|
|
120
122
|
"CFG_NO_COLOR=\(.no_color == true)"
|
|
121
123
|
' "$CBP_CFG" 2>/dev/null)"
|
|
122
124
|
fi
|
|
@@ -401,3 +403,21 @@ if should_show WORKTREE "$CFG_WORKTREE"; then
|
|
|
401
403
|
printf "%b\n" "$L6"
|
|
402
404
|
fi
|
|
403
405
|
fi
|
|
406
|
+
|
|
407
|
+
# ============================================================
|
|
408
|
+
# LINE 7 — Infra drift (monorepo feat branches behind main)
|
|
409
|
+
# ============================================================
|
|
410
|
+
# Only the codebyplan monorepo (templates/ present) on a feat branch can carry
|
|
411
|
+
# stale .claude/ infra. No fetch — counts against the cached origin/main only.
|
|
412
|
+
if should_show INFRA_DRIFT "$CFG_INFRA_DRIFT"; then
|
|
413
|
+
case "$BRANCH" in
|
|
414
|
+
feat/*)
|
|
415
|
+
if [ -d "$CBP_ROOT/packages/codebyplan-package/templates" ]; then
|
|
416
|
+
BEHIND="$(git -C "$CBP_ROOT" rev-list --count HEAD..origin/main -- .claude packages/codebyplan-package/templates 2>/dev/null)"
|
|
417
|
+
if [ -n "$BEHIND" ] && [ "$BEHIND" -gt 0 ] 2>/dev/null; then
|
|
418
|
+
printf "%b\n" "${YELLOW}⚠ infra ${BEHIND} behind${RST} ${DIM}→ /cbp-refresh-infra${RST}"
|
|
419
|
+
fi
|
|
420
|
+
fi
|
|
421
|
+
;;
|
|
422
|
+
esac
|
|
423
|
+
fi
|
|
@@ -64,6 +64,14 @@ while IFS= read -r FILE; do
|
|
|
64
64
|
continue
|
|
65
65
|
fi
|
|
66
66
|
|
|
67
|
+
# Skip files under a __tests__/ directory — fixtures, helpers, setup, and
|
|
68
|
+
# other test infrastructure are imported by the test files that exercise
|
|
69
|
+
# them; requiring a dedicated .test.ts for a fixture is nonsensical.
|
|
70
|
+
if echo "$FILE" | grep -qE '/__tests__/'; then
|
|
71
|
+
SKIPPED=$((SKIPPED + 1))
|
|
72
|
+
continue
|
|
73
|
+
fi
|
|
74
|
+
|
|
67
75
|
# Skip infrastructure / generated / config files (generic skips — harmless if user doesn't have these dirs)
|
|
68
76
|
if echo "$FILE" | grep -qE '^\.claude/|^docs/|^supabase/|\.config\.|\.json$|\.md$|\.ya?ml$|\.sh$|\.scss$|\.css$'; then
|
|
69
77
|
continue
|
|
@@ -207,48 +207,6 @@ else
|
|
|
207
207
|
fi
|
|
208
208
|
fi
|
|
209
209
|
|
|
210
|
-
# --- cbp-mcp-worktree-inject.sh ---
|
|
211
|
-
|
|
212
|
-
if [ ! -f "$HOOKS_DIR/cbp-mcp-worktree-inject.sh" ]; then
|
|
213
|
-
test_result "cbp-mcp-worktree-inject.sh present" "passed" "missing"
|
|
214
|
-
else
|
|
215
|
-
test_result "cbp-mcp-worktree-inject.sh present" "passed" "passed"
|
|
216
|
-
|
|
217
|
-
FIRST_LINE=$(head -1 "$HOOKS_DIR/cbp-mcp-worktree-inject.sh")
|
|
218
|
-
if echo "$FIRST_LINE" | grep -q '^#!/'; then
|
|
219
|
-
test_result "cbp-mcp-worktree-inject.sh has shebang" "passed" "passed"
|
|
220
|
-
else
|
|
221
|
-
test_result "cbp-mcp-worktree-inject.sh has shebang" "passed" "missing"
|
|
222
|
-
fi
|
|
223
|
-
|
|
224
|
-
if grep -q '@scope: org-shared' "$HOOKS_DIR/cbp-mcp-worktree-inject.sh"; then
|
|
225
|
-
test_result "cbp-mcp-worktree-inject.sh has @scope: org-shared" "passed" "passed"
|
|
226
|
-
else
|
|
227
|
-
test_result "cbp-mcp-worktree-inject.sh has @scope: org-shared" "passed" "missing"
|
|
228
|
-
fi
|
|
229
|
-
|
|
230
|
-
FIXTURES_DIR="$HOOKS_DIR/__test-fixtures__/cbp-mcp-worktree-inject"
|
|
231
|
-
if [ -d "$FIXTURES_DIR" ]; then
|
|
232
|
-
# already-has-id.json — expect exit 0 (passthrough)
|
|
233
|
-
ACTUAL_EXIT=$(bash "$HOOKS_DIR/cbp-mcp-worktree-inject.sh" < "$FIXTURES_DIR/already-has-id.json" >/dev/null 2>&1; echo $?)
|
|
234
|
-
if [ "$ACTUAL_EXIT" = "0" ]; then
|
|
235
|
-
test_result "cbp-mcp-worktree-inject.sh already-has-id exits 0" "passed" "passed"
|
|
236
|
-
else
|
|
237
|
-
test_result "cbp-mcp-worktree-inject.sh already-has-id exits 0" "passed" "failed (exit $ACTUAL_EXIT)"
|
|
238
|
-
fi
|
|
239
|
-
|
|
240
|
-
# missing-id-both-empty.json — resolvers return empty (in test env), expect exit 0
|
|
241
|
-
ACTUAL_EXIT=$(bash "$HOOKS_DIR/cbp-mcp-worktree-inject.sh" < "$FIXTURES_DIR/missing-id-both-empty.json" >/dev/null 2>&1; echo $?)
|
|
242
|
-
if [ "$ACTUAL_EXIT" = "0" ]; then
|
|
243
|
-
test_result "cbp-mcp-worktree-inject.sh missing-id passthrough exits 0" "passed" "passed"
|
|
244
|
-
else
|
|
245
|
-
test_result "cbp-mcp-worktree-inject.sh missing-id passthrough exits 0" "passed" "failed (exit $ACTUAL_EXIT)"
|
|
246
|
-
fi
|
|
247
|
-
else
|
|
248
|
-
test_result "cbp-mcp-worktree-inject.sh fixtures dir present" "passed" "missing"
|
|
249
|
-
fi
|
|
250
|
-
fi
|
|
251
|
-
|
|
252
210
|
# --- cbp-mcp-round-sync.sh ---
|
|
253
211
|
|
|
254
212
|
if [ ! -f "$HOOKS_DIR/cbp-mcp-round-sync.sh" ]; then
|
|
@@ -35,15 +35,6 @@
|
|
|
35
35
|
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/cbp-mcp-migration-guard.sh"
|
|
36
36
|
}
|
|
37
37
|
]
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
"matcher": "mcp__codebyplan__(update_task|complete_task|complete_round|update_checkpoint)",
|
|
41
|
-
"hooks": [
|
|
42
|
-
{
|
|
43
|
-
"type": "command",
|
|
44
|
-
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/cbp-mcp-worktree-inject.sh"
|
|
45
|
-
}
|
|
46
|
-
]
|
|
47
38
|
}
|
|
48
39
|
],
|
|
49
40
|
"PostToolUse": [
|
|
@@ -34,7 +34,14 @@ The `install`/`update`/`uninstall` flow handles these files identically to how i
|
|
|
34
34
|
|
|
35
35
|
## Current status
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
Four rules are shipped:
|
|
38
|
+
|
|
39
|
+
| Rule file | Summary |
|
|
40
|
+
|---|---|
|
|
41
|
+
| `scope-vocabulary.md` | Canonical scope-marker enum (`org-shared` / `project-shared` / `repo-only:<name>`) enforced by three validators |
|
|
42
|
+
| `context-file-loading.md` | Context-file load contract — who loads what, when, and how missing files are handled |
|
|
43
|
+
| `todo-backend.md` | Todos queue contract, six DB-layer workflow invariants, and writer obligations for MCP mutators |
|
|
44
|
+
| `supabase-branch-lifecycle.md` | Supabase preview-branch lifecycle mirrors the git feat-branch lifecycle — lazy create on first DB change, delete wherever the git branch is removed |
|
|
38
45
|
|
|
39
46
|
## Contributing a rule
|
|
40
47
|
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
---
|
|
2
|
+
scope: org-shared
|
|
3
|
+
description: Supabase preview-branch lifecycle mirrors the git feat-branch lifecycle
|
|
4
|
+
paths:
|
|
5
|
+
- "supabase/migrations/**"
|
|
6
|
+
- ".codebyplan/shipment.json"
|
|
7
|
+
- ".codebyplan/git.json"
|
|
8
|
+
- ".claude/skills/cbp-supabase-migrate/**"
|
|
9
|
+
- ".claude/skills/cbp-supabase-branch-check/**"
|
|
10
|
+
- ".claude/skills/cbp-checkpoint-end/**"
|
|
11
|
+
- ".claude/skills/cbp-git-worktree-remove/**"
|
|
12
|
+
- ".claude/skills/cbp-ship-main/**"
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Supabase Branch Lifecycle
|
|
16
|
+
|
|
17
|
+
When a checkpoint or standalone task does DB work on its own feat branch, that branch gets
|
|
18
|
+
a Supabase preview branch whose lifecycle mirrors the git branch — created on first DB
|
|
19
|
+
change, deleted when the git branch is removed.
|
|
20
|
+
|
|
21
|
+
## Contract
|
|
22
|
+
|
|
23
|
+
Each feat branch that touches the database owns exactly one Supabase preview branch, named
|
|
24
|
+
identically to the git branch. The git branch is the source of truth; the Supabase branch
|
|
25
|
+
follows it.
|
|
26
|
+
|
|
27
|
+
## Create (lazy)
|
|
28
|
+
|
|
29
|
+
The Supabase branch is created by `cbp-supabase-migrate` (Step 2.3) on the **first DB
|
|
30
|
+
change** for the branch — never eagerly at git-branch creation time. Creation is guarded
|
|
31
|
+
by the skill's db_paths detection so the step fires only when the invocation actually
|
|
32
|
+
touches the database.
|
|
33
|
+
|
|
34
|
+
The branch is named **verbatim** after the git branch, slashes included (e.g.
|
|
35
|
+
`feat/CHK-144-supabase-branch-lifecycle`). This identical naming is the linchpin: the
|
|
36
|
+
GitHub branching integration reconciles to the same branch on PR open rather than creating
|
|
37
|
+
a duplicate.
|
|
38
|
+
|
|
39
|
+
After creation, the branch name and resulting `project_ref` are recorded on the parent
|
|
40
|
+
checkpoint or standalone task context (via `mcp__codebyplan__update_checkpoint` /
|
|
41
|
+
`mcp__codebyplan__update_task`) and may also be noted in `.codebyplan/shipment.json` so
|
|
42
|
+
cleanup skills can discover and remove it without querying the API.
|
|
43
|
+
|
|
44
|
+
## Delete
|
|
45
|
+
|
|
46
|
+
The Supabase branch is removed wherever the git branch is deleted:
|
|
47
|
+
|
|
48
|
+
| Skill | Trigger |
|
|
49
|
+
|---|---|
|
|
50
|
+
| `cbp-checkpoint-end` | stale-branch cleanup + current feat-branch delete on ship |
|
|
51
|
+
| `cbp-git-worktree-remove` | worktree teardown removes the coupled Supabase branch |
|
|
52
|
+
| `cbp-ship-main` | `branch_deleted` event after PR merge |
|
|
53
|
+
|
|
54
|
+
Deletion is **existence-checked and idempotent** — a not-found response is treated as
|
|
55
|
+
success. This tolerates the GitHub integration auto-deleting the preview branch on PR
|
|
56
|
+
close before the skill runs.
|
|
57
|
+
|
|
58
|
+
These skills use `delete_branch` (MCP tool), never `merge_branch`. Production migrations
|
|
59
|
+
reach main via the existing merge path (GitHub rebuild / `last_shipped_migration_version`);
|
|
60
|
+
there is no separate Supabase branch merge step.
|
|
61
|
+
|
|
62
|
+
## Exclusions
|
|
63
|
+
|
|
64
|
+
This lifecycle applies **only to feat branches**. It MUST NOT fire for:
|
|
65
|
+
|
|
66
|
+
- The main/production branch (`branch_config.production`, default `"main"`)
|
|
67
|
+
- Any branch listed in `branch_config.protected[]`
|
|
68
|
+
- A standalone task running directly on the production branch
|
|
69
|
+
- The integration branch (`branch_config.integration`) when non-null — it gets a persistent branch via `cbp-supabase-setup`, not a lazy ephemeral one.
|
|
70
|
+
|
|
71
|
+
`cbp-supabase-migrate` Step 2.3 Guard 1 enforces this by reading `.codebyplan/git.json`
|
|
72
|
+
and skipping provisioning when the current branch matches `$PRODUCTION`, `$PROTECTED`, or
|
|
73
|
+
a non-null `$INTEGRATION`.
|
|
74
|
+
|
|
75
|
+
## Guards
|
|
76
|
+
|
|
77
|
+
Skills that delete Supabase branches MUST:
|
|
78
|
+
|
|
79
|
+
1. Verify the branch name matches the feat branch being removed (never delete by
|
|
80
|
+
`project_ref` alone).
|
|
81
|
+
2. Never delete the parent/production project (`rrvtrumtkhrsbhcyrwvf`) itself.
|
|
82
|
+
3. Never delete a persistent/long-lived branch that does not correspond to the git branch
|
|
83
|
+
being torn down.
|
|
84
|
+
|
|
85
|
+
## PR Gate (retained)
|
|
86
|
+
|
|
87
|
+
`cbp-supabase-branch-check` runs as a required PR gate, independent of the create/delete
|
|
88
|
+
coupling. By-name resolution works whether the branch was created by `cbp-supabase-migrate`
|
|
89
|
+
or auto-created by the GitHub integration — both paths use the same branch name.
|
|
90
|
+
|
|
91
|
+
## Skill Map
|
|
92
|
+
|
|
93
|
+
| Role | Skill |
|
|
94
|
+
|---|---|
|
|
95
|
+
| Create (lazy) | `cbp-supabase-migrate` (Step 2.3) |
|
|
96
|
+
| Delete | `cbp-checkpoint-end`, `cbp-git-worktree-remove`, `cbp-ship-main` |
|
|
97
|
+
| PR gate | `cbp-supabase-branch-check` |
|
|
98
|
+
|
|
99
|
+
Each skill in the Skill Map above carries an inline back-reference to this rule at its create or teardown step.
|
|
@@ -47,8 +47,7 @@ These values are part of the CBP baseline and should not be weakened:
|
|
|
47
47
|
"Bash(git push --force:*)",
|
|
48
48
|
"Bash(git push -f:*)",
|
|
49
49
|
"Bash(git checkout -- :*)",
|
|
50
|
-
"Bash(git add
|
|
51
|
-
"Bash(git add -A:*)",
|
|
50
|
+
"Bash(git add:*)",
|
|
52
51
|
"Bash(rm -rf:*)",
|
|
53
52
|
"Bash(pnpm add:*)",
|
|
54
53
|
"Bash(pnpm install:*)",
|
|
@@ -95,6 +95,8 @@ git push -u origin "feat/CHK-{NNN}-{slug}"
|
|
|
95
95
|
|
|
96
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.)
|
|
97
97
|
|
|
98
|
+
**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
|
+
|
|
98
100
|
### Step 10: Show Result + Auto-Trigger Plan
|
|
99
101
|
|
|
100
102
|
```
|
|
@@ -141,13 +141,25 @@ C) Keep all
|
|
|
141
141
|
|
|
142
142
|
Only delete with explicit user confirmation. Delete both local and remote:
|
|
143
143
|
```bash
|
|
144
|
-
git branch -d "$BRANCH"
|
|
145
|
-
git push origin --delete "$BRANCH"
|
|
144
|
+
git branch -d "$BRANCH" && git push origin --delete "$BRANCH"
|
|
146
145
|
```
|
|
147
146
|
|
|
147
|
+
Only after both the local and remote git delete above succeed, run a conditional Supabase preview-branch teardown for that branch name (do not suppress the delete output — a failed local delete must stay visible):
|
|
148
|
+
|
|
149
|
+
> Lifecycle contract: see [[supabase-branch-lifecycle]].
|
|
150
|
+
|
|
151
|
+
- Call `mcp__supabase__list_branches` with `project_id: rrvtrumtkhrsbhcyrwvf`.
|
|
152
|
+
- Scan the returned list for an entry whose `name` exactly equals `$BRANCH`.
|
|
153
|
+
- If found: call `mcp__supabase__delete_branch` with its `branch_id`. Record the branch name in `SUPABASE_BRANCHES_DELETED[]`.
|
|
154
|
+
- If not found: no-op silently — the GitHub integration may have already removed it on PR close; not-found is success, NOT an error.
|
|
155
|
+
- 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.
|
|
156
|
+
- Never delete the parent project `rrvtrumtkhrsbhcyrwvf` itself or any persistent/production branch.
|
|
157
|
+
|
|
158
|
+
Accumulate all Supabase branch names removed across the loop in `SUPABASE_BRANCHES_DELETED`.
|
|
159
|
+
|
|
148
160
|
### Step 9: Current Feat Branch Cleanup
|
|
149
161
|
|
|
150
|
-
|
|
162
|
+
Before asking about the current feat branch, present a partial summary of what has shipped so far — runtime surfaces (from `/cbp-ship` Step 7), stale branches cleaned (Step 8), and the `SUPABASE_BRANCHES_DELETED` accumulated so far — then ask about the current feat branch via AskUserQuestion (the complete shipment record is finalised in Step 10):
|
|
151
163
|
|
|
152
164
|
```
|
|
153
165
|
The current feat branch [BRANCH] has been fully merged.
|
|
@@ -166,6 +178,14 @@ git branch -d "$FEAT_BRANCH"
|
|
|
166
178
|
git push origin --delete "$FEAT_BRANCH"
|
|
167
179
|
```
|
|
168
180
|
|
|
181
|
+
After the feat branch git delete, run the same conditional Supabase teardown for `$FEAT_BRANCH`:
|
|
182
|
+
|
|
183
|
+
- Call `mcp__supabase__list_branches` with `project_id: rrvtrumtkhrsbhcyrwvf`.
|
|
184
|
+
- Scan for an entry whose `name` exactly equals `$FEAT_BRANCH`.
|
|
185
|
+
- If found: call `mcp__supabase__delete_branch` with its `branch_id`. Add `$FEAT_BRANCH` to `SUPABASE_BRANCHES_DELETED[]`.
|
|
186
|
+
- If not found: no-op silently — idempotent, not-found is success.
|
|
187
|
+
- 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.
|
|
188
|
+
|
|
169
189
|
### Step 10: Save Shipment Results and Summary
|
|
170
190
|
|
|
171
191
|
Update checkpoint context via MCP `update_checkpoint`. The `shipment` block contains both branch promotion AND runtime surface results (from `/cbp-ship` Step 7):
|
|
@@ -177,8 +197,9 @@ context.shipment: {
|
|
|
177
197
|
feat_to_base: { pr_url, merged: true/false },
|
|
178
198
|
surfaces: [...], // populated by /cbp-ship — per-surface deploy results
|
|
179
199
|
skipped: [...], // populated by /cbp-ship — surfaces explicitly skipped
|
|
180
|
-
stale_branches_cleaned: [list of deleted branches],
|
|
181
|
-
feat_branch_deleted: true/false
|
|
200
|
+
stale_branches_cleaned: [list of deleted git branches],
|
|
201
|
+
feat_branch_deleted: true/false,
|
|
202
|
+
supabase_branches_deleted: [list of Supabase preview branch names removed in Steps 8–9]
|
|
182
203
|
}
|
|
183
204
|
```
|
|
184
205
|
|
|
@@ -198,6 +219,7 @@ Present summary:
|
|
|
198
219
|
### Branch Operations
|
|
199
220
|
- Stale branches deleted: [N] ([list])
|
|
200
221
|
- Feat branch: [deleted/kept]
|
|
222
|
+
- Supabase preview branches deleted: [N] ([list from supabase_branches_deleted], or "none")
|
|
201
223
|
|
|
202
224
|
### Before/After Branch State
|
|
203
225
|
- Before: [list of feat/* branches]
|
|
@@ -57,7 +57,7 @@ This mirrors the CHK-104 hard-lock model — never wrest a checkpoint from a liv
|
|
|
57
57
|
|
|
58
58
|
If the checkpoint is already `active` AND `worktree_id` already equals `CALLER_WT` (the Step 3 no-op row), skip this step entirely and proceed to Step 5 — nothing to write.
|
|
59
59
|
|
|
60
|
-
Otherwise set the checkpoint `active` via MCP `update_checkpoint(checkpoint_id, status: "active"`, plus `worktree_id: CALLER_WT` when claiming per Step 3
|
|
60
|
+
Otherwise set the checkpoint `active` via MCP `update_checkpoint(checkpoint_id, status: "active"`, plus `worktree_id: CALLER_WT` when claiming per Step 3. The server resolves the caller's worktree identity from the JWT/ctx (CHK-140 TASK-3 — `caller_worktree_id` input field removed). If the checkpoint was already `active` but a claim is still needed, skip the status write and only write `worktree_id`.
|
|
61
61
|
|
|
62
62
|
### Step 5: Route
|
|
63
63
|
|
|
@@ -78,7 +78,7 @@ Show a one-line confirmation before routing:
|
|
|
78
78
|
## Integration
|
|
79
79
|
|
|
80
80
|
- **Reads**: MCP `get_checkpoints`, `get_tasks`; `npx codebyplan resolve-worktree`
|
|
81
|
-
- **Writes**: MCP `update_checkpoint` (status + worktree_id
|
|
81
|
+
- **Writes**: MCP `update_checkpoint` (status + worktree_id; server resolves caller worktree from JWT/ctx)
|
|
82
82
|
- **Triggered by**: `/cbp-checkpoint-plan` (auto when claimed at create), `/cbp-todo` (planned-but-pending gate), or user directly
|
|
83
83
|
- **Triggers**: `/cbp-task-start` (auto when claimed), or `/cbp-checkpoint-plan` (when the checkpoint is unplanned)
|
|
84
84
|
- **Never**: plans or creates tasks — that is `/cbp-checkpoint-plan`
|
|
@@ -116,7 +116,12 @@ Only use `--force` if the user confirms.
|
|
|
116
116
|
|
|
117
117
|
### Step 9: Delete Branch (if requested)
|
|
118
118
|
|
|
119
|
-
**Protected branch check:**
|
|
119
|
+
**Protected branch check:** Read the protected set from `.codebyplan/git.json`:
|
|
120
|
+
```bash
|
|
121
|
+
PRODUCTION=$(jq -r '.branch_config.production // "main"' .codebyplan/git.json)
|
|
122
|
+
PROTECTED=$(jq -r '.branch_config.protected[]? // empty' .codebyplan/git.json)
|
|
123
|
+
```
|
|
124
|
+
If `$BRANCH_NAME` equals `$PRODUCTION` or appears in `$PROTECTED` — refuse deletion and stop.
|
|
120
125
|
|
|
121
126
|
**Checkpoint verification:** Before deleting a feat branch, verify that the associated checkpoint has completed via `/cbp-checkpoint-end`. If the checkpoint is still active, warn the user that unshipped work may be lost.
|
|
122
127
|
|
|
@@ -126,6 +131,17 @@ git branch -d "$BRANCH_NAME" && git push origin --delete "$BRANCH_NAME"
|
|
|
126
131
|
|
|
127
132
|
Use `-d` (not `-D`) to prevent deleting unmerged work. If it fails because the branch is not fully merged, inform the user and ask if they want to force delete with `-D`.
|
|
128
133
|
|
|
134
|
+
After the git branch delete succeeds, run a conditional Supabase preview-branch teardown for `$BRANCH_NAME`:
|
|
135
|
+
|
|
136
|
+
> Lifecycle contract: see [[supabase-branch-lifecycle]].
|
|
137
|
+
|
|
138
|
+
- Call `mcp__supabase__list_branches` with `project_id: rrvtrumtkhrsbhcyrwvf`.
|
|
139
|
+
- Scan the returned list for an entry whose `name` exactly equals `$BRANCH_NAME`.
|
|
140
|
+
- If found: call `mcp__supabase__delete_branch` with its `branch_id`. Report "Supabase preview branch deleted: `$BRANCH_NAME`".
|
|
141
|
+
- If not found: no-op silently — the GitHub integration may have already removed it on PR close; not-found is success, NOT an error.
|
|
142
|
+
- 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_NAME` may still exist and should be verified in the dashboard. Do not treat an API failure as a not-found success.
|
|
143
|
+
- Never delete the parent project `rrvtrumtkhrsbhcyrwvf` itself or any persistent/production branch.
|
|
144
|
+
|
|
129
145
|
### Step 10: Show Result
|
|
130
146
|
|
|
131
147
|
```
|
|
@@ -12,7 +12,7 @@ Activate the session, open a fresh session log, and surface the previous log's p
|
|
|
12
12
|
|
|
13
13
|
## Instructions
|
|
14
14
|
|
|
15
|
-
Run Steps 0 through 5.8 silently (no intermediate output) — except Step 1.4 may surface a one-line fast-forward note or warning, and Step 5.7 may surface an approval gate. (Step numbers are organizational labels; execution order is 0 → 1 → 1.4 → 2 → 3 → 4 → 4.5 → 5 → 5.7 → 5.8 → 6 → 7.) Produce ONE output block at Step 6, then auto-trigger or stop per Step 7.
|
|
15
|
+
Run Steps 0 through 5.8 silently (no intermediate output) — except Step 1.4 may surface a one-line fast-forward note or warning, Step 1.5 may surface a one-line infra-drift nudge, and Step 5.7 may surface an approval gate. (Step numbers are organizational labels; execution order is 0 → 1 → 1.4 → 1.5 → 2 → 3 → 4 → 4.5 → 5 → 5.7 → 5.8 → 6 → 7.) Produce ONE output block at Step 6, then auto-trigger or stop per Step 7.
|
|
16
16
|
|
|
17
17
|
### Step 0: MCP Health Check
|
|
18
18
|
|
|
@@ -49,7 +49,7 @@ RESOLVE_JSON=$(npx codebyplan resolve-worktree --json)
|
|
|
49
49
|
|
|
50
50
|
Extract `worktree_id` and `error_kind` from the JSON output.
|
|
51
51
|
|
|
52
|
-
- `error_kind` is `null` or `"tuple_miss"` → healthy. `WORKTREE_ID` = `worktree_id` (may be `null`: a legitimate main-repo or unregistered-worktree case — proceed normally;
|
|
52
|
+
- `error_kind` is `null` or `"tuple_miss"` → healthy. `WORKTREE_ID` = `worktree_id` (may be `null`: a legitimate main-repo or unregistered-worktree case — proceed normally; the server resolves worktree identity from the JWT/ctx, falling back to the repo main-worktree when no specific worktree is matched).
|
|
53
53
|
- `error_kind` is `local_config_read_failed`, `local_config_write_failed`, `legacy_file_blocks_dir`, `api_failed`, `git_failed`, or `unhandled` → **broken local state**. Hold the `error_kind` for Step 6 to display as a distress warning. Session continues (non-blocking — unlike `/cbp-todo`, session-start does NOT hard-stop on a non-tuple-miss distress).
|
|
54
54
|
|
|
55
55
|
Pass `WORKTREE_ID` to MCP tools that support it. Null `WORKTREE_ID` means the (device, path, branch) tuple is unregistered — note this for Step 6.
|
|
@@ -77,6 +77,31 @@ CURRENT="$(git rev-parse --abbrev-ref HEAD)"
|
|
|
77
77
|
|
|
78
78
|
Never rebase, reset, force-push, or stash. A non-fast-forwardable home branch is a signal to reconcile manually, not to overwrite.
|
|
79
79
|
|
|
80
|
+
### Step 1.5: Infra Drift Check
|
|
81
|
+
|
|
82
|
+
Surface — never block — when this worktree's CBP tooling has fallen behind. Runs after Step 1.4 and may add one line to the Step 6 output. Two mutually-exclusive concepts, keyed on repo type (`$PRODUCTION` is the branch resolved in Step 1.4):
|
|
83
|
+
|
|
84
|
+
- **Monorepo (concept A)** — both `packages/codebyplan-package/templates/` and `scripts/infra-drift.mjs` exist. Step 1.4 skips the fetch on a feat branch, so refresh `origin/$PRODUCTION` best-effort first, then run the reporter:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
git fetch origin "$PRODUCTION" 2>/dev/null || true
|
|
88
|
+
node scripts/infra-drift.mjs 2>/dev/null || true
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
The script self-guards (feat branch + behind > 0) and emits at most one `⚠ .claude/ infra is N behind — run /cbp-refresh-infra` line. Hold any output for Step 6.
|
|
92
|
+
|
|
93
|
+
- **Consumer (concept B)** — no `templates/`, but an install manifest exists (`.claude/.cbp.manifest.json`, falling back to `.cbp-claude.manifest.json` then `.codebyplan-claude.manifest.json`). Compare its `version` to the latest published `codebyplan`, offline-safe:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
LATEST="$(npm view codebyplan version 2>/dev/null)"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
When `$LATEST` is non-empty and newer than the manifest `version`, hold one line for Step 6: `⚠ codebyplan {installed} → {LATEST} — run npx codebyplan@latest claude update`. Any failure (offline, npm absent) → silent.
|
|
100
|
+
|
|
101
|
+
- **Neither** → skip silently.
|
|
102
|
+
|
|
103
|
+
Concept B never fires in the monorepo — the `templates/` guard routes the source repo to concept A only (its manifest `version` is intentionally stale). Fully non-blocking; every failure path falls through with no output.
|
|
104
|
+
|
|
80
105
|
### Step 2: Check Dev Server
|
|
81
106
|
|
|
82
107
|
**Skip if `server_type` is `"none"`.**
|
|
@@ -198,7 +223,7 @@ Three-branch gate using `owned_count` and `total_count` from Step 5.8:
|
|
|
198
223
|
|
|
199
224
|
- **Triggered by**: user invocation, `/clear` recovery
|
|
200
225
|
- **Resolves**: `npx codebyplan resolve-worktree --json` (worktree id + distress signal; non-tuple-miss distress is non-blocking at session-start)
|
|
201
|
-
- **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 1 — single call shared by Step 4 and Step 4.5), MCP `health_check`, 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
|
|
226
|
+
- **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 1 — single call shared by Step 4 and Step 4.5), MCP `health_check`, 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) or the install manifest + `npm view codebyplan version` (Step 1.5 consumer drift)
|
|
202
227
|
- **Writes**: MCP `create_session_log` (new, possibly empty), MCP `update_session_state` (activate)
|
|
203
228
|
- **Spawns**: none
|
|
204
229
|
- **Triggers**: `/cbp-git-commit` (conditional, on user approval), `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)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
scope: org-shared
|
|
3
|
-
name: cbp-e2e
|
|
3
|
+
name: cbp-setup-e2e
|
|
4
4
|
description: Detect installed E2E frameworks, ask which to enable, record credentials source (gitignored env-file path + var names only, never secrets), and write/refresh .codebyplan/e2e.json. Interactive, idempotent.
|
|
5
5
|
argument-hint: "[--force]"
|
|
6
6
|
model: sonnet
|