codebyplan 1.13.62 → 1.13.64
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 +1108 -2061
- package/package.json +1 -1
- package/templates/agents/cbp-e2e-playwright.md +10 -10
- package/templates/hooks/cbp-mcp-round-sync.sh +4 -15
- package/templates/hooks/cbp-skill-context-guard.sh +33 -13
- package/templates/hooks/cbp-test-hooks.sh +85 -0
- package/templates/hooks/hooks.json +0 -9
- package/templates/rules/architecture-map.md +6 -0
- package/templates/rules/cbp-operating-gotchas.md +13 -1
- package/templates/rules/e2e-mandatory.md +5 -0
- package/templates/rules/model-invocation-convention.md +1 -1
- package/templates/rules/scope-vocabulary.md +5 -0
- package/templates/rules/supabase-branch-lifecycle.md +2 -2
- package/templates/rules/task-routing-recommendation.md +1 -1
- package/templates/rules/todo-backend.md +11 -8
- package/templates/settings.project.base.json +9 -12
- package/templates/skills/cbp-build-cc-agent/SKILL.md +3 -0
- package/templates/skills/cbp-build-cc-agent/reference/frontmatter-fields.md +31 -0
- package/templates/skills/cbp-build-cc-agent/reference/permission-modes.md +6 -0
- package/templates/skills/cbp-build-cc-agent/templates/agent.md +1 -0
- package/templates/skills/cbp-build-cc-settings/reference/cbp-permission-policy.md +11 -4
- package/templates/skills/cbp-build-cc-skill/SKILL.md +1 -0
- package/templates/skills/cbp-build-cc-skill/reference/frontmatter-fields.md +14 -0
- package/templates/skills/cbp-build-cc-skill/templates/skill.md +1 -0
- package/templates/skills/cbp-checkpoint-create/SKILL.md +12 -22
- package/templates/skills/cbp-checkpoint-end/SKILL.md +37 -0
- package/templates/skills/cbp-checkpoint-plan/SKILL.md +10 -8
- package/templates/skills/cbp-checkpoint-start/SKILL.md +27 -19
- package/templates/skills/cbp-checkpoint-update/SKILL.md +1 -1
- package/templates/skills/cbp-clear-prep/SKILL.md +1 -1
- package/templates/skills/cbp-finalize/SKILL.md +2 -2
- package/templates/skills/cbp-finalize/reference/checkpoint-done-branching.md +1 -1
- package/templates/skills/cbp-finalize/reference/next-step-heuristic.md +1 -1
- package/templates/skills/cbp-round-complete/SKILL.md +3 -24
- package/templates/skills/cbp-round-plan/SKILL.md +1 -1
- package/templates/skills/cbp-session-end/SKILL.md +40 -30
- package/templates/skills/cbp-session-start/SKILL.md +7 -7
- package/templates/skills/cbp-session-start/qa-regression.md +32 -25
- package/templates/skills/cbp-standalone-task-complete/SKILL.md +2 -5
- package/templates/skills/cbp-standalone-task-create/SKILL.md +5 -13
- package/templates/skills/cbp-standalone-task-start/SKILL.md +10 -10
- package/templates/skills/cbp-task-create/SKILL.md +1 -1
- package/templates/skills/cbp-task-start/SKILL.md +10 -10
- package/templates/skills/cbp-todo/SKILL.md +23 -38
- package/templates/skills/cbp-todo/qa-regression.md +21 -27
- package/templates/skills/cbp-verify/reference/round-scope.md +1 -2
- package/templates/hooks/cbp-mcp-caller-worktree-inject.sh +0 -78
package/package.json
CHANGED
|
@@ -31,20 +31,20 @@ pnpm exec playwright install --with-deps chromium
|
|
|
31
31
|
|
|
32
32
|
Resolve the apps/{app} dev-server port at config-read time via the shared resolver
|
|
33
33
|
`apps/{app}/e2e/resolve-web-dev-port.ts` — imported by BOTH `playwright.config.ts` and
|
|
34
|
-
`e2e/auth.setup.ts` (single source of truth). It reads the per-
|
|
34
|
+
`e2e/auth.setup.ts` (single source of truth). It reads the per-checkout, branch-keyed
|
|
35
35
|
`.codebyplan/server.local.json` overlay first, then the committed `.codebyplan/server.json`.
|
|
36
36
|
Match by label rather than array position — a monorepo can have several Next.js allocations
|
|
37
37
|
with similar label prefixes.
|
|
38
38
|
|
|
39
39
|
**Label-matching rules** (`findWebDevPort`):
|
|
40
40
|
|
|
41
|
-
- `server.local.json` overlay: each label has
|
|
42
|
-
parenthetical group (e.g. `"Web Dev (<
|
|
41
|
+
- `server.local.json` overlay: each label has a branch-keyed suffix appended as the last
|
|
42
|
+
parenthetical group (e.g. `"Web Dev (<branch-keyed-suffix>)"`). Strip exactly ONE trailing
|
|
43
43
|
`" (…)"` group, then require the result `=== "Web Dev"`.
|
|
44
|
-
- `"Web Dev (<
|
|
45
|
-
- `"Web Dev (<other-
|
|
44
|
+
- `"Web Dev (<branch-keyed-suffix>)"` → strip → `"Web Dev"` ✓
|
|
45
|
+
- `"Web Dev (<other-suffix>) (<branch-keyed-suffix>)"` → strip → `"Web Dev (<other-suffix>)"` ✗
|
|
46
46
|
- `server.json` committed base: require `label === "Web Dev"` exactly (do NOT strip —
|
|
47
|
-
`"Web Dev (<other-
|
|
47
|
+
`"Web Dev (<other-suffix>)"` must not match).
|
|
48
48
|
|
|
49
49
|
**Resolution order** (first hit wins):
|
|
50
50
|
|
|
@@ -108,7 +108,7 @@ import { resolveWebDevPort } from "./e2e/resolve-web-dev-port";
|
|
|
108
108
|
// findWebDevPort, parsePortFromUrl, and resolveWebDevPort live in the shared
|
|
109
109
|
// module ./e2e/resolve-web-dev-port.ts (imported above) — single source of
|
|
110
110
|
// truth, also consumed by e2e/auth.setup.ts. Resolution order:
|
|
111
|
-
// 0. PLAYWRIGHT_BASE_URL → 1. server.local.json → 2. server.json
|
|
111
|
+
// 0. PLAYWRIGHT_BASE_URL → 1. server.local.json (branch-keyed overlay) → 2. server.json
|
|
112
112
|
// → 3. E2E_BASE_URL → 4. 3010.
|
|
113
113
|
const port = resolveWebDevPort();
|
|
114
114
|
|
|
@@ -198,7 +198,7 @@ timing**: it loads creds from `.env.local` + `.codebyplan/e2e.env`, calls
|
|
|
198
198
|
the project ref from `NEXT_PUBLIC_SUPABASE_URL`, and writes a `sb-<projectref>-auth-token`
|
|
199
199
|
cookie (domain `localhost`) into `state.json` using the same `encodeAuthCookie` from
|
|
200
200
|
`e2e/auth-cookie.ts` that global-setup consumes. This makes seeding deterministic in any
|
|
201
|
-
|
|
201
|
+
checkout — run `pnpm e2e:auth-setup` (optionally `--port N`) when `state.json` is missing or
|
|
202
202
|
its refresh token has expired. Do NOT reintroduce a browser-login flow (the `(auth)/login`
|
|
203
203
|
page is a client component whose `onSubmit` only attaches after hydration — clicking submit
|
|
204
204
|
pre-hydration falls through to a native GET and never authenticates).
|
|
@@ -261,8 +261,8 @@ any already-running process, so the dev-server readiness probe is the active gua
|
|
|
261
261
|
path.
|
|
262
262
|
|
|
263
263
|
**Port alignment**: parse `playwright.config.ts` `baseURL` port; compare to the resolved
|
|
264
|
-
port from `.codebyplan/server.local.json` (
|
|
265
|
-
`.codebyplan/server.json` (committed base). On mismatch ask which is correct, then propose
|
|
264
|
+
port from `.codebyplan/server.local.json` (per-checkout branch-keyed overlay, checked first)
|
|
265
|
+
then `.codebyplan/server.json` (committed base). On mismatch ask which is correct, then propose
|
|
266
266
|
an Edit to align them.
|
|
267
267
|
|
|
268
268
|
## Quality Fixture (MANDATORY)
|
|
@@ -20,13 +20,10 @@
|
|
|
20
20
|
# - Web-UI flag (app_file_approval_by_user) consumption + reset
|
|
21
21
|
# - Writes both PATCH /api/rounds/${ROUND_ID} and PATCH /api/tasks/${TASK_ID}
|
|
22
22
|
#
|
|
23
|
-
# Caller
|
|
24
|
-
#
|
|
25
|
-
#
|
|
26
|
-
#
|
|
27
|
-
# CLI and passes it via --caller-worktree-id so the server can honor the
|
|
28
|
-
# feat-worktree lock. The hook itself stays non-fatal (exits 0) and surfaces
|
|
29
|
-
# the CLI's stderr output to the user.
|
|
23
|
+
# Caller identity:
|
|
24
|
+
# Worktree-based caller injection was retired in CHK-225. The hook no longer
|
|
25
|
+
# resolves or threads any worktree id; user identity travels via the MCP JWT.
|
|
26
|
+
# The hook stays fail-open and exits 0.
|
|
30
27
|
#
|
|
31
28
|
# Flags:
|
|
32
29
|
# --dry-run Pass through to CLI (prints merged payload, no API writes).
|
|
@@ -83,16 +80,8 @@ if [ -z "$TASK_ID" ]; then
|
|
|
83
80
|
exit 0
|
|
84
81
|
fi
|
|
85
82
|
|
|
86
|
-
# Resolve worktree id before invoking the CLI so the server can honor the
|
|
87
|
-
# feat-worktree lock. On miss (unregistered worktree) the CLI falls back to
|
|
88
|
-
# its in-process resolve and hard-fails with guidance if still unresolved.
|
|
89
|
-
WORKTREE_ID=$(npx codebyplan resolve-worktree 2>/dev/null)
|
|
90
|
-
|
|
91
83
|
# Delegate to the codebyplan CLI (single source of truth for merge semantics)
|
|
92
84
|
CMD_ARGS=("round" "sync-approvals" "--round-id" "$ROUND_ID" "--task-id" "$TASK_ID")
|
|
93
|
-
if [ -n "$WORKTREE_ID" ]; then
|
|
94
|
-
CMD_ARGS+=("--caller-worktree-id" "$WORKTREE_ID")
|
|
95
|
-
fi
|
|
96
85
|
[ "$DRY_RUN" = "true" ] && CMD_ARGS+=("--dry-run")
|
|
97
86
|
|
|
98
87
|
if npx codebyplan "${CMD_ARGS[@]}"; then
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
# @scope: org-shared
|
|
3
3
|
# Hook: PreToolUse (Skill)
|
|
4
|
-
# Purpose: Deny heavy close-out skills when context window
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
4
|
+
# Purpose: Deny heavy close-out skills when context window exceeds the model-aware threshold:
|
|
5
|
+
# 200K tokens for standard models (CBP_CONTEXT_WARN_TOKENS, default 200000);
|
|
6
|
+
# 800K tokens for 1M-context models whose id contains "[1m]"
|
|
7
|
+
# (CBP_CONTEXT_WARN_TOKENS_1M, default 800000).
|
|
8
|
+
# Reads transcript_path from stdin, extracts the latest assistant message.usage
|
|
9
|
+
# AND model id in one pass — same logic as cbp-context-window-notify.sh.
|
|
10
|
+
# If total exceeds the tier threshold AND the skill is in the heavy close-out
|
|
11
|
+
# allowlist, emits hookSpecificOutput.permissionDecision=deny directing Claude
|
|
12
|
+
# to run /cbp-clear-prep. Always exits 0 — fail-open.
|
|
13
|
+
# No model id found → standard tier (fail-conservative).
|
|
9
14
|
|
|
10
15
|
set -euo pipefail
|
|
11
16
|
|
|
@@ -17,8 +22,6 @@ TRANSCRIPT=$(echo "$INPUT" | jq -r '.transcript_path // ""' 2>/dev/null) || TRAN
|
|
|
17
22
|
[ -z "$TRANSCRIPT" ] && exit 0
|
|
18
23
|
[ ! -f "$TRANSCRIPT" ] && exit 0
|
|
19
24
|
|
|
20
|
-
THRESHOLD="${CBP_CONTEXT_WARN_TOKENS:-200000}"
|
|
21
|
-
|
|
22
25
|
# Heavy close-out allowlist (cbp-clear-prep + cbp-clear-continue deliberately excluded so
|
|
23
26
|
# they always run even when context > threshold).
|
|
24
27
|
HEAVY_SKILLS="cbp-round-build cbp-verify cbp-standalone-task-testing cbp-checkpoint-check cbp-checkpoint-end"
|
|
@@ -33,20 +36,37 @@ for heavy in $HEAVY_SKILLS; do
|
|
|
33
36
|
done
|
|
34
37
|
[ "$IS_HEAVY" = "false" ] && exit 0
|
|
35
38
|
|
|
36
|
-
#
|
|
37
|
-
|
|
39
|
+
# Extract model id AND token sum from the latest assistant message with usage, in one pass.
|
|
40
|
+
# Outputs two tab-separated fields: MODEL_ID <tab> TOTAL.
|
|
41
|
+
# Use cut -f1/f2 (not read -r A B) to correctly handle an empty first field (no .message.model).
|
|
42
|
+
_TSV=$(tail -n 400 "$TRANSCRIPT" \
|
|
38
43
|
| jq -rR 'fromjson? | select(.message.usage != null)
|
|
39
|
-
| (.message.
|
|
40
|
-
|
|
41
|
-
|
|
44
|
+
| [ (.message.model // ""),
|
|
45
|
+
((.message.usage.input_tokens // 0)
|
|
46
|
+
+ (.message.usage.cache_creation_input_tokens // 0)
|
|
47
|
+
+ (.message.usage.cache_read_input_tokens // 0)) ]
|
|
48
|
+
| @tsv' 2>/dev/null | tail -1) || _TSV=""
|
|
49
|
+
MODEL_ID=$(printf '%s' "${_TSV:-}" | cut -f1)
|
|
50
|
+
TOTAL=$(printf '%s' "${_TSV:-}" | cut -f2)
|
|
51
|
+
MODEL_ID="${MODEL_ID:-}"
|
|
42
52
|
TOTAL="${TOTAL:-0}"
|
|
43
53
|
|
|
54
|
+
# Tier selection: [1m] in model id → 1M tier; otherwise standard (fail-conservative)
|
|
55
|
+
if printf '%s' "$MODEL_ID" | grep -qF '[1m]'; then
|
|
56
|
+
THRESHOLD="${CBP_CONTEXT_WARN_TOKENS_1M:-800000}"
|
|
57
|
+
TIER="1M"
|
|
58
|
+
else
|
|
59
|
+
THRESHOLD="${CBP_CONTEXT_WARN_TOKENS:-200000}"
|
|
60
|
+
TIER="standard"
|
|
61
|
+
fi
|
|
62
|
+
|
|
44
63
|
if [ "$TOTAL" -ge "$THRESHOLD" ] 2>/dev/null; then
|
|
45
64
|
jq -n \
|
|
46
65
|
--argjson tokens "$TOTAL" \
|
|
47
66
|
--argjson threshold "$THRESHOLD" \
|
|
48
67
|
--arg skill "$SKILL_NAME" \
|
|
49
|
-
|
|
68
|
+
--arg tier "$TIER" \
|
|
69
|
+
'{hookSpecificOutput:{permissionDecision:"deny",permissionDecisionReason:("Context window at \($tokens) tokens (\($tier) tier, threshold \($threshold)) is too large to safely run /\($skill). Run /cbp-clear-prep now to capture a handoff, then /clear, then /cbp-clear-continue to resume.")}}'
|
|
50
70
|
fi
|
|
51
71
|
|
|
52
72
|
exit 0
|
|
@@ -614,6 +614,91 @@ else
|
|
|
614
614
|
|
|
615
615
|
fi
|
|
616
616
|
|
|
617
|
+
echo ""
|
|
618
|
+
|
|
619
|
+
# ===== HOOK SMOKE TESTS — cbp-skill-context-guard model-aware tier (CHK-224) =====
|
|
620
|
+
echo "## Hook Smoke Tests — cbp-skill-context-guard model-aware tier (CHK-224)"
|
|
621
|
+
|
|
622
|
+
FIXTURES_GUARD_MODEL="$HOOKS_DIR/__test-fixtures__/cbp-skill-context-guard"
|
|
623
|
+
|
|
624
|
+
# Case M1: standard model @201K → deny (standard tier, 200K threshold)
|
|
625
|
+
if [ -f "$FIXTURES_GUARD_MODEL/over-threshold-standard.jsonl" ]; then
|
|
626
|
+
STDIN=$(jq -n \
|
|
627
|
+
--arg t "$FIXTURES_GUARD_MODEL/over-threshold-standard.jsonl" \
|
|
628
|
+
--arg s "cbp-round-build" \
|
|
629
|
+
'{transcript_path:$t,tool_input:{skill:$s}}')
|
|
630
|
+
OUTPUT=$(echo "$STDIN" | CBP_CONTEXT_WARN_TOKENS=200000 bash "$GUARD_HOOK" 2>/dev/null)
|
|
631
|
+
EXIT_CODE=$?
|
|
632
|
+
if [ "$EXIT_CODE" = "0" ] \
|
|
633
|
+
&& echo "$OUTPUT" | jq -e '.hookSpecificOutput.permissionDecision == "deny"' >/dev/null 2>&1; then
|
|
634
|
+
test_result "cbp-skill-context-guard.sh standard model @201K → deny (standard tier)" "passed" "passed"
|
|
635
|
+
else
|
|
636
|
+
test_result "cbp-skill-context-guard.sh standard model @201K → deny (standard tier)" "passed" "failed (exit=$EXIT_CODE output=$(echo "$OUTPUT" | head -c 80))"
|
|
637
|
+
fi
|
|
638
|
+
fi
|
|
639
|
+
|
|
640
|
+
# Case M2: [1m] model @201K → empty stdout (allowed; 201K is below 800K 1M-tier threshold)
|
|
641
|
+
if [ -f "$FIXTURES_GUARD_MODEL/over-threshold-1m.jsonl" ]; then
|
|
642
|
+
STDIN=$(jq -n \
|
|
643
|
+
--arg t "$FIXTURES_GUARD_MODEL/over-threshold-1m.jsonl" \
|
|
644
|
+
--arg s "cbp-round-build" \
|
|
645
|
+
'{transcript_path:$t,tool_input:{skill:$s}}')
|
|
646
|
+
OUTPUT=$(echo "$STDIN" | CBP_CONTEXT_WARN_TOKENS_1M=800000 bash "$GUARD_HOOK" 2>/dev/null)
|
|
647
|
+
EXIT_CODE=$?
|
|
648
|
+
if [ "$EXIT_CODE" = "0" ] && [ -z "$OUTPUT" ]; then
|
|
649
|
+
test_result "cbp-skill-context-guard.sh [1m] model @201K → empty stdout (under 800K 1M tier)" "passed" "passed"
|
|
650
|
+
else
|
|
651
|
+
test_result "cbp-skill-context-guard.sh [1m] model @201K → empty stdout (under 800K 1M tier)" "passed" "failed (exit=$EXIT_CODE output=$(echo "$OUTPUT" | head -c 80))"
|
|
652
|
+
fi
|
|
653
|
+
fi
|
|
654
|
+
|
|
655
|
+
# Case M3: [1m] model @850K → deny (1M tier, 800K threshold)
|
|
656
|
+
if [ -f "$FIXTURES_GUARD_MODEL/over-threshold-1m-denied.jsonl" ]; then
|
|
657
|
+
STDIN=$(jq -n \
|
|
658
|
+
--arg t "$FIXTURES_GUARD_MODEL/over-threshold-1m-denied.jsonl" \
|
|
659
|
+
--arg s "cbp-round-build" \
|
|
660
|
+
'{transcript_path:$t,tool_input:{skill:$s}}')
|
|
661
|
+
OUTPUT=$(echo "$STDIN" | CBP_CONTEXT_WARN_TOKENS_1M=800000 bash "$GUARD_HOOK" 2>/dev/null)
|
|
662
|
+
EXIT_CODE=$?
|
|
663
|
+
if [ "$EXIT_CODE" = "0" ] \
|
|
664
|
+
&& echo "$OUTPUT" | jq -e '.hookSpecificOutput.permissionDecision == "deny"' >/dev/null 2>&1; then
|
|
665
|
+
test_result "cbp-skill-context-guard.sh [1m] model @850K → deny (1M tier)" "passed" "passed"
|
|
666
|
+
else
|
|
667
|
+
test_result "cbp-skill-context-guard.sh [1m] model @850K → deny (1M tier)" "passed" "failed (exit=$EXIT_CODE output=$(echo "$OUTPUT" | head -c 80))"
|
|
668
|
+
fi
|
|
669
|
+
fi
|
|
670
|
+
|
|
671
|
+
# Case M4: env override CBP_CONTEXT_WARN_TOKENS=150000 + standard model @201K → deny
|
|
672
|
+
if [ -f "$FIXTURES_GUARD_MODEL/over-threshold-standard.jsonl" ]; then
|
|
673
|
+
STDIN=$(jq -n \
|
|
674
|
+
--arg t "$FIXTURES_GUARD_MODEL/over-threshold-standard.jsonl" \
|
|
675
|
+
--arg s "cbp-round-build" \
|
|
676
|
+
'{transcript_path:$t,tool_input:{skill:$s}}')
|
|
677
|
+
OUTPUT=$(echo "$STDIN" | CBP_CONTEXT_WARN_TOKENS=150000 bash "$GUARD_HOOK" 2>/dev/null)
|
|
678
|
+
EXIT_CODE=$?
|
|
679
|
+
if [ "$EXIT_CODE" = "0" ] \
|
|
680
|
+
&& echo "$OUTPUT" | jq -e '.hookSpecificOutput.permissionDecision == "deny"' >/dev/null 2>&1; then
|
|
681
|
+
test_result "cbp-skill-context-guard.sh env CBP_CONTEXT_WARN_TOKENS=150000 + standard @201K → deny" "passed" "passed"
|
|
682
|
+
else
|
|
683
|
+
test_result "cbp-skill-context-guard.sh env CBP_CONTEXT_WARN_TOKENS=150000 + standard @201K → deny" "passed" "failed (exit=$EXIT_CODE output=$(echo "$OUTPUT" | head -c 80))"
|
|
684
|
+
fi
|
|
685
|
+
fi
|
|
686
|
+
|
|
687
|
+
# Case M5: env override CBP_CONTEXT_WARN_TOKENS_1M=900000 + [1m] model @850K → empty stdout (allowed)
|
|
688
|
+
if [ -f "$FIXTURES_GUARD_MODEL/over-threshold-1m-denied.jsonl" ]; then
|
|
689
|
+
STDIN=$(jq -n \
|
|
690
|
+
--arg t "$FIXTURES_GUARD_MODEL/over-threshold-1m-denied.jsonl" \
|
|
691
|
+
--arg s "cbp-round-build" \
|
|
692
|
+
'{transcript_path:$t,tool_input:{skill:$s}}')
|
|
693
|
+
OUTPUT=$(echo "$STDIN" | CBP_CONTEXT_WARN_TOKENS_1M=900000 bash "$GUARD_HOOK" 2>/dev/null)
|
|
694
|
+
EXIT_CODE=$?
|
|
695
|
+
if [ "$EXIT_CODE" = "0" ] && [ -z "$OUTPUT" ]; then
|
|
696
|
+
test_result "cbp-skill-context-guard.sh env CBP_CONTEXT_WARN_TOKENS_1M=900000 + [1m] @850K → empty stdout (override keeps allowed)" "passed" "passed"
|
|
697
|
+
else
|
|
698
|
+
test_result "cbp-skill-context-guard.sh env CBP_CONTEXT_WARN_TOKENS_1M=900000 + [1m] @850K → empty stdout (override keeps allowed)" "passed" "failed (exit=$EXIT_CODE output=$(echo "$OUTPUT" | head -c 80))"
|
|
699
|
+
fi
|
|
700
|
+
fi
|
|
701
|
+
|
|
617
702
|
# ===== STRUCTURAL ASSERTIONS — cbp-clear-* skills (CHK-217) =====
|
|
618
703
|
echo ""
|
|
619
704
|
echo "## Structural Assertions — cbp-clear-* skills (CHK-217)"
|
|
@@ -69,15 +69,6 @@
|
|
|
69
69
|
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/cbp-mcp-migration-guard.sh"
|
|
70
70
|
}
|
|
71
71
|
]
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
"matcher": "mcp__codebyplan__(update_checkpoint|complete_checkpoint|update_task|complete_task|add_round|update_round|complete_round|create_standalone_task|update_standalone_task|complete_standalone_task|add_standalone_round|update_standalone_round|complete_standalone_round|update_standalone_file_change)",
|
|
75
|
-
"hooks": [
|
|
76
|
-
{
|
|
77
|
-
"type": "command",
|
|
78
|
-
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/cbp-mcp-caller-worktree-inject.sh"
|
|
79
|
-
}
|
|
80
|
-
]
|
|
81
72
|
}
|
|
82
73
|
],
|
|
83
74
|
"PostToolUse": [
|
|
@@ -38,7 +38,9 @@ SHARED tooling behavior only — repo-specific gotchas belong in that repo's own
|
|
|
38
38
|
- **`complete_task` checks file approval on the round's `files_changed`, not the task's.**
|
|
39
39
|
Reconcile approvals via `update_round` (set each entry `user_approved: true`), not
|
|
40
40
|
`update_task` alone — updating only the task leaves the round entries unapproved and
|
|
41
|
-
`complete_task` rejects with "files are not approved".
|
|
41
|
+
`complete_task` rejects with "files are not approved". After a merge-main pulls in foreign
|
|
42
|
+
files or carried directory-slash round artifacts, `complete_task` can hard-fail "N files not
|
|
43
|
+
approved"; fix by re-writing each affected round's `files_changed` via `update_round`.
|
|
42
44
|
|
|
43
45
|
- **CLI transport uses REST (reads) and OAuth+MCP (writes) — a 502 from `codebyplan round sync-approvals` is transient MCP churn, not an outage.** The CLI exits 0 with a warning and MCP tools still work. A missing `CODEBYPLAN_API_KEY` surfaces as an `ApiError`, not a 502. `sync-approvals` can also drag untracked per-device dirs into `files_changed` — run it from the repo root or pass `--caller-worktree-id`.
|
|
44
46
|
|
|
@@ -50,6 +52,16 @@ SHARED tooling behavior only — repo-specific gotchas belong in that repo's own
|
|
|
50
52
|
|
|
51
53
|
- **Re-run config-driven gates after merging main into a feat branch.** A merge can add or change `.codebyplan/shipment.json`, ports, branch config, `e2e.json`, and `eslint.json` — treat the post-merge state as a fresh baseline before continuing.
|
|
52
54
|
|
|
55
|
+
- **MCP write calls can return 403 via Cloudflare WAF when the JSONB payload contains DDL
|
|
56
|
+
keywords (table-drop statements, function-drop statements, or raw query clauses).** Paraphrase
|
|
57
|
+
or base64-encode any user-provided SQL content before embedding it in a JSONB field — never
|
|
58
|
+
pass raw DDL verbatim in MCP context payloads.
|
|
59
|
+
|
|
60
|
+
- **A "Merge origin/main" commit can integrate ZERO commits if it merged a stale local ref.**
|
|
61
|
+
Always `git fetch` and re-check the behind-count before treating a merge as complete — a
|
|
62
|
+
clean merge with no new commits is a sign the local ref was stale, not that the branch was
|
|
63
|
+
already up to date.
|
|
64
|
+
|
|
53
65
|
## Behavioral Preferences
|
|
54
66
|
|
|
55
67
|
- **Never `git stash`** — for any reason. To inspect or compare other state use
|
|
@@ -32,7 +32,7 @@ not via `disable-model-invocation`:
|
|
|
32
32
|
under what condition, so the intent is auditable and overridable.
|
|
33
33
|
|
|
34
34
|
See `.claude/skills/cbp-build-cc-settings/reference/cbp-permission-policy.md` for the full
|
|
35
|
-
`allow` vs `ask` split and the auto-trigger +
|
|
35
|
+
`allow` vs `ask` split and the auto-trigger + model-aware context-guard (200K standard / 800K on `[1m]` sessions).
|
|
36
36
|
|
|
37
37
|
## Related
|
|
38
38
|
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
paths:
|
|
3
|
+
- ".claude/**"
|
|
4
|
+
---
|
|
5
|
+
|
|
1
6
|
# Scope Vocabulary
|
|
2
7
|
|
|
3
8
|
Canonical scope-marker enum for `.claude/` files. The marker classifies a structural file's distribution scope — but it is **required only on user-created files**, not on the assets the `codebyplan` package distributes.
|
|
@@ -47,7 +47,7 @@ The Supabase branch is removed wherever the git branch is deleted:
|
|
|
47
47
|
| Skill | Trigger |
|
|
48
48
|
|---|---|
|
|
49
49
|
| `cbp-checkpoint-end` | stale-branch cleanup + current feat-branch delete on ship |
|
|
50
|
-
| `codebyplan worktree remove
|
|
50
|
+
| `codebyplan worktree remove <path>` | git-worktree teardown removes the coupled Supabase branch (branch-keyed, not identity-keyed) |
|
|
51
51
|
| `cbp-ship-main` | `branch_deleted` event after PR merge |
|
|
52
52
|
| `cbp-standalone-task-complete` | `branch_deleted` event after standalone PR merge (Step 7.3) |
|
|
53
53
|
|
|
@@ -93,7 +93,7 @@ or auto-created by the GitHub integration — both paths use the same branch nam
|
|
|
93
93
|
| Role | Skill |
|
|
94
94
|
|---|---|
|
|
95
95
|
| Create (lazy) | `cbp-supabase-migrate` (Step 2.3) |
|
|
96
|
-
| Delete | `cbp-checkpoint-end`, `cbp-standalone-task-complete`, `codebyplan worktree remove
|
|
96
|
+
| Delete | `cbp-checkpoint-end`, `cbp-standalone-task-complete`, `codebyplan worktree remove <path>`, `cbp-ship-main` |
|
|
97
97
|
| PR gate | `cbp-supabase-branch-check` |
|
|
98
98
|
|
|
99
99
|
Each skill in the Skill Map above carries an inline back-reference to this rule at its create or teardown step.
|
|
@@ -45,7 +45,7 @@ After task completion, routes use single-directive form (never A/B/C menus):
|
|
|
45
45
|
|
|
46
46
|
**Checkpoint-bound task complete:**
|
|
47
47
|
- More tasks in checkpoint → auto-triggers next task (same context)
|
|
48
|
-
- Last task in checkpoint → auto-triggers `cbp-checkpoint-check` (ask-tier permission prompt is the human gate; the
|
|
48
|
+
- Last task in checkpoint → auto-triggers `cbp-checkpoint-check` (ask-tier permission prompt is the human gate; the model-aware context guard handles oversized contexts — 200K standard, 800K on `[1m]` sessions)
|
|
49
49
|
|
|
50
50
|
**Standalone task complete:**
|
|
51
51
|
- Always → `Next: /cbp-session-end` (or `/cbp-standalone-task-create` for new work)
|
|
@@ -12,16 +12,16 @@ The todos queue is materialised by `apps/todo-worker` (CHK-122) and consumed by
|
|
|
12
12
|
|
|
13
13
|
## 1. Six workflow invariants — DB-layer guards, never bypassable
|
|
14
14
|
|
|
15
|
-
Defined in `supabase/migrations/20260511211900_chk111_workflow_invariants.sql
|
|
15
|
+
Defined in `supabase/migrations/20260511211900_chk111_workflow_invariants.sql` (updated by `supabase/migrations/20260612000000_chk225_task1_user_locks.sql`). These are `BEFORE UPDATE` triggers — they refuse invalid state transitions and produce structured `RAISE EXCEPTION` errors with `HINT` pointing at the offending row. **Do NOT port these to TS.** The DB layer is the bypass-proof contract.
|
|
16
16
|
|
|
17
17
|
| # | Trigger | What it enforces |
|
|
18
18
|
|---|---------|------------------|
|
|
19
|
-
| 1 | `trg_enforce_checkpoint_activation_worktree` | A checkpoint cannot be activated without `
|
|
20
|
-
| 2 | `
|
|
19
|
+
| 1 | `trg_enforce_checkpoint_activation_worktree` | A checkpoint cannot be activated without `assigned_user_id` set (CHK-225: was `worktree_id`) |
|
|
20
|
+
| 2 | `trg_enforce_standalone_task_workflow_invariants` | A standalone task cannot be moved to `in_progress` without `assigned_user_id` (CHK-225: was `assigned_worktree_id`) |
|
|
21
21
|
| 3 | `trg_enforce_task_workflow_invariants` | ≤ 1 `in_progress` task per checkpoint |
|
|
22
22
|
| 4 | `trg_enforce_single_in_progress_round_per_task` | ≤ 1 `in_progress` round per task |
|
|
23
|
-
| 5 | `trg_enforce_single_active_scope_per_worktree` | ≤ 1 active (checkpoint OR standalone task) per
|
|
24
|
-
| 6 | `trg_enforce_standalone_task_scope_per_worktree` | ≤ 1 `in_progress` standalone task per
|
|
23
|
+
| 5 | `trg_enforce_single_active_scope_per_worktree` | ≤ 1 active (checkpoint OR standalone task) per `assigned_user_id` (CHK-225: was per `worktree_id`) |
|
|
24
|
+
| 6 | `trg_enforce_standalone_task_scope_per_worktree` | ≤ 1 `in_progress` standalone task per `assigned_user_id` (CHK-225: was per `assigned_worktree_id`) |
|
|
25
25
|
|
|
26
26
|
The worker is a passive cross-checker (`apps/todo-worker/src/invariants/check.ts`) — if its check disagrees with the DB, the DB wins.
|
|
27
27
|
|
|
@@ -34,7 +34,7 @@ MCP write → enqueueTodosJob → todos_jobs (status='pending')
|
|
|
34
34
|
↓
|
|
35
35
|
worker claim_todos_job (SELECT … FOR UPDATE SKIP LOCKED)
|
|
36
36
|
↓
|
|
37
|
-
computeTodos(repo,
|
|
37
|
+
computeTodos(repo, user) → desired rows
|
|
38
38
|
↓
|
|
39
39
|
apply_todos RPC → todos table (status='current' / 'pending')
|
|
40
40
|
↓
|
|
@@ -71,7 +71,7 @@ The queue head (`get_todos` `rows[0]`) maps to one of these slash commands. The
|
|
|
71
71
|
|
|
72
72
|
## 5. Heartbeat policy
|
|
73
73
|
|
|
74
|
-
The worker's `node-cron` heartbeat runs at `0 0 * * *` (UTC midnight). It enumerates every `(repo,
|
|
74
|
+
The worker's `node-cron` heartbeat runs at `0 0 * * *` (UTC midnight). It enumerates every `(repo, user)` pair with an active checkpoint OR in-progress standalone task (via `assigned_user_id`) and enqueues a `HEARTBEAT_SWEEP` todos_jobs row for each. This catches drift from missed `enqueueTodosJob` calls in MCP writers.
|
|
75
75
|
|
|
76
76
|
Backoff: a failed job retries at `now + 2^attempts minutes` (cap 60min). After 3 attempts, the job stays `failed` and the heartbeat picks it up again at the next sweep.
|
|
77
77
|
|
|
@@ -83,7 +83,6 @@ The shared enqueue helper lives at `packages/mcp-tools/src/tools/enqueue-todos.t
|
|
|
83
83
|
enqueueTodosJob(
|
|
84
84
|
client: SupabaseClient,
|
|
85
85
|
repoId: string,
|
|
86
|
-
callerWorktreeId: string | undefined,
|
|
87
86
|
userId: string | null,
|
|
88
87
|
reason: string
|
|
89
88
|
): Promise<void>
|
|
@@ -108,6 +107,8 @@ Every workflow mutator MUST call `void enqueueTodosJob(...)` after the mutation
|
|
|
108
107
|
|
|
109
108
|
CHK-111 shipped the original todos queue as Postgres triggers + a 583-LOC `regenerate_todos_for_repo` PL/pgSQL function. CHK-122 ported the regen to `apps/todo-worker` (Node) for shared infrastructure with `apps/docs-ingest` (CHK-116), easier testing, and per-user fanout. The 10 `trg_*_todos` triggers and the 4 `wrap_*` wrappers were dropped in migration `20260521000000_chk122_drop_legacy_todos_regen.sql`. The 6 BEFORE-UPDATE invariant triggers stayed.
|
|
110
109
|
|
|
110
|
+
CHK-225 updated the invariant triggers from worktree-scoped to user-scoped (`assigned_user_id`). The trigger names were preserved for continuity; only the function bodies changed. Migration: `20260612000000_chk225_task1_user_locks.sql`.
|
|
111
|
+
|
|
111
112
|
## 8. Deployment — Railway
|
|
112
113
|
|
|
113
114
|
`apps/todo-worker` runs as a Railway service alongside `apps/backend`. Setup:
|
|
@@ -119,3 +120,5 @@ CHK-111 shipped the original todos queue as Postgres triggers + a 583-LOC `regen
|
|
|
119
120
|
5. Save the resulting `project_ref` to `.codebyplan.json` `shipment.surfaces.railway-todo-worker.project_ref`.
|
|
120
121
|
|
|
121
122
|
Smoke after deploy: run `/cbp-finalize` in any worktree → tail Railway logs → expect a `claim → apply` cycle within `WORKER_POLL_MS`.
|
|
123
|
+
|
|
124
|
+
**CHK-225 deploy note**: apply migration `20260612100000` (drops `worktree_id` from `todos` + `todos_jobs`, dedup todos rows, updates `apply_todos` RPC) BEFORE running `railway up` for the worker. Until the migration lands, the worker's 3-arg `apply_todos` call fails with a function-not-found error.
|
|
@@ -66,7 +66,6 @@
|
|
|
66
66
|
"mcp__codebyplan__create_project",
|
|
67
67
|
"mcp__codebyplan__create_repo",
|
|
68
68
|
"mcp__codebyplan__delete_session_log",
|
|
69
|
-
"mcp__codebyplan__delete_worktree",
|
|
70
69
|
"mcp__codebyplan__release_assignment",
|
|
71
70
|
"mcp__stripe__create_customer",
|
|
72
71
|
"mcp__stripe__create_product",
|
|
@@ -148,23 +147,16 @@
|
|
|
148
147
|
"mcp__codebyplan__get_checkpoints",
|
|
149
148
|
"mcp__codebyplan__get_current_task",
|
|
150
149
|
"mcp__codebyplan__get_eslint_presets",
|
|
151
|
-
"mcp__codebyplan__get_eslint_repo_config",
|
|
152
150
|
"mcp__codebyplan__get_file_changes",
|
|
153
|
-
"mcp__codebyplan__get_library_doc_job",
|
|
154
151
|
"mcp__codebyplan__get_repos",
|
|
155
152
|
"mcp__codebyplan__get_rounds",
|
|
156
153
|
"mcp__codebyplan__get_server_config",
|
|
157
154
|
"mcp__codebyplan__get_session_log",
|
|
158
155
|
"mcp__codebyplan__get_session_logs",
|
|
159
156
|
"mcp__codebyplan__get_session_state",
|
|
160
|
-
"mcp__codebyplan__get_task_template",
|
|
161
|
-
"mcp__codebyplan__get_task_templates",
|
|
162
157
|
"mcp__codebyplan__get_tasks",
|
|
163
158
|
"mcp__codebyplan__get_todos",
|
|
164
|
-
"mcp__codebyplan__get_worktrees",
|
|
165
|
-
"mcp__codebyplan__list_tech_stack_sync_sessions",
|
|
166
159
|
"mcp__codebyplan__get_chunk",
|
|
167
|
-
"mcp__codebyplan__get_library_toc",
|
|
168
160
|
"mcp__codebyplan__list_migrations",
|
|
169
161
|
"mcp__codebyplan__lookup_symbol",
|
|
170
162
|
"mcp__codebyplan__resolve_library_id",
|
|
@@ -183,11 +175,18 @@
|
|
|
183
175
|
"mcp__codebyplan__create_session_log",
|
|
184
176
|
"mcp__codebyplan__update_session_log",
|
|
185
177
|
"mcp__codebyplan__update_session_state",
|
|
186
|
-
"mcp__codebyplan__create_worktree",
|
|
187
178
|
"mcp__codebyplan__flag_stale_chunk",
|
|
188
179
|
"mcp__codebyplan__update_eslint_repo_config",
|
|
189
180
|
"mcp__codebyplan__update_server_config",
|
|
190
|
-
"
|
|
181
|
+
"mcp__codebyplan__get_standalone_tasks",
|
|
182
|
+
"mcp__codebyplan__get_current_standalone_task",
|
|
183
|
+
"mcp__codebyplan__get_standalone_rounds",
|
|
184
|
+
"mcp__codebyplan__create_standalone_task",
|
|
185
|
+
"mcp__codebyplan__update_standalone_task",
|
|
186
|
+
"mcp__codebyplan__complete_standalone_task",
|
|
187
|
+
"mcp__codebyplan__add_standalone_round",
|
|
188
|
+
"mcp__codebyplan__update_standalone_round",
|
|
189
|
+
"mcp__codebyplan__complete_standalone_round",
|
|
191
190
|
"Bash(codebyplan check:*)",
|
|
192
191
|
"Bash(npx codebyplan check:*)",
|
|
193
192
|
"Bash(codebyplan session:*)",
|
|
@@ -196,8 +195,6 @@
|
|
|
196
195
|
"Bash(npx codebyplan supabase:*)",
|
|
197
196
|
"Bash(codebyplan whoami:*)",
|
|
198
197
|
"Bash(npx codebyplan whoami:*)",
|
|
199
|
-
"Bash(codebyplan resolve-worktree:*)",
|
|
200
|
-
"Bash(npx codebyplan resolve-worktree:*)",
|
|
201
198
|
"Bash(codebyplan version-status:*)",
|
|
202
199
|
"Bash(npx codebyplan version-status:*)",
|
|
203
200
|
"Bash(codebyplan worktree:*)",
|
|
@@ -77,6 +77,7 @@ Check each against the task and include only when they add value:
|
|
|
77
77
|
| Background execution | `background: true` | Agent should always run concurrently |
|
|
78
78
|
| Bounded turns | `maxTurns: N` | Cap runaway loops |
|
|
79
79
|
| Subagent spawning | `tools: Agent(worker, researcher)` | Only if run as main thread via `--agent` |
|
|
80
|
+
| Memory store | `memory: user \| project \| local` | Which memory store the agent reads/writes |
|
|
80
81
|
|
|
81
82
|
Cross-references for complex cases:
|
|
82
83
|
|
|
@@ -136,5 +137,7 @@ Report:
|
|
|
136
137
|
- Subagents cannot spawn other subagents — the `Agent` tool only applies when the agent runs as the main thread
|
|
137
138
|
- `bypassPermissions` and `acceptEdits` inherited from the parent cannot be weakened by the child
|
|
138
139
|
- Preloaded skills inject _full content_ at startup — don't preload `disable-model-invocation: true` skills
|
|
140
|
+
- `Task(` was renamed to `Agent(` in v2.1.63 — use `Agent(...)` in `tools:` allowlists; `Task()` is a stale alias that still works but should not appear in new agents
|
|
141
|
+
- Plugin agents (`.claude/agents/`) ignore `hooks`, `mcpServers`, and `permissionMode` — these fields parse without error but have no runtime effect for plugin agents
|
|
139
142
|
- Restart the session or use `/agents` to load a newly written agent file
|
|
140
143
|
- Flat form `.claude/agents/{name}.md` is the default and matches all 12 existing CBP agents; folder form `{name}/AGENT.md` is optional and only for agents that bundle supporting files alongside them
|
|
@@ -18,6 +18,7 @@ Source: official Claude Code sub-agents spec. Only `name` and `description` are
|
|
|
18
18
|
| `effort` | string | `low` \| `medium` \| `high` \| `xhigh` \| `max`. **Plugin agents authored in CBP MUST set this explicitly** (no commented-out placeholder); see [/cbp-build-cc-mode](../../build-cc-mode/SKILL.md) for the matrix |
|
|
19
19
|
| `isolation` | string | `worktree` — gives the agent a temporary git worktree |
|
|
20
20
|
| `color` | string | `red` \| `blue` \| `green` \| `yellow` \| `purple` \| `orange` \| `pink` \| `cyan` |
|
|
21
|
+
| `memory` | string | Which memory store the agent reads/writes: `user` \| `project` \| `local` |
|
|
21
22
|
| `initialPrompt` | string | Auto-submitted first user turn when the agent is the main session agent |
|
|
22
23
|
|
|
23
24
|
## Tool-allowlist special forms
|
|
@@ -34,3 +35,33 @@ Source: official Claude Code sub-agents spec. Only `name` and `description` are
|
|
|
34
35
|
2. Per-invocation `model` parameter passed by Claude
|
|
35
36
|
3. The `model` field in this file
|
|
36
37
|
4. Main conversation's model
|
|
38
|
+
|
|
39
|
+
## Task( → Agent( rename (v2.1.63)
|
|
40
|
+
|
|
41
|
+
The `Agent` tool replaces the older `Task` tool. `Task()` still works as a stale alias but new agents should use `Agent(...)` in their `tools:` allowlists. Example: `tools: Agent(worker, researcher)` — not `Task(worker, researcher)`. The runtime accepts both forms; prefer `Agent`.
|
|
42
|
+
|
|
43
|
+
## Plugin agent limitations
|
|
44
|
+
|
|
45
|
+
Plugin agents (those defined in `.claude/agents/`) ignore the following fields — they are parsed without error but have **no runtime effect**:
|
|
46
|
+
|
|
47
|
+
- `hooks` — lifecycle hooks are silently no-opped for plugin agents
|
|
48
|
+
- `mcpServers` — scoped MCP server definitions are ignored
|
|
49
|
+
- `permissionMode` — the parent session's permission mode applies unchanged; the child cannot set its own
|
|
50
|
+
|
|
51
|
+
This is distinct from agents run as the main thread via `claude --agent`, where these fields take full effect.
|
|
52
|
+
|
|
53
|
+
## Skills-preload constraint
|
|
54
|
+
|
|
55
|
+
Skills listed in `skills:` are preloaded — their full content is injected into the agent's context at startup. Do NOT preload skills that carry `disable-model-invocation: true`. A preloaded skill with that flag is loaded at startup but can never be invoked at runtime, so its content wastes context and its intent cannot be fulfilled.
|
|
56
|
+
|
|
57
|
+
## CBP-only fields (not read by Claude Code)
|
|
58
|
+
|
|
59
|
+
`scope:` is **CBP framework metadata** — it is NOT part of the official Claude Code sub-agents spec and is not read by the Claude Code runtime. It declares the agent's distribution class:
|
|
60
|
+
|
|
61
|
+
| Value | Meaning |
|
|
62
|
+
|-------|---------|
|
|
63
|
+
| `org-shared` | Ships identically to every consuming repo via the `codebyplan` package |
|
|
64
|
+
| `project-shared` | Shared across repos in a single project family |
|
|
65
|
+
| `repo-only:<name>` | Bound to one repo; `<name>` is the repo slug |
|
|
66
|
+
|
|
67
|
+
Required only on user-created agents (no template twin). Package-managed agents are `org-shared` by default — no marker needed. See [rules/scope-vocabulary.md](../../../../rules/scope-vocabulary.md).
|
|
@@ -16,3 +16,9 @@ Source: official Claude Code sub-agents and permission-modes specs.
|
|
|
16
16
|
- If parent is `bypassPermissions` or `acceptEdits`, child cannot weaken it
|
|
17
17
|
- If parent is `auto`, child inherits `auto` and its `permissionMode` is ignored
|
|
18
18
|
- Otherwise the child's `permissionMode` takes effect as declared
|
|
19
|
+
|
|
20
|
+
## Plugin agents
|
|
21
|
+
|
|
22
|
+
Plugin agents (those defined in `.claude/agents/` and loaded by the runtime, not run via `claude --agent`) **ignore `permissionMode` entirely**. The field is valid YAML and parses without error, but has no runtime effect — the parent session's permission mode applies unchanged.
|
|
23
|
+
|
|
24
|
+
Likewise, `hooks` and `mcpServers` are ignored for plugin agents regardless of the parent session's permission mode. These fields only take effect when the agent runs as the main thread via `claude --agent`.
|
|
@@ -6,6 +6,7 @@ tools: Read, Grep, Glob, Bash
|
|
|
6
6
|
# disallowedTools: Write, Edit # alternative to tools — inherits then removes
|
|
7
7
|
# review with /cbp-build-cc-mode if defaults don't fit this agent's purpose
|
|
8
8
|
model: sonnet
|
|
9
|
+
# memory: user # user | project | local — which memory store this agent reads/writes
|
|
9
10
|
# permissionMode: default # default | acceptEdits | auto | dontAsk | bypassPermissions | plan
|
|
10
11
|
# maxTurns: 20
|
|
11
12
|
effort: xhigh
|
|
@@ -24,7 +24,7 @@ Precedence is `deny > ask > allow`; arrays union across scopes (managed/user/pro
|
|
|
24
24
|
|
|
25
25
|
- **Non-lifecycle, non-shipment `/cbp-*` skills** — authoring (`cbp-build-cc-*`), frontend (`cbp-frontend-*`), git (`cbp-git-*`, `cbp-merge-main`, `cbp-refresh-infra`), round work (`cbp-round-plan`, `cbp-verify` — `cbp-verify` is the autonomous verify stage that runs deterministic gates, proves execution, spawns the fresh-context reviewer, and routes to `cbp-round-complete` or `cbp-round-plan`, so it runs without a prompt), setup/configure (`cbp-setup-*`, `cbp-ship-configure`, `cbp-supabase-*`), task prep (`cbp-task-create`/`-start`, `cbp-standalone-task-check`/`-testing`), planning (`cbp-checkpoint-plan`/`-update`), plus `cbp-session-start` and `cbp-todo`. Invoking a skill is the intended mode of operation; the gated side effects happen inside via the Bash/MCP tools the skill calls, which carry their own tiering. The lifecycle/state-transition and plan-approval skills are the exception — they live in `ask` (next section).
|
|
26
26
|
- **All `mcp__codebyplan__*` reads** (`get_*`, `list_*`, `search_*`, `health_check`, `lookup_symbol`, `resolve_library_id`, `get_chunk`).
|
|
27
|
-
- **Routine workflow-write MCP tools** the pipeline calls many times per task: create/update/complete checkpoint, task, and round; session log + session-state writes; `create_worktree`, `add_library`, `flag_stale_chunk`, `update_server_config`, `update_eslint_repo_config
|
|
27
|
+
- **Routine workflow-write MCP tools** the pipeline calls many times per task: create/update/complete checkpoint, task, and round; session log + session-state writes; `create_worktree`, `add_library`, `flag_stale_chunk`, `update_server_config`, `update_eslint_repo_config`. Gating these with `ask` would make the autonomous workflow unusable.
|
|
28
28
|
- **Read/safe CLI commands** (both `codebyplan X` and `npx codebyplan X`): `whoami`, `resolve-worktree`, `statusline`, `ports`, `tech-stack`, `eslint`, `round`, `help`, `--version`.
|
|
29
29
|
|
|
30
30
|
### `ask` — the deliberate confirm-gate
|
|
@@ -66,11 +66,18 @@ This means:
|
|
|
66
66
|
- A skill in `ask` that is auto-triggered shows a permission prompt — that prompt is the gate;
|
|
67
67
|
say so in the routing prose.
|
|
68
68
|
|
|
69
|
-
### The
|
|
69
|
+
### The model-aware context guard
|
|
70
70
|
|
|
71
71
|
The `cbp-skill-context-guard.sh` PreToolUse hook denies heavy close-out skills when the
|
|
72
|
-
context window exceeds
|
|
73
|
-
|
|
72
|
+
context window exceeds the model-aware threshold:
|
|
73
|
+
|
|
74
|
+
- **Standard models**: `CBP_CONTEXT_WARN_TOKENS` (default 200 000 tokens)
|
|
75
|
+
- **1M-context models** (model id contains `[1m]`): `CBP_CONTEXT_WARN_TOKENS_1M` (default 800 000 tokens)
|
|
76
|
+
|
|
77
|
+
When no model id is found in the transcript the hook fails conservative to the standard 200K
|
|
78
|
+
tier. Each env var overrides only its own tier — the other tier is unaffected.
|
|
79
|
+
|
|
80
|
+
The heavy allowlist is: `cbp-round-build`, `cbp-verify`, `cbp-standalone-task-testing`,
|
|
74
81
|
`cbp-checkpoint-check`, `cbp-checkpoint-end`.
|
|
75
82
|
|
|
76
83
|
When the guard fires, it directs the model to run `/cbp-clear-prep` instead. The flow is:
|