codebyplan 1.13.64 → 1.13.66
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/README.md +118 -75
- package/dist/__tests__/helpers.d.ts +22 -0
- package/dist/__tests__/helpers.d.ts.map +1 -0
- package/dist/ci-public.d.ts +20 -0
- package/dist/ci-public.d.ts.map +1 -0
- package/dist/ci.js +11 -2
- package/dist/cli/arch-map.d.ts +33 -0
- package/dist/cli/arch-map.d.ts.map +1 -0
- package/dist/cli/branch.d.ts +10 -0
- package/dist/cli/branch.d.ts.map +1 -0
- package/dist/cli/bump.d.ts +12 -0
- package/dist/cli/bump.d.ts.map +1 -0
- package/dist/cli/cd.d.ts +20 -0
- package/dist/cli/cd.d.ts.map +1 -0
- package/dist/cli/check.d.ts +30 -0
- package/dist/cli/check.d.ts.map +1 -0
- package/dist/cli/checkpoint.d.ts +17 -0
- package/dist/cli/checkpoint.d.ts.map +1 -0
- package/dist/cli/ci.d.ts +31 -0
- package/dist/cli/ci.d.ts.map +1 -0
- package/dist/cli/claude/__test-helpers__/expect-manifest.d.ts +7 -0
- package/dist/cli/claude/__test-helpers__/expect-manifest.d.ts.map +1 -0
- package/dist/cli/claude/__test-helpers__/tmp-fixture.d.ts +64 -0
- package/dist/cli/claude/__test-helpers__/tmp-fixture.d.ts.map +1 -0
- package/dist/cli/claude/audit-mode.d.ts +16 -0
- package/dist/cli/claude/audit-mode.d.ts.map +1 -0
- package/dist/cli/claude/generate.d.ts +23 -0
- package/dist/cli/claude/generate.d.ts.map +1 -0
- package/dist/cli/claude/install.d.ts +55 -0
- package/dist/cli/claude/install.d.ts.map +1 -0
- package/dist/cli/claude/migrate-memory.d.ts +117 -0
- package/dist/cli/claude/migrate-memory.d.ts.map +1 -0
- package/dist/cli/claude/readme.d.ts +28 -0
- package/dist/cli/claude/readme.d.ts.map +1 -0
- package/dist/cli/claude/status.d.ts +41 -0
- package/dist/cli/claude/status.d.ts.map +1 -0
- package/dist/cli/claude/uninstall.d.ts +21 -0
- package/dist/cli/claude/uninstall.d.ts.map +1 -0
- package/dist/cli/claude/update.d.ts +25 -0
- package/dist/cli/claude/update.d.ts.map +1 -0
- package/dist/cli/claude/verify-parity.d.ts +25 -0
- package/dist/cli/claude/verify-parity.d.ts.map +1 -0
- package/dist/cli/cleanup-plan-folders.d.ts +21 -0
- package/dist/cli/cleanup-plan-folders.d.ts.map +1 -0
- package/dist/cli/commit.d.ts +25 -0
- package/dist/cli/commit.d.ts.map +1 -0
- package/dist/cli/config.d.ts +50 -0
- package/dist/cli/config.d.ts.map +1 -0
- package/dist/cli/confirm.d.ts +9 -0
- package/dist/cli/confirm.d.ts.map +1 -0
- package/dist/cli/create-org.d.ts +9 -0
- package/dist/cli/create-org.d.ts.map +1 -0
- package/dist/cli/create-project.d.ts +10 -0
- package/dist/cli/create-project.d.ts.map +1 -0
- package/dist/cli/create-repo.d.ts +14 -0
- package/dist/cli/create-repo.d.ts.map +1 -0
- package/dist/cli/docs.d.ts +41 -0
- package/dist/cli/docs.d.ts.map +1 -0
- package/dist/cli/doctor.d.ts +17 -0
- package/dist/cli/doctor.d.ts.map +1 -0
- package/dist/cli/e2e/verify-round.d.ts +46 -0
- package/dist/cli/e2e/verify-round.d.ts.map +1 -0
- package/dist/cli/e2e.d.ts +11 -0
- package/dist/cli/e2e.d.ts.map +1 -0
- package/dist/cli/eslint.d.ts +20 -0
- package/dist/cli/eslint.d.ts.map +1 -0
- package/dist/cli/export-writer.d.ts +99 -0
- package/dist/cli/export-writer.d.ts.map +1 -0
- package/dist/cli/handoff.d.ts +13 -0
- package/dist/cli/handoff.d.ts.map +1 -0
- package/dist/cli/login.d.ts +10 -0
- package/dist/cli/login.d.ts.map +1 -0
- package/dist/cli/logout.d.ts +2 -0
- package/dist/cli/logout.d.ts.map +1 -0
- package/dist/cli/lsp.d.ts +16 -0
- package/dist/cli/lsp.d.ts.map +1 -0
- package/dist/cli/migration-collisions.d.ts +10 -0
- package/dist/cli/migration-collisions.d.ts.map +1 -0
- package/dist/cli/ports.d.ts +29 -0
- package/dist/cli/ports.d.ts.map +1 -0
- package/dist/cli/process-exit-signal.d.ts +24 -0
- package/dist/cli/process-exit-signal.d.ts.map +1 -0
- package/dist/cli/round.d.ts +79 -0
- package/dist/cli/round.d.ts.map +1 -0
- package/dist/cli/scaffold-publish-workflow.d.ts +16 -0
- package/dist/cli/scaffold-publish-workflow.d.ts.map +1 -0
- package/dist/cli/session/freshness-gate.d.ts +21 -0
- package/dist/cli/session/freshness-gate.d.ts.map +1 -0
- package/dist/cli/session/home-ff.d.ts +16 -0
- package/dist/cli/session/home-ff.d.ts.map +1 -0
- package/dist/cli/session/infra-files.d.ts +21 -0
- package/dist/cli/session/infra-files.d.ts.map +1 -0
- package/dist/cli/session/start.d.ts +70 -0
- package/dist/cli/session/start.d.ts.map +1 -0
- package/dist/cli/session.d.ts +17 -0
- package/dist/cli/session.d.ts.map +1 -0
- package/dist/cli/setup.d.ts +2 -0
- package/dist/cli/setup.d.ts.map +1 -0
- package/dist/cli/ship.d.ts +16 -0
- package/dist/cli/ship.d.ts.map +1 -0
- package/dist/cli/slug.d.ts +10 -0
- package/dist/cli/slug.d.ts.map +1 -0
- package/dist/cli/standalone-task.d.ts +31 -0
- package/dist/cli/standalone-task.d.ts.map +1 -0
- package/dist/cli/statusline.d.ts +10 -0
- package/dist/cli/statusline.d.ts.map +1 -0
- package/dist/cli/supabase/new-migration.d.ts +24 -0
- package/dist/cli/supabase/new-migration.d.ts.map +1 -0
- package/dist/cli/supabase/preview-check.d.ts +30 -0
- package/dist/cli/supabase/preview-check.d.ts.map +1 -0
- package/dist/cli/supabase/resolve-preview.d.ts +19 -0
- package/dist/cli/supabase/resolve-preview.d.ts.map +1 -0
- package/dist/cli/supabase/teardown-preview.d.ts +22 -0
- package/dist/cli/supabase/teardown-preview.d.ts.map +1 -0
- package/dist/cli/sync.d.ts +13 -0
- package/dist/cli/sync.d.ts.map +1 -0
- package/dist/cli/task.d.ts +17 -0
- package/dist/cli/task.d.ts.map +1 -0
- package/dist/cli/tech-stack.d.ts +11 -0
- package/dist/cli/tech-stack.d.ts.map +1 -0
- package/dist/cli/upgrade-auth.d.ts +2 -0
- package/dist/cli/upgrade-auth.d.ts.map +1 -0
- package/dist/cli/upload-e2e-images.d.ts +18 -0
- package/dist/cli/upload-e2e-images.d.ts.map +1 -0
- package/dist/cli/validate-waves.d.ts +22 -0
- package/dist/cli/validate-waves.d.ts.map +1 -0
- package/dist/cli/version-status.d.ts +42 -0
- package/dist/cli/version-status.d.ts.map +1 -0
- package/dist/cli/watch.d.ts +18 -0
- package/dist/cli/watch.d.ts.map +1 -0
- package/dist/cli/whoami.d.ts +5 -0
- package/dist/cli/whoami.d.ts.map +1 -0
- package/dist/cli/worktree/add.d.ts +81 -0
- package/dist/cli/worktree/add.d.ts.map +1 -0
- package/dist/cli/worktree/create.d.ts +46 -0
- package/dist/cli/worktree/create.d.ts.map +1 -0
- package/dist/cli/worktree/path.d.ts +19 -0
- package/dist/cli/worktree/path.d.ts.map +1 -0
- package/dist/cli/worktree/remove.d.ts +60 -0
- package/dist/cli/worktree/remove.d.ts.map +1 -0
- package/dist/cli/worktree.d.ts +15 -0
- package/dist/cli/worktree.d.ts.map +1 -0
- package/dist/cli.js +6194 -5429
- package/dist/dispatch.d.ts +64 -0
- package/dist/dispatch.d.ts.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/lib/agents-generator.d.ts +42 -0
- package/dist/lib/agents-generator.d.ts.map +1 -0
- package/dist/lib/api.d.ts +54 -0
- package/dist/lib/api.d.ts.map +1 -0
- package/dist/lib/atomic-write.d.ts +27 -0
- package/dist/lib/atomic-write.d.ts.map +1 -0
- package/dist/lib/branch-checkout.d.ts +47 -0
- package/dist/lib/branch-checkout.d.ts.map +1 -0
- package/dist/lib/branch-port-resolver.d.ts +58 -0
- package/dist/lib/branch-port-resolver.d.ts.map +1 -0
- package/dist/lib/bump.d.ts +97 -0
- package/dist/lib/bump.d.ts.map +1 -0
- package/dist/lib/cd-init.d.ts +86 -0
- package/dist/lib/cd-init.d.ts.map +1 -0
- package/dist/lib/check-baseline.d.ts +91 -0
- package/dist/lib/check-baseline.d.ts.map +1 -0
- package/dist/lib/check.d.ts +178 -0
- package/dist/lib/check.d.ts.map +1 -0
- package/dist/lib/ci-init.d.ts +106 -0
- package/dist/lib/ci-init.d.ts.map +1 -0
- package/dist/lib/ci-resolve.d.ts +60 -0
- package/dist/lib/ci-resolve.d.ts.map +1 -0
- package/dist/lib/claude-mode-audit.d.ts +41 -0
- package/dist/lib/claude-mode-audit.d.ts.map +1 -0
- package/dist/lib/claude-plan.d.ts +34 -0
- package/dist/lib/claude-plan.d.ts.map +1 -0
- package/dist/lib/commit-scope.d.ts +21 -0
- package/dist/lib/commit-scope.d.ts.map +1 -0
- package/dist/lib/e2e.d.ts +157 -0
- package/dist/lib/e2e.d.ts.map +1 -0
- package/dist/lib/eslint-generator.d.ts +86 -0
- package/dist/lib/eslint-generator.d.ts.map +1 -0
- package/dist/lib/file-lock.d.ts +44 -0
- package/dist/lib/file-lock.d.ts.map +1 -0
- package/dist/lib/flags.d.ts +115 -0
- package/dist/lib/flags.d.ts.map +1 -0
- package/dist/lib/gh-required-checks.d.ts +76 -0
- package/dist/lib/gh-required-checks.d.ts.map +1 -0
- package/dist/lib/git-utils.d.ts +46 -0
- package/dist/lib/git-utils.d.ts.map +1 -0
- package/dist/lib/gitignore-block.d.ts +32 -0
- package/dist/lib/gitignore-block.d.ts.map +1 -0
- package/dist/lib/gitignore-detect.d.ts +117 -0
- package/dist/lib/gitignore-detect.d.ts.map +1 -0
- package/dist/lib/handoff-file.d.ts +63 -0
- package/dist/lib/handoff-file.d.ts.map +1 -0
- package/dist/lib/hash.d.ts +9 -0
- package/dist/lib/hash.d.ts.map +1 -0
- package/dist/lib/lsp-detect.d.ts +42 -0
- package/dist/lib/lsp-detect.d.ts.map +1 -0
- package/dist/lib/manifest.d.ts +88 -0
- package/dist/lib/manifest.d.ts.map +1 -0
- package/dist/lib/mcp-client.d.ts +39 -0
- package/dist/lib/mcp-client.d.ts.map +1 -0
- package/dist/lib/migrate-branch-model.d.ts +34 -0
- package/dist/lib/migrate-branch-model.d.ts.map +1 -0
- package/dist/lib/migrate-local-config.d.ts +39 -0
- package/dist/lib/migrate-local-config.d.ts.map +1 -0
- package/dist/lib/migration-collisions.d.ts +61 -0
- package/dist/lib/migration-collisions.d.ts.map +1 -0
- package/dist/lib/port-verify.d.ts +73 -0
- package/dist/lib/port-verify.d.ts.map +1 -0
- package/dist/lib/prompt.d.ts +41 -0
- package/dist/lib/prompt.d.ts.map +1 -0
- package/dist/lib/readme-generator.d.ts +108 -0
- package/dist/lib/readme-generator.d.ts.map +1 -0
- package/dist/lib/repo-reader.d.ts +59 -0
- package/dist/lib/repo-reader.d.ts.map +1 -0
- package/dist/lib/scaffold-cd-workflow.d.ts +48 -0
- package/dist/lib/scaffold-cd-workflow.d.ts.map +1 -0
- package/dist/lib/scaffold-ci-workflow.d.ts +83 -0
- package/dist/lib/scaffold-ci-workflow.d.ts.map +1 -0
- package/dist/lib/scaffold-publish-workflow.d.ts +48 -0
- package/dist/lib/scaffold-publish-workflow.d.ts.map +1 -0
- package/dist/lib/server-detect.d.ts +20 -0
- package/dist/lib/server-detect.d.ts.map +1 -0
- package/dist/lib/session.d.ts +371 -0
- package/dist/lib/session.d.ts.map +1 -0
- package/dist/lib/settings-merge.d.ts +268 -0
- package/dist/lib/settings-merge.d.ts.map +1 -0
- package/dist/lib/ship.d.ts +84 -0
- package/dist/lib/ship.d.ts.map +1 -0
- package/dist/lib/slug.d.ts +26 -0
- package/dist/lib/slug.d.ts.map +1 -0
- package/dist/lib/spawn.d.ts +12 -0
- package/dist/lib/spawn.d.ts.map +1 -0
- package/dist/lib/state-client.d.ts +54 -0
- package/dist/lib/state-client.d.ts.map +1 -0
- package/dist/lib/state-store.d.ts +153 -0
- package/dist/lib/state-store.d.ts.map +1 -0
- package/dist/lib/state-sync.d.ts +101 -0
- package/dist/lib/state-sync.d.ts.map +1 -0
- package/dist/lib/statusline-config.d.ts +55 -0
- package/dist/lib/statusline-config.d.ts.map +1 -0
- package/dist/lib/structure-generator.d.ts +63 -0
- package/dist/lib/structure-generator.d.ts.map +1 -0
- package/dist/lib/supabase.d.ts +87 -0
- package/dist/lib/supabase.d.ts.map +1 -0
- package/dist/lib/sync-approvals.d.ts +108 -0
- package/dist/lib/sync-approvals.d.ts.map +1 -0
- package/dist/lib/tech-detect.d.ts +77 -0
- package/dist/lib/tech-detect.d.ts.map +1 -0
- package/dist/lib/template-walker.d.ts +26 -0
- package/dist/lib/template-walker.d.ts.map +1 -0
- package/dist/lib/templates-dir.d.ts +25 -0
- package/dist/lib/templates-dir.d.ts.map +1 -0
- package/dist/lib/types.d.ts +843 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/validate-waves.d.ts +38 -0
- package/dist/lib/validate-waves.d.ts.map +1 -0
- package/dist/lib/verify-parity.d.ts +154 -0
- package/dist/lib/verify-parity.d.ts.map +1 -0
- package/dist/lib/version.d.ts +3 -0
- package/dist/lib/version.d.ts.map +1 -0
- package/dist/lib/watch-daemon.d.ts +114 -0
- package/dist/lib/watch-daemon.d.ts.map +1 -0
- package/dist/lib/worktree.d.ts +56 -0
- package/dist/lib/worktree.d.ts.map +1 -0
- package/dist/oauth/browser.d.ts +8 -0
- package/dist/oauth/browser.d.ts.map +1 -0
- package/dist/oauth/client-registration.d.ts +16 -0
- package/dist/oauth/client-registration.d.ts.map +1 -0
- package/dist/oauth/device-flow.d.ts +40 -0
- package/dist/oauth/device-flow.d.ts.map +1 -0
- package/dist/oauth/jwt-decode.d.ts +10 -0
- package/dist/oauth/jwt-decode.d.ts.map +1 -0
- package/dist/oauth/keychain.d.ts +17 -0
- package/dist/oauth/keychain.d.ts.map +1 -0
- package/dist/oauth/token-refresh.d.ts +7 -0
- package/dist/oauth/token-refresh.d.ts.map +1 -0
- package/dist/oauth/types.d.ts +28 -0
- package/dist/oauth/types.d.ts.map +1 -0
- package/dist/oauth/urls.d.ts +16 -0
- package/dist/oauth/urls.d.ts.map +1 -0
- package/package.json +5 -6
- package/templates/agents/cbp-security-agent.md +0 -1
- package/templates/agents/cbp-stripe-agent.md +0 -1
- package/templates/agents/cbp-testing-qa-agent.md +0 -1
- package/templates/github-workflows/ci.yml +5 -0
- package/templates/hooks/cbp-session-id-stamp.sh +67 -0
- package/templates/hooks/cbp-skill-context-guard.sh +0 -1
- package/templates/hooks/cbp-test-hooks.sh +105 -0
- package/templates/hooks/validate-structure-lib.sh +36 -9
- package/templates/rules/handoff-file-convention.md +65 -0
- package/templates/settings.project.base.json +17 -1
- package/templates/skills/cbp-checkpoint-check/SKILL.md +0 -1
- package/templates/skills/cbp-checkpoint-complete/SKILL.md +32 -0
- package/templates/skills/cbp-clear-continue/SKILL.md +23 -2
- package/templates/skills/cbp-clear-prep/SKILL.md +22 -2
- package/templates/skills/cbp-finalize/SKILL.md +36 -0
- package/templates/skills/cbp-session-end/SKILL.md +23 -25
- package/templates/skills/cbp-session-start/SKILL.md +24 -2
- package/templates/skills/cbp-setup-cd/SKILL.md +0 -1
- package/templates/skills/cbp-setup-ci/SKILL.md +0 -1
- package/templates/skills/cbp-standalone-task-complete/SKILL.md +32 -0
- package/templates/skills/cbp-stripe/SKILL.md +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codebyplan",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.66",
|
|
4
4
|
"description": "CLI for CodeByPlan — AI-powered development planning and tracking",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -52,18 +52,17 @@
|
|
|
52
52
|
"registry": "https://registry.npmjs.org/"
|
|
53
53
|
},
|
|
54
54
|
"engines": {
|
|
55
|
-
"node": ">=
|
|
55
|
+
"node": ">=22"
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
58
|
"@napi-rs/keyring": "^1.1.6",
|
|
59
|
-
"@supabase/supabase-js": "^2.106.0"
|
|
60
|
-
"ws": ">=8.20.1"
|
|
59
|
+
"@supabase/supabase-js": "^2.106.0"
|
|
61
60
|
},
|
|
62
61
|
"devDependencies": {
|
|
63
62
|
"@eslint/js": "^9.18.0",
|
|
64
|
-
"@types/node": "^
|
|
63
|
+
"@types/node": "^22",
|
|
65
64
|
"@vitest/eslint-plugin": "^1.1.44",
|
|
66
|
-
"esbuild": "
|
|
65
|
+
"esbuild": "^0.28.1",
|
|
67
66
|
"eslint": "^9.18.0",
|
|
68
67
|
"eslint-config-prettier": "^10.0.1",
|
|
69
68
|
"eslint-plugin-no-secrets": "^2.2.1",
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
---
|
|
2
|
-
scope: org-shared
|
|
3
2
|
name: cbp-stripe-agent
|
|
4
3
|
description: Stripe integration specialist. Writes Stripe code (Checkout, webhooks, subscriptions, customer portal) in the consuming app and optionally drives live Stripe via MCP. Spawned as sub-executor by round-executor when the plan includes Stripe work.
|
|
5
4
|
tools: Read, Write, Edit, Glob, Grep, Bash, AskUserQuestion
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
---
|
|
2
|
-
scope: org-shared
|
|
3
2
|
name: cbp-testing-qa-agent
|
|
4
3
|
description: Combined testing, QA generation, and default checklists. Runs build/lint/types/unit-tests/audit, generates auto QA items, applies default production checklists. Does NOT consume e2e screenshots or frontend-ui findings.
|
|
5
4
|
tools: Read, Glob, Grep, Bash, AskUserQuestion
|
|
@@ -40,6 +40,8 @@ jobs:
|
|
|
40
40
|
ci:
|
|
41
41
|
name: Lint + typecheck + test + build
|
|
42
42
|
runs-on: ubuntu-latest
|
|
43
|
+
# Cap the job so a hung step can't burn the 6h default and waste runner minutes.
|
|
44
|
+
timeout-minutes: 20
|
|
43
45
|
steps:
|
|
44
46
|
- name: Checkout
|
|
45
47
|
uses: actions/checkout@v4
|
|
@@ -85,6 +87,9 @@ jobs:
|
|
|
85
87
|
ci-strict:
|
|
86
88
|
name: Strict whole-repo green{{STRICT_NAME_SUFFIX}}
|
|
87
89
|
runs-on: ubuntu-latest{{STRICT_CONTINUE_ON_ERROR_LINE}}
|
|
90
|
+
# Whole-repo green is heavier than the soft tier; allow more headroom but
|
|
91
|
+
# still cap it so a hang can't run to the 6h default.
|
|
92
|
+
timeout-minutes: 30
|
|
88
93
|
steps:
|
|
89
94
|
- name: Checkout
|
|
90
95
|
uses: actions/checkout@v4
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# @scope: org-shared
|
|
3
|
+
# Hook: SessionStart
|
|
4
|
+
# Purpose: Stamp the Claude harness session UUID into
|
|
5
|
+
# .codebyplan/state/session/session-id.json so the CLI create-log path
|
|
6
|
+
# (and other session-aware tools) can correlate log entries with the
|
|
7
|
+
# running Claude session.
|
|
8
|
+
#
|
|
9
|
+
# Hook-safe: all errors are swallowed, always exits 0. Non-fatal / best-effort.
|
|
10
|
+
# No-op when not inside a codebyplan repo or when the session UUID cannot be
|
|
11
|
+
# derived from the hook payload.
|
|
12
|
+
#
|
|
13
|
+
# UUID derivation order:
|
|
14
|
+
# 1. stdin JSON payload `.session_id` field
|
|
15
|
+
# 2. basename (without extension) of `.transcript_path` field
|
|
16
|
+
# 3. no-op — exit 0 without writing
|
|
17
|
+
|
|
18
|
+
# C0 — require jq; if absent, exit 0 (fail-open).
|
|
19
|
+
if ! command -v jq > /dev/null 2>&1; then
|
|
20
|
+
exit 0
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
# Resolve the project dir: Claude Code sets CLAUDE_PROJECT_DIR; fall back to pwd.
|
|
24
|
+
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
|
|
25
|
+
|
|
26
|
+
# No-op when not inside a codebyplan repo (sentinel file absent).
|
|
27
|
+
if [ ! -f "$PROJECT_DIR/.codebyplan/repo.json" ]; then
|
|
28
|
+
exit 0
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
# Read stdin once into a variable.
|
|
32
|
+
INPUT=$(cat)
|
|
33
|
+
|
|
34
|
+
# Derive the session UUID — try session_id field first.
|
|
35
|
+
SESSION_UUID=$(printf '%s' "$INPUT" | jq -r '.session_id // empty' 2>/dev/null)
|
|
36
|
+
|
|
37
|
+
# Fall back to transcript_path basename (strip directory + extension).
|
|
38
|
+
if [ -z "$SESSION_UUID" ]; then
|
|
39
|
+
TRANSCRIPT=$(printf '%s' "$INPUT" | jq -r '.transcript_path // empty' 2>/dev/null)
|
|
40
|
+
if [ -n "$TRANSCRIPT" ]; then
|
|
41
|
+
BASENAME=$(basename "$TRANSCRIPT")
|
|
42
|
+
SESSION_UUID="${BASENAME%.*}"
|
|
43
|
+
fi
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
# If still no UUID, nothing to write — exit gracefully.
|
|
47
|
+
if [ -z "$SESSION_UUID" ]; then
|
|
48
|
+
exit 0
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
# UUID guard — accept only a canonical UUID (8-4-4-4-12 hex) to avoid
|
|
52
|
+
# stamping garbage values (e.g. a literal "null" or an arbitrary path stem).
|
|
53
|
+
UUID_PATTERN='^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$'
|
|
54
|
+
if ! printf '%s' "$SESSION_UUID" | grep -qE "$UUID_PATTERN"; then
|
|
55
|
+
exit 0
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
# Ensure the target directory exists.
|
|
59
|
+
SESSION_DIR="$PROJECT_DIR/.codebyplan/state/session"
|
|
60
|
+
mkdir -p "$SESSION_DIR" 2>/dev/null || true
|
|
61
|
+
|
|
62
|
+
# Stamp the session UUID with an ISO timestamp.
|
|
63
|
+
STAMPED_AT=$(date -u +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null)
|
|
64
|
+
printf '{"claude_session_id":"%s","stamped_at":"%s"}\n' "$SESSION_UUID" "$STAMPED_AT" \
|
|
65
|
+
> "$SESSION_DIR/session-id.json" 2>/dev/null || true
|
|
66
|
+
|
|
67
|
+
exit 0
|
|
@@ -614,6 +614,111 @@ else
|
|
|
614
614
|
|
|
615
615
|
fi
|
|
616
616
|
|
|
617
|
+
# ===== HOOK SMOKE TESTS — cbp-session-id-stamp (CHK-231) =====
|
|
618
|
+
echo "## Hook Smoke Tests — cbp-session-id-stamp (CHK-231)"
|
|
619
|
+
|
|
620
|
+
STAMP_HOOK="$HOOKS_DIR/cbp-session-id-stamp.sh"
|
|
621
|
+
|
|
622
|
+
if [ ! -f "$STAMP_HOOK" ]; then
|
|
623
|
+
test_result "cbp-session-id-stamp.sh present" "passed" "missing"
|
|
624
|
+
else
|
|
625
|
+
test_result "cbp-session-id-stamp.sh present" "passed" "passed"
|
|
626
|
+
|
|
627
|
+
FIRST_LINE=$(head -1 "$STAMP_HOOK")
|
|
628
|
+
if echo "$FIRST_LINE" | grep -q '^#!/'; then
|
|
629
|
+
test_result "cbp-session-id-stamp.sh has shebang" "passed" "passed"
|
|
630
|
+
else
|
|
631
|
+
test_result "cbp-session-id-stamp.sh has shebang" "passed" "missing"
|
|
632
|
+
fi
|
|
633
|
+
|
|
634
|
+
if grep -q '@scope: org-shared' "$STAMP_HOOK"; then
|
|
635
|
+
test_result "cbp-session-id-stamp.sh has @scope: org-shared" "passed" "passed"
|
|
636
|
+
else
|
|
637
|
+
test_result "cbp-session-id-stamp.sh has @scope: org-shared" "passed" "missing"
|
|
638
|
+
fi
|
|
639
|
+
|
|
640
|
+
if bash -n "$STAMP_HOOK" 2>/dev/null; then
|
|
641
|
+
test_result "cbp-session-id-stamp.sh bash -n syntax ok" "passed" "passed"
|
|
642
|
+
else
|
|
643
|
+
test_result "cbp-session-id-stamp.sh bash -n syntax ok" "passed" "failed"
|
|
644
|
+
fi
|
|
645
|
+
|
|
646
|
+
# Case 1: session_id present in payload → session-id.json written with that UUID
|
|
647
|
+
ISO=$(mktemp -d)
|
|
648
|
+
mkdir -p "$ISO/.codebyplan"
|
|
649
|
+
printf '{}' > "$ISO/.codebyplan/repo.json"
|
|
650
|
+
FAKE_UUID="aaaabbbb-cccc-dddd-eeee-ffffffffffff"
|
|
651
|
+
PAYLOAD=$(jq -n --arg s "$FAKE_UUID" '{session_id:$s}')
|
|
652
|
+
EXIT_CODE=$(echo "$PAYLOAD" | CLAUDE_PROJECT_DIR="$ISO" bash "$STAMP_HOOK" >/dev/null 2>&1; echo $?)
|
|
653
|
+
STAMPED_ID=$(jq -r '.claude_session_id // empty' "$ISO/.codebyplan/state/session/session-id.json" 2>/dev/null)
|
|
654
|
+
if [ "$EXIT_CODE" = "0" ] && [ "$STAMPED_ID" = "$FAKE_UUID" ]; then
|
|
655
|
+
test_result "cbp-session-id-stamp.sh session_id present → session-id.json written with UUID" "passed" "passed"
|
|
656
|
+
else
|
|
657
|
+
test_result "cbp-session-id-stamp.sh session_id present → session-id.json written with UUID" "passed" "failed (exit=$EXIT_CODE stamped=$STAMPED_ID)"
|
|
658
|
+
fi
|
|
659
|
+
rm -rf "$ISO"
|
|
660
|
+
|
|
661
|
+
# Case 2: no session_id but transcript_path present (basename is a valid UUID) →
|
|
662
|
+
# UUID derived from transcript basename and written to session-id.json.
|
|
663
|
+
ISO=$(mktemp -d)
|
|
664
|
+
mkdir -p "$ISO/.codebyplan"
|
|
665
|
+
printf '{}' > "$ISO/.codebyplan/repo.json"
|
|
666
|
+
TRANSCRIPT_UUID="11112222-3333-4444-5555-666677778888"
|
|
667
|
+
PAYLOAD=$(jq -n --arg t "/tmp/sessions/${TRANSCRIPT_UUID}.jsonl" '{transcript_path:$t}')
|
|
668
|
+
EXIT_CODE=$(echo "$PAYLOAD" | CLAUDE_PROJECT_DIR="$ISO" bash "$STAMP_HOOK" >/dev/null 2>&1; echo $?)
|
|
669
|
+
STAMPED_ID=$(jq -r '.claude_session_id // empty' "$ISO/.codebyplan/state/session/session-id.json" 2>/dev/null)
|
|
670
|
+
if [ "$EXIT_CODE" = "0" ] && [ "$STAMPED_ID" = "$TRANSCRIPT_UUID" ]; then
|
|
671
|
+
test_result "cbp-session-id-stamp.sh transcript_path fallback → UUID derived from basename" "passed" "passed"
|
|
672
|
+
else
|
|
673
|
+
test_result "cbp-session-id-stamp.sh transcript_path fallback → UUID derived from basename" "passed" "failed (exit=$EXIT_CODE stamped=$STAMPED_ID)"
|
|
674
|
+
fi
|
|
675
|
+
rm -rf "$ISO"
|
|
676
|
+
|
|
677
|
+
# Case 3: neither session_id nor transcript_path → no-op (no file written), exit 0
|
|
678
|
+
ISO=$(mktemp -d)
|
|
679
|
+
mkdir -p "$ISO/.codebyplan"
|
|
680
|
+
printf '{}' > "$ISO/.codebyplan/repo.json"
|
|
681
|
+
PAYLOAD='{"tool_name":"some_tool"}'
|
|
682
|
+
EXIT_CODE=$(echo "$PAYLOAD" | CLAUDE_PROJECT_DIR="$ISO" bash "$STAMP_HOOK" >/dev/null 2>&1; echo $?)
|
|
683
|
+
STAMP_FILE="$ISO/.codebyplan/state/session/session-id.json"
|
|
684
|
+
if [ "$EXIT_CODE" = "0" ] && [ ! -f "$STAMP_FILE" ]; then
|
|
685
|
+
test_result "cbp-session-id-stamp.sh neither present → no-op, exit 0, no file written" "passed" "passed"
|
|
686
|
+
else
|
|
687
|
+
test_result "cbp-session-id-stamp.sh neither present → no-op, exit 0, no file written" "passed" "failed (exit=$EXIT_CODE file_exists=$([ -f "$STAMP_FILE" ] && echo yes || echo no))"
|
|
688
|
+
fi
|
|
689
|
+
rm -rf "$ISO"
|
|
690
|
+
|
|
691
|
+
# Case 4: outside a codebyplan repo (no .codebyplan/repo.json) → no-op, exit 0
|
|
692
|
+
ISO=$(mktemp -d)
|
|
693
|
+
FAKE_UUID="aaaabbbb-cccc-dddd-eeee-ffffffffffff"
|
|
694
|
+
PAYLOAD=$(jq -n --arg s "$FAKE_UUID" '{session_id:$s}')
|
|
695
|
+
EXIT_CODE=$(echo "$PAYLOAD" | CLAUDE_PROJECT_DIR="$ISO" bash "$STAMP_HOOK" >/dev/null 2>&1; echo $?)
|
|
696
|
+
STAMP_FILE="$ISO/.codebyplan/state/session/session-id.json"
|
|
697
|
+
if [ "$EXIT_CODE" = "0" ] && [ ! -f "$STAMP_FILE" ]; then
|
|
698
|
+
test_result "cbp-session-id-stamp.sh no repo.json → no-op, exit 0" "passed" "passed"
|
|
699
|
+
else
|
|
700
|
+
test_result "cbp-session-id-stamp.sh no repo.json → no-op, exit 0" "passed" "failed (exit=$EXIT_CODE file_exists=$([ -f "$STAMP_FILE" ] && echo yes || echo no))"
|
|
701
|
+
fi
|
|
702
|
+
rm -rf "$ISO"
|
|
703
|
+
|
|
704
|
+
# Case 5: session_id present but not a canonical UUID → guard rejects, no file written, exit 0
|
|
705
|
+
ISO=$(mktemp -d)
|
|
706
|
+
mkdir -p "$ISO/.codebyplan"
|
|
707
|
+
printf '{}' > "$ISO/.codebyplan/repo.json"
|
|
708
|
+
PAYLOAD=$(jq -n '{session_id:"not-a-valid-uuid"}')
|
|
709
|
+
EXIT_CODE=$(echo "$PAYLOAD" | CLAUDE_PROJECT_DIR="$ISO" bash "$STAMP_HOOK" >/dev/null 2>&1; echo $?)
|
|
710
|
+
STAMP_FILE="$ISO/.codebyplan/state/session/session-id.json"
|
|
711
|
+
if [ "$EXIT_CODE" = "0" ] && [ ! -f "$STAMP_FILE" ]; then
|
|
712
|
+
test_result "cbp-session-id-stamp.sh invalid UUID → guard rejects, no file written" "passed" "passed"
|
|
713
|
+
else
|
|
714
|
+
test_result "cbp-session-id-stamp.sh invalid UUID → guard rejects, no file written" "passed" "failed (exit=$EXIT_CODE file_exists=$([ -f "$STAMP_FILE" ] && echo yes || echo no))"
|
|
715
|
+
fi
|
|
716
|
+
rm -rf "$ISO"
|
|
717
|
+
|
|
718
|
+
fi
|
|
719
|
+
|
|
720
|
+
echo ""
|
|
721
|
+
|
|
617
722
|
echo ""
|
|
618
723
|
|
|
619
724
|
# ===== HOOK SMOKE TESTS — cbp-skill-context-guard model-aware tier (CHK-224) =====
|
|
@@ -103,17 +103,44 @@ has_scope_comment() {
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
# has_template_twin <rel_path_under_claude>
|
|
106
|
-
# Returns 0 when the
|
|
107
|
-
#
|
|
108
|
-
#
|
|
109
|
-
#
|
|
110
|
-
#
|
|
111
|
-
#
|
|
112
|
-
#
|
|
113
|
-
#
|
|
114
|
-
#
|
|
106
|
+
# Returns 0 when the file is package-MANAGED (a template twin exists) — org-shared
|
|
107
|
+
# is its implicit default and a scope marker is NOT required. <rel_path_under_claude>
|
|
108
|
+
# is the path beneath .claude/ (e.g. "rules/foo.md", "skills/x/SKILL.md").
|
|
109
|
+
#
|
|
110
|
+
# Resolution order:
|
|
111
|
+
# 1. The install manifest (.claude/.cbp.manifest.json, with mid/legacy filename
|
|
112
|
+
# fallback). Its files[].dest entries are the authoritative record of what
|
|
113
|
+
# codebyplan installed INTO THIS repo — independent of where the package
|
|
114
|
+
# lives on disk (pnpm symlinks, hoisting, monorepo sub-packages). Requires jq.
|
|
115
|
+
# 2. Filesystem probe of the package's templates dir — fallback when there is no
|
|
116
|
+
# manifest/jq, and a backstop so a stale manifest never hides a genuine twin:
|
|
117
|
+
# Monorepo: $REPO_ROOT/packages/codebyplan-package/templates/<rel>
|
|
118
|
+
# Consumer: $REPO_ROOT/node_modules/codebyplan/templates/<rel>
|
|
119
|
+
# Returns non-zero when no twin is found by either path. Callers treat non-zero as
|
|
120
|
+
# "user-created": a scope marker is then required (the conservative fallback).
|
|
115
121
|
has_template_twin() {
|
|
116
122
|
local rel="$1"
|
|
123
|
+
|
|
124
|
+
# 1. Authoritative: the install manifest lists every managed file by dest path.
|
|
125
|
+
if command -v jq >/dev/null 2>&1; then
|
|
126
|
+
local manifest
|
|
127
|
+
for manifest in \
|
|
128
|
+
"$REPO_ROOT/.claude/.cbp.manifest.json" \
|
|
129
|
+
"$REPO_ROOT/.claude/.cbp-claude.manifest.json" \
|
|
130
|
+
"$REPO_ROOT/.claude/.codebyplan-claude.manifest.json"; do
|
|
131
|
+
if [ -f "$manifest" ]; then
|
|
132
|
+
if jq -e --arg rel "$rel" 'any(.files[]?; .dest == $rel)' "$manifest" >/dev/null 2>&1; then
|
|
133
|
+
return 0
|
|
134
|
+
fi
|
|
135
|
+
# Manifest found but does not list this file — stop scanning older
|
|
136
|
+
# manifest names and fall through to the filesystem probe (a stale
|
|
137
|
+
# manifest must not hide a genuine template twin).
|
|
138
|
+
break
|
|
139
|
+
fi
|
|
140
|
+
done
|
|
141
|
+
fi
|
|
142
|
+
|
|
143
|
+
# 2. Fallback / backstop: probe the package's templates dir directly.
|
|
117
144
|
[ -f "$REPO_ROOT/packages/codebyplan-package/templates/$rel" ] && return 0
|
|
118
145
|
[ -f "$REPO_ROOT/node_modules/codebyplan/templates/$rel" ] && return 0
|
|
119
146
|
return 1
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Handoff File Convention
|
|
2
|
+
|
|
3
|
+
Per-level handoff notes for cross-session context. Files live under
|
|
4
|
+
`.codebyplan/handoff/` and are committed (negation entry `!.codebyplan/handoff/`
|
|
5
|
+
in the managed `.gitignore` block).
|
|
6
|
+
|
|
7
|
+
## Layout
|
|
8
|
+
|
|
9
|
+
| Level | Path template | Number format |
|
|
10
|
+
|------------|--------------------------------------------------|-------------------|
|
|
11
|
+
| repo | `.codebyplan/handoff/repo.md` | n/a (per-section) |
|
|
12
|
+
| checkpoint | `.codebyplan/handoff/checkpoint/<NNN>.md` | 3-digit zero-pad |
|
|
13
|
+
| task | `.codebyplan/handoff/task/<NNN>-<T>.md` | CHK zero-pad + T |
|
|
14
|
+
| standalone | `.codebyplan/handoff/standalone/<N>.md` | bare number |
|
|
15
|
+
|
|
16
|
+
## repo.md — per-worktree sections
|
|
17
|
+
|
|
18
|
+
`repo.md` uses `## <worktree-label>` sections so multiple worktrees can write
|
|
19
|
+
to the same file without conflict. Label resolution order:
|
|
20
|
+
|
|
21
|
+
1. Read `.codebyplan/state/worktrees.json`; find entry whose `branch` matches
|
|
22
|
+
the current git branch; use its `name`.
|
|
23
|
+
2. Fallback: git branch name with `/` replaced by `-`.
|
|
24
|
+
|
|
25
|
+
Each CLI verb (`write`, `append`, `clear`) operates on the current worktree's
|
|
26
|
+
section only. Merge conflicts are structurally impossible: two worktrees write
|
|
27
|
+
to different `##` sections of the same file.
|
|
28
|
+
|
|
29
|
+
## Empty = absent / whitespace-only
|
|
30
|
+
|
|
31
|
+
A handoff is considered **empty** when the file is absent OR its content is
|
|
32
|
+
whitespace-only. The CLI deletes the file when it becomes empty:
|
|
33
|
+
|
|
34
|
+
- Non-repo levels: `write --content ""` and `clear` both delete the file.
|
|
35
|
+
- repo level: `write --content ""` and `clear` remove the current worktree's
|
|
36
|
+
`##` section; the file is deleted when no non-empty sections remain.
|
|
37
|
+
|
|
38
|
+
All delete operations swallow ENOENT (idempotent).
|
|
39
|
+
|
|
40
|
+
## CLI verbs
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
codebyplan handoff read --level <l> [--number N] [--task T]
|
|
44
|
+
codebyplan handoff write --level <l> [--number N] [--task T] --content "..."
|
|
45
|
+
codebyplan handoff append --level <l> [--number N] [--task T] --content "..."
|
|
46
|
+
codebyplan handoff clear --level <l> [--number N] [--task T]
|
|
47
|
+
codebyplan handoff status [--json]
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## status --json shape (stable contract)
|
|
51
|
+
|
|
52
|
+
```json
|
|
53
|
+
{
|
|
54
|
+
"nonEmpty": [{ "level": "checkpoint", "identifier": "005", "path": "/abs/path" }],
|
|
55
|
+
"empty": []
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
`status` is consumed by TASK-3 session-start/end gates to decide whether a
|
|
60
|
+
handoff prompt is shown. TASK-4 web UI reads the same files via the API.
|
|
61
|
+
|
|
62
|
+
## Content format
|
|
63
|
+
|
|
64
|
+
Freeform markdown. No structured schema is enforced; the files are human-written
|
|
65
|
+
notes surfaced to Claude at session boundaries.
|
|
@@ -252,13 +252,29 @@
|
|
|
252
252
|
"Bash(codebyplan cd:*)",
|
|
253
253
|
"Bash(npx codebyplan cd:*)",
|
|
254
254
|
"Bash(codebyplan cleanup-plan-folders:*)",
|
|
255
|
-
"Bash(npx codebyplan cleanup-plan-folders:*)"
|
|
255
|
+
"Bash(npx codebyplan cleanup-plan-folders:*)",
|
|
256
|
+
"Bash(codebyplan handoff:*)",
|
|
257
|
+
"Bash(npx codebyplan handoff:*)"
|
|
256
258
|
]
|
|
257
259
|
},
|
|
258
260
|
"attribution": {
|
|
259
261
|
"commit": "",
|
|
260
262
|
"pr": ""
|
|
261
263
|
},
|
|
264
|
+
"hooks": {
|
|
265
|
+
"SessionStart": [
|
|
266
|
+
{
|
|
267
|
+
"hooks": [
|
|
268
|
+
{
|
|
269
|
+
"_owner": "codebyplan-claude",
|
|
270
|
+
"_hook_id": "cbp-session-id-stamp.sh",
|
|
271
|
+
"type": "command",
|
|
272
|
+
"command": "bash ./.claude/hooks/cbp-session-id-stamp.sh"
|
|
273
|
+
}
|
|
274
|
+
]
|
|
275
|
+
}
|
|
276
|
+
]
|
|
277
|
+
},
|
|
262
278
|
"showClearContextOnPlanAccept": false,
|
|
263
279
|
"syntaxHighlightingDisabled": false
|
|
264
280
|
}
|
|
@@ -72,6 +72,38 @@ Complete remaining tasks first, then run `/cbp-checkpoint-complete`.
|
|
|
72
72
|
```
|
|
73
73
|
Stop here.
|
|
74
74
|
|
|
75
|
+
### Step 2.6: Verify Checkpoint Handoff Is Resolved
|
|
76
|
+
|
|
77
|
+
Run `codebyplan handoff status --json` and parse the output.
|
|
78
|
+
|
|
79
|
+
Check if `nonEmpty[]` contains an entry where `level === 'checkpoint'` AND `identifier === '{NNN}'`
|
|
80
|
+
(the 3-digit zero-padded checkpoint number — e.g. `231`).
|
|
81
|
+
|
|
82
|
+
If a matching entry is found, BLOCK with:
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
## Cannot Complete Checkpoint — Handoff Unresolved
|
|
86
|
+
|
|
87
|
+
CHK-[NNN] has unresolved handoff content at `.codebyplan/handoff/checkpoint/[NNN].md`.
|
|
88
|
+
|
|
89
|
+
The handoff file contains scope that has not been resolved. You must clear it before
|
|
90
|
+
completing this checkpoint. Three options — pick exactly one:
|
|
91
|
+
|
|
92
|
+
1. **Absorb** — address the pending scope now, then clear:
|
|
93
|
+
`codebyplan handoff clear --level checkpoint --number [NNN]`
|
|
94
|
+
2. **Defer** — create a follow-up checkpoint or standalone task to cover the scope,
|
|
95
|
+
then clear: `codebyplan handoff clear --level checkpoint --number [NNN]`
|
|
96
|
+
3. **Escalate** — move the content to the repo handoff:
|
|
97
|
+
`codebyplan handoff append --level repo --content "<content>"`
|
|
98
|
+
then clear: `codebyplan handoff clear --level checkpoint --number [NNN]`
|
|
99
|
+
|
|
100
|
+
Never silently delete handoff content — it represents tracked scope.
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
(STOP)
|
|
104
|
+
|
|
105
|
+
If no matching entry: continue to Step 3.
|
|
106
|
+
|
|
75
107
|
### Step 3: Aggregate QA
|
|
76
108
|
|
|
77
109
|
Collect QA results from all tasks and rounds. Build checkpoint-level QA summary:
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
---
|
|
2
|
-
scope: org-shared
|
|
3
2
|
name: cbp-clear-continue
|
|
4
3
|
description: Resume work after /clear by reading .codebyplan/clear/handoff.md and re-invoking the previously-blocked heavy skill. Reports a friendly error if no handoff file exists.
|
|
5
4
|
model: inherit
|
|
@@ -48,6 +47,28 @@ Resuming from handoff:
|
|
|
48
47
|
Next action: /<next-action>
|
|
49
48
|
```
|
|
50
49
|
|
|
50
|
+
### Step 2.5 — Surface committed handoffs
|
|
51
|
+
|
|
52
|
+
Surface any committed handoff files before proceeding. Non-blocking.
|
|
53
|
+
|
|
54
|
+
1. Run `codebyplan handoff status --json` → parse `nonEmpty[]`.
|
|
55
|
+
2. If `nonEmpty` is empty → skip silently.
|
|
56
|
+
3. For each entry in `nonEmpty`, read the content:
|
|
57
|
+
- `repo` → `codebyplan handoff read --level repo`
|
|
58
|
+
- `checkpoint` → `codebyplan handoff read --level checkpoint --number <identifier>`
|
|
59
|
+
- `task` → split identifier `"<NNN>-<T>"` → `codebyplan handoff read --level task --number <NNN> --task <T>`
|
|
60
|
+
- `standalone` → `codebyplan handoff read --level standalone --number <identifier>`
|
|
61
|
+
4. Display:
|
|
62
|
+
```
|
|
63
|
+
Handoff notes from previous session(s):
|
|
64
|
+
|
|
65
|
+
[<level>: <identifier>]
|
|
66
|
+
<content>
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
```
|
|
70
|
+
5. Non-blocking — proceed to Step 3 regardless.
|
|
71
|
+
|
|
51
72
|
### Step 3 — Delete the handoff BEFORE re-invoking
|
|
52
73
|
|
|
53
74
|
Delete `.codebyplan/clear/handoff.md` once its contents have been read and displayed:
|
|
@@ -80,7 +101,7 @@ the guard will deny again. Follow the same cycle: `/cbp-clear-prep` → `/clear`
|
|
|
80
101
|
## Integration
|
|
81
102
|
|
|
82
103
|
- **Invoked by**: user after `/clear` following `/cbp-clear-prep`
|
|
83
|
-
- **Reads**: `.codebyplan/clear/handoff.md`
|
|
104
|
+
- **Reads**: `.codebyplan/clear/handoff.md` (Step 1); `codebyplan handoff status --json` + `codebyplan handoff read` (Step 2.5 — committed handoff surfacing)
|
|
84
105
|
- **Deletes**: `.codebyplan/clear/handoff.md` (Step 3, before resuming)
|
|
85
106
|
- **Then invokes**: the skill from `next_action` via Skill tool
|
|
86
107
|
- **Companion**: `.claude/skills/cbp-clear-prep/SKILL.md` writes the handoff
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
---
|
|
2
|
-
scope: org-shared
|
|
3
2
|
name: cbp-clear-prep
|
|
4
3
|
description: Capture a clear-context handoff when the context window is too large to run a heavy skill. Reads active task/round state, writes .codebyplan/clear/handoff.md, then instructs the user to run /clear and /cbp-clear-continue to resume.
|
|
5
4
|
argument-hint: "[blocked-skill]"
|
|
@@ -86,6 +85,27 @@ next_action: /<skill-name> <args if any>
|
|
|
86
85
|
After /clear, run: /cbp-clear-continue
|
|
87
86
|
```
|
|
88
87
|
|
|
88
|
+
### Step 4.5 — Flush carryover to committed handoff
|
|
89
|
+
|
|
90
|
+
If `checkpoint_number` from Step 2 is `unknown` → skip silently (no reliable key).
|
|
91
|
+
|
|
92
|
+
Otherwise:
|
|
93
|
+
|
|
94
|
+
1. Compose a brief carryover note:
|
|
95
|
+
```markdown
|
|
96
|
+
## Context-clear carryover — CHK-<N>
|
|
97
|
+
|
|
98
|
+
Captured: <ISO now>
|
|
99
|
+
Blocked skill: <blocked_skill>
|
|
100
|
+
Next action: `<next_action>`
|
|
101
|
+
|
|
102
|
+
<in-flight notes from Step 3>
|
|
103
|
+
```
|
|
104
|
+
2. Run `codebyplan handoff write --level checkpoint --number <N> --content "<content>"`.
|
|
105
|
+
3. Output: `Carryover handoff written to .codebyplan/handoff/checkpoint/<NNN>.md`.
|
|
106
|
+
|
|
107
|
+
Non-blocking — Step 5 continues regardless.
|
|
108
|
+
|
|
89
109
|
### Step 5 — Instruct the user
|
|
90
110
|
|
|
91
111
|
Output exactly this summary (fill in the real values):
|
|
@@ -116,7 +136,7 @@ The user must run both commands manually.
|
|
|
116
136
|
## Integration
|
|
117
137
|
|
|
118
138
|
- **Invoked when**: `cbp-skill-context-guard` PreToolUse hook emits `permissionDecision: deny`
|
|
119
|
-
- **Writes**: `.codebyplan/clear/handoff.md`
|
|
139
|
+
- **Writes**: `.codebyplan/clear/handoff.md` (Step 4 — transient, gitignored); `codebyplan handoff write --level checkpoint --number <N>` (Step 4.5 — committed carryover flush; skipped when checkpoint_number unknown)
|
|
120
140
|
- **Next**: user runs `/clear`, then `/cbp-clear-continue`
|
|
121
141
|
- **Companion**: `.claude/skills/cbp-clear-continue/SKILL.md` reads `.codebyplan/clear/handoff.md`
|
|
122
142
|
- **Guard hook**: `.claude/hooks/cbp-skill-context-guard.sh` — fires when context exceeds the model-aware threshold: `CBP_CONTEXT_WARN_TOKENS` (default 200000) for standard models; `CBP_CONTEXT_WARN_TOKENS_1M` (default 800000) for `[1m]`-context models. No model id found → standard tier (fail-conservative).
|
|
@@ -85,6 +85,42 @@ Stop here.
|
|
|
85
85
|
|
|
86
86
|
`task.context.verify_verdict` must exist and have `verdict: 'READY'` (written by `/cbp-verify` Phase 6 when it runs at task scope — whole-repo `codebyplan check --scope task`, holistic `cbp-verify-reviewer`, and the single batched human walkthrough all passed). If absent or not `READY`, surface "Run `/cbp-verify` first" and stop.
|
|
87
87
|
|
|
88
|
+
### Step 2.6: Verify Task Handoff Is Resolved
|
|
89
|
+
|
|
90
|
+
Run `codebyplan handoff status --json` and parse the output.
|
|
91
|
+
|
|
92
|
+
Check if `nonEmpty[]` contains an entry where `level === 'task'` AND `identifier === '{NNN}-{T}'`
|
|
93
|
+
(the 3-digit zero-padded checkpoint number, hyphen, task number — e.g. `231-3`).
|
|
94
|
+
|
|
95
|
+
> Gate scope is intentional: only **task**-level handoffs block here. Checkpoint-level handoffs
|
|
96
|
+
> (written by `/cbp-session-end` as resume-pointers) are deliberately scoped to
|
|
97
|
+
> `/cbp-checkpoint-complete`, NOT task finalize — do not "fix" this to gate on checkpoint level.
|
|
98
|
+
|
|
99
|
+
If a matching entry is found, BLOCK with:
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
## Cannot Complete Task — Handoff Unresolved
|
|
103
|
+
|
|
104
|
+
TASK-[N] has unresolved handoff content at `.codebyplan/handoff/task/[NNN]-[T].md`.
|
|
105
|
+
|
|
106
|
+
The handoff file contains scope that has not been resolved. You must clear it before
|
|
107
|
+
completing this task. Three options — pick exactly one:
|
|
108
|
+
|
|
109
|
+
1. **Absorb** — address the pending scope in current work, then clear:
|
|
110
|
+
`codebyplan handoff clear --level task --number [NNN] --task [T]`
|
|
111
|
+
2. **Defer** — create a follow-up task or standalone task to cover the scope,
|
|
112
|
+
then clear: `codebyplan handoff clear --level task --number [NNN] --task [T]`
|
|
113
|
+
3. **Escalate** — move the content to the repo handoff:
|
|
114
|
+
`codebyplan handoff append --level repo --content "<content>"`
|
|
115
|
+
then clear: `codebyplan handoff clear --level task --number [NNN] --task [T]`
|
|
116
|
+
|
|
117
|
+
Never silently delete handoff content — it represents tracked scope.
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
(STOP)
|
|
121
|
+
|
|
122
|
+
If no matching entry: continue to Step 3.
|
|
123
|
+
|
|
88
124
|
### Step 3: Verify QA and File Approval
|
|
89
125
|
|
|
90
126
|
Load `task.qa` and `task.files_changed`:
|