codebyplan 1.13.44 → 1.13.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +5038 -1551
- package/package.json +1 -1
- package/templates/agents/cbp-task-check.md +1 -3
- package/templates/agents/cbp-task-planner.md +8 -6
- package/templates/hooks/cbp-auto-test-hooks.sh +1 -0
- package/templates/hooks/cbp-e2e-spec-patterns.sh +100 -0
- package/templates/hooks/cbp-lint-format-on-edit.sh +1 -0
- package/templates/hooks/cbp-maestro-yaml-validate.sh +1 -0
- package/templates/hooks/cbp-pre-commit-quality-gate.sh +1 -0
- package/templates/hooks/cbp-statusline.sh +0 -0
- package/templates/hooks/cbp-subagent-statusline.sh +0 -0
- package/templates/hooks/cbp-test-coverage-gate.sh +1 -0
- package/templates/hooks/cbp-test-hooks.sh +1 -0
- package/templates/hooks/hooks.json +4 -0
- package/templates/hooks/verify-parity.sh +20 -0
- package/templates/rules/parallel-waves.md +8 -3
- package/templates/rules/scope-vocabulary.md +4 -3
- package/templates/settings.project.base.json +22 -0
- package/templates/skills/cbp-build-cc-claude-file/SKILL.md +11 -1
- package/templates/skills/cbp-build-cc-claude-file/scripts/validate-claude-file.sh +72 -0
- package/templates/skills/cbp-build-cc-mode/SKILL.md +12 -16
- package/templates/skills/cbp-build-cc-rule/SKILL.md +11 -1
- package/templates/skills/cbp-build-cc-rule/scripts/validate-rule.sh +69 -0
- package/templates/skills/cbp-build-cc-settings/SKILL.md +2 -2
- package/templates/skills/cbp-build-cc-settings/scripts/validate-settings.sh +67 -0
- package/templates/skills/cbp-checkpoint-create/SKILL.md +12 -4
- package/templates/skills/cbp-checkpoint-end/SKILL.md +19 -11
- package/templates/skills/cbp-git-commit/SKILL.md +10 -12
- package/templates/skills/cbp-git-worktree-create/SKILL.md +7 -48
- package/templates/skills/cbp-git-worktree-remove/SKILL.md +23 -40
- package/templates/skills/cbp-map-architecture/SKILL.md +1 -0
- package/templates/skills/cbp-merge-main/SKILL.md +21 -26
- package/templates/skills/cbp-refresh-arch-map/SKILL.md +1 -0
- package/templates/skills/cbp-round-check/SKILL.md +37 -36
- package/templates/skills/cbp-round-execute/SKILL.md +9 -3
- package/templates/skills/cbp-session-end/SKILL.md +27 -47
- package/templates/skills/cbp-session-start/SKILL.md +35 -51
- package/templates/skills/cbp-standalone-task-start/SKILL.md +10 -19
- package/templates/skills/cbp-supabase-migrate/SKILL.md +24 -27
- package/templates/skills/cbp-task-start/SKILL.md +9 -21
- package/templates/skills/cbp-task-testing/SKILL.md +18 -10
|
@@ -88,14 +88,22 @@ This is the first identity-stamping point — when claiming, passing `worktree_i
|
|
|
88
88
|
|
|
89
89
|
Read `.codebyplan/git.json` `branch_config.production` (default `"main"`) as `BASE`. codebyplan repos are main-only — never create or branch from a `development`/integration branch.
|
|
90
90
|
|
|
91
|
+
Compute the slug deterministically:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
SLUG=$(codebyplan slug "{checkpoint title}")
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Then create and push the branch:
|
|
98
|
+
|
|
91
99
|
```bash
|
|
92
100
|
git fetch origin "$BASE" 2>/dev/null || true
|
|
93
|
-
git checkout -b "feat/CHK-{NNN}
|
|
94
|
-
|| git checkout -b "feat/CHK-{NNN}
|
|
95
|
-
git push -u origin "feat/CHK-{NNN}
|
|
101
|
+
git checkout -b "feat/CHK-{NNN}-$SLUG" "origin/$BASE" 2>/dev/null \
|
|
102
|
+
|| git checkout -b "feat/CHK-{NNN}-$SLUG" "$BASE"
|
|
103
|
+
git push -u origin "feat/CHK-{NNN}-$SLUG"
|
|
96
104
|
```
|
|
97
105
|
|
|
98
|
-
|
|
106
|
+
Persist the branch via `codebyplan checkpoint update --id <checkpoint-id> --branch-name "feat/CHK-{NNN}-$SLUG"` (CLI write-through; break-glass: MCP `update_checkpoint`). (The dedicated `/cbp-git-branch-feat-create` skill is the canonical config-driven helper if you prefer to delegate.)
|
|
99
107
|
|
|
100
108
|
**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.
|
|
101
109
|
|
|
@@ -166,12 +166,19 @@ Only after both the local and remote git delete above succeed, run a conditional
|
|
|
166
166
|
|
|
167
167
|
> Lifecycle contract: see [[supabase-branch-lifecycle]].
|
|
168
168
|
|
|
169
|
-
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
169
|
+
- Resolve the parent project ref and apply the lifecycle guard in one deterministic call:
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
codebyplan supabase teardown-preview "$BRANCH"
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Parse its JSON `{ status, parent_ref, project_ref, reason }`. The command never deletes anything — it reads the parent ref from `.codebyplan/shipment.json` (`.shipment.surfaces.supabase.project_ref`) and applies the protected / production / parent-ref guard from [[supabase-branch-lifecycle]].
|
|
176
|
+
- If `status === "rejected"`: STOP the teardown for this branch and surface `reason` — never delete a production / protected / integration branch or one whose preview ref equals the parent.
|
|
177
|
+
- Otherwise (`allowed` or `not_found`), use `parent_ref` for the live existence check — `mcp__supabase__list_branches` with `project_id: <parent_ref>`, then scan for an entry whose `name` exactly equals `$BRANCH`:
|
|
178
|
+
- If found: call `mcp__supabase__delete_branch` with its `branch_id`. Record the branch name in `SUPABASE_BRANCHES_DELETED[]`.
|
|
179
|
+
- If not found: no-op silently — the GitHub integration may have already removed it on PR close; not-found is success, NOT an error.
|
|
180
|
+
- 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.
|
|
181
|
+
- Never delete the parent project (`parent_ref` from `codebyplan supabase teardown-preview`) itself or any persistent/production branch — the `teardown-preview` guard enforces this.
|
|
175
182
|
|
|
176
183
|
Accumulate all Supabase branch names removed across the loop in `SUPABASE_BRANCHES_DELETED`.
|
|
177
184
|
|
|
@@ -198,11 +205,12 @@ git push origin --delete "$FEAT_BRANCH"
|
|
|
198
205
|
|
|
199
206
|
After the feat branch git delete, run the same conditional Supabase teardown for `$FEAT_BRANCH`:
|
|
200
207
|
|
|
201
|
-
-
|
|
202
|
-
-
|
|
203
|
-
-
|
|
204
|
-
- If
|
|
205
|
-
- If
|
|
208
|
+
- Run `codebyplan supabase teardown-preview "$FEAT_BRANCH"` and parse its JSON `{ status, parent_ref, project_ref, reason }` (reads the parent ref from `.codebyplan/shipment.json`, applies the lifecycle guard, never deletes).
|
|
209
|
+
- If `status === "rejected"`: STOP the teardown and surface `reason` — never delete a production / protected / integration branch or one whose preview ref equals the parent.
|
|
210
|
+
- Otherwise (`allowed` or `not_found`), use `parent_ref` for the live existence check — `mcp__supabase__list_branches` with `project_id: <parent_ref>`, then scan for an entry whose `name` exactly equals `$FEAT_BRANCH`:
|
|
211
|
+
- If found: call `mcp__supabase__delete_branch` with its `branch_id`. Add `$FEAT_BRANCH` to `SUPABASE_BRANCHES_DELETED[]`.
|
|
212
|
+
- If not found: no-op silently — idempotent, not-found is success.
|
|
213
|
+
- 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.
|
|
206
214
|
|
|
207
215
|
### Step 10: Save Shipment Results and Summary
|
|
208
216
|
|
|
@@ -108,21 +108,19 @@ REPO_PATH="$(git rev-parse --show-toplevel)"
|
|
|
108
108
|
|
|
109
109
|
**If `--files` provided:** Use the manual file list.
|
|
110
110
|
|
|
111
|
-
**If `--scope-task`:** Resolve via
|
|
111
|
+
**If `--scope-task`:** Resolve via the deterministic CLI.
|
|
112
|
+
|
|
113
|
+
First, read `task.files_changed[].path` (local-first from `.codebyplan/state/checkpoints/*/tasks/*.json`; on miss run `npx codebyplan sync` once, then re-read; MCP `get_current_task` as documented break-glass when the state dir is absent and sync fails) and format as a CSV string. Then compute the intersection:
|
|
112
114
|
|
|
113
115
|
```bash
|
|
114
|
-
#
|
|
115
|
-
|
|
116
|
-
#
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
# 2. Read staged paths
|
|
120
|
-
staged_paths=$(git diff --cached --name-only)
|
|
121
|
-
# 3. Compute intersection
|
|
122
|
-
intersect=$(comm -12 <(echo "$task_paths" | sort) <(echo "$staged_paths" | sort))
|
|
116
|
+
TASK_FILES_CSV="path1,path2,path3" # CSV string of task.files_changed[].path (local-first)
|
|
117
|
+
SCOPE_RESULT=$(codebyplan commit --scope-task --task-files "$TASK_FILES_CSV")
|
|
118
|
+
# Parse JSON: { files: string[], count: number }
|
|
119
|
+
FILES=$(echo "$SCOPE_RESULT" | jq -r '.files[]')
|
|
120
|
+
COUNT=$(echo "$SCOPE_RESULT" | jq -r '.count')
|
|
123
121
|
```
|
|
124
122
|
|
|
125
|
-
If `
|
|
123
|
+
If `COUNT === 0` (empty `files[]`): emit error and STOP.
|
|
126
124
|
|
|
127
125
|
```
|
|
128
126
|
## Error: No Task Files Staged
|
|
@@ -135,7 +133,7 @@ Options:
|
|
|
135
133
|
- Or use --all to commit the foreign-staged files instead.
|
|
136
134
|
```
|
|
137
135
|
|
|
138
|
-
If
|
|
136
|
+
If `COUNT > 0`: use `FILES` as the file list for Step 5.
|
|
139
137
|
|
|
140
138
|
**If `--task`, `--all`, or no scope:** No filtering — all staged files committed.
|
|
141
139
|
|
|
@@ -159,59 +159,18 @@ If the main repo has no `.codebyplan/e2e.env` yet, provision it after setup by r
|
|
|
159
159
|
cd "$WORKTREE_PATH" && git push -u origin "$BRANCH_NAME"
|
|
160
160
|
```
|
|
161
161
|
|
|
162
|
-
### Step 9: Register Worktree
|
|
162
|
+
### Step 9: Register Worktree and Write `.codebyplan/` Config
|
|
163
163
|
|
|
164
|
-
|
|
164
|
+
Run `codebyplan worktree create "$BRANCH_NAME" --path "$WORKTREE_PATH"` and parse the JSON output (`{ worktree_files_written: boolean, mcp_registered: boolean, worktree_id?, warn? }`):
|
|
165
165
|
|
|
166
|
-
|
|
166
|
+
- If `warn` is present: surface it as a non-blocking warning.
|
|
167
|
+
- Save the returned `worktree_id` for reference (if present).
|
|
167
168
|
|
|
168
|
-
|
|
169
|
-
MCP create_worktree:
|
|
170
|
-
repo_id: [repo-id from CLAUDE.md]
|
|
171
|
-
name: $BRANCH_NAME
|
|
172
|
-
path: $WORKTREE_PATH
|
|
173
|
-
status: "active"
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
Save the returned `worktree_id` for reference.
|
|
177
|
-
|
|
178
|
-
### Step 10: Write `.codebyplan/` directory
|
|
179
|
-
|
|
180
|
-
Create the `.codebyplan/` directory in the worktree root and write per-concern config stubs:
|
|
181
|
-
|
|
182
|
-
```bash
|
|
183
|
-
mkdir -p "$WORKTREE_PATH/.codebyplan"
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
Write `.codebyplan/repo.json` with the correct `repo_id`:
|
|
187
|
-
|
|
188
|
-
```json
|
|
189
|
-
{
|
|
190
|
-
"repo_id": "[repo-id from CLAUDE.md]"
|
|
191
|
-
}
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
Write stubs for the other per-concern files (populated by `npx codebyplan sync` on first run):
|
|
195
|
-
|
|
196
|
-
```bash
|
|
197
|
-
# .codebyplan/server.json — server port and type config
|
|
198
|
-
echo '{}' > "$WORKTREE_PATH/.codebyplan/server.json"
|
|
199
|
-
|
|
200
|
-
# .codebyplan/git.json — branch config
|
|
201
|
-
echo '{}' > "$WORKTREE_PATH/.codebyplan/git.json"
|
|
202
|
-
|
|
203
|
-
# .codebyplan/shipment.json — surface shipment config
|
|
204
|
-
echo '{}' > "$WORKTREE_PATH/.codebyplan/shipment.json"
|
|
205
|
-
|
|
206
|
-
# .codebyplan/vendor.json — vendor docs path
|
|
207
|
-
echo '{}' > "$WORKTREE_PATH/.codebyplan/vendor.json"
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
The `.codebyplan/device.local.json` file is created by `npx codebyplan setup` on the device (gitignored). The `worktree_id` is never COMMITTED; it may be cached per-device in the gitignored `.codebyplan/worktree.local.json` (branch-keyed, re-derivable via `codebyplan resolve-worktree --cache`), otherwise resolved at runtime from the `(device_id, repo path, branch)` tuple via `npx codebyplan resolve-worktree`.
|
|
169
|
+
The CLI atomically writes the `.codebyplan/` directory with per-concern config stubs and registers the worktree in the CodeByPlan database. The `.codebyplan/device.local.json` file is created by `npx codebyplan setup` on the device (gitignored). The `worktree_id` is never COMMITTED; it may be cached per-device in the gitignored `.codebyplan/worktree.local.json` (branch-keyed, re-derivable via `codebyplan resolve-worktree --cache`), otherwise resolved at runtime from the `(device_id, repo path, branch)` tuple via `npx codebyplan resolve-worktree`.
|
|
211
170
|
|
|
212
171
|
No need to mark as `skip-worktree` — the committed files are merge-safe per CHK-108 and CHK-120.
|
|
213
172
|
|
|
214
|
-
### Step
|
|
173
|
+
### Step 10: Show Result
|
|
215
174
|
|
|
216
175
|
```
|
|
217
176
|
## Worktree Created
|
|
@@ -238,4 +197,4 @@ No need to mark as `skip-worktree` — the committed files are merge-safe per CH
|
|
|
238
197
|
## Integration
|
|
239
198
|
|
|
240
199
|
- **Related**: `/cbp-git-worktree-remove` (cleanup and deregister)
|
|
241
|
-
- **
|
|
200
|
+
- **CLI**: `codebyplan worktree create <name> --path <abs>` (Step 9 — writes `.codebyplan/` config and registers worktree)
|
|
@@ -49,31 +49,17 @@ Set:
|
|
|
49
49
|
- `WORKTREE_PATH` = resolved path
|
|
50
50
|
- `BRANCH_NAME` = branch checked out in that worktree
|
|
51
51
|
|
|
52
|
-
### Step 4: Look Up Worktree in CodeByPlan
|
|
52
|
+
### Step 4: Look Up and Deregister Worktree in CodeByPlan
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
Run `codebyplan worktree remove "$BRANCH_NAME"` and parse the JSON output (`{ mcp_deregistered: boolean, warn? }`):
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
MCP get_worktrees:
|
|
60
|
-
repo_id: [repo-id from CLAUDE.md]
|
|
61
|
-
status: "active"
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
Match by `name` = `$BRANCH_NAME` or `path` = `$WORKTREE_PATH`.
|
|
65
|
-
|
|
66
|
-
Set `WORKTREE_ID` = matched worktree's `id`.
|
|
67
|
-
|
|
68
|
-
If not found in CodeByPlan, note it and continue with local removal.
|
|
56
|
+
- If `warn` is present: surface it as a non-blocking warning. The worktree was not found in CodeByPlan or deregistration failed, but local removal will proceed.
|
|
57
|
+
- If `mcp_deregistered === true`: worktree was successfully deregistered.
|
|
58
|
+
- If `mcp_deregistered === false`: worktree was not registered or deregistration failed; continue with local removal.
|
|
69
59
|
|
|
70
60
|
### Step 5: Check for Assigned Checkpoints
|
|
71
61
|
|
|
72
|
-
If
|
|
73
|
-
|
|
74
|
-
```
|
|
75
|
-
⚠ This worktree has [N] checkpoint(s) assigned. They will become unassigned.
|
|
76
|
-
```
|
|
62
|
+
If the worktree was successfully deregistered in Step 4 (`mcp_deregistered === true`), any checkpoints that were assigned to it will become unassigned. This is expected behavior and requires no additional action.
|
|
77
63
|
|
|
78
64
|
### Step 6: Confirm with User
|
|
79
65
|
|
|
@@ -92,16 +78,7 @@ Ask:
|
|
|
92
78
|
2. Remove worktree and delete branch
|
|
93
79
|
3. Cancel
|
|
94
80
|
|
|
95
|
-
### Step 7:
|
|
96
|
-
|
|
97
|
-
If `WORKTREE_ID` was found, delete the worktree record:
|
|
98
|
-
|
|
99
|
-
```
|
|
100
|
-
MCP delete_worktree:
|
|
101
|
-
worktree_id: [worktree-id]
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
### Step 8: Remove Git Worktree
|
|
81
|
+
### Step 7: Remove Git Worktree
|
|
105
82
|
|
|
106
83
|
```bash
|
|
107
84
|
git worktree remove "$WORKTREE_PATH"
|
|
@@ -114,7 +91,7 @@ git worktree remove --force "$WORKTREE_PATH"
|
|
|
114
91
|
|
|
115
92
|
Only use `--force` if the user confirms.
|
|
116
93
|
|
|
117
|
-
### Step
|
|
94
|
+
### Step 8: Delete Branch (if requested)
|
|
118
95
|
|
|
119
96
|
**Protected branch check:** Read the protected set from `.codebyplan/git.json`:
|
|
120
97
|
```bash
|
|
@@ -135,15 +112,21 @@ After the git branch delete succeeds, run a conditional Supabase preview-branch
|
|
|
135
112
|
|
|
136
113
|
> Lifecycle contract: see [[supabase-branch-lifecycle]].
|
|
137
114
|
|
|
138
|
-
- Resolve the parent project ref
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
115
|
+
- Resolve the parent project ref and apply the lifecycle guard in one deterministic call:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
codebyplan supabase teardown-preview "$BRANCH_NAME"
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Parse its JSON `{ status, parent_ref, project_ref, reason }`. The command never deletes anything — it reads the parent ref from `.codebyplan/shipment.json` (`.shipment.surfaces.supabase.project_ref`) and applies the protected / production / parent-ref guard from [[supabase-branch-lifecycle]].
|
|
122
|
+
- If `status === "rejected"`: STOP the teardown and surface `reason` — never delete a production / protected / integration branch or one whose preview ref equals the parent.
|
|
123
|
+
- Otherwise (`allowed` or `not_found`), use `parent_ref` for the live existence check — `mcp__supabase__list_branches` with `project_id: <parent_ref>`, then scan for an entry whose `name` exactly equals `$BRANCH_NAME`:
|
|
124
|
+
- If found: call `mcp__supabase__delete_branch` with its `branch_id`. Report "Supabase preview branch deleted: `$BRANCH_NAME`".
|
|
125
|
+
- If not found: no-op silently — the GitHub integration may have already removed it on PR close; not-found is success, NOT an error.
|
|
126
|
+
- 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.
|
|
127
|
+
- Never delete the parent project (`parent_ref` from `codebyplan supabase teardown-preview`) itself or any persistent/production branch — the `teardown-preview` guard enforces this.
|
|
145
128
|
|
|
146
|
-
### Step
|
|
129
|
+
### Step 9: Show Result
|
|
147
130
|
|
|
148
131
|
```
|
|
149
132
|
## Worktree Removed
|
|
@@ -159,4 +142,4 @@ After the git branch delete succeeds, run a conditional Supabase preview-branch
|
|
|
159
142
|
## Integration
|
|
160
143
|
|
|
161
144
|
- **Related**: `/cbp-git-worktree-create` (create and register)
|
|
162
|
-
- **
|
|
145
|
+
- **CLI**: `codebyplan worktree remove <name>` (Step 4 — deregister from CodeByPlan)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
scope: org-shared
|
|
3
3
|
name: cbp-map-architecture
|
|
4
|
+
effort: xhigh
|
|
4
5
|
description: Orchestrate architecture map generation for one or all modules. Spawns the cbp-map-architecture agent per module, writes per-module .md files to .claude/architecture/, regenerates INDEX.md and graph.md, and stamps each module via the CLI. Idempotent — safe to re-run.
|
|
5
6
|
argument-hint: '[--module <path>] [--deep <path,...>]'
|
|
6
7
|
allowed-tools: Read, Write, Edit, Glob, Grep, Bash, Task
|
|
@@ -69,36 +69,24 @@ Triggered by `/cbp-task-start` (Step 3.6, optional stale-check), `/cbp-task-comp
|
|
|
69
69
|
|
|
70
70
|
Supabase migrations are version-keyed by their numeric filename prefix. Two files sharing a prefix break `supabase db push`: the schema_migrations table records ONE version per prefix, the second file at the same prefix becomes orphaned, and every subsequent migration stalls — surfacing as the Supabase Preview check failing with `MIGRATIONS_FAILED`. Catch this BEFORE committing the merge, while a clean rollback is one `git merge --abort` away.
|
|
71
71
|
|
|
72
|
-
1. Probe both sides of the would-be merge
|
|
72
|
+
1. Probe both sides of the would-be merge via the deterministic CLI:
|
|
73
73
|
|
|
74
74
|
```bash
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
| sed 's|.*/||' | sort > /tmp/cbp-merge-their-names.txt
|
|
75
|
+
PROBE=$(codebyplan migration-collisions --base "$BASE" --json)
|
|
76
|
+
# Parse JSON: { base, collisions: [{ prefix, ours: string[], theirs: string[] }] }
|
|
77
|
+
COLLISIONS=$(echo "$PROBE" | jq '.collisions')
|
|
79
78
|
```
|
|
80
79
|
|
|
81
|
-
2.
|
|
80
|
+
2. If `COLLISIONS` is empty (`[]`), proceed silently to Step 2.
|
|
82
81
|
|
|
83
|
-
|
|
84
|
-
# Files unique to each side (same-named files are NOT collisions)
|
|
85
|
-
comm -23 /tmp/cbp-merge-our-names.txt /tmp/cbp-merge-their-names.txt > /tmp/cbp-merge-only-ours.txt
|
|
86
|
-
comm -13 /tmp/cbp-merge-our-names.txt /tmp/cbp-merge-their-names.txt > /tmp/cbp-merge-only-theirs.txt
|
|
87
|
-
# True collision: a prefix in only-ours also appears in only-theirs (same prefix, different basename)
|
|
88
|
-
COLLISIONS=$(cat /tmp/cbp-merge-only-ours.txt /tmp/cbp-merge-only-theirs.txt \
|
|
89
|
-
| sed 's|_.*||' | sort | uniq -d)
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
3. If `COLLISIONS` is empty, proceed silently to Step 2.
|
|
93
|
-
|
|
94
|
-
4. If `COLLISIONS` is non-empty, for each colliding prefix list both file paths (one from `HEAD`, one from `origin/{BASE}`) and surface via AskUserQuestion:
|
|
82
|
+
3. If `COLLISIONS` is non-empty, for each colliding prefix in the array (each element has `prefix`, `ours[]`, `theirs[]`) surface via AskUserQuestion:
|
|
95
83
|
|
|
96
84
|
- **Rename HEAD-side (Recommended when a main migration is already applied to a shared remote)** — rename the local file to a fresh, sequential timestamp that respects existing apply-order dependencies (probe `supabase migration list --db-url <preview>` if a preview branch exists, or inspect FK references in surrounding migrations). The orchestrator runs `git mv <old> <new>` itself; the rename lands in the git index and is picked up by the re-probe at step 5.
|
|
97
85
|
- **Rename main-side (manual, OUT-OF-SKILL)** — only when the main file definitely has not been applied anywhere yet AND the user has write access to `{BASE}`. This skill does NOT touch the main branch: it runs on a feat branch (Step 0 enforces this) and the Key Rules below forbid any push from this skill. The user must, in a separate terminal: `git checkout {BASE} && git mv <old> <new> && git commit -m "fix(migration): rename to resolve collision with feat/..." && git push origin {BASE}`. After that push is confirmed remote-side, re-invoke `/cbp-merge-main` — Step 1 will fetch the updated main tip and Step 1.5 will re-probe with the rename in place.
|
|
98
86
|
- **Defer to a new task in the active checkpoint** — `git merge --abort` is unnecessary because Step 2 has not started. Create a CHK-bound task per `cbp-round-end` reference `findings-presentation.md` "Infra Issue Absorption Contract — Resolve-in-Current-Scope by Default" and STOP `/cbp-merge-main`. Resume after the task completes.
|
|
99
87
|
- **Abort merge** — STOP the skill. User decides later.
|
|
100
88
|
|
|
101
|
-
|
|
89
|
+
4. After any HEAD-side rename action, re-execute Step 1.5 (collisions may chain — fixing one can expose another). The CLI probes the HEAD side via `git ls-files` (so staged renames are visible), matching the documented re-probe behavior. Main-side renames require a fresh `/cbp-merge-main` invocation (the user manually fetched and re-ran per option 2 above), not an in-skill loop.
|
|
102
90
|
|
|
103
91
|
This check is intentionally placed BEFORE Step 2's `git merge`: catching collisions pre-merge means no merge commit to revert, no conflict-resolution work to throw away, no Supabase Preview poll to fail.
|
|
104
92
|
|
|
@@ -165,27 +153,34 @@ This check is intentionally placed BEFORE Step 2's `git merge`: catching collisi
|
|
|
165
153
|
|
|
166
154
|
Run a scoped subset of the testing-qa check matrix INLINE (no agent spawn — this skill stays lightweight):
|
|
167
155
|
|
|
168
|
-
1.
|
|
156
|
+
1. From the repo root, run:
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
codebyplan check --scope merged --json
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
`--scope merged` runs `gate6`, `lint`, `typecheck`, and `tests` (no `audit` — that is `task` scope only). The runner is **whole-repo + baseline**: it runs `turbo run lint|typecheck|test` across every package and diffs against the committed `.check-baseline.json`, so only NEW per-package failures fail a check (`status: 'fail'` with a non-empty `new_failures`). `gate6` (sibling-identity parity) is ALWAYS hard-fail and never baselined. Capture the JSON result.
|
|
163
|
+
|
|
164
|
+
2. For each result entry where `status === 'fail'`, surface its `stdout`/`stderr` and present an AskUserQuestion:
|
|
169
165
|
- **Continue (commit-as-is)** — leave the merge committed; flag QA failure in output.
|
|
170
166
|
- **Abort merge** — `git reset --hard HEAD~1` to revert just the merge commit. Stop the skill.
|
|
171
167
|
- **Skip (mark warn)** — leave the merge committed; treat as warn, not fail.
|
|
172
168
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
3. `pnpm test --run` — only if any merged file matches typical source globs (`src/**`, `apps/**/src/**`, `packages/**/src/**`). Same three-option prompt on failure.
|
|
176
|
-
|
|
177
|
-
4. Build a `qa_summary` object:
|
|
169
|
+
3. Build a `qa_summary` object from the runner's results array:
|
|
178
170
|
|
|
179
171
|
```
|
|
180
172
|
{
|
|
173
|
+
"gate6": "pass" | "fail" | "warn" | "skipped",
|
|
181
174
|
"lint": "pass" | "fail" | "warn" | "skipped",
|
|
182
|
-
"
|
|
175
|
+
"typecheck": "pass" | "fail" | "warn" | "skipped",
|
|
183
176
|
"tests": "pass" | "fail" | "warn" | "skipped",
|
|
184
177
|
"merged_files_count": N,
|
|
185
178
|
"user_choice_on_failure": "continue" | "abort" | "skip" | null
|
|
186
179
|
}
|
|
187
180
|
```
|
|
188
181
|
|
|
182
|
+
Map runner `status` values: `"pass"` → `"pass"`, `"skipped"` → `"skipped"`, `"fail"` → `"fail"` or `"warn"` per the user's choice above.
|
|
183
|
+
|
|
189
184
|
Do NOT auto-revert without user consent. User-driven gating is the contract.
|
|
190
185
|
|
|
191
186
|
### Step 5: Output
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
scope: org-shared
|
|
3
3
|
name: cbp-refresh-arch-map
|
|
4
|
+
effort: high
|
|
4
5
|
description: Drift-scoped refresh of the .claude/architecture/ map — re-runs the cbp-map-architecture agent for ONLY the modules whose stamped git SHA has changed, regenerates INDEX.md + graph.md, and re-stamps. Idempotent; no-op when no module has drifted.
|
|
5
6
|
argument-hint: '[--module <path>]'
|
|
6
7
|
allowed-tools: Read, Write, Edit, Glob, Grep, Bash, Task
|
|
@@ -30,7 +30,7 @@ Set `KIND` for the rest of this skill. MCP tool names vary by KIND:
|
|
|
30
30
|
|
|
31
31
|
# Round Check Command
|
|
32
32
|
|
|
33
|
-
Run automated checks independently with mandatory execution. Updates round QA. Hard fails if mandatory checks (
|
|
33
|
+
Run automated checks independently with mandatory execution. Updates round QA. Hard fails if mandatory checks (gate6/lint/typecheck/tests) fail.
|
|
34
34
|
|
|
35
35
|
## Instructions
|
|
36
36
|
|
|
@@ -41,80 +41,80 @@ Use Kind Detection above to set KIND. Then:
|
|
|
41
41
|
- **checkpoint KIND**: Read `.codebyplan/state/checkpoints/<checkpointId>/tasks/<taskId>.json` (local-first) to find active task, then read `.codebyplan/state/checkpoints/<checkpointId>/tasks/<taskId>/rounds/<roundId>.json` to find the in-progress round. If missing/stale, run `npx codebyplan sync` once and re-read. Break-glass fallback: MCP `get_current_task(repo_id)` + `get_rounds(task_id)` when state dir is absent and sync fails.
|
|
42
42
|
- **standalone KIND**: MCP `get_current_standalone_task(repo_id)` to find active task, then `get_standalone_rounds(standalone_task_id)` to find the in-progress round. (Standalone KIND still uses MCP until a later task.)
|
|
43
43
|
|
|
44
|
-
### Step 2:
|
|
44
|
+
### Step 2: Run Core Check Matrix
|
|
45
|
+
|
|
46
|
+
From the repo root, run:
|
|
45
47
|
|
|
46
|
-
Find the correct app directory:
|
|
47
48
|
```bash
|
|
48
|
-
|
|
49
|
+
codebyplan check --scope round --json
|
|
49
50
|
```
|
|
50
|
-
Identify app dir from project structure (e.g., `apps/web/` for Next.js).
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
Capture the JSON output. The runner is **whole-repo + baseline**: it runs `turbo run lint|typecheck|test` across every package and diffs each per-package result against the committed `.check-baseline.json`, so a pre-existing failure in an unrelated package does NOT fail the check — only a NEW failure does. The result shape is:
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"results": [
|
|
57
|
+
{"check": "gate6"|"lint"|"typecheck"|"tests"|"audit", "status": "pass"|"fail"|"skipped",
|
|
58
|
+
"exit_code": number|null, "command": string, "stdout": string, "stderr": string,
|
|
59
|
+
"executed": boolean, "new_failures"?: string[]}
|
|
60
|
+
],
|
|
61
|
+
"any_failed": boolean,
|
|
62
|
+
"hard_fail_checks": [ ...names of checks that FAILED ]
|
|
63
|
+
}
|
|
64
|
+
```
|
|
55
65
|
|
|
56
|
-
|
|
57
|
-
|-------|---------|-----------|
|
|
58
|
-
| **Build** | `cd {app_dir} && npm run build 2>&1` | YES |
|
|
59
|
-
| **Lint** | `cd {app_dir} && npm run lint 2>&1` | YES |
|
|
60
|
-
| **Types** | `cd {app_dir} && npx tsc --noEmit 2>&1` | YES |
|
|
66
|
+
Five checks run in order: `gate6` (sibling-identity parity — `node scripts/check-sibling-identity.mjs`), `lint`, `typecheck`, `tests`, `audit`. For the baselined checks (`lint`/`typecheck`/`tests`) `new_failures` lists the packages that newly fail (not in the baseline); `status` is `pass` when `new_failures` is empty **even if the underlying command exited non-zero** (those failures are pre-existing/baselined). `audit.new_failures` lists new GHSA advisory ids not in the allowlist. **`gate6` is ALWAYS hard-fail — it is never baselined**; its `new_failures` field is omitted (absent/`undefined` in the JSON, not `null`), and a sibling-parity divergence fails the round regardless of the baseline.
|
|
61
67
|
|
|
62
|
-
|
|
63
|
-
- Run the command via Bash tool
|
|
64
|
-
- Log `EXECUTED: <command>` or `FAILED: <command> (exit code: N)`
|
|
65
|
-
- If skipping (infrastructure-only changes): log `SKIPPED: <command> (reason: no app code changed)`
|
|
68
|
+
`hard_fail_checks` is dynamic — it lists only the checks that failed (`[]` when all pass; e.g. `["gate6"]` or `["typecheck","tests"]`), drawn from `results[].check`. The hard-fail checks for `--scope round` are `gate6`, `lint`, `typecheck`, and `tests` (`audit` is `--scope task` only). If `any_failed === true` (equivalently, `hard_fail_checks` is non-empty), this is a **hard fail** — surface each failing result's `stdout`/`stderr` (and `new_failures`) and stop.
|
|
66
69
|
|
|
67
|
-
### Step
|
|
70
|
+
### Step 3: Execute Conditional Checks
|
|
68
71
|
|
|
69
72
|
| Check | Command | Condition |
|
|
70
73
|
|-------|---------|-----------|
|
|
71
|
-
| **Tests** | `cd {app_dir} && npx vitest --run 2>&1` | Test files exist |
|
|
72
74
|
| **A11y** | Static check (aria, alt, focus) | UI files changed |
|
|
73
75
|
| **API Health** | `curl -s -o /dev/null -w "%{http_code}" http://localhost:{PORT}/` | API routes changed |
|
|
74
76
|
| **Visual** | Visual check flow (page-map + visual-check) | UI work + dev server running |
|
|
75
77
|
|
|
76
|
-
### Step
|
|
78
|
+
### Step 4: Analyze Output
|
|
77
79
|
|
|
78
|
-
Scan
|
|
80
|
+
Scan each runner result's `stdout`/`stderr` for:
|
|
79
81
|
- **Warnings** (not just errors)
|
|
80
82
|
- **Deprecation notices** (`grep -i "deprecat"` in output)
|
|
81
83
|
- **Console.log in changed files**: `grep -rn "console\.\(log\|debug\|info\)" {changed_files}` (exclude tests)
|
|
82
84
|
- **Bundle size warnings**
|
|
83
85
|
|
|
84
|
-
### Step
|
|
86
|
+
### Step 5: Save QA Results
|
|
85
87
|
|
|
86
88
|
Update round QA:
|
|
87
89
|
- **checkpoint KIND**: `codebyplan round update --id <round_id> --task-id <task_id> --checkpoint-id <checkpoint_id> --qa '<json>'` (CLI write-through: local state file + REST). Break-glass fallback: MCP `update_round(round_id, qa: ...)` when the CLI is unavailable.
|
|
88
90
|
- **standalone KIND**: MCP `update_standalone_round(standalone_round_id, qa: ...)`. (Standalone KIND still uses MCP until a later task.)
|
|
89
91
|
|
|
92
|
+
Map each runner result entry to a QA item:
|
|
93
|
+
|
|
90
94
|
```json
|
|
91
95
|
{
|
|
92
96
|
"items": [
|
|
93
|
-
{"type": "auto", "check": "
|
|
94
|
-
{"type": "auto", "check": "lint", "status": "
|
|
95
|
-
{"type": "auto", "check": "
|
|
96
|
-
{"type": "auto", "check": "tests", "status": "
|
|
97
|
+
{"type": "auto", "check": "gate6", "status": "pass", "ran_at": "...", "notes": null, "executed": true},
|
|
98
|
+
{"type": "auto", "check": "lint", "status": "pass", "ran_at": "...", "notes": null, "executed": true},
|
|
99
|
+
{"type": "auto", "check": "typecheck", "status": "fail", "ran_at": "...", "notes": "1 new failing package", "executed": true},
|
|
100
|
+
{"type": "auto", "check": "tests", "status": "pass", "ran_at": "...", "notes": "no new failures (baselined)", "executed": true}
|
|
97
101
|
]
|
|
98
102
|
}
|
|
99
103
|
```
|
|
100
104
|
|
|
101
|
-
### Step
|
|
105
|
+
### Step 6: Show Results
|
|
102
106
|
|
|
103
107
|
```
|
|
104
108
|
## Round Check Results
|
|
105
109
|
|
|
106
110
|
| Check | Status | Executed | Notes |
|
|
107
111
|
|-------|--------|----------|-------|
|
|
108
|
-
|
|
|
109
|
-
|
|
|
110
|
-
|
|
|
111
|
-
|
|
|
112
|
-
|
|
|
113
|
-
|
|
114
|
-
### Build Analysis
|
|
115
|
-
- Warnings: [N]
|
|
116
|
-
- Deprecations: [N]
|
|
117
|
-
- Console.logs in code: [N]
|
|
112
|
+
| gate6 | pass | yes | sibling-identity OK |
|
|
113
|
+
| lint | pass | yes | - |
|
|
114
|
+
| typecheck | fail | yes | 1 new failing package |
|
|
115
|
+
| tests | pass | yes | no new failures (baselined) |
|
|
116
|
+
| A11y | pass | yes | - |
|
|
117
|
+
| Visual| pass | yes | screenshots saved |
|
|
118
118
|
|
|
119
119
|
**Result**: [N] passed, [N] failed, [N] skipped
|
|
120
120
|
**Hard fail**: [yes/no]
|
|
@@ -129,4 +129,5 @@ If soft failures only: `Run /cbp-round-start to trigger auto-fix, or fix manuall
|
|
|
129
129
|
- **Reads (standalone KIND)**: MCP `get_current_standalone_task` / `get_standalone_rounds` (standalone KIND still uses MCP until a later task)
|
|
130
130
|
- **Writes (checkpoint KIND)**: `codebyplan round update` (qa field). Break-glass: MCP `update_round`.
|
|
131
131
|
- **Writes (standalone KIND)**: MCP `update_standalone_round` (qa field). (Standalone KIND still uses MCP until a later task.)
|
|
132
|
+
- **Runner**: `codebyplan check --scope round --json` (whole-repo + baseline via `turbo run`; runs gate6 + lint + typecheck + tests; `--files` is accepted but ignored in whole-repo mode)
|
|
132
133
|
- **Standalone**: Can be run independently at any time
|
|
@@ -178,7 +178,13 @@ Per-wave hard-fail signal — true when ANY hold:
|
|
|
178
178
|
|
|
179
179
|
- `testing_qa_output.totals.hard_fail === true`.
|
|
180
180
|
- For any framework `f` in `round.context.e2e_outputs`: `e2e_outputs[f].status === 'failed'` OR `e2e_outputs[f].test_results?.failed > 0`.
|
|
181
|
-
-
|
|
181
|
+
- **E2E deterministic gate** (replaces the former judgment-based `e2e_eligible_skipped` evaluation): when `round.context.e2e_eligible[]` is non-empty, first persist `e2e_eligible` / `e2e_outputs` to round context via MCP `update_round` (the Step 7 write, pulled forward — the CLI reads the round row from the DB), then run:
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
codebyplan e2e verify-round --round-id <round_id> --task-id <task_id>
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Exit 0 = e2e pass. Exit 1 = one or more deterministic hard-fails — the stdout JSON's `failed_checks[]` identifies which (`e2e_eligible_skipped`, `zero_assertion_run`, `empty_gallery`); the `rules/e2e-mandatory.md` valid-skip list and the vscode-test empty-gallery exception are honored by the CLI. When `e2e_eligible[]` is empty, skip the CLI call — nothing to verify.
|
|
182
188
|
|
|
183
189
|
**All waves hard_fail: false** → proceed to Step 7. **Any wave hard_fail: true**:
|
|
184
190
|
|
|
@@ -197,9 +203,9 @@ When `cbp-testing-qa-agent` spawn fails OR the resolved `testing_profile` is `cl
|
|
|
197
203
|
|
|
198
204
|
`codebyplan round update --id <round-id> --task-id <uuid> --checkpoint-id <uuid> --context <json>` (CLI write-through: local state at `.codebyplan/state/checkpoints/<checkpointId>/tasks/<taskId>/rounds/<roundId>.json` + REST). Break-glass fallback: MCP `update_round` when the CLI is unavailable.
|
|
199
205
|
|
|
200
|
-
- `context`: { ...existing, executor_output, testing_qa_output, e2e_eligible, e2e_outputs, frontend_ui_review }
|
|
206
|
+
- `context`: { ...existing, executor_output, testing_qa_output, e2e_eligible, e2e_outputs, frontend_ui_review } — when e2e ran, `e2e_eligible` / `e2e_outputs` were already persisted by the Step 6 pull-forward write; re-include them in this merge payload (the `update_round` REPLACE contract requires re-sending every field that should remain — this is a consolidating merge, not a second write of new data).
|
|
201
207
|
|
|
202
|
-
`e2e_outputs` (a framework-keyed map of specialist outputs, e.g. `{ playwright: {...}, maestro: {...} }`)
|
|
208
|
+
`e2e_outputs` (a framework-keyed map of specialist outputs, e.g. `{ playwright: {...}, maestro: {...} }`) is present when ≥1 eligible framework ran. `frontend_ui_review` is present only when ≥1 eligible framework ran AND Step 5b ran (non-empty screenshots). `e2e_eligible[]` records which frameworks were eligible this round and drives the Step 6 E2E deterministic gate.
|
|
203
209
|
|
|
204
210
|
### Step 8: Auto-trigger Round End
|
|
205
211
|
|