codebyplan 1.12.0 → 1.13.3
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 +2648 -2033
- package/package.json +2 -2
- package/templates/github-workflows/publish.yml +207 -0
- package/templates/hooks/README.md +1 -13
- package/templates/hooks/cbp-test-coverage-gate.sh +8 -0
- package/templates/hooks/cbp-test-hooks.sh +0 -42
- package/templates/hooks/hooks.json +0 -9
- package/templates/settings.project.base.json +154 -3
- package/templates/skills/cbp-build-cc-settings/SKILL.md +2 -0
- package/templates/skills/cbp-build-cc-settings/reference/cbp-permission-policy.md +48 -0
- package/templates/skills/cbp-checkpoint-end/SKILL.md +7 -0
- package/templates/skills/cbp-checkpoint-start/SKILL.md +2 -2
- package/templates/skills/cbp-session-start/SKILL.md +1 -1
- package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/SKILL.md +1 -1
- package/templates/skills/cbp-setup-eslint/SKILL.md +199 -0
- package/templates/skills/cbp-setup-eslint/reference/base.md +82 -0
- package/templates/skills/cbp-setup-eslint/reference/cli.md +56 -0
- package/templates/skills/cbp-setup-eslint/reference/e2e.md +68 -0
- package/templates/skills/cbp-setup-eslint/reference/jest.md +59 -0
- package/templates/skills/cbp-setup-eslint/reference/nestjs.md +69 -0
- package/templates/skills/cbp-setup-eslint/reference/nextjs.md +63 -0
- package/templates/skills/cbp-setup-eslint/reference/node.md +74 -0
- package/templates/skills/cbp-setup-eslint/reference/react-native.md +60 -0
- package/templates/skills/cbp-setup-eslint/reference/react.md +82 -0
- package/templates/skills/cbp-setup-eslint/reference/tailwind.md +64 -0
- package/templates/skills/cbp-setup-eslint/reference/testing-react.md +57 -0
- package/templates/skills/cbp-setup-eslint/reference/vitest.md +62 -0
- package/templates/skills/cbp-ship/reference/versioning.md +31 -3
- package/templates/skills/cbp-ship-configure/SKILL.md +16 -36
- package/templates/skills/cbp-ship-configure/reference/npm-package.md +15 -6
- package/templates/skills/cbp-ship-main/SKILL.md +4 -0
- package/templates/skills/cbp-task-complete/SKILL.md +1 -3
- package/templates/skills/cbp-task-start/SKILL.md +3 -3
- package/templates/hooks/cbp-mcp-worktree-inject.sh +0 -76
- /package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/reference/maestro.md +0 -0
- /package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/reference/playwright.md +0 -0
- /package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/reference/tauri.md +0 -0
- /package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/reference/vscode.md +0 -0
- /package/templates/skills/{cbp-e2e-setup → cbp-setup-e2e}/reference/xcuitest.md +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codebyplan",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.13.3",
|
|
4
4
|
"description": "CLI for CodeByPlan — AI-powered development planning and tracking",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"homepage": "https://codebyplan.com",
|
|
34
34
|
"repository": {
|
|
35
35
|
"type": "git",
|
|
36
|
-
"url": "https://github.com/
|
|
36
|
+
"url": "https://github.com/midevyou/codebyplan.git",
|
|
37
37
|
"directory": "packages/codebyplan-package"
|
|
38
38
|
},
|
|
39
39
|
"license": "MIT",
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# Generated by: codebyplan scaffold-publish-workflow
|
|
2
|
+
#
|
|
3
|
+
# This workflow publishes the codebyplan npm package on every merge to main
|
|
4
|
+
# where the committed package.json version exceeds the version currently on npm.
|
|
5
|
+
# No release PR, no conventional-commit parsing — the version committed in the
|
|
6
|
+
# feat branch is the version that ships.
|
|
7
|
+
#
|
|
8
|
+
# Two values a consuming repo must adjust:
|
|
9
|
+
# 1. paths: — set to the package directory whose package.json drives versioning
|
|
10
|
+
# (current value: 'packages/codebyplan-package/**')
|
|
11
|
+
# 2. npm view <package-name> — replace `codebyplan` with the actual package name
|
|
12
|
+
# in the "Check version vs published" step
|
|
13
|
+
#
|
|
14
|
+
# Everything else (OIDC auth, pnpm 10.12.4, Node 20, build:npm → publish) is
|
|
15
|
+
# intentionally generic and works as-is for any single-package npm publish.
|
|
16
|
+
|
|
17
|
+
name: Publish codebyplan to npm
|
|
18
|
+
|
|
19
|
+
on:
|
|
20
|
+
push:
|
|
21
|
+
branches:
|
|
22
|
+
- main
|
|
23
|
+
paths:
|
|
24
|
+
- "packages/codebyplan-package/**"
|
|
25
|
+
workflow_dispatch:
|
|
26
|
+
inputs:
|
|
27
|
+
dry_run:
|
|
28
|
+
description: "Print what would be published without actually publishing"
|
|
29
|
+
type: boolean
|
|
30
|
+
default: false
|
|
31
|
+
|
|
32
|
+
permissions:
|
|
33
|
+
contents: write
|
|
34
|
+
id-token: write
|
|
35
|
+
|
|
36
|
+
jobs:
|
|
37
|
+
check-version:
|
|
38
|
+
name: Check if publish needed
|
|
39
|
+
runs-on: ubuntu-latest
|
|
40
|
+
outputs:
|
|
41
|
+
should_publish: ${{ steps.check.outputs.should_publish }}
|
|
42
|
+
version: ${{ steps.check.outputs.version }}
|
|
43
|
+
steps:
|
|
44
|
+
- name: Checkout
|
|
45
|
+
uses: actions/checkout@v4
|
|
46
|
+
|
|
47
|
+
- name: Check version vs published
|
|
48
|
+
id: check
|
|
49
|
+
run: |
|
|
50
|
+
VERSION=$(jq -r '.version' packages/codebyplan-package/package.json)
|
|
51
|
+
if [ -z "$VERSION" ] || [ "$VERSION" = "null" ]; then
|
|
52
|
+
echo "ERROR: could not read .version from packages/codebyplan-package/package.json"
|
|
53
|
+
exit 1
|
|
54
|
+
fi
|
|
55
|
+
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
|
56
|
+
|
|
57
|
+
# Pre-release versions (e.g. 1.2.3-beta.1) must never auto-publish to the
|
|
58
|
+
# 'latest' dist-tag — sort -V is not semver-aware for pre-release suffixes,
|
|
59
|
+
# and this workflow always publishes to latest. Publish pre-releases
|
|
60
|
+
# manually with `npm publish --tag <pre-id>`. The version core (X.Y.Z) has
|
|
61
|
+
# no hyphen, so any '-' marks a pre-release.
|
|
62
|
+
case "$VERSION" in
|
|
63
|
+
*-*)
|
|
64
|
+
echo "VERSION=${VERSION} is a pre-release — skipping auto-publish."
|
|
65
|
+
echo "should_publish=false" >> "$GITHUB_OUTPUT"
|
|
66
|
+
exit 0
|
|
67
|
+
;;
|
|
68
|
+
esac
|
|
69
|
+
|
|
70
|
+
# Manual dispatch: always publish (recovery / forced re-publish path).
|
|
71
|
+
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
|
72
|
+
echo "Manual dispatch — skipping gt check, will publish."
|
|
73
|
+
echo "should_publish=true" >> "$GITHUB_OUTPUT"
|
|
74
|
+
exit 0
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
# Push path: compare committed version against the npm registry.
|
|
78
|
+
# Distinguish "never published" (E404 → first publish) from a transient
|
|
79
|
+
# registry/network error (abort rather than blindly publish).
|
|
80
|
+
NPM_OUT=$(npm view codebyplan version 2>&1)
|
|
81
|
+
NPM_EXIT=$?
|
|
82
|
+
if [ "$NPM_EXIT" -ne 0 ]; then
|
|
83
|
+
if echo "$NPM_OUT" | grep -q "E404"; then
|
|
84
|
+
echo "Package not yet published — first publish."
|
|
85
|
+
echo "should_publish=true" >> "$GITHUB_OUTPUT"
|
|
86
|
+
exit 0
|
|
87
|
+
fi
|
|
88
|
+
echo "ERROR: npm view failed (exit ${NPM_EXIT}): ${NPM_OUT}"
|
|
89
|
+
exit 1
|
|
90
|
+
fi
|
|
91
|
+
PUBLISHED="$NPM_OUT"
|
|
92
|
+
|
|
93
|
+
# sort -V: version-aware sort. If VERSION sorts AFTER PUBLISHED, it is greater.
|
|
94
|
+
GREATER=$(printf '%s\n%s\n' "$PUBLISHED" "$VERSION" | sort -V | tail -n1)
|
|
95
|
+
if [ "$GREATER" = "$VERSION" ] && [ "$VERSION" != "$PUBLISHED" ]; then
|
|
96
|
+
echo "VERSION=${VERSION} > PUBLISHED=${PUBLISHED} — will publish."
|
|
97
|
+
echo "should_publish=true" >> "$GITHUB_OUTPUT"
|
|
98
|
+
else
|
|
99
|
+
echo "VERSION=${VERSION} <= PUBLISHED=${PUBLISHED} — skipping publish."
|
|
100
|
+
echo "should_publish=false" >> "$GITHUB_OUTPUT"
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
publish-codebyplan:
|
|
104
|
+
name: Publish to npm (OIDC)
|
|
105
|
+
needs: check-version
|
|
106
|
+
if: needs.check-version.outputs.should_publish == 'true'
|
|
107
|
+
runs-on: ubuntu-latest
|
|
108
|
+
permissions:
|
|
109
|
+
# OIDC token for npm Trusted Publishing — no long-lived NPM_TOKEN needed.
|
|
110
|
+
id-token: write
|
|
111
|
+
contents: read
|
|
112
|
+
steps:
|
|
113
|
+
- uses: actions/checkout@v4
|
|
114
|
+
|
|
115
|
+
- name: Setup pnpm
|
|
116
|
+
uses: pnpm/action-setup@v4
|
|
117
|
+
with:
|
|
118
|
+
version: 10.12.4
|
|
119
|
+
|
|
120
|
+
# Deliberately NO registry-url: actions/setup-node would write an
|
|
121
|
+
# `_authToken=${NODE_AUTH_TOKEN}` line into .npmrc, and that (empty) token
|
|
122
|
+
# shadows OIDC trusted publishing — npm uses the token path and gets E404
|
|
123
|
+
# instead of doing the OIDC exchange. publishConfig.registry handles the
|
|
124
|
+
# target registry for `npm publish`.
|
|
125
|
+
- name: Setup Node
|
|
126
|
+
uses: actions/setup-node@v4
|
|
127
|
+
with:
|
|
128
|
+
node-version: 20
|
|
129
|
+
cache: pnpm
|
|
130
|
+
|
|
131
|
+
- name: Install dependencies
|
|
132
|
+
run: pnpm install --frozen-lockfile
|
|
133
|
+
|
|
134
|
+
- name: Build packages/codebyplan-package
|
|
135
|
+
working-directory: packages/codebyplan-package
|
|
136
|
+
run: pnpm build:npm
|
|
137
|
+
|
|
138
|
+
# npm Trusted Publishing (OIDC) requires npm >= 11.5.1; Node 20 ships npm 10.x.
|
|
139
|
+
- name: Upgrade npm for trusted publishing
|
|
140
|
+
run: |
|
|
141
|
+
npm install -g npm@latest
|
|
142
|
+
npm --version
|
|
143
|
+
echo "OIDC token request URL present: ${ACTIONS_ID_TOKEN_REQUEST_URL:+yes}"
|
|
144
|
+
|
|
145
|
+
- name: Dry-run check
|
|
146
|
+
if: ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run == true }}
|
|
147
|
+
working-directory: packages/codebyplan-package
|
|
148
|
+
run: |
|
|
149
|
+
echo "dry_run=true — skipping actual publish."
|
|
150
|
+
echo "Would publish: codebyplan@${{ needs.check-version.outputs.version }}"
|
|
151
|
+
|
|
152
|
+
# No NODE_AUTH_TOKEN: npm >= 11.5.1 exchanges the GitHub OIDC token for a
|
|
153
|
+
# short-lived publish token. Requires a Trusted Publisher configured for
|
|
154
|
+
# this repo + workflow on npmjs.com.
|
|
155
|
+
#
|
|
156
|
+
# NO --provenance by default: npm provenance attestation only supports
|
|
157
|
+
# PUBLIC source repositories (the registry returns E422 "Unsupported
|
|
158
|
+
# source repository visibility: private" otherwise). This works for both
|
|
159
|
+
# public and private repos. If your source repo is PUBLIC and you want
|
|
160
|
+
# supply-chain attestation, add `--provenance` to the command below.
|
|
161
|
+
- name: Publish to npm
|
|
162
|
+
if: ${{ github.event_name != 'workflow_dispatch' || inputs.dry_run != true }}
|
|
163
|
+
working-directory: packages/codebyplan-package
|
|
164
|
+
run: npm publish --access public
|
|
165
|
+
|
|
166
|
+
tag-and-release:
|
|
167
|
+
name: Tag + GitHub release
|
|
168
|
+
needs: [check-version, publish-codebyplan]
|
|
169
|
+
if: |
|
|
170
|
+
needs.check-version.outputs.should_publish == 'true' &&
|
|
171
|
+
needs.publish-codebyplan.result == 'success' &&
|
|
172
|
+
!(github.event_name == 'workflow_dispatch' && inputs.dry_run == true)
|
|
173
|
+
runs-on: ubuntu-latest
|
|
174
|
+
permissions:
|
|
175
|
+
contents: write
|
|
176
|
+
steps:
|
|
177
|
+
- name: Checkout
|
|
178
|
+
uses: actions/checkout@v4
|
|
179
|
+
|
|
180
|
+
- name: Create tag and release (idempotent)
|
|
181
|
+
env:
|
|
182
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
183
|
+
VERSION: ${{ needs.check-version.outputs.version }}
|
|
184
|
+
run: |
|
|
185
|
+
TAG="v${VERSION}"
|
|
186
|
+
|
|
187
|
+
# Idempotent: skip tag creation if it already exists.
|
|
188
|
+
if git ls-remote --tags origin "refs/tags/${TAG}" | grep -q "${TAG}"; then
|
|
189
|
+
echo "Tag ${TAG} already exists — skipping tag creation."
|
|
190
|
+
else
|
|
191
|
+
git config user.name "github-actions[bot]"
|
|
192
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
193
|
+
git tag "${TAG}"
|
|
194
|
+
git push origin "${TAG}"
|
|
195
|
+
echo "Created and pushed tag ${TAG}."
|
|
196
|
+
fi
|
|
197
|
+
|
|
198
|
+
# Create GitHub release (idempotent: gh release create fails if exists; check first).
|
|
199
|
+
if gh release view "${TAG}" > /dev/null 2>&1; then
|
|
200
|
+
echo "GitHub release ${TAG} already exists — skipping."
|
|
201
|
+
else
|
|
202
|
+
gh release create "${TAG}" \
|
|
203
|
+
--title "codebyplan v${VERSION}" \
|
|
204
|
+
--notes "codebyplan v${VERSION} — published to npm: https://www.npmjs.com/package/codebyplan/v/${VERSION} (install: npm install -g codebyplan@${VERSION})" \
|
|
205
|
+
--latest
|
|
206
|
+
echo "Created GitHub release ${TAG}."
|
|
207
|
+
fi
|
|
@@ -228,18 +228,6 @@ Denies any `git stash` command (including `git -C <dir> stash` and `git stash po
|
|
|
228
228
|
|
|
229
229
|
---
|
|
230
230
|
|
|
231
|
-
### `cbp-mcp-worktree-inject.sh` — PreToolUse, matcher `mcp__codebyplan__(update_task|complete_task|complete_round|update_checkpoint)`
|
|
232
|
-
|
|
233
|
-
Auto-injects `caller_worktree_id` into CodeByPlan MCP mutation calls when it's missing, resolving it via `npx codebyplan resolve-worktree` (with `--fallback-from-branch`). Closes the manual worktree-pinning workaround so MCP writes pass the server-side worktree pre-guard without hand-editing every call.
|
|
234
|
-
|
|
235
|
-
**Blocks vs warns**: neither — emits an `updatedInput` to add the field when resolvable, otherwise passes the call through unchanged (graceful passthrough preserves backwards-compat).
|
|
236
|
-
|
|
237
|
-
**Skips when**: the call already carries `caller_worktree_id`, or no worktree can be resolved (both → clean passthrough). A no-op in repos that don't use the CodeByPlan MCP.
|
|
238
|
-
|
|
239
|
-
**Opt out**: settings.json override removing this entry, or plugin disable.
|
|
240
|
-
|
|
241
|
-
---
|
|
242
|
-
|
|
243
231
|
### `cbp-mcp-round-sync.sh` — PostToolUse, matcher `mcp__codebyplan__complete_round`
|
|
244
232
|
|
|
245
233
|
After a `complete_round` MCP call succeeds, reconciles the round's `files_changed[]` against `git status`: new files in the diff are added (unapproved), and approval records no longer in the diff are flagged `removed_from_diff` (never deleted — lifecycle preserved).
|
|
@@ -258,7 +246,7 @@ After a `complete_round` MCP call succeeds, reconciles the round's `files_change
|
|
|
258
246
|
|
|
259
247
|
Test suite for the plugin's 10 registered hooks. Runs two passes:
|
|
260
248
|
|
|
261
|
-
1. **Header check** — every registered hook (`lint-format-on-edit`, `test-coverage-gate`, `pre-commit-quality-gate`, `maestro-yaml-validate`, `notify`, `auto-test-hooks`, `mcp-migration-guard`, `validate-git-stash-deny`, `cbp-mcp-
|
|
249
|
+
1. **Header check** — every registered hook (`lint-format-on-edit`, `test-coverage-gate`, `pre-commit-quality-gate`, `maestro-yaml-validate`, `notify`, `auto-test-hooks`, `mcp-migration-guard`, `validate-git-stash-deny`, `cbp-mcp-round-sync`) carries the required `# Hook:` and `# Purpose:` header comments. `statusline` uses its own `# Claude Code Status Line` marker.
|
|
262
250
|
2. **Functional smoke tests** — each hook is invoked with synthetic stdin matching its fast-path / graceful-degrade input; all must exit 0.
|
|
263
251
|
|
|
264
252
|
Not in `hooks.json` — invoked indirectly via `auto-test-hooks.sh` on hook edits, or directly via `bash ${CLAUDE_PLUGIN_ROOT}/hooks/test-hooks.sh`.
|
|
@@ -64,6 +64,14 @@ while IFS= read -r FILE; do
|
|
|
64
64
|
continue
|
|
65
65
|
fi
|
|
66
66
|
|
|
67
|
+
# Skip files under a __tests__/ directory — fixtures, helpers, setup, and
|
|
68
|
+
# other test infrastructure are imported by the test files that exercise
|
|
69
|
+
# them; requiring a dedicated .test.ts for a fixture is nonsensical.
|
|
70
|
+
if echo "$FILE" | grep -qE '/__tests__/'; then
|
|
71
|
+
SKIPPED=$((SKIPPED + 1))
|
|
72
|
+
continue
|
|
73
|
+
fi
|
|
74
|
+
|
|
67
75
|
# Skip infrastructure / generated / config files (generic skips — harmless if user doesn't have these dirs)
|
|
68
76
|
if echo "$FILE" | grep -qE '^\.claude/|^docs/|^supabase/|\.config\.|\.json$|\.md$|\.ya?ml$|\.sh$|\.scss$|\.css$'; then
|
|
69
77
|
continue
|
|
@@ -207,48 +207,6 @@ else
|
|
|
207
207
|
fi
|
|
208
208
|
fi
|
|
209
209
|
|
|
210
|
-
# --- cbp-mcp-worktree-inject.sh ---
|
|
211
|
-
|
|
212
|
-
if [ ! -f "$HOOKS_DIR/cbp-mcp-worktree-inject.sh" ]; then
|
|
213
|
-
test_result "cbp-mcp-worktree-inject.sh present" "passed" "missing"
|
|
214
|
-
else
|
|
215
|
-
test_result "cbp-mcp-worktree-inject.sh present" "passed" "passed"
|
|
216
|
-
|
|
217
|
-
FIRST_LINE=$(head -1 "$HOOKS_DIR/cbp-mcp-worktree-inject.sh")
|
|
218
|
-
if echo "$FIRST_LINE" | grep -q '^#!/'; then
|
|
219
|
-
test_result "cbp-mcp-worktree-inject.sh has shebang" "passed" "passed"
|
|
220
|
-
else
|
|
221
|
-
test_result "cbp-mcp-worktree-inject.sh has shebang" "passed" "missing"
|
|
222
|
-
fi
|
|
223
|
-
|
|
224
|
-
if grep -q '@scope: org-shared' "$HOOKS_DIR/cbp-mcp-worktree-inject.sh"; then
|
|
225
|
-
test_result "cbp-mcp-worktree-inject.sh has @scope: org-shared" "passed" "passed"
|
|
226
|
-
else
|
|
227
|
-
test_result "cbp-mcp-worktree-inject.sh has @scope: org-shared" "passed" "missing"
|
|
228
|
-
fi
|
|
229
|
-
|
|
230
|
-
FIXTURES_DIR="$HOOKS_DIR/__test-fixtures__/cbp-mcp-worktree-inject"
|
|
231
|
-
if [ -d "$FIXTURES_DIR" ]; then
|
|
232
|
-
# already-has-id.json — expect exit 0 (passthrough)
|
|
233
|
-
ACTUAL_EXIT=$(bash "$HOOKS_DIR/cbp-mcp-worktree-inject.sh" < "$FIXTURES_DIR/already-has-id.json" >/dev/null 2>&1; echo $?)
|
|
234
|
-
if [ "$ACTUAL_EXIT" = "0" ]; then
|
|
235
|
-
test_result "cbp-mcp-worktree-inject.sh already-has-id exits 0" "passed" "passed"
|
|
236
|
-
else
|
|
237
|
-
test_result "cbp-mcp-worktree-inject.sh already-has-id exits 0" "passed" "failed (exit $ACTUAL_EXIT)"
|
|
238
|
-
fi
|
|
239
|
-
|
|
240
|
-
# missing-id-both-empty.json — resolvers return empty (in test env), expect exit 0
|
|
241
|
-
ACTUAL_EXIT=$(bash "$HOOKS_DIR/cbp-mcp-worktree-inject.sh" < "$FIXTURES_DIR/missing-id-both-empty.json" >/dev/null 2>&1; echo $?)
|
|
242
|
-
if [ "$ACTUAL_EXIT" = "0" ]; then
|
|
243
|
-
test_result "cbp-mcp-worktree-inject.sh missing-id passthrough exits 0" "passed" "passed"
|
|
244
|
-
else
|
|
245
|
-
test_result "cbp-mcp-worktree-inject.sh missing-id passthrough exits 0" "passed" "failed (exit $ACTUAL_EXIT)"
|
|
246
|
-
fi
|
|
247
|
-
else
|
|
248
|
-
test_result "cbp-mcp-worktree-inject.sh fixtures dir present" "passed" "missing"
|
|
249
|
-
fi
|
|
250
|
-
fi
|
|
251
|
-
|
|
252
210
|
# --- cbp-mcp-round-sync.sh ---
|
|
253
211
|
|
|
254
212
|
if [ ! -f "$HOOKS_DIR/cbp-mcp-round-sync.sh" ]; then
|
|
@@ -35,15 +35,6 @@
|
|
|
35
35
|
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/cbp-mcp-migration-guard.sh"
|
|
36
36
|
}
|
|
37
37
|
]
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
"matcher": "mcp__codebyplan__(update_task|complete_task|complete_round|update_checkpoint)",
|
|
41
|
-
"hooks": [
|
|
42
|
-
{
|
|
43
|
-
"type": "command",
|
|
44
|
-
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/cbp-mcp-worktree-inject.sh"
|
|
45
|
-
}
|
|
46
|
-
]
|
|
47
38
|
}
|
|
48
39
|
],
|
|
49
40
|
"PostToolUse": [
|
|
@@ -13,7 +13,9 @@
|
|
|
13
13
|
"spinnerTipsEnabled": true,
|
|
14
14
|
"terminalProgressBarEnabled": true,
|
|
15
15
|
"viewMode": "default",
|
|
16
|
-
"worktree": {
|
|
16
|
+
"worktree": {
|
|
17
|
+
"baseRef": "fresh"
|
|
18
|
+
},
|
|
17
19
|
"autoScrollEnabled": true,
|
|
18
20
|
"cleanupPeriodDays": 30,
|
|
19
21
|
"includeGitInstructions": true,
|
|
@@ -45,10 +47,159 @@
|
|
|
45
47
|
"Bash(pnpm install:*)",
|
|
46
48
|
"Bash(npm install:*)",
|
|
47
49
|
"Bash(npm i:*)",
|
|
48
|
-
"Bash(npx add:*)"
|
|
50
|
+
"Bash(npx add:*)",
|
|
51
|
+
"Skill(cbp-checkpoint-end)",
|
|
52
|
+
"Skill(cbp-ship)",
|
|
53
|
+
"Skill(cbp-ship-main)",
|
|
54
|
+
"mcp__codebyplan__accept_invite",
|
|
55
|
+
"mcp__codebyplan__change_role",
|
|
56
|
+
"mcp__codebyplan__create_launch",
|
|
57
|
+
"mcp__codebyplan__update_launch",
|
|
58
|
+
"mcp__codebyplan__delete_launch",
|
|
59
|
+
"mcp__codebyplan__create_repo",
|
|
60
|
+
"mcp__codebyplan__delete_session_log",
|
|
61
|
+
"mcp__codebyplan__delete_worktree",
|
|
62
|
+
"mcp__codebyplan__invite_member",
|
|
63
|
+
"mcp__codebyplan__remove_member",
|
|
64
|
+
"mcp__codebyplan__revoke_invite",
|
|
65
|
+
"mcp__codebyplan__release_assignment",
|
|
66
|
+
"Bash(codebyplan setup:*)",
|
|
67
|
+
"Bash(npx codebyplan setup:*)",
|
|
68
|
+
"Bash(codebyplan login:*)",
|
|
69
|
+
"Bash(npx codebyplan login:*)",
|
|
70
|
+
"Bash(codebyplan logout:*)",
|
|
71
|
+
"Bash(npx codebyplan logout:*)",
|
|
72
|
+
"Bash(codebyplan upgrade-auth:*)",
|
|
73
|
+
"Bash(npx codebyplan upgrade-auth:*)",
|
|
74
|
+
"Bash(codebyplan config:*)",
|
|
75
|
+
"Bash(npx codebyplan config:*)",
|
|
76
|
+
"Bash(codebyplan branch:*)",
|
|
77
|
+
"Bash(npx codebyplan branch:*)",
|
|
78
|
+
"Bash(codebyplan ship:*)",
|
|
79
|
+
"Bash(npx codebyplan ship:*)",
|
|
80
|
+
"Bash(codebyplan claude:*)",
|
|
81
|
+
"Bash(npx codebyplan claude:*)"
|
|
82
|
+
],
|
|
83
|
+
"allow": [
|
|
84
|
+
"Skill(cbp-build-cc-agent)",
|
|
85
|
+
"Skill(cbp-build-cc-claude-file)",
|
|
86
|
+
"Skill(cbp-build-cc-memory)",
|
|
87
|
+
"Skill(cbp-build-cc-mode)",
|
|
88
|
+
"Skill(cbp-build-cc-rule)",
|
|
89
|
+
"Skill(cbp-build-cc-settings)",
|
|
90
|
+
"Skill(cbp-build-cc-skill)",
|
|
91
|
+
"Skill(cbp-checkpoint-check)",
|
|
92
|
+
"Skill(cbp-checkpoint-complete)",
|
|
93
|
+
"Skill(cbp-checkpoint-create)",
|
|
94
|
+
"Skill(cbp-checkpoint-plan)",
|
|
95
|
+
"Skill(cbp-checkpoint-start)",
|
|
96
|
+
"Skill(cbp-checkpoint-update)",
|
|
97
|
+
"Skill(cbp-frontend-a11y)",
|
|
98
|
+
"Skill(cbp-frontend-design)",
|
|
99
|
+
"Skill(cbp-frontend-ui)",
|
|
100
|
+
"Skill(cbp-frontend-ux)",
|
|
101
|
+
"Skill(cbp-git-branch-feat-create)",
|
|
102
|
+
"Skill(cbp-git-commit)",
|
|
103
|
+
"Skill(cbp-git-worktree-create)",
|
|
104
|
+
"Skill(cbp-git-worktree-remove)",
|
|
105
|
+
"Skill(cbp-merge-main)",
|
|
106
|
+
"Skill(cbp-refresh-infra)",
|
|
107
|
+
"Skill(cbp-round-check)",
|
|
108
|
+
"Skill(cbp-round-end)",
|
|
109
|
+
"Skill(cbp-round-execute)",
|
|
110
|
+
"Skill(cbp-round-input)",
|
|
111
|
+
"Skill(cbp-round-start)",
|
|
112
|
+
"Skill(cbp-round-update)",
|
|
113
|
+
"Skill(cbp-session-end)",
|
|
114
|
+
"Skill(cbp-session-start)",
|
|
115
|
+
"Skill(cbp-setup-e2e)",
|
|
116
|
+
"Skill(cbp-setup-eslint)",
|
|
117
|
+
"Skill(cbp-ship-configure)",
|
|
118
|
+
"Skill(cbp-supabase-branch-check)",
|
|
119
|
+
"Skill(cbp-supabase-migrate)",
|
|
120
|
+
"Skill(cbp-supabase-setup)",
|
|
121
|
+
"Skill(cbp-task-check)",
|
|
122
|
+
"Skill(cbp-task-complete)",
|
|
123
|
+
"Skill(cbp-task-create)",
|
|
124
|
+
"Skill(cbp-task-start)",
|
|
125
|
+
"Skill(cbp-task-testing)",
|
|
126
|
+
"Skill(cbp-todo)",
|
|
127
|
+
"mcp__codebyplan__get_checkpoints",
|
|
128
|
+
"mcp__codebyplan__get_current_task",
|
|
129
|
+
"mcp__codebyplan__get_eslint_presets",
|
|
130
|
+
"mcp__codebyplan__get_eslint_repo_config",
|
|
131
|
+
"mcp__codebyplan__get_file_changes",
|
|
132
|
+
"mcp__codebyplan__get_launch",
|
|
133
|
+
"mcp__codebyplan__get_launches",
|
|
134
|
+
"mcp__codebyplan__get_library_doc_job",
|
|
135
|
+
"mcp__codebyplan__get_next_action",
|
|
136
|
+
"mcp__codebyplan__get_repos",
|
|
137
|
+
"mcp__codebyplan__get_rounds",
|
|
138
|
+
"mcp__codebyplan__get_server_config",
|
|
139
|
+
"mcp__codebyplan__get_session_log",
|
|
140
|
+
"mcp__codebyplan__get_session_logs",
|
|
141
|
+
"mcp__codebyplan__get_session_state",
|
|
142
|
+
"mcp__codebyplan__get_task_template",
|
|
143
|
+
"mcp__codebyplan__get_task_templates",
|
|
144
|
+
"mcp__codebyplan__get_tasks",
|
|
145
|
+
"mcp__codebyplan__get_todos",
|
|
146
|
+
"mcp__codebyplan__get_work_plan",
|
|
147
|
+
"mcp__codebyplan__get_worktrees",
|
|
148
|
+
"mcp__codebyplan__list_tech_stack_sync_sessions",
|
|
149
|
+
"mcp__codebyplan__get_chunk",
|
|
150
|
+
"mcp__codebyplan__list_migrations",
|
|
151
|
+
"mcp__codebyplan__lookup_symbol",
|
|
152
|
+
"mcp__codebyplan__resolve_library_id",
|
|
153
|
+
"mcp__codebyplan__search_chunks",
|
|
154
|
+
"mcp__codebyplan__health_check",
|
|
155
|
+
"mcp__codebyplan__add_library",
|
|
156
|
+
"mcp__codebyplan__add_round",
|
|
157
|
+
"mcp__codebyplan__complete_round",
|
|
158
|
+
"mcp__codebyplan__update_round",
|
|
159
|
+
"mcp__codebyplan__complete_checkpoint",
|
|
160
|
+
"mcp__codebyplan__create_checkpoint",
|
|
161
|
+
"mcp__codebyplan__update_checkpoint",
|
|
162
|
+
"mcp__codebyplan__complete_task",
|
|
163
|
+
"mcp__codebyplan__create_task",
|
|
164
|
+
"mcp__codebyplan__update_task",
|
|
165
|
+
"mcp__codebyplan__create_session_log",
|
|
166
|
+
"mcp__codebyplan__update_session_log",
|
|
167
|
+
"mcp__codebyplan__update_session_state",
|
|
168
|
+
"mcp__codebyplan__create_worktree",
|
|
169
|
+
"mcp__codebyplan__flag_stale_chunk",
|
|
170
|
+
"mcp__codebyplan__list_invites",
|
|
171
|
+
"mcp__codebyplan__list_members",
|
|
172
|
+
"mcp__codebyplan__update_eslint_repo_config",
|
|
173
|
+
"mcp__codebyplan__update_server_config",
|
|
174
|
+
"mcp__codebyplan__update_task_template",
|
|
175
|
+
"Bash(codebyplan whoami:*)",
|
|
176
|
+
"Bash(npx codebyplan whoami:*)",
|
|
177
|
+
"Bash(codebyplan resolve-worktree:*)",
|
|
178
|
+
"Bash(npx codebyplan resolve-worktree:*)",
|
|
179
|
+
"Bash(codebyplan statusline:*)",
|
|
180
|
+
"Bash(npx codebyplan statusline:*)",
|
|
181
|
+
"Bash(codebyplan ports:*)",
|
|
182
|
+
"Bash(npx codebyplan ports:*)",
|
|
183
|
+
"Bash(codebyplan tech-stack:*)",
|
|
184
|
+
"Bash(npx codebyplan tech-stack:*)",
|
|
185
|
+
"Bash(codebyplan eslint:*)",
|
|
186
|
+
"Bash(npx codebyplan eslint:*)",
|
|
187
|
+
"Bash(codebyplan round:*)",
|
|
188
|
+
"Bash(npx codebyplan round:*)",
|
|
189
|
+
"Bash(codebyplan help:*)",
|
|
190
|
+
"Bash(npx codebyplan help:*)",
|
|
191
|
+
"Bash(codebyplan --version:*)",
|
|
192
|
+
"Bash(npx codebyplan --version:*)",
|
|
193
|
+
"Bash(codebyplan bump:*)",
|
|
194
|
+
"Bash(npx codebyplan bump:*)",
|
|
195
|
+
"Bash(codebyplan scaffold-publish-workflow:*)",
|
|
196
|
+
"Bash(npx codebyplan scaffold-publish-workflow:*)"
|
|
49
197
|
]
|
|
50
198
|
},
|
|
51
|
-
"attribution": {
|
|
199
|
+
"attribution": {
|
|
200
|
+
"commit": "",
|
|
201
|
+
"pr": ""
|
|
202
|
+
},
|
|
52
203
|
"showClearContextOnPlanAccept": false,
|
|
53
204
|
"syntaxHighlightingDisabled": false
|
|
54
205
|
}
|
|
@@ -76,6 +76,8 @@ Rules follow `Tool` or `Tool(specifier)`. Evaluated in order: **deny → ask →
|
|
|
76
76
|
|
|
77
77
|
Full patterns: [reference/permission-rules.md](reference/permission-rules.md).
|
|
78
78
|
|
|
79
|
+
CBP-specific policy — which `codebyplan` CLI commands, `mcp__codebyplan__*` tools, and `/cbp-*` skills are pre-categorized `allow` vs `ask`, why, and how `codebyplan claude install/update` auto-populates them: [reference/cbp-permission-policy.md](reference/cbp-permission-policy.md).
|
|
80
|
+
|
|
79
81
|
Common examples:
|
|
80
82
|
|
|
81
83
|
```json
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# CodeByPlan Permission Policy
|
|
2
|
+
|
|
3
|
+
How the CodeByPlan surface — CLI commands, `mcp__codebyplan__*` tools, and `/cbp-*` skills — is pre-categorized into `permissions.allow` / `permissions.ask` in the settings the `codebyplan` package ships. Authored by CHK-157.
|
|
4
|
+
|
|
5
|
+
## Where it lives + how it propagates
|
|
6
|
+
|
|
7
|
+
The curated arrays live in `templates/settings.project.base.json` inside the `codebyplan` npm package. `codebyplan claude install` and `codebyplan claude update` **union-merge** those `allow` / `ask` / `deny` arrays into the consuming repo's `.claude/settings.json` (the merge engine is `mergeBaseSettingsIntoSettings` in `src/lib/settings-merge.ts`); `codebyplan claude uninstall` strips them back out (`stripBaseSettingsFromSettings`). A user's own permission entries are preserved across all three operations (union on merge, membership-filter on strip).
|
|
8
|
+
|
|
9
|
+
No new plumbing was added — the categorization is **data** in the base template plus the completeness guard described below.
|
|
10
|
+
|
|
11
|
+
## The interaction with `bypassPermissions`
|
|
12
|
+
|
|
13
|
+
CBP repos ship `permissions.defaultMode: "bypassPermissions"`. Under that mode, routine tool calls are auto-allowed without prompting — so the `allow` list is mostly an **explicit, documented enumeration** (and it takes effect verbatim if a repo ever lowers the mode). The harness still honors `ask` and `deny` under bypass, which is why the base settings have always carried an `ask` list (`git push --force`, `pnpm add`, …). Therefore:
|
|
14
|
+
|
|
15
|
+
- **`ask` is the operative "decide carefully" surface** — the deliberate stop-and-confirm set.
|
|
16
|
+
- **`deny`** is the hard block (dangerous `rm -rf` variants).
|
|
17
|
+
- **`allow`** is the explicit full enumeration of the rest of the CBP surface.
|
|
18
|
+
|
|
19
|
+
Precedence is `deny > ask > allow`; arrays union across scopes (managed/user/project/local).
|
|
20
|
+
|
|
21
|
+
## The three tiers
|
|
22
|
+
|
|
23
|
+
### `allow` — the autonomous workflow surface
|
|
24
|
+
|
|
25
|
+
- **All `/cbp-*` skills** except the production-shipment trio below. 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.
|
|
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`, `update_task_template`. Gating these with `ask` would make the autonomous workflow unusable.
|
|
28
|
+
- **Read/safe CLI commands** (both `codebyplan X` and `npx codebyplan X`): `whoami`, `resolve-worktree`, `statusline`, `ports`, `tech-stack`, `eslint`, `round`, `help`, `--version`.
|
|
29
|
+
|
|
30
|
+
### `ask` — the deliberate confirm-gate
|
|
31
|
+
|
|
32
|
+
- **Production-shipment skills**: `cbp-ship`, `cbp-ship-main`, `cbp-checkpoint-end` — these promote/deploy to production, so they prompt even in an otherwise auto-allowed setup.
|
|
33
|
+
- **Destructive / admin / external MCP tools**: `delete_session_log`, `delete_worktree`, `delete_launch`, `create_repo`, `create_launch`, `update_launch`, `release_assignment`, and the membership tools `invite_member`, `remove_member`, `change_role`, `accept_invite`, `revoke_invite`.
|
|
34
|
+
- **Mutating / external / clobber-risk CLI commands** (both prefixes): `setup`, `login`, `logout`, `upgrade-auth`, `config` (can overwrite committed `.codebyplan/` files), `branch` (rewrites branch config), `ship`, `claude` (`install`/`update`/`uninstall` overwrite `.claude/`).
|
|
35
|
+
|
|
36
|
+
### `deny` — unchanged
|
|
37
|
+
|
|
38
|
+
The pre-existing dangerous-`rm -rf` blocks. This policy does not alter `deny` semantics.
|
|
39
|
+
|
|
40
|
+
## Completeness guard (the "decide carefully" guarantee)
|
|
41
|
+
|
|
42
|
+
`src/lib/settings-permissions-completeness.test.ts` re-derives the live surface from source — skill directory names under `templates/skills/`, `registerToolWithAuthz(server, "...")` names in `packages/mcp-tools/src/tools/*.ts`, and `arg === "..."` CLI subcommands in `src/index.ts` — and fails if any item is not in exactly one tier. So a **newly-added skill, MCP tool, or CLI subcommand forces a deliberate allow-vs-ask decision** before the suite goes green; nothing slips in uncategorized. The test also round-trips the curated arrays through the install-merge and uninstall-strip engine.
|
|
43
|
+
|
|
44
|
+
When you add a skill / MCP tool / CLI subcommand, add its matching rule (`Skill(<name>)`, `mcp__codebyplan__<name>`, or `Bash(codebyplan <sub>:*)` + `Bash(npx codebyplan <sub>:*)`) to `allow` or `ask` in `templates/settings.project.base.json` — and mirror it into any dogfooding `.claude/settings.json`.
|
|
45
|
+
|
|
46
|
+
## Scope
|
|
47
|
+
|
|
48
|
+
`scope: org-shared` — CBP-framework infrastructure that lands identically in every consuming repo via the `codebyplan` package.
|
|
@@ -30,6 +30,8 @@ Before any shipment logic, ensure the feat branch is current against main. Shipm
|
|
|
30
30
|
2. If the skill exits with failure (offline, unresolved conflicts, user-aborted): surface the failure and STOP `/cbp-checkpoint-end` — shipment is not safe until the branch is reconciled. The user resolves and re-invokes.
|
|
31
31
|
3. On clean success: continue to Step 1.
|
|
32
32
|
|
|
33
|
+
> **Version bumps ride this shipment automatically.** `codebyplan ship` (invoked by `/cbp-ship-main` in Step 5) patch-bumps every changed workspace package and commits `chore(release): bump versions` on the feat branch AFTER this main-sync merge and BEFORE push + PR creation — so the bump rides the same feat→main PR (no separate release PR). No manual bump step is required here; the planned bumps surface in the Step 5 report. See `cbp-ship/reference/versioning.md` (`in-branch-bump` mode).
|
|
34
|
+
|
|
33
35
|
### Step 1: Get Active Checkpoint
|
|
34
36
|
|
|
35
37
|
Use MCP `get_current_task` with repo_id. Get the active checkpoint.
|
|
@@ -195,6 +197,7 @@ context.shipment: {
|
|
|
195
197
|
timestamp: [ISO],
|
|
196
198
|
branch_config: { base, protected },
|
|
197
199
|
feat_to_base: { pr_url, merged: true/false },
|
|
200
|
+
version_bumps: [...], // from `codebyplan ship` bumps[] — packages patch-bumped on the feat branch this shipment
|
|
198
201
|
surfaces: [...], // populated by /cbp-ship — per-surface deploy results
|
|
199
202
|
skipped: [...], // populated by /cbp-ship — surfaces explicitly skipped
|
|
200
203
|
stale_branches_cleaned: [list of deleted git branches],
|
|
@@ -211,6 +214,10 @@ Present summary:
|
|
|
211
214
|
### Branch Promotion
|
|
212
215
|
- **feat -> [BASE]**: [PR URL] (merged)
|
|
213
216
|
|
|
217
|
+
### Version Bumps
|
|
218
|
+
- [package]: [currentVersion] → [nextVersion]
|
|
219
|
+
(From `context.shipment.version_bumps[]` — committed as `chore(release): bump versions`; publishes on merge. Omit this section if no packages were bumped.)
|
|
220
|
+
|
|
214
221
|
### Runtime Surfaces (via /cbp-ship)
|
|
215
222
|
| Surface | Variant | Status | URL/ID |
|
|
216
223
|
| ... | ... | ... | ... |
|
|
@@ -57,7 +57,7 @@ This mirrors the CHK-104 hard-lock model — never wrest a checkpoint from a liv
|
|
|
57
57
|
|
|
58
58
|
If the checkpoint is already `active` AND `worktree_id` already equals `CALLER_WT` (the Step 3 no-op row), skip this step entirely and proceed to Step 5 — nothing to write.
|
|
59
59
|
|
|
60
|
-
Otherwise set the checkpoint `active` via MCP `update_checkpoint(checkpoint_id, status: "active"`, plus `worktree_id: CALLER_WT` when claiming per Step 3
|
|
60
|
+
Otherwise set the checkpoint `active` via MCP `update_checkpoint(checkpoint_id, status: "active"`, plus `worktree_id: CALLER_WT` when claiming per Step 3. The server resolves the caller's worktree identity from the JWT/ctx (CHK-140 TASK-3 — `caller_worktree_id` input field removed). If the checkpoint was already `active` but a claim is still needed, skip the status write and only write `worktree_id`.
|
|
61
61
|
|
|
62
62
|
### Step 5: Route
|
|
63
63
|
|
|
@@ -78,7 +78,7 @@ Show a one-line confirmation before routing:
|
|
|
78
78
|
## Integration
|
|
79
79
|
|
|
80
80
|
- **Reads**: MCP `get_checkpoints`, `get_tasks`; `npx codebyplan resolve-worktree`
|
|
81
|
-
- **Writes**: MCP `update_checkpoint` (status + worktree_id
|
|
81
|
+
- **Writes**: MCP `update_checkpoint` (status + worktree_id; server resolves caller worktree from JWT/ctx)
|
|
82
82
|
- **Triggered by**: `/cbp-checkpoint-plan` (auto when claimed at create), `/cbp-todo` (planned-but-pending gate), or user directly
|
|
83
83
|
- **Triggers**: `/cbp-task-start` (auto when claimed), or `/cbp-checkpoint-plan` (when the checkpoint is unplanned)
|
|
84
84
|
- **Never**: plans or creates tasks — that is `/cbp-checkpoint-plan`
|
|
@@ -49,7 +49,7 @@ RESOLVE_JSON=$(npx codebyplan resolve-worktree --json)
|
|
|
49
49
|
|
|
50
50
|
Extract `worktree_id` and `error_kind` from the JSON output.
|
|
51
51
|
|
|
52
|
-
- `error_kind` is `null` or `"tuple_miss"` → healthy. `WORKTREE_ID` = `worktree_id` (may be `null`: a legitimate main-repo or unregistered-worktree case — proceed normally;
|
|
52
|
+
- `error_kind` is `null` or `"tuple_miss"` → healthy. `WORKTREE_ID` = `worktree_id` (may be `null`: a legitimate main-repo or unregistered-worktree case — proceed normally; the server resolves worktree identity from the JWT/ctx, falling back to the repo main-worktree when no specific worktree is matched).
|
|
53
53
|
- `error_kind` is `local_config_read_failed`, `local_config_write_failed`, `legacy_file_blocks_dir`, `api_failed`, `git_failed`, or `unhandled` → **broken local state**. Hold the `error_kind` for Step 6 to display as a distress warning. Session continues (non-blocking — unlike `/cbp-todo`, session-start does NOT hard-stop on a non-tuple-miss distress).
|
|
54
54
|
|
|
55
55
|
Pass `WORKTREE_ID` to MCP tools that support it. Null `WORKTREE_ID` means the (device, path, branch) tuple is unregistered — note this for Step 6.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
scope: org-shared
|
|
3
|
-
name: cbp-e2e
|
|
3
|
+
name: cbp-setup-e2e
|
|
4
4
|
description: Detect installed E2E frameworks, ask which to enable, record credentials source (gitignored env-file path + var names only, never secrets), and write/refresh .codebyplan/e2e.json. Interactive, idempotent.
|
|
5
5
|
argument-hint: "[--force]"
|
|
6
6
|
model: sonnet
|