codebyplan 1.13.10 → 1.13.12
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 +2317 -2293
- package/package.json +1 -1
- package/templates/agents/cbp-research.md +2 -0
- package/templates/agents/cbp-round-executor.md +2 -0
- package/templates/agents/cbp-task-planner.md +4 -1
- package/templates/hooks/cbp-canonical-templates-nudge.sh +68 -0
- package/templates/hooks/hooks.json +4 -0
- package/templates/rules/agent-claim-verification.md +50 -0
- package/templates/rules/context-file-loading.md +1 -0
- package/templates/rules/parallel-waves.md +59 -0
- package/templates/skills/cbp-round-update/SKILL.md +21 -0
- package/templates/skills/cbp-task-start/SKILL.md +19 -1
package/package.json
CHANGED
|
@@ -9,6 +9,8 @@ effort: xhigh
|
|
|
9
9
|
|
|
10
10
|
# Research Agent
|
|
11
11
|
|
|
12
|
+
> Adheres to [[agent-claim-verification]] — cite a source file (`path:line`) or vendor docs before asserting any JSON key, schema field, env-var, or API shape exists.
|
|
13
|
+
|
|
12
14
|
Intelligent research with discovery levels (0-3). Consults `.claude/docs/stack/` first, uses web research when needed, produces DISCOVERY.md for Level 2+.
|
|
13
15
|
|
|
14
16
|
## Purpose
|
|
@@ -9,6 +9,8 @@ effort: xhigh
|
|
|
9
9
|
|
|
10
10
|
# Round Executor Agent
|
|
11
11
|
|
|
12
|
+
> Adheres to [[agent-claim-verification]] — cite a source file (`path:line`) or vendor docs before asserting any JSON key, schema field, env-var, or API shape exists.
|
|
13
|
+
|
|
12
14
|
Execute an already-approved implementation plan. The planner agent has already done analysis and the user has approved the plan - this agent focuses purely on quality execution.
|
|
13
15
|
|
|
14
16
|
## Purpose
|
|
@@ -531,6 +531,7 @@ After Phase 5 (solution design) and before Phase 6 (context summary), decompose
|
|
|
531
531
|
3. **Check DAG invariant**: `depends_on[]` must be acyclic. Any cycle is a plan error — resolve by merging the cyclic waves.
|
|
532
532
|
4. **Populate `skill_preloads[]`**: for each wave whose `files[]` contains UI-bearing paths (`*.tsx`, `*.jsx`, `*.scss`, etc.), add `"frontend-design"` and `"frontend-a11y"` to `skill_preloads[]` (in that order).
|
|
533
533
|
5. **Single-wave default**: if no independence is found, produce ONE wave covering all files. Parallel waves add orchestration overhead — only decompose when the benefit is clear.
|
|
534
|
+
6. **15-file cap**: after decomposition (including the single-wave default), count files in each wave. If any wave would exceed 15 files, auto-split it using the proximity-split algorithm in priority order: (a) **shared directory subtree** — split at the deepest common ancestor that produces two groups each ≥3 files; (b) **shared module** — split at the next directory level below the common ancestor; (c) **arbitrary boundary** — split at the 15-file boundary and add a one-line `note` on the continuation wave explaining the boundary. Split siblings are **independent**: do NOT add `depends_on` between them unless a real shared-file or data dependency requires ordering. **Tail rule**: choose boundaries so every resulting wave holds 3–15 files. A split must never leave a wave with <3 files; rebalance the boundary rather than absorbing a tail into a sibling in a way that pushes it above 15. The 3–15 range is a hard invariant — there is no exception above 15. **Apply the cap iteratively**: after a split, re-check each resulting wave and split again any that still exceeds 15 — a 40-file single-concern plan therefore yields ≥3 waves. When no natural boundary yields groups each ≥3 files, take the smallest ≥3-file prefix as one wave and apply the same procedure to the remainder. The single-wave default is itself subject to this cap. See `rules/parallel-waves.md` for the full algorithm and invariants.
|
|
534
535
|
|
|
535
536
|
**Output** (added to plan):
|
|
536
537
|
|
|
@@ -541,6 +542,7 @@ plan.waves:
|
|
|
541
542
|
files: string[]
|
|
542
543
|
depends_on: string[]
|
|
543
544
|
skill_preloads: string[]
|
|
545
|
+
note: string # optional — set on continuation waves from an arbitrary-boundary split
|
|
544
546
|
```
|
|
545
547
|
|
|
546
548
|
If `files_to_modify[]` contains ≤5 files across a single app, skip decomposition and emit a single wave or omit `waves[]` entirely (single-wave default in `round-execute` handles this gracefully).
|
|
@@ -550,7 +552,8 @@ If `files_to_modify[]` contains ≤5 files across a single app, skip decompositi
|
|
|
550
552
|
- [ ] Every file in `files_to_modify[]` appears in exactly one wave
|
|
551
553
|
- [ ] `depends_on[]` forms a DAG (no cycles)
|
|
552
554
|
- [ ] UI-bearing waves have `frontend-design` + `frontend-a11y` in `skill_preloads[]`
|
|
553
|
-
- [ ] Each wave has ≥3 files (if not, merge into
|
|
555
|
+
- [ ] Each wave has ≥3 files (if not, merge into sibling wave)
|
|
556
|
+
- [ ] No wave has >15 files (if so, apply the proximity-split algorithm)
|
|
554
557
|
|
|
555
558
|
### Phase 6: Build Context Summary
|
|
556
559
|
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# @scope: org-shared
|
|
3
|
+
# @event: PreToolUse
|
|
4
|
+
# @matcher: Edit|Write|MultiEdit
|
|
5
|
+
# Advisory source-of-truth nudge. When editing a GATE-6-tracked .claude/ file
|
|
6
|
+
# (skills/agents/hooks/rules) that already has a packages/codebyplan-package/
|
|
7
|
+
# templates/ counterpart, remind the author to mirror the change so the two
|
|
8
|
+
# trees stay byte-identical (scripts/check-sibling-identity.mjs / GATE 6).
|
|
9
|
+
#
|
|
10
|
+
# Fires ONLY in the templates source repo, detected by the presence of
|
|
11
|
+
# packages/codebyplan-package/templates/. Always exits 0 — advisory only,
|
|
12
|
+
# never blocks the edit. (set -u catches typos; -e / -o pipefail are
|
|
13
|
+
# deliberately omitted so the hook can never abort mid-run.)
|
|
14
|
+
|
|
15
|
+
set -u
|
|
16
|
+
|
|
17
|
+
INPUT=$(cat)
|
|
18
|
+
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
|
|
19
|
+
|
|
20
|
+
case "$TOOL_NAME" in
|
|
21
|
+
Edit|Write|MultiEdit) ;;
|
|
22
|
+
*) exit 0 ;;
|
|
23
|
+
esac
|
|
24
|
+
|
|
25
|
+
# MultiEdit shares the single top-level tool_input.file_path with Edit/Write
|
|
26
|
+
# (only the per-edit content differs); filePath is a defensive camelCase fallback.
|
|
27
|
+
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.filePath // empty' 2>/dev/null)
|
|
28
|
+
[ -z "$FILE_PATH" ] && exit 0
|
|
29
|
+
|
|
30
|
+
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
|
|
31
|
+
[ -z "$REPO_ROOT" ] && exit 0
|
|
32
|
+
# Symlink-resolve so a /Users vs /private/Users mismatch (macOS) still compares equal.
|
|
33
|
+
REPO_ROOT=$(cd "$REPO_ROOT" 2>/dev/null && pwd -P || echo "$REPO_ROOT")
|
|
34
|
+
|
|
35
|
+
TEMPLATES_DIR="$REPO_ROOT/packages/codebyplan-package/templates"
|
|
36
|
+
# Not the templates source repo → nothing to mirror.
|
|
37
|
+
[ -d "$TEMPLATES_DIR" ] || exit 0
|
|
38
|
+
|
|
39
|
+
# Resolve the edited path to a repo-root-relative form. Absolute paths are
|
|
40
|
+
# symlink-normalised (so the prefix match is apples-to-apples); relative paths
|
|
41
|
+
# are taken as-is.
|
|
42
|
+
case "$FILE_PATH" in
|
|
43
|
+
/*)
|
|
44
|
+
_dir=$(cd "$(dirname "$FILE_PATH")" 2>/dev/null && pwd -P || echo "")
|
|
45
|
+
[ -z "$_dir" ] && exit 0
|
|
46
|
+
FILE_PATH="$_dir/$(basename "$FILE_PATH")"
|
|
47
|
+
case "$FILE_PATH" in
|
|
48
|
+
"$REPO_ROOT"/*) REL="${FILE_PATH#"$REPO_ROOT"/}" ;;
|
|
49
|
+
*) exit 0 ;;
|
|
50
|
+
esac
|
|
51
|
+
;;
|
|
52
|
+
*) REL="$FILE_PATH" ;;
|
|
53
|
+
esac
|
|
54
|
+
|
|
55
|
+
# Only the GATE-6-tracked subtrees: .claude/{skills,agents,hooks,rules}/...
|
|
56
|
+
case "$REL" in
|
|
57
|
+
.claude/skills/*|.claude/agents/*|.claude/hooks/*|.claude/rules/*) ;;
|
|
58
|
+
*) exit 0 ;;
|
|
59
|
+
esac
|
|
60
|
+
|
|
61
|
+
SUBREL="${REL#.claude/}"
|
|
62
|
+
COUNTERPART="$TEMPLATES_DIR/$SUBREL"
|
|
63
|
+
|
|
64
|
+
if [ -e "$COUNTERPART" ]; then
|
|
65
|
+
echo "cbp: editing .claude/$SUBREL — also mirror this change to packages/codebyplan-package/templates/$SUBREL to keep them byte-identical (GATE 6: node scripts/check-sibling-identity.mjs). Advisory only; continuing." >&2
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
exit 0
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
scope: org-shared
|
|
3
|
+
name: agent-claim-verification
|
|
4
|
+
description: Subagents must cite the source file (path:line) or vendor docs before asserting that any JSON key, schema field, env-var name, or external API shape exists.
|
|
5
|
+
paths:
|
|
6
|
+
- ".claude/agents/**/*"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Agent Claim Verification
|
|
10
|
+
|
|
11
|
+
<!-- Delivery: subagents receive this rule via the [[agent-claim-verification]] pointer in each
|
|
12
|
+
agent's .md file. The `paths:` frontmatter surfaces it when an agent file is being *edited*,
|
|
13
|
+
not when the agent is *running* — both mechanisms are intentional, so don't drop the pointer.
|
|
14
|
+
Scope is agents-only by design (cbp-round-executor, cbp-research); skill files are out of
|
|
15
|
+
scope this round. -->
|
|
16
|
+
|
|
17
|
+
Subagents routinely emit tool calls and explanatory text that depend on a named thing *existing* — a JSON config key, a schema field, an environment-variable name, an external API's request/response shape. When that name is recalled from memory instead of read from the source, it is often subtly wrong: a renamed field, a key that moved to a different file, an API shape from an older version. Those hallucinated names cost correction rounds.
|
|
18
|
+
|
|
19
|
+
## The Rule
|
|
20
|
+
|
|
21
|
+
Before stating that a **JSON key, schema field, env-var name, or external API shape exists**, the agent MUST first read the authoritative source and cite it inline:
|
|
22
|
+
|
|
23
|
+
- **In-repo facts** → cite the source file as `path:line` (e.g. `packages/cli/src/config.ts:42`).
|
|
24
|
+
- **External library / API facts** → cite the vendored docs as `vendor/{lib}/v{ver}/{file}` (or the upstream URL when no vendor mirror exists).
|
|
25
|
+
|
|
26
|
+
A claim that cannot be cited has not been verified — do not state it as fact. Read the file first, or mark the statement explicitly as an assumption still to confirm.
|
|
27
|
+
|
|
28
|
+
## Applies When
|
|
29
|
+
|
|
30
|
+
- Emitting a tool call whose correctness depends on a named key/field/shape (passing a config key, asserting an MCP tool parameter, referencing a settings field).
|
|
31
|
+
- Writing explanatory prose that asserts a named key/field/env-var/API shape is present.
|
|
32
|
+
|
|
33
|
+
## Does NOT Apply To
|
|
34
|
+
|
|
35
|
+
- **Structural proposals** — "this *should* be a new `retryDelay` field" is a proposal, not a claim. Proposals describe what ought to exist; they need no citation.
|
|
36
|
+
- Well-known language/runtime built-ins (`Array.prototype.map`, `JSON.parse`) — not the failure mode this rule targets.
|
|
37
|
+
|
|
38
|
+
## Examples
|
|
39
|
+
|
|
40
|
+
**BAD** (unverified — the field name is recalled, not read):
|
|
41
|
+
|
|
42
|
+
> The merge config supports a `retryDelay` field, so set it to 500.
|
|
43
|
+
|
|
44
|
+
**GOOD** (read and cited):
|
|
45
|
+
|
|
46
|
+
> The merge config schema at `packages/codebyplan-package/src/lib/settings-merge.ts:31` defines `conflictStrategy` (there is no `retryDelay` field), so use `conflictStrategy: "theirs"`.
|
|
47
|
+
|
|
48
|
+
## Why
|
|
49
|
+
|
|
50
|
+
Silent recall of config/API names is the single cheapest-to-prevent class of subagent error: one `Read` before the claim replaces a correction round after it. The citation doubles as an audit trail — a reviewer can confirm the fact at the cited line without re-deriving it.
|
|
@@ -23,6 +23,7 @@ paths:
|
|
|
23
23
|
| `context/testing/eslint.md` | `cbp-improve-round` | Phase 1.5 | Config-file compliance audit |
|
|
24
24
|
| `context/mcp-docs.md` | `cbp-task-planner` | Phase 2.6 | MCP library doc lookup contract — per-dependency consultation via DocsByPlan MCP tools (resolve_library_id → search_chunks/lookup_symbol → get_chunk) |
|
|
25
25
|
| `context/mcp-docs.md` | `cbp-round-executor` | Step 3.4 | Library-specific reference — pre-write API verification via DocsByPlan MCP tools |
|
|
26
|
+
| `rules/parallel-waves.md` | `cbp-task-planner` | Phase 5.6 | Wave schema, invariants (3..15 file-count), and the proximity-split algorithm (a `rules/` file, not `context/**`; listed here for consumer discoverability) |
|
|
26
27
|
|
|
27
28
|
New context files MUST be added here in the same change that introduces the consumer — or the file is orphan infrastructure.
|
|
28
29
|
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
scope: org-shared
|
|
3
|
+
name: parallel-waves
|
|
4
|
+
description: Wave schema, invariants, and proximity-split algorithm for cbp-task-planner Phase 5.6 wave decomposition.
|
|
5
|
+
paths:
|
|
6
|
+
- .claude/agents/cbp-task-planner.md
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Parallel Waves
|
|
10
|
+
|
|
11
|
+
Authoritative expansion of `cbp-task-planner` Phase 5.6. The planner reads this file at wave decomposition time.
|
|
12
|
+
|
|
13
|
+
## Wave Schema
|
|
14
|
+
|
|
15
|
+
Each entry in `plan.waves[]` carries these fields (source: `.claude/agents/cbp-task-planner.md:540`):
|
|
16
|
+
|
|
17
|
+
```yaml
|
|
18
|
+
- name: string # short identifier, e.g. "web-ui", "backend", "db"
|
|
19
|
+
agent_type: 'round-executor' | 'inline'
|
|
20
|
+
files: string[] # repo-relative paths owned by this wave
|
|
21
|
+
depends_on: string[] # names of waves that must complete before this one starts
|
|
22
|
+
skill_preloads: string[] # skills invoked by the executor before Step 3 (e.g. "frontend-design")
|
|
23
|
+
note: string # optional — required on continuation waves from an arbitrary-boundary split
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Invariants
|
|
27
|
+
|
|
28
|
+
**(I) Disjoint files** — a file appears in exactly one wave. If two waves need a shared file, assign it to the earlier wave; the later wave lists the earlier in `depends_on`.
|
|
29
|
+
|
|
30
|
+
**(II) DAG** — `depends_on[]` must be acyclic. A cycle is a plan error; resolve by merging the cyclic waves.
|
|
31
|
+
|
|
32
|
+
**(III) 3–15 files per wave** — every wave holds between 3 and 15 files (inclusive).
|
|
33
|
+
- Below 3: merge into a sibling wave.
|
|
34
|
+
- Above 15: apply the proximity-split algorithm below.
|
|
35
|
+
- Sole exception — trivially small plans are exempt from the lower bound: a plan with fewer than 3 total files uses one single wave, and a single-app plan with ≤5 total files MAY skip decomposition entirely (one wave, or `waves[]` omitted — see `cbp-task-planner` Phase 5.6). Zero waves (omitted `waves[]`) trivially satisfies this invariant.
|
|
36
|
+
|
|
37
|
+
**(IV) UI skill preloads** — for each wave whose `files[]` contains UI-bearing paths (`*.tsx`, `*.jsx`, `*.scss`, etc.), add `"frontend-design"` and `"frontend-a11y"` to `skill_preloads[]` in that order (source: `.claude/agents/cbp-task-planner.md:532`).
|
|
38
|
+
|
|
39
|
+
## Proximity-Split Algorithm
|
|
40
|
+
|
|
41
|
+
When a wave would exceed 15 files, split it in priority order:
|
|
42
|
+
|
|
43
|
+
1. **Shared directory subtree** — split at the deepest common ancestor that produces two groups each ≥3 files. This is the preferred split because it keeps logically related files together.
|
|
44
|
+
2. **Shared module** — split at the next directory level below the common ancestor when subtree split cannot achieve ≥3 per group.
|
|
45
|
+
3. **Arbitrary boundary** — split at the 15-file boundary as a last resort. The continuation wave MUST carry a one-line `note` field explaining the boundary (e.g. `"files 16–28 of auth module, continued from auth-1"`).
|
|
46
|
+
|
|
47
|
+
**Independence clause** — split siblings are independent. Do NOT add `depends_on` between them unless a real shared-file or data dependency requires ordering.
|
|
48
|
+
|
|
49
|
+
**Tail rule** — choose split boundaries so every resulting wave holds 3–15 files. A split must never leave a wave with fewer than 3 files; rebalance the boundary rather than absorbing a tail into a sibling in a way that pushes that sibling above 15. The 3–15 range is a hard invariant — there is no exception above 15.
|
|
50
|
+
|
|
51
|
+
## Single-Wave Default
|
|
52
|
+
|
|
53
|
+
When no cross-app or cross-concern independence is found, the planner emits one wave covering all files. The 15-file cap applies to this single wave — if the total exceeds 15, apply the proximity-split algorithm even though the original decomposition was a single wave.
|
|
54
|
+
|
|
55
|
+
## Cross-References
|
|
56
|
+
|
|
57
|
+
- `agents/cbp-task-planner.md` Phase 5.6 — consumer of this rule; steps 1–6 and verification checklist.
|
|
58
|
+
- `agents/cbp-round-executor.md` Step 2.6 — wave-mode skill preloads.
|
|
59
|
+
- `skills/cbp-round-execute/SKILL.md` Step 3 — per-wave executor dispatch.
|
|
@@ -61,6 +61,23 @@ Given the parse from Step 1:
|
|
|
61
61
|
|
|
62
62
|
If no task found: `No active task. Nothing to update.`
|
|
63
63
|
|
|
64
|
+
### Step 1.6: Permission Gate
|
|
65
|
+
|
|
66
|
+
Step 1 (parse) and Step 1.5 (resolve task + round) are read-only. Step 2 onward mutates state — the `sync-approvals` CLI write, `complete_round`, and the auto-trigger of the next step. Before any of that, confirm the user wants this skill to run.
|
|
67
|
+
|
|
68
|
+
This gate fires on **every** invocation — manual, auto-triggered by `/cbp-round-end`, and on every iteration of the Step 4 auto-loop. There is no bypass. It sits **before** and is independent of the top-of-file HARD GATE (which governs Step 2's exit code, not user consent), and it is distinct from the Branch A clean-exit route choice in Step 5 (that one picks where to go next; this one authorizes running at all).
|
|
69
|
+
|
|
70
|
+
Ask via AskUserQuestion, naming the resolved round and disclosing the actions:
|
|
71
|
+
|
|
72
|
+
> Update ROUND-{N} of TASK-{M}?
|
|
73
|
+
> This will sync the git diff + file approvals, complete the round, and route to the next step (which may auto-start a new round).
|
|
74
|
+
>
|
|
75
|
+
> - **Proceed** — run the skill
|
|
76
|
+
> - **Cancel** — do nothing
|
|
77
|
+
|
|
78
|
+
- **Proceed** → continue to Step 2.
|
|
79
|
+
- **Cancel** → abort cleanly: make NO writes (no `sync-approvals`, no `complete_round`, no auto-trigger) and exit with one line: `Cancelled by user — ROUND-{N} not updated.`
|
|
80
|
+
|
|
64
81
|
### Step 2: Sync git diff + approvals via CLI
|
|
65
82
|
|
|
66
83
|
Run:
|
|
@@ -103,6 +120,8 @@ Procedure:
|
|
|
103
120
|
2. **If `next_index > (round.context.auto_loop_cap ?? 5)`**: surface the cap-exhausted prompt via AskUserQuestion (options: extend cap, stop loop / drop into round-input, close task as-is). Persist `round.context.auto_loop_cap_exhausted = { user_choice, decided_at }` and route per choice.
|
|
104
121
|
3. **Otherwise**: persist `round.context.auto_loop_decision = { spawned_next: true, next_index, decided_at }` on the CURRENT round via `update_round` (audit trail), then auto-trigger `/cbp-round-input` with NO AskUserQuestion. Pass `auto_loop_mode: true`, `auto_loop_index: next_index`, `auto_loop_cap: (prior cap ?? 5)` forward — round-start Step 4 persists them on the new round.
|
|
105
122
|
|
|
123
|
+
> **Permission-gate note**: the "NO AskUserQuestion" in item 3 governs only the auto-loop's decision to spawn `/cbp-round-input` — it does not add a prompt for that hand-off. It is NOT a bypass of the Step 1.6 permission gate: when the spawned round eventually re-enters `/cbp-round-update`, Step 1.6 prompts again (the gate always fires, including inside the auto-loop).
|
|
124
|
+
|
|
106
125
|
If BOTH signals are clean, fall through to Step 5 (exit routing).
|
|
107
126
|
|
|
108
127
|
### Step 5: Exit Routing
|
|
@@ -163,6 +182,7 @@ Unreachable in the auto-loop path — Step 4 catches it first. Retained for MANU
|
|
|
163
182
|
|
|
164
183
|
## Key Rules
|
|
165
184
|
|
|
185
|
+
- **Step 1.6 permission gate fires first** — every invocation (incl. auto-trigger and the Step 4 auto-loop) asks the user to confirm before any write; **Cancel** is a clean abort (no `sync-approvals`, no `complete_round`, no auto-trigger).
|
|
166
186
|
- **Step 2 (CLI) must exit 0** — if it fails, STOP. The merge semantics are enforced by the CLI.
|
|
167
187
|
- **Step 4 owns the dirty-loop case**; Step 5 owns the clean-exit case. Step 5 Branch C is for manual invocation only.
|
|
168
188
|
- **NEVER ask user to git add files** — only reads staging status. **NEVER stage files** — Claude does not touch git staging area.
|
|
@@ -170,6 +190,7 @@ Unreachable in the auto-loop path — Step 4 catches it first. Retained for MANU
|
|
|
170
190
|
|
|
171
191
|
## Integration
|
|
172
192
|
|
|
193
|
+
- **Gates**: Step 1.6 permission gate — asks the user to confirm before any side effect; **Cancel** aborts cleanly with no writes. Fires on every invocation incl. the Step 4 auto-loop; sits before and independent of the top-of-file Step 2 hard gate.
|
|
173
194
|
- **Triggered by**: `/cbp-round-end` (auto), or user manually
|
|
174
195
|
- **Reads**: MCP `get_current_task`, `get_rounds`; delegates git+approval sync to `npx codebyplan round sync-approvals`
|
|
175
196
|
- **Writes**: MCP `update_round` (auto_loop_decision / auto_loop_exit / auto_loop_cap_exhausted), `complete_round`; round+task files_changed written by CLI
|
|
@@ -65,6 +65,23 @@ task-start: no task found for `{ARG}`.
|
|
|
65
65
|
- For `45`: no standalone TASK-45 exists. If a checkpoint-bound TASK-45 exists, invoke as `{chk}-45`.
|
|
66
66
|
```
|
|
67
67
|
|
|
68
|
+
### Step 2.5: Permission Gate
|
|
69
|
+
|
|
70
|
+
Steps 1–2 are read-only (argument parse + DB resolve). Everything from Step 3 onward mutates state — branch switch/create, the clean-slate commit, the task status write, and the round-1 auto-start. Before any of that, confirm the user wants this skill to run.
|
|
71
|
+
|
|
72
|
+
This gate fires on **every** invocation — manual, auto-triggered from the pipeline, and inside any auto-loop. There is no bypass.
|
|
73
|
+
|
|
74
|
+
Ask via AskUserQuestion, naming the resolved task and disclosing the actions:
|
|
75
|
+
|
|
76
|
+
> Start TASK-{N} — {checkpoint or standalone title}?
|
|
77
|
+
> This will switch/create its feat branch, commit a clean slate if the working tree is dirty, set the task `in_progress`, and auto-start round 1.
|
|
78
|
+
>
|
|
79
|
+
> - **Proceed** — run the skill
|
|
80
|
+
> - **Cancel** — do nothing
|
|
81
|
+
|
|
82
|
+
- **Proceed** → continue to Step 3.
|
|
83
|
+
- **Cancel** → abort cleanly: make NO writes (no branch switch, no commit, no `update_task`, no `/cbp-round-start` trigger) and exit with one line: `Cancelled by user — TASK-{N} not started.`
|
|
84
|
+
|
|
68
85
|
### Step 3: Branch Auto-Handling
|
|
69
86
|
|
|
70
87
|
The task MUST run on its target feat branch. Claude switches/creates that branch automatically — never asks the user to do it.
|
|
@@ -226,7 +243,7 @@ If worktree_id present, include `claim_worktree_id` to auto-claim the checkpoint
|
|
|
226
243
|
|
|
227
244
|
### Step 6: Auto-trigger Round Start
|
|
228
245
|
|
|
229
|
-
|
|
246
|
+
The Step 2.5 permission gate already covered this hand-off (the user approved running the skill, round-1 auto-start included), so no further prompt is needed here — automatically trigger `/cbp-round-start` for the first round.
|
|
230
247
|
|
|
231
248
|
```
|
|
232
249
|
Starting first round...
|
|
@@ -236,6 +253,7 @@ Trigger `/cbp-round-start` (which will use task.requirements for round 1).
|
|
|
236
253
|
|
|
237
254
|
## Integration
|
|
238
255
|
|
|
256
|
+
- **Gates**: Step 2.5 permission gate — asks the user to confirm before any side effect; **Cancel** aborts cleanly with no writes. Fires on every invocation (manual, auto-trigger, auto-loop).
|
|
239
257
|
- **Reads**: MCP `get_current_task`, `get_tasks`, `get_rounds`
|
|
240
258
|
- **Writes**: MCP `update_task`
|
|
241
259
|
- **Triggers**: `/cbp-round-start` (auto, round 1)
|