codebyplan 1.13.62 → 1.13.63
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +1108 -2061
- package/package.json +1 -1
- package/templates/agents/cbp-e2e-playwright.md +10 -10
- package/templates/hooks/cbp-mcp-round-sync.sh +4 -15
- package/templates/hooks/cbp-test-hooks.sh +0 -81
- package/templates/hooks/hooks.json +0 -9
- package/templates/rules/cbp-operating-gotchas.md +8 -10
- package/templates/rules/supabase-branch-lifecycle.md +2 -2
- package/templates/rules/todo-backend.md +11 -8
- package/templates/settings.project.base.json +0 -5
- package/templates/skills/cbp-build-cc-settings/reference/cbp-permission-policy.md +1 -1
- package/templates/skills/cbp-checkpoint-create/SKILL.md +12 -22
- package/templates/skills/cbp-checkpoint-end/SKILL.md +37 -0
- package/templates/skills/cbp-checkpoint-plan/SKILL.md +10 -8
- package/templates/skills/cbp-checkpoint-start/SKILL.md +27 -19
- package/templates/skills/cbp-checkpoint-update/SKILL.md +1 -1
- package/templates/skills/cbp-finalize/SKILL.md +2 -2
- package/templates/skills/cbp-round-complete/SKILL.md +3 -24
- package/templates/skills/cbp-round-plan/SKILL.md +1 -1
- package/templates/skills/cbp-session-end/SKILL.md +40 -30
- package/templates/skills/cbp-session-start/SKILL.md +7 -7
- package/templates/skills/cbp-session-start/qa-regression.md +32 -25
- package/templates/skills/cbp-standalone-task-complete/SKILL.md +2 -5
- package/templates/skills/cbp-standalone-task-create/SKILL.md +5 -13
- package/templates/skills/cbp-standalone-task-start/SKILL.md +10 -10
- package/templates/skills/cbp-task-create/SKILL.md +1 -1
- package/templates/skills/cbp-task-start/SKILL.md +10 -10
- package/templates/skills/cbp-todo/SKILL.md +23 -38
- package/templates/skills/cbp-todo/qa-regression.md +21 -27
- package/templates/skills/cbp-verify/reference/round-scope.md +1 -2
- package/templates/hooks/cbp-mcp-caller-worktree-inject.sh +0 -78
|
@@ -8,7 +8,7 @@ effort: high
|
|
|
8
8
|
|
|
9
9
|
# Checkpoint Start Command
|
|
10
10
|
|
|
11
|
-
The activation + claim gate of the checkpoint pipeline. `/cbp-checkpoint-plan` produces tasks but deliberately leaves the checkpoint `pending` and
|
|
11
|
+
The activation + claim gate of the checkpoint pipeline. `/cbp-checkpoint-plan` produces tasks but deliberately leaves the checkpoint `pending` and unclaimed so it can sit in a team queue. This skill flips it to `active` — the server auto-stamps `assigned_user_id` from the caller's JWT on activation — and routes into the first task.
|
|
12
12
|
|
|
13
13
|
## Pipeline
|
|
14
14
|
|
|
@@ -20,7 +20,13 @@ The activation + claim gate of the checkpoint pipeline. `/cbp-checkpoint-plan` p
|
|
|
20
20
|
|
|
21
21
|
### Step 0: Parse `$ARGUMENTS`
|
|
22
22
|
|
|
23
|
-
Source `repo_id` from `.codebyplan/repo.json`. Resolve
|
|
23
|
+
Source `repo_id` from `.codebyplan/repo.json`. Resolve the current user once for the whole skill:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npx codebyplan whoami --json # → {"user_id":"<uuid>","email":"…"} or null
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
`USER_ID` = `user_id` from the result (may be null for anonymous/keychain-empty callers).
|
|
24
30
|
|
|
25
31
|
| Shape | Resolves to |
|
|
26
32
|
|-------|-------------|
|
|
@@ -31,55 +37,57 @@ Malformed (non-numeric, contains `-`): surface `checkpoint-start: invalid argume
|
|
|
31
37
|
|
|
32
38
|
### Step 1: Load Checkpoint + Tasks
|
|
33
39
|
|
|
34
|
-
Read `.codebyplan/state/checkpoints/<id>.json` for `status`, `
|
|
40
|
+
Read `.codebyplan/state/checkpoints/<id>.json` for `status`, `assigned_user_id`, `plan` (local-first; if missing/stale run `npx codebyplan sync` once; break-glass: MCP `get_checkpoints`). Read task files under `.codebyplan/state/checkpoints/<id>/tasks/*.json` (fallback: MCP `get_tasks(checkpoint_id)`).
|
|
35
41
|
|
|
36
42
|
### Step 2: Planned-Gate
|
|
37
43
|
|
|
38
44
|
A checkpoint must be planned before it can start.
|
|
39
45
|
|
|
40
|
-
- **No tasks AND empty `plan.steps[]`** → refuse: surface `CHK-NNN is not planned yet.` and auto-trigger `/cbp-checkpoint-plan {NNN}`. STOP. (An unplanned checkpoint is
|
|
46
|
+
- **No tasks AND empty `plan.steps[]`** → refuse: surface `CHK-NNN is not planned yet.` and auto-trigger `/cbp-checkpoint-plan {NNN}`. STOP. (An unplanned checkpoint is unassigned, so there is nothing to own yet — always kick off planning, matching `/cbp-todo` Rule A.)
|
|
41
47
|
- **Already `active`** → no activation needed; skip to Step 3 for a claim-check only, then Step 5.
|
|
42
48
|
- **`pending` with tasks** → proceed.
|
|
43
49
|
|
|
44
50
|
### Step 3: Claim Logic
|
|
45
51
|
|
|
46
|
-
Compare the checkpoint's `
|
|
52
|
+
Compare the checkpoint's `assigned_user_id` against `USER_ID`:
|
|
47
53
|
|
|
48
|
-
| Checkpoint `
|
|
49
|
-
|
|
50
|
-
| null (
|
|
51
|
-
| equals `
|
|
52
|
-
| a DIFFERENT
|
|
54
|
+
| Checkpoint `assigned_user_id` | Action |
|
|
55
|
+
|-------------------------------|--------|
|
|
56
|
+
| null (open — not yet claimed) | Proceed to Step 4 activation. The server will stamp `assigned_user_id = USER_ID` (from JWT) on `status=active`. If `USER_ID` is null (anonymous caller), warn the checkpoint will stay unclaimed and proceed. |
|
|
57
|
+
| equals `USER_ID` | Already yours — no-op. Proceed to Step 5. |
|
|
58
|
+
| a DIFFERENT user (non-null) | STOP. Surface: `CHK-NNN is assigned to user <assigned_user_id-email-or-uuid>; you are <USER_ID-email-or-uuid>. Ask the owner to release the assignment, or a maintainer can use the release_assignment tool, then re-run /cbp-checkpoint-start.` Do not activate. |
|
|
53
59
|
|
|
54
|
-
|
|
60
|
+
Never wrest a checkpoint from another user.
|
|
55
61
|
|
|
56
62
|
### Step 4: Activate
|
|
57
63
|
|
|
58
|
-
If the checkpoint is already `active` AND `
|
|
64
|
+
If the checkpoint is already `active` AND `assigned_user_id` already equals `USER_ID` (the Step 3 no-op row), skip this step entirely and proceed to Step 5 — nothing to write.
|
|
65
|
+
|
|
66
|
+
Otherwise set the checkpoint `active` via `codebyplan checkpoint update --id <checkpoint-id> --status active` (CLI write-through; break-glass: MCP `update_checkpoint`). The server auto-stamps `assigned_user_id = ctx.userId` (from the JWT) on activation — no client-side user param required. After the write, read the row back to confirm `assigned_user_id` is non-null.
|
|
59
67
|
|
|
60
|
-
|
|
68
|
+
If the checkpoint was already `active` but `assigned_user_id` is still null (edge case: prior activation without a valid JWT), re-read and surface a warning rather than silently proceeding.
|
|
61
69
|
|
|
62
70
|
### Step 5: Route
|
|
63
71
|
|
|
64
72
|
Follow the close-out routing convention — auto-trigger the next same-context step, never an A/B/C menu. `{first-pending-task}` is the lowest-numbered pending task from Step 1 (not necessarily TASK-1, since additive re-planning may have completed earlier ones):
|
|
65
73
|
|
|
66
|
-
- **Claimed by THIS session** (`
|
|
67
|
-
- **`
|
|
74
|
+
- **Claimed by THIS session** (`USER_ID` is non-null and now owns the checkpoint): auto-trigger `/cbp-task-start {chk}-{first-pending-task}` in the same context.
|
|
75
|
+
- **`USER_ID` null / anonymous**: surface a single directive — `Next: /cbp-task-start {chk}-{first-pending-task}` — and let the user proceed.
|
|
68
76
|
|
|
69
77
|
Show a one-line confirmation before routing:
|
|
70
78
|
|
|
71
79
|
```
|
|
72
80
|
## Checkpoint Started
|
|
73
81
|
|
|
74
|
-
**CHK-NNN**: [title] • **Status**: active • **Claimed by**: [
|
|
82
|
+
**CHK-NNN**: [title] • **Status**: active • **Claimed by**: [user email or "open"]
|
|
75
83
|
**Next task**: TASK-[N] — [title]
|
|
76
84
|
**Worktree**: `npx codebyplan worktree add CHK-{NNN}`
|
|
77
85
|
```
|
|
78
86
|
|
|
79
87
|
## Integration
|
|
80
88
|
|
|
81
|
-
- **Reads**: `.codebyplan/state/checkpoints/<id>.json`, `checkpoints/<id>/tasks/*.json` (local-first; `npx codebyplan sync` if stale; break-glass: MCP `get_checkpoints`, `get_tasks`); `npx codebyplan
|
|
82
|
-
- **Writes**: `codebyplan checkpoint update --status active
|
|
83
|
-
- **Triggered by**: `/cbp-checkpoint-plan` (auto when
|
|
89
|
+
- **Reads**: `.codebyplan/state/checkpoints/<id>.json`, `checkpoints/<id>/tasks/*.json` (local-first; `npx codebyplan sync` if stale; break-glass: MCP `get_checkpoints`, `get_tasks`); `npx codebyplan whoami --json`
|
|
90
|
+
- **Writes**: `codebyplan checkpoint update --status active` (CLI write-through; break-glass: MCP `update_checkpoint`; server auto-stamps `assigned_user_id` from JWT on activation)
|
|
91
|
+
- **Triggered by**: `/cbp-checkpoint-plan` (auto when open/unclaimed or assigned to the current user), `/cbp-todo` (planned-but-pending gate), or user directly
|
|
84
92
|
- **Triggers**: `/cbp-task-start` (auto when claimed), or `/cbp-checkpoint-plan` (when the checkpoint is unplanned)
|
|
85
93
|
- **Never**: plans or creates tasks — that is `/cbp-checkpoint-plan`
|
|
@@ -43,7 +43,7 @@ Given the parse from Step 0.5:
|
|
|
43
43
|
| Parse | Resolution path |
|
|
44
44
|
|-------|-----------------|
|
|
45
45
|
| `{chk}` | Scan `.codebyplan/state/checkpoints/*.json` for `number === {chk}` (local-first; if missing/stale run `npx codebyplan sync` once; break-glass: MCP `get_checkpoints`). |
|
|
46
|
-
| _(empty)_ | Read `.codebyplan/state/session/current.json`
|
|
46
|
+
| _(empty)_ | Read `.codebyplan/state/session/current.json` to find the active checkpoint (fallback: MCP `get_current_task`). If no active checkpoint, scan local state for `pending` checkpoints (fallback: MCP `get_checkpoints` filtered by `pending`). |
|
|
47
47
|
|
|
48
48
|
### Step 1.5: Detect Entry Context (from `/cbp-finalize` expand path)
|
|
49
49
|
|
|
@@ -133,7 +133,7 @@ Skip the push only when nothing was committed in Step 5 AND `/cbp-merge-main` re
|
|
|
133
133
|
|
|
134
134
|
### Step 7: Complete Task
|
|
135
135
|
|
|
136
|
-
MCP `complete_task(task_id)
|
|
136
|
+
MCP `complete_task(task_id)`. The server keys on the JWT user (`ctx.userId`) — no worktree param is needed. The server auto-clears `assigned_user_id` on the task; if this was the last sibling task, it also clears the parent checkpoint's assignment.
|
|
137
137
|
|
|
138
138
|
### Step 8: Run Cleanup + Migration (inline)
|
|
139
139
|
|
|
@@ -190,7 +190,7 @@ direct you to run `/cbp-clear-prep` first; otherwise checkpoint-check starts on
|
|
|
190
190
|
- **Triggered by**: `/cbp-verify` (auto, scope=task, when it writes `verify_verdict.verdict === 'READY'`)
|
|
191
191
|
- **Chain**: `/cbp-verify` (scope=task READY) → `/cbp-finalize`
|
|
192
192
|
- **Reads**: `.codebyplan/state/checkpoints/*.json`, `checkpoints/<id>/tasks/*.json`, `checkpoints/<id>/tasks/<id>/rounds/*.json`, `todos.json` (local-first; `npx codebyplan sync` on miss; MCP `get_current_task`/`get_rounds`/`get_tasks` break-glass) — including each round's `verify_manifest` and `task.context.verify_verdict`
|
|
193
|
-
- **Writes**: `codebyplan task update` for `files_changed` (CLI write-through; MCP `update_task` break-glass); MCP `complete_task` for task completion
|
|
193
|
+
- **Writes**: `codebyplan task update` for `files_changed` (CLI write-through; MCP `update_task` break-glass); MCP `complete_task` for task completion
|
|
194
194
|
- **Uses skills (inline, no sub-agent)**: `cleanup` (if deletions), `migration` (if exports renamed)
|
|
195
195
|
- **Triggers**: Same-context transitions auto-trigger via the Skill tool (next task in checkpoint → `cbp-task-start {N}`, `allow`-tier, fires silently). Checkpoint-done → auto-triggers `cbp-checkpoint-check` via Skill tool (`ask`-tier, permission prompt IS the human gate). No-task-anywhere fallback → directive `Next: Run /clear, then /cbp-session-end.`
|
|
196
196
|
- **Checkpoint-bound only** — for standalone tasks use `/cbp-standalone-task-complete`
|
|
@@ -25,7 +25,7 @@ Set `KIND` for the rest of this skill. MCP tool names vary by KIND:
|
|
|
25
25
|
| Get task | local state (break-glass: `get_current_task`) | `get_current_standalone_task(repo_id)` |
|
|
26
26
|
| Get rounds | local state (break-glass: `get_rounds`) | `get_standalone_rounds(standalone_task_id)` |
|
|
27
27
|
| Update round | `update_round(round_id, ...)` | `update_standalone_round(standalone_round_id, ...)` |
|
|
28
|
-
| Complete round | `complete_round(round_id, duration_minutes?)` | `complete_standalone_round(standalone_round_id, duration_minutes
|
|
28
|
+
| Complete round | `complete_round(round_id, duration_minutes?)` | `complete_standalone_round(standalone_round_id, duration_minutes?)` |
|
|
29
29
|
|
|
30
30
|
# Round Complete Command
|
|
31
31
|
|
|
@@ -84,20 +84,7 @@ Reconcile which files the user has approved by staging them. Run:
|
|
|
84
84
|
npx codebyplan round sync-approvals --round-id <round_id> --task-id <task_id>
|
|
85
85
|
```
|
|
86
86
|
|
|
87
|
-
The CLI
|
|
88
|
-
1. `--caller-worktree-id <uuid>` override (if passed — skips all resolution)
|
|
89
|
-
2. Per-device branch-keyed cache (`.codebyplan/worktree.local.json`)
|
|
90
|
-
3. In-process tuple API call: `POST /worktrees/resolve` using `(device_id, repo_path, branch)`
|
|
91
|
-
|
|
92
|
-
On the write path (non `--dry-run`), if the worktree id cannot be resolved the CLI **hard-fails with exit 1** and prints an actionable message. To pre-populate the cache:
|
|
93
|
-
|
|
94
|
-
```
|
|
95
|
-
npx codebyplan resolve-worktree --cache
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
If this worktree is not yet registered, run `npx codebyplan setup` first, then re-run `/cbp-round-complete`.
|
|
99
|
-
|
|
100
|
-
The CLI parses `git status --short`, merges drift + staging + web-UI flag, and writes both round and task (forwarding `caller_worktree_id` on both writes so the server honors the feat-worktree lock). A **cleanly staged** file (`git add`-ed, no further unstaged changes) becomes `user_approved: true`.
|
|
87
|
+
The CLI parses `git status --short`, merges drift + staging + web-UI flag, and writes both round and task. A **cleanly staged** file (`git add`-ed, no further unstaged changes) becomes `user_approved: true`.
|
|
101
88
|
|
|
102
89
|
Read the stdout JSON: `{ added, stale_marked, reactivated, total_files }`.
|
|
103
90
|
|
|
@@ -110,14 +97,7 @@ This is the **single** explicit reconcile owned by this skill. (The `cbp-mcp-rou
|
|
|
110
97
|
Calculate duration from the round's `started_at` to now in minutes.
|
|
111
98
|
|
|
112
99
|
- **checkpoint KIND**: `codebyplan round complete --id <round_id> --task-id <task_id> --checkpoint-id <checkpoint_id>` (CLI write-through: local state file + REST). Break-glass fallback: MCP `complete_round(round_id, duration_minutes)` when the CLI is unavailable. Note: the CLI does not accept `duration_minutes`; the backend computes duration server-side.
|
|
113
|
-
- **standalone KIND**: MCP `complete_standalone_round(standalone_round_id, duration_minutes
|
|
114
|
-
|
|
115
|
-
```
|
|
116
|
-
Warning: could not resolve caller_worktree_id (npx codebyplan resolve-worktree returned empty).
|
|
117
|
-
The complete_standalone_round call may be rejected by the pre-guard. Proceed anyway? (yes / no)
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
If the user confirms yes, proceed with `caller_worktree_id: ""`. If no, stop.
|
|
100
|
+
- **standalone KIND**: MCP `complete_standalone_round(standalone_round_id, duration_minutes)`. The server keys on the JWT user (`ctx.userId`) — no worktree param needed or accepted.
|
|
121
101
|
|
|
122
102
|
`complete_round` / `complete_standalone_round` sets the round `completed`, locks all `file_changes` for the round (`approval_locked: true`), and returns `unapproved_files[]` + `unapproved_count`. Hold those for routing.
|
|
123
103
|
|
|
@@ -158,7 +138,6 @@ Payload: `round.context.round_complete = { staged_count, unstaged_count, route,
|
|
|
158
138
|
- **Permission prompt = confirmation** — gated by `ask`-tier `Skill(cbp-round-complete)`. Because the skill is `disable-model-invocation: true`, this gate applies to the user's **direct** `/cbp-round-complete` invocation. NEVER add an AskUserQuestion to confirm running; the harness prompt is the gate. A declined permission is a clean no-op.
|
|
159
139
|
- **Step 2 (CLI) must exit 0** — if it fails, STOP before `complete_round`. The merge semantics are enforced by the CLI.
|
|
160
140
|
- **NEVER ask the user to git add files** — Step 2 only reads staging status. **NEVER stage files** — Claude does not touch the git staging area; the user's `git add` is the approval signal.
|
|
161
|
-
- **standalone KIND Step 3**: `caller_worktree_id` is REQUIRED for `complete_standalone_round` — always resolve and pass it.
|
|
162
141
|
|
|
163
142
|
## Integration
|
|
164
143
|
|
|
@@ -25,7 +25,7 @@ Set `KIND` for the rest of this skill. Read/write sources vary by KIND:
|
|
|
25
25
|
| Get rounds | local state (break-glass: `get_rounds`) | `get_standalone_rounds(standalone_task_id)` |
|
|
26
26
|
| Add round | `codebyplan round add` (break-glass: `add_round`) | `add_standalone_round(standalone_task_id, ...)` |
|
|
27
27
|
| Update round | `codebyplan round update` (break-glass: `update_round`) | `update_standalone_round(standalone_round_id, ...)` |
|
|
28
|
-
| Complete round | `complete_round(round_id, duration_minutes?)` | `complete_standalone_round(standalone_round_id, duration_minutes
|
|
28
|
+
| Complete round | `complete_round(round_id, duration_minutes?)` | `complete_standalone_round(standalone_round_id, duration_minutes?)` |
|
|
29
29
|
| Update task | `codebyplan task update` (break-glass: `update_task`) | `update_standalone_task(standalone_task_id, ...)` |
|
|
30
30
|
|
|
31
31
|
> **Note**: The `standalone` KIND column uses MCP tools unchanged — standalone local-first migration is out of scope and will be addressed in a later task.
|
|
@@ -22,35 +22,46 @@ Always write a session log for this session — **even if empty**. `/cbp-session
|
|
|
22
22
|
2. Pull facts from local state files rather than narrating from memory:
|
|
23
23
|
- Rounds added/completed, tasks advanced/completed during this session (read from `.codebyplan/state/checkpoints/` subtree)
|
|
24
24
|
- Decisions, blockers, or discoveries recorded in checkpoint/task context
|
|
25
|
-
|
|
26
|
-
### Step 1.3: Capture Handoff Snapshot
|
|
27
|
-
|
|
28
|
-
Snapshot the current next-action so the next `/cbp-session-start` (Step 4.5) can auto-resume. The handoff write-path + payload shape are specified inline here and in `/cbp-session-start` Step 4.5 (freshness gate).
|
|
29
|
-
|
|
30
|
-
1. Read `.codebyplan/state/todos.json` (local-first) and take the queue head `rows[0]` (rows are ordered by `sort_order`; `rows[0]` is the current next-action). If missing/stale, run `npx codebyplan sync` once and re-read. Break-glass fallback: MCP `get_todos({ repo_id, worktree_id })` when the state dir is absent and sync fails. The worker stamps `command`, `instructions`, `state`, and the entity ids `checkpoint_id` / `task_id` / `round_id` on every row.
|
|
31
|
-
2. If `rows[0]` exists and its `command` is non-empty (active work in flight):
|
|
32
|
-
```yaml
|
|
33
|
-
handoff:
|
|
34
|
-
command: <rows[0].command> # e.g. "/cbp-verify"
|
|
35
|
-
instructions: <rows[0].instructions> # human-readable trigger reason
|
|
36
|
-
state: <rows[0].state> # workflow state label
|
|
37
|
-
context: # entity ids used by the Step 4.5 freshness probe
|
|
38
|
-
checkpoint_id: <rows[0].checkpoint_id>
|
|
39
|
-
task_id: <rows[0].task_id>
|
|
40
|
-
round_id: <rows[0].round_id>
|
|
41
|
-
captured_at: <ISO now> # for entity-drift freshness comparison
|
|
42
|
-
captured_session_log_id: <current session log id>
|
|
43
|
-
```
|
|
44
|
-
3. If the queue is empty or `rows[0].command` is empty / idle: set `handoff = null` so the next session's probe falls through to `/cbp-todo`.
|
|
45
|
-
4. Hold `handoff` in context for Step 1's `update_session_log` call below — it ships in the same write as `ended_at` and `summary`.
|
|
46
|
-
|
|
47
|
-
Continuing Step 1:
|
|
48
|
-
|
|
49
|
-
3. Run `codebyplan session update-log --id <log-id> --ended-at <now> --summary <text> --pending <text> --handoff <json>` (CLI write-through: updates `.codebyplan/state/session/current.json` + REST). Break-glass fallback: MCP `update_session_log` when the CLI is unavailable. Fields:
|
|
25
|
+
3. Run `codebyplan session update-log --id <log-id> --ended-at <now> --summary <text> --pending <text> --git-branch <current-branch>` (CLI write-through: updates `.codebyplan/state/session/current.json` + REST). Break-glass fallback: MCP `update_session_log` when the CLI is unavailable. Fields:
|
|
50
26
|
- `ended_at`: now (maps to the `closed_at` column per TASK-2 alias)
|
|
51
|
-
- `handoff`: from Step 1.3 (jsonb or `null`; MCP write surface aliases to the `content` column transparently per CHK-111 Migration A — `handoff` wins over `content` when both are passed)
|
|
52
27
|
- `summary`: concise — may be empty if nothing happened
|
|
53
28
|
- `pending`: open items the next session should see first
|
|
29
|
+
- `git_branch`: the current git branch (informational; `git rev-parse --abbrev-ref HEAD`)
|
|
30
|
+
- **Do NOT pass `--handoff` / `handoff` field.** The DB handoff field is no longer written here. Omit entirely — never pass `handoff:null` (it clobbers summary/pending content).
|
|
31
|
+
|
|
32
|
+
### Step 1.3: Optional Handoff File (mid-work only)
|
|
33
|
+
|
|
34
|
+
When an active in-progress task or round exists, offer to write a handoff file so the next session can auto-resume. Skip entirely when not mid-work.
|
|
35
|
+
|
|
36
|
+
1. Read `.codebyplan/state/todos.json` (local-first) and check `rows[0]` (queue head, ordered by `sort_order`). If missing/stale, run `npx codebyplan sync` once and re-read. Break-glass fallback: MCP `get_todos({ repo_id })` when the state dir is absent and sync fails. The worker stamps `command`, `instructions`, `state`, and entity ids `checkpoint_id` / `task_id` / `round_id` on every row.
|
|
37
|
+
|
|
38
|
+
2. **If `rows[0]` exists and its `command` is non-empty** (active work in flight):
|
|
39
|
+
- Determine the handoff file path. The directory is keyed by the human-facing **number** (`<NNN>` checkpoint number / `<N>` standalone task number) — matching the committed `.codebyplan/checkpoint/<NNN>/` plan-artifact convention and the session-start resume probe (which globs by number). Resolve the number from local state (break-glass: MCP):
|
|
40
|
+
- Checkpoint work: read `.codebyplan/state/checkpoints/<rows[0].checkpoint_id>.json` → `number` (break-glass: MCP `get_checkpoints`). Path: `.codebyplan/checkpoint/<NNN>/handoff.md`.
|
|
41
|
+
- Standalone work: read the standalone task's `number` from local standalone state (break-glass: MCP `get_standalone_tasks`). Path: `.codebyplan/standalone/<N>/handoff.md`.
|
|
42
|
+
- Offer to write the file:
|
|
43
|
+
```
|
|
44
|
+
Write handoff file for next session?
|
|
45
|
+
<path>
|
|
46
|
+
|
|
47
|
+
Reply: yes | no
|
|
48
|
+
```
|
|
49
|
+
- On `yes`: write the file with this structure:
|
|
50
|
+
```markdown
|
|
51
|
+
---
|
|
52
|
+
command: <rows[0].command>
|
|
53
|
+
state: <rows[0].state>
|
|
54
|
+
captured_at: <ISO now>
|
|
55
|
+
checkpoint_id: <rows[0].checkpoint_id or null>
|
|
56
|
+
task_id: <rows[0].task_id or null>
|
|
57
|
+
round_id: <rows[0].round_id or null>
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
<rows[0].instructions — human-readable trigger reason>
|
|
61
|
+
```
|
|
62
|
+
- The file is committed with the session's final commit (Step 1.5) or the user can stage it manually.
|
|
63
|
+
|
|
64
|
+
3. **If the queue is empty or `rows[0].command` is empty/idle**: skip — no handoff file is written.
|
|
54
65
|
|
|
55
66
|
### Step 1.5: Commit Non-Task Files
|
|
56
67
|
|
|
@@ -117,7 +128,7 @@ Stop this worktree's Realtime watch daemon, non-blocking and non-fatal:
|
|
|
117
128
|
npx codebyplan watch stop 2>/dev/null || true
|
|
118
129
|
```
|
|
119
130
|
|
|
120
|
-
This SIGTERMs the per-worktree pidfile daemon started by `cbp-session-start-hook.sh`. Silently ignored when no daemon is running
|
|
131
|
+
This SIGTERMs the per-worktree pidfile daemon started by `cbp-session-start-hook.sh`. Silently ignored when no daemon is running. If there is no daemon to stop (e.g. session-start was skipped), `watch stop` itself exits 0 — the `|| true` guard is defense-in-depth only, so Step 3's session-state write never sees a failure from this step.
|
|
121
132
|
|
|
122
133
|
### Step 3: Update Session State
|
|
123
134
|
|
|
@@ -134,9 +145,8 @@ You can close this window.
|
|
|
134
145
|
## Integration
|
|
135
146
|
|
|
136
147
|
- **Triggered by**: user invocation (prompted by `/cbp-todo` when no work remains)
|
|
137
|
-
- **Reads**: `.codebyplan/repo.json`; local-first reads (with `npx codebyplan sync` + MCP break-glass): `.codebyplan/state/session/current.json` (Step 1 resolve log), `.codebyplan/state/todos.json` (Step 1.3
|
|
138
|
-
- **Writes**: `codebyplan session update-log --id <id> ...` (Step 1 finalize — CLI write-through to `.codebyplan/state/session/current.json`; break-glass: MCP `update_session_log
|
|
148
|
+
- **Reads**: `.codebyplan/repo.json`; local-first reads (with `npx codebyplan sync` + MCP break-glass): `.codebyplan/state/session/current.json` (Step 1 resolve log), `.codebyplan/state/todos.json` (Step 1.3 mid-work detection + Step 1.5 active-task lookup), `.codebyplan/state/checkpoints/<id>/tasks/<id>/rounds/` (Step 1.5 task-file resolution); `codebyplan session freshness-gate` (Step 1.7 package-freshness gate, without --halt-on-update); `codebyplan session infra-files --json --task-files <csv>` (Step 1.5 infra-file set math)
|
|
149
|
+
- **Writes**: `codebyplan session update-log --id <id> --git-branch <branch> ...` (Step 1 finalize — CLI write-through to `.codebyplan/state/session/current.json`; break-glass: MCP `update_session_log`; handoff field never passed), `codebyplan session create-log` (Step 1 fallback when no log exists; break-glass: MCP `create_session_log`), optional handoff file at `.codebyplan/checkpoint/<NNN>/handoff.md` or `.codebyplan/standalone/<N>/handoff.md` (Step 1.3, mid-work only), `codebyplan session update-state --action deactivate` (Step 3 — CLI write-through to `.codebyplan/state/session/state.json`; break-glass: MCP `update_session_state`)
|
|
139
150
|
- **Spawns**: none
|
|
140
151
|
- **Triggers**: none at the skill-contract level. Step 1.5 may invoke `/cbp-git-commit` inline on user approval; Step 1.7 may invoke `/cbp-git-commit` on the `result === 'updated'` path (committing changed `.claude/` and `.codebyplan/` paths).
|
|
141
152
|
- **Paired with**: `/cbp-session-start`
|
|
142
|
-
- **Pairs with**: `/cbp-session-start` Step 4.5 (handoff payload shape + freshness-gate contract; specified inline — no separate rule file)
|
|
@@ -41,7 +41,7 @@ codebyplan session start --json
|
|
|
41
41
|
The orchestrator performs (in order, all fail-safe):
|
|
42
42
|
|
|
43
43
|
1. Resolve `repo_id` from `.codebyplan/repo.json`
|
|
44
|
-
2. `codebyplan
|
|
44
|
+
2. `codebyplan whoami --json` → `user_id`, `user_error_kind` (CHK-225 retired worktree identity — concurrency is user-level via `assigned_user_id`; the removed `resolve-worktree` verb no longer exists)
|
|
45
45
|
3. `codebyplan session freshness-gate --halt-on-update` → update_halt short-circuit (no activate, no create-log when halt)
|
|
46
46
|
4. Infra-drift nudge (monorepo-only), arch-map drift nudge, LSP binary nudge
|
|
47
47
|
5. Read previous session log from `.codebyplan/state/session/current.json` (sync on miss)
|
|
@@ -49,7 +49,7 @@ The orchestrator performs (in order, all fail-safe):
|
|
|
49
49
|
7. `codebyplan session update-state --action activate` (write-through)
|
|
50
50
|
8. `codebyplan session create-log` → `session_log_id`
|
|
51
51
|
9. Infra-files set math: active task round files subtracted from `git status --porcelain`
|
|
52
|
-
10. `get_checkpoints({ repo_id, status:'active' })` → ownership partition (owned vs
|
|
52
|
+
10. `get_checkpoints({ repo_id, status:'active' })` → ownership partition (owned by you vs other users)
|
|
53
53
|
11. Compute `next_action` + render the Step 6 output block
|
|
54
54
|
|
|
55
55
|
The envelope shape:
|
|
@@ -58,8 +58,8 @@ The envelope shape:
|
|
|
58
58
|
{
|
|
59
59
|
status: 'ok' | 'update_halt',
|
|
60
60
|
session_log_id: string | null,
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
user_id: string | null,
|
|
62
|
+
user_error_kind: string | null,
|
|
63
63
|
infra_drift_nudge: string | null,
|
|
64
64
|
arch_map_nudge: string | null,
|
|
65
65
|
lsp_nudges: string[],
|
|
@@ -104,13 +104,13 @@ Route from `envelope.next_action`:
|
|
|
104
104
|
- **`resume_handoff`** — trigger `envelope.handoff.command` directly with `envelope.handoff.context` / `envelope.handoff.state`. Skip Step 5.7.
|
|
105
105
|
- **`commit_then_todo`** — run Step 5.7 (infra commit gate), then trigger `/cbp-todo`.
|
|
106
106
|
- **`trigger_todo`** — trigger `/cbp-todo` (owns active work, or idle path).
|
|
107
|
-
- **`stop`** — do NOT auto-trigger `/cbp-todo`. The Ownership block in `rendered_block` communicates the situation; the user must
|
|
107
|
+
- **`stop`** — do NOT auto-trigger `/cbp-todo`. The Ownership block in `rendered_block` communicates the situation; the user must coordinate with the owning user or start new work explicitly.
|
|
108
108
|
|
|
109
109
|
## Integration
|
|
110
110
|
|
|
111
111
|
- **Triggered by**: user invocation, `/clear` recovery
|
|
112
|
-
- **Reads**: MCP `health_check` (Step 0 hard gate — stays MCP unconditionally); `codebyplan session start --json` (Steps 1–5.8 — the orchestrator reads `.codebyplan/repo.json`, `.codebyplan/git.json`, `.codebyplan/state/session/current.json`, `.codebyplan/state/todos.json`, `.codebyplan/state/checkpoints/` entity files, `scripts/infra-drift.mjs`, `.codebyplan/architecture.json`, `.codebyplan/lsp.json`)
|
|
113
|
-
- **Writes**: orchestrator calls `codebyplan session update-state --action activate` (Step 7) and `codebyplan session create-log` (Step 8) — both SKIPPED on Step 0 hard-fail and on `status: update_halt`
|
|
112
|
+
- **Reads**: MCP `health_check` (Step 0 hard gate — stays MCP unconditionally); `codebyplan session start --json` (Steps 1–5.8 — the orchestrator runs `codebyplan whoami --json` for caller identity and reads `.codebyplan/repo.json`, `.codebyplan/git.json`, `.codebyplan/state/session/current.json`, `.codebyplan/state/todos.json`, `.codebyplan/state/checkpoints/` entity files, `scripts/infra-drift.mjs`, `.codebyplan/architecture.json`, `.codebyplan/lsp.json`)
|
|
113
|
+
- **Writes**: orchestrator calls `codebyplan session update-state --action activate` (Step 7) and `codebyplan session create-log` (Step 8 — user-level; no worktree_id in the body) — both SKIPPED on Step 0 hard-fail and on `status: update_halt`
|
|
114
114
|
- **Spawns**: none
|
|
115
115
|
- **Triggers**: `/cbp-git-commit` (conditional, on user approval at Step 5.7), `envelope.handoff.command` (on `next_action: resume_handoff`), `/cbp-todo` (on `next_action: trigger_todo` or `commit_then_todo`); STOPS with no trigger on `next_action: stop` or `mcp_update_halt`
|
|
116
116
|
- **Paired with**: `/cbp-session-end`
|
|
@@ -1,52 +1,59 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: cbp-session-start-qa-regression
|
|
3
|
-
description: Manual regression procedure for the cbp-session-start
|
|
3
|
+
description: Manual regression procedure for the cbp-session-start user-identity awareness + user-lock routing (CHK-225 TASK-5)
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# cbp-session-start —
|
|
6
|
+
# cbp-session-start — User-Identity Regression
|
|
7
7
|
|
|
8
|
-
Manual procedure verifying that `/cbp-session-start` correctly resolves the caller's
|
|
8
|
+
Manual procedure verifying that `/cbp-session-start` correctly resolves the caller's user identity (via `codebyplan whoami --json`), gates Step 7 auto-trigger on user-level ownership, and surfaces distress signals non-blocking. Run these by hand whenever the SKILL's envelope-consumption logic (Step 0 health gate, the `codebyplan session start` invocation, the Step 5.7 commit gate, or the Step 7 `next_action` routing) changes.
|
|
9
9
|
|
|
10
|
-
Since the
|
|
10
|
+
Since the user resolution, handoff freshness, ownership partition, and Step 6 render are now computed inside `codebyplan session start` (Steps 1–5.8 collapsed into one CLI call), the deterministic behavior is covered by unit tests (`src/cli/session/start.test.ts`, `src/lib/session.test.ts`). These scenarios are now best verified by inspecting the **envelope** the CLI emits — run `codebyplan session start --json` and read its fields — rather than tracing SKILL prose. The `ownership`, `next_action`, `handoff.fresh`, and `user_error_kind` fields below correspond to envelope keys.
|
|
11
11
|
|
|
12
12
|
Repo under test: `2ff6d405-39c5-47b8-a6d1-59f998ac0537`.
|
|
13
13
|
|
|
14
14
|
## Preconditions
|
|
15
15
|
|
|
16
16
|
- The SKILL keeps Step 0 (`health_check`) as a hard gate, then delegates Steps 1–5.8 to `codebyplan session start --json` — confirm with `grep -n 'session start --json' SKILL.md` → at least one hit.
|
|
17
|
-
- The orchestrator resolves
|
|
17
|
+
- The orchestrator resolves user identity via `whoami --json` and partitions ownership via `get_checkpoints({ repo_id, status: 'active' })` — confirm the envelope carries `user_id` / `user_error_kind` / `owned_count` / `total_count`.
|
|
18
18
|
- The Step 6 Ownership block (the envelope's `rendered_block`) is READ-ONLY — confirm no "reassign", "release_assignment", or "transfer" language appears in SKILL.md: `grep -n 'reassign\|release_assignment\|transfer' SKILL.md` → no hits.
|
|
19
|
-
- The handoff freshness gate includes the cross-
|
|
19
|
+
- The handoff freshness gate includes the cross-user stale rule (checkpoint `assigned_user_id` non-null and differs from caller) — covered by the `probeHandoff` unit tests; the envelope surfaces the outcome as `handoff.fresh`.
|
|
20
20
|
|
|
21
|
-
## Scenario A —
|
|
21
|
+
## Scenario A — current user owns an active CHK → auto-trigger
|
|
22
22
|
|
|
23
|
-
1. Run
|
|
24
|
-
2. `get_checkpoints({ repo_id, status: 'active' })` returns at least one entry whose `
|
|
25
|
-
3. **Expected**: envelope `owned_count >= 1`, `next_action: 'trigger_todo'`. `rendered_block` shows `Ownership: N active CHK(s), N owned by
|
|
23
|
+
1. Run signed in as a user whose `user_id` matches the active checkpoint's `assigned_user_id` (or the checkpoint's `assigned_user_id` is `null`).
|
|
24
|
+
2. `get_checkpoints({ repo_id, status: 'active' })` returns at least one entry whose `assigned_user_id === user_id` (or is null).
|
|
25
|
+
3. **Expected**: envelope `owned_count >= 1`, `next_action: 'trigger_todo'`. `rendered_block` shows `Ownership: N active CHK(s), N owned by you`. The SKILL's Step 7 fires `/cbp-todo`.
|
|
26
26
|
|
|
27
|
-
## Scenario B — active CHK(s) exist
|
|
27
|
+
## Scenario B — active CHK(s) exist, all owned by a different user → Ownership block + STOP
|
|
28
28
|
|
|
29
|
-
Repro:
|
|
29
|
+
Repro: current user is `alice@example.com` (`uuid-A`). The only active checkpoint is CHK-136, assigned to `bob@example.com` (`uuid-B`).
|
|
30
30
|
|
|
31
|
-
1. `
|
|
32
|
-
2. `get_checkpoints({ repo_id, status: 'active' })` returns CHK-136 with `
|
|
33
|
-
3. Step 5.8: `owned_count = 0`, `total_count = 1`, `
|
|
34
|
-
4. **Expected**: envelope `owned_count = 0`, `total_count = 1`, `next_action: 'stop'`, `cross_checkpoints = [CHK-136]`. `rendered_block` shows `Ownership: 1 active CHK(s), 0 owned by
|
|
31
|
+
1. `whoami --json` returns `{"user_id":"uuid-A","email":"alice@example.com"}`.
|
|
32
|
+
2. `get_checkpoints({ repo_id, status: 'active' })` returns CHK-136 with `assigned_user_id = "uuid-B"`.
|
|
33
|
+
3. Step 5.8: `owned_count = 0`, `total_count = 1`, `cross_checkpoints = [CHK-136]`.
|
|
34
|
+
4. **Expected**: envelope `owned_count = 0`, `total_count = 1`, `next_action: 'stop'`, `cross_checkpoints = [CHK-136]`. `rendered_block` shows `Ownership: 1 active CHK(s), 0 owned by you` and `[Other users: CHK-136 (…)]`. The SKILL **STOPS** on `next_action: 'stop'` — `/cbp-todo` is NOT auto-triggered. No reassignment language appears.
|
|
35
35
|
|
|
36
36
|
## Scenario C — no active CHKs anywhere → idle /cbp-todo trigger
|
|
37
37
|
|
|
38
38
|
1. `get_checkpoints({ repo_id, status: 'active' })` returns `[]`.
|
|
39
39
|
2. Step 5.8: `owned_count = 0`, `total_count = 0`.
|
|
40
|
-
3. **Expected**: envelope `owned_count = 0`, `total_count = 0`, `next_action: 'trigger_todo'`. `rendered_block` shows `Ownership: 0 active CHK(s), 0 owned by
|
|
40
|
+
3. **Expected**: envelope `owned_count = 0`, `total_count = 0`, `next_action: 'trigger_todo'`. `rendered_block` shows `Ownership: 0 active CHK(s), 0 owned by you`. The SKILL fires `/cbp-todo` (idle path → checkpoint-create or session-end suggestion).
|
|
41
41
|
|
|
42
|
-
## Scenario D —
|
|
42
|
+
## Scenario D — stale handoff pointing to a different user's checkpoint → handoff marked stale, falls through
|
|
43
43
|
|
|
44
|
-
1. The most-recent closed session log contains a handoff payload whose `context.checkpoint_id` resolves to a checkpoint with `
|
|
45
|
-
2. Caller `
|
|
46
|
-
3. **Expected**: the orchestrator's handoff freshness gate hits the cross-
|
|
44
|
+
1. The most-recent closed session log contains a handoff payload whose `context.checkpoint_id` resolves to a checkpoint with `assigned_user_id = "uuid-B"` (a different user).
|
|
45
|
+
2. Caller `user_id = "uuid-A"`.
|
|
46
|
+
3. **Expected**: the orchestrator's handoff freshness gate hits the cross-user stale rule (`checkpoint.assigned_user_id` non-null AND differs from caller) → envelope `handoff.fresh: false`. The mismatched handoff is NOT auto-resumed (`next_action` is never `resume_handoff`); ownership/routing proceed normally per `owned_count`/`total_count`.
|
|
47
47
|
|
|
48
|
-
## Scenario E —
|
|
48
|
+
## Scenario E — whoami distress (identity unresolved) → session proceeds, non-blocking warning
|
|
49
49
|
|
|
50
|
-
1. `
|
|
51
|
-
2. **Expected**: the envelope carries `
|
|
52
|
-
3. **Compound case** (distress typically leaves `
|
|
50
|
+
1. `whoami --json` returns `{"user_id":null,"error_kind":"local_config_read_failed"}` (or any other non-null, non-tuple-miss `error_kind`).
|
|
51
|
+
2. **Expected**: the envelope carries `user_error_kind: 'local_config_read_failed'`; `status` stays `'ok'` (non-blocking). `rendered_block` surfaces `⚠ whoami: local_config_read_failed — identity could not be resolved; routing may be unreliable. Run \`npx codebyplan whoami\` to check identity.` ABOVE the Ownership block. The orchestrator still activates + creates the session log. `next_action` routes per the `owned_count`/`total_count` values as normal — the skill does NOT hard-stop the way `/cbp-todo` does on the same distress kinds.
|
|
52
|
+
3. **Compound case** (distress typically leaves `user_id` null): ownership then classifies every checkpoint with a non-null `assigned_user_id` as `cross_checkpoints[]` (only open, null-`assigned_user_id` checkpoints land in `owned_checkpoints[]`). So if all active checkpoints are assigned, `owned_count = 0` and `next_action: 'stop'` — the distress warning + Ownership block are the only output. The created session log records the caller's JWT user server-side; the envelope `user_id: null` (the resolver could not read local identity) is expected, not a failure.
|
|
53
|
+
|
|
54
|
+
## Scenario F — anonymous session (whoami returns null / signed out) → session proceeds, open checkpoints treated as own
|
|
55
|
+
|
|
56
|
+
1. `whoami --json` returns `null` (signed out), empty output, or exits non-zero.
|
|
57
|
+
2. `user_id` is treated as null (anonymous) with `user_error_kind: 'tuple_miss'`.
|
|
58
|
+
3. `get_checkpoints({ repo_id, status: 'active' })` returns checkpoints with `assigned_user_id` null or set to real user IDs.
|
|
59
|
+
4. **Expected**: ownership classifies null-`assigned_user_id` checkpoints as `owned_checkpoints[]` (no user to compare against) and non-null-`assigned_user_id` checkpoints as `cross_checkpoints[]` (anonymous caller cannot claim them). `rendered_block` shows the `⚠ Not signed in — run \`npx codebyplan login\` to sign in` line below the User line. `next_action` routes per `owned_count`/`total_count` as normal — the session does NOT hard-stop solely due to anonymous identity. The session log is created in Step 8.
|
|
@@ -11,7 +11,7 @@ effort: xhigh
|
|
|
11
11
|
|
|
12
12
|
Complete a standalone task. Auto-triggered by `/cbp-standalone-task-testing` when all tests pass. Can also be run manually.
|
|
13
13
|
|
|
14
|
-
This skill is gated by an `ask`-tier `Skill(cbp-standalone-task-complete)` permission rule in `settings.json` (shipped templates). **The permission prompt IS the user confirmation** — there is NO completion-confirmation AskUserQuestion inside this skill
|
|
14
|
+
This skill is gated by an `ask`-tier `Skill(cbp-standalone-task-complete)` permission rule in `settings.json` (shipped templates). **The permission prompt IS the user confirmation** — there is NO completion-confirmation AskUserQuestion inside this skill. A declined permission is a clean no-op (nothing committed, merged, pushed, or completed).
|
|
15
15
|
|
|
16
16
|
## Instructions
|
|
17
17
|
|
|
@@ -227,9 +227,7 @@ Complete via the CLI (wraps the `complete_standalone_task` MCP tool):
|
|
|
227
227
|
codebyplan standalone-task complete --id <standalone_task.id>
|
|
228
228
|
```
|
|
229
229
|
|
|
230
|
-
The
|
|
231
|
-
|
|
232
|
-
If the CLI exits 1 with a "could not resolve caller_worktree_id" message, run `npx codebyplan setup` (or `codebyplan resolve-worktree --cache`) from this worktree, then re-run the command.
|
|
230
|
+
The server keys on the JWT user (`ctx.userId`) — no worktree param is needed. The server auto-clears `assigned_user_id` on the task on success.
|
|
233
231
|
|
|
234
232
|
### Step 8: Run Cleanup + Migration (inline)
|
|
235
233
|
|
|
@@ -266,7 +264,6 @@ Do NOT use AskUserQuestion for routing. Do NOT use the Skill tool to auto-trigge
|
|
|
266
264
|
|
|
267
265
|
## Key Rules
|
|
268
266
|
|
|
269
|
-
- **`caller_worktree_id` is REQUIRED** for `complete_standalone_task`
|
|
270
267
|
- **Branch shipping lives here** (not in checkpoint-end) — standalone tasks self-ship to production via `codebyplan ship`
|
|
271
268
|
- **Single-directive routing** — no menus, no auto-triggers via Skill tool
|
|
272
269
|
- **No checkpoint** — never check `checkpoint_id`, always treat task as standalone
|
|
@@ -88,28 +88,20 @@ To create the best task definition, I need to clarify:
|
|
|
88
88
|
|
|
89
89
|
Skip if requirements are already clear from Step 1.
|
|
90
90
|
|
|
91
|
-
### Step 6:
|
|
91
|
+
### Step 6: Create Standalone Task
|
|
92
92
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
- If non-empty: pass as `assigned_worktree_id` in Step 7. This engages the hard-lock from creation.
|
|
96
|
-
- If empty: warn the user that the task will be unassigned and offer to run `npx codebyplan setup` from the current directory first. After setup, re-resolve and proceed. If the user declines, create without `assigned_worktree_id`.
|
|
97
|
-
|
|
98
|
-
### Step 7: Create Standalone Task
|
|
99
|
-
|
|
100
|
-
Create via the CLI (wraps the `create_standalone_task` MCP tool; auto-resolves `caller_worktree_id`):
|
|
93
|
+
Create via the CLI (wraps the `create_standalone_task` MCP tool):
|
|
101
94
|
|
|
102
95
|
```bash
|
|
103
96
|
codebyplan standalone-task create \
|
|
104
97
|
--title "<concise task title>" \
|
|
105
98
|
--number <next number from Step 3> \
|
|
106
99
|
--requirements "<numbered requirements list>" \
|
|
107
|
-
--context '<JSON: decisions from Q&A + source findings>'
|
|
108
|
-
--assigned-worktree-id <from Step 6, if resolved>
|
|
100
|
+
--context '<JSON: decisions from Q&A + source findings>'
|
|
109
101
|
```
|
|
110
102
|
|
|
111
103
|
- `--repo-id` is optional — the CLI reads it from `.codebyplan/repo.json`.
|
|
112
|
-
-
|
|
104
|
+
- Task assignment is user-based — the server stamps `assigned_user_id` from the JWT on creation; no worktree param is needed.
|
|
113
105
|
- On success the CLI prints the created row JSON (including `.id`) to stdout.
|
|
114
106
|
|
|
115
107
|
```
|
|
@@ -127,7 +119,7 @@ codebyplan standalone-task create \
|
|
|
127
119
|
- Files likely touched: [relevant paths]
|
|
128
120
|
```
|
|
129
121
|
|
|
130
|
-
### Step
|
|
122
|
+
### Step 7: Route
|
|
131
123
|
|
|
132
124
|
```
|
|
133
125
|
Standalone TASK-[N] created successfully.
|
|
@@ -106,20 +106,20 @@ If `current` is still in `branch_config.protected`, block with a hard error citi
|
|
|
106
106
|
1. Run `git status --short` to check for uncommitted files.
|
|
107
107
|
2. If uncommitted files exist → commit them with `chore: clean slate for task start`. Prefer `git add -A && git commit -m "..."`.
|
|
108
108
|
|
|
109
|
-
### Step 3.5:
|
|
109
|
+
### Step 3.5: User-Match Verification
|
|
110
110
|
|
|
111
|
-
Before activating, verify the
|
|
111
|
+
Before activating, verify the current user is allowed to claim/edit the standalone task row.
|
|
112
112
|
|
|
113
|
-
1. `
|
|
114
|
-
2. `
|
|
115
|
-
3. If `
|
|
113
|
+
1. Resolve the current user: `CURRENT_USER=$(npx codebyplan whoami --json 2>/dev/null)` → parse `user_id` and `email` from the JSON. If the command fails or returns null/empty, `CURRENT_USER_ID` is null (anonymous session).
|
|
114
|
+
2. `TARGET_USER = task.assigned_user_id`.
|
|
115
|
+
3. If `TARGET_USER IS NOT NULL AND TARGET_USER != CURRENT_USER_ID`, surface error and abort:
|
|
116
116
|
|
|
117
117
|
```
|
|
118
|
-
Standalone TASK-N is assigned to
|
|
119
|
-
Use the release_assignment MCP tool (requires maintainer role) if
|
|
118
|
+
Standalone TASK-N is assigned to user {TARGET_EMAIL} ({TARGET_USER}); you are logged in as {CURRENT_EMAIL} ({CURRENT_USER_ID}).
|
|
119
|
+
Use the release_assignment MCP tool (requires maintainer role) if that user is no longer active, then re-run /cbp-standalone-task-start.
|
|
120
120
|
```
|
|
121
121
|
|
|
122
|
-
4. If `
|
|
122
|
+
4. If `TARGET_USER IS NULL` or matches `CURRENT_USER_ID`, proceed.
|
|
123
123
|
|
|
124
124
|
### Step 3.6: Main-Drift Check (optional)
|
|
125
125
|
|
|
@@ -150,13 +150,13 @@ Load context from DB:
|
|
|
150
150
|
|
|
151
151
|
### Step 5: Set Task Status
|
|
152
152
|
|
|
153
|
-
Set status via the CLI (wraps `update_standalone_task
|
|
153
|
+
Set status via the CLI (wraps `update_standalone_task`):
|
|
154
154
|
|
|
155
155
|
```bash
|
|
156
156
|
codebyplan standalone-task update --id <task.id> --status in_progress
|
|
157
157
|
```
|
|
158
158
|
|
|
159
|
-
`--id` is the standalone task UUID resolved in Step 2. The
|
|
159
|
+
`--id` is the standalone task UUID resolved in Step 2. The server keys on the JWT user for authz — no worktree or caller params are needed or accepted; all worktree-identity flags are deprecated and silently ignored server-side.
|
|
160
160
|
|
|
161
161
|
### Step 6: Auto-trigger Round Start
|
|
162
162
|
|
|
@@ -146,7 +146,7 @@ Use `codebyplan task create --checkpoint-id <id> ...` (CLI write-through) to cre
|
|
|
146
146
|
- **requirements**: Numbered requirements list
|
|
147
147
|
- **context**: Include decisions from Q&A, dependencies, source findings
|
|
148
148
|
|
|
149
|
-
**For checkpoint-bound tasks**,
|
|
149
|
+
**For checkpoint-bound tasks**, assignment is user-based — the task's `assigned_user_id` is stamped server-side from the JWT; no caller-worktree param is needed.
|
|
150
150
|
|
|
151
151
|
```
|
|
152
152
|
## Task Created
|