codebyplan 1.13.35 → 1.13.37

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 CHANGED
@@ -14,7 +14,7 @@ var VERSION, PACKAGE_NAME;
14
14
  var init_version = __esm({
15
15
  "src/lib/version.ts"() {
16
16
  "use strict";
17
- VERSION = "1.13.35";
17
+ VERSION = "1.13.37";
18
18
  PACKAGE_NAME = "codebyplan";
19
19
  }
20
20
  });
@@ -5677,6 +5677,13 @@ function defaultPrBody(feat, base) {
5677
5677
  Merge \`${feat}\` \u2192 \`${base}\`.
5678
5678
  `;
5679
5679
  }
5680
+ function evaluateChecks(checks) {
5681
+ const failed = checks.filter(
5682
+ (c) => c.bucket !== "pass" && c.bucket !== "skipping" && c.bucket !== "pending"
5683
+ ).map((c) => c.name);
5684
+ const pending = checks.filter((c) => c.bucket === "pending").length;
5685
+ return { passed: failed.length === 0 && pending === 0, failed, pending };
5686
+ }
5680
5687
  async function pollChecks(feat, timeoutSeconds, cwd, _sleepMs = (ms) => new Promise((r) => setTimeout(r, ms))) {
5681
5688
  const deadline = Date.now() + timeoutSeconds * 1e3;
5682
5689
  const POLL_INTERVAL_MS = 15e3;
@@ -5689,7 +5696,7 @@ async function pollChecks(feat, timeoutSeconds, cwd, _sleepMs = (ms) => new Prom
5689
5696
  while (Date.now() < deadline) {
5690
5697
  const ghResult = spawnSync6(
5691
5698
  "gh",
5692
- ["pr", "checks", feat, "--json", "name,state,conclusion"],
5699
+ ["pr", "checks", feat, "--json", "name,state,bucket"],
5693
5700
  {
5694
5701
  cwd,
5695
5702
  encoding: "utf-8",
@@ -5727,17 +5734,14 @@ async function pollChecks(feat, timeoutSeconds, cwd, _sleepMs = (ms) => new Prom
5727
5734
  return { passed: true };
5728
5735
  }
5729
5736
  iteration++;
5730
- const pending = checks.filter(
5731
- (c) => c.state === "PENDING" || c.state === "QUEUED" || c.state === "IN_PROGRESS"
5732
- );
5733
- const failed = checks.filter(
5734
- (c) => c.state === "COMPLETED" && c.conclusion !== null && c.conclusion !== "SUCCESS" && c.conclusion !== "NEUTRAL" && c.conclusion !== "SKIPPED"
5735
- );
5736
- if (failed.length > 0) {
5737
- const names = failed.map((c) => c.name).join(", ");
5738
- return { passed: false, reason: `Checks failed: ${names}` };
5737
+ const result = evaluateChecks(checks);
5738
+ if (result.failed.length > 0) {
5739
+ return {
5740
+ passed: false,
5741
+ reason: `Checks failed: ${result.failed.join(", ")}`
5742
+ };
5739
5743
  }
5740
- if (pending.length === 0) {
5744
+ if (result.pending === 0) {
5741
5745
  return { passed: true };
5742
5746
  }
5743
5747
  await _sleepMs(POLL_INTERVAL_MS);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codebyplan",
3
- "version": "1.13.35",
3
+ "version": "1.13.37",
4
4
  "description": "CLI for CodeByPlan — AI-powered development planning and tracking",
5
5
  "type": "module",
6
6
  "bin": {
@@ -8,7 +8,7 @@ This file is the **consumer contract** for DocsByPlan: what the MCP tools are, w
8
8
 
9
9
  ## What DocsByPlan Is
10
10
 
11
- A DB-backed, version-aware library-doc retrieval service exposed via MCP at `codebyplan.com/mcp`. It replaces the retired `vendor/` filesystem mirror. Docs are ingested by the `apps/docs-ingest` worker, chunked and ranked by trust score, and served to agents on demand. The DB is the sole source of truth — there are no local files to read.
11
+ A DB-backed, version-aware library-doc retrieval service exposed via MCP at `mcp.codebyplan.com/mcp`. It replaces the retired `vendor/` filesystem mirror. Docs are ingested by the `apps/docs-ingest` worker, chunked and ranked by trust score, and served to agents on demand. The DB is the sole source of truth — there are no local files to read.
12
12
 
13
13
  Purpose: Claude (planner + executor agents + the orchestrator) consults DocsByPlan **before** writing library-specific code, so that:
14
14
 
@@ -133,7 +133,7 @@ This file answers one question for one audience: **"As an agent (planner or exec
133
133
  |---------|-----------|
134
134
  | Ingest pipeline | `apps/docs-ingest` |
135
135
  | Register a new library | `/cbp-add-library {pkg}` |
136
- | MCP tool endpoint | `codebyplan.com/mcp` |
136
+ | MCP tool endpoint | `mcp.codebyplan.com/mcp` |
137
137
  | Loading rule registration | `.claude/rules/context-file-loading.md` (Phase 2.6 / Step 3.4 mapping rows) |
138
138
  | Planner integration | `packages/codebyplan-package/templates/agents/task-planner.md` Phase 2.6 |
139
139
  | Executor integration | `packages/codebyplan-package/templates/agents/round-executor.md` Step 3.4 |
@@ -10,6 +10,7 @@ paths:
10
10
  - ".claude/skills/cbp-checkpoint-end/**"
11
11
  - ".claude/skills/cbp-git-worktree-remove/**"
12
12
  - ".claude/skills/cbp-ship-main/**"
13
+ - ".claude/skills/cbp-standalone-task-complete/**"
13
14
  ---
14
15
 
15
16
  # Supabase Branch Lifecycle
@@ -50,6 +51,7 @@ The Supabase branch is removed wherever the git branch is deleted:
50
51
  | `cbp-checkpoint-end` | stale-branch cleanup + current feat-branch delete on ship |
51
52
  | `cbp-git-worktree-remove` | worktree teardown removes the coupled Supabase branch |
52
53
  | `cbp-ship-main` | `branch_deleted` event after PR merge |
54
+ | `cbp-standalone-task-complete` | `branch_deleted` event after standalone PR merge (Step 7.3) |
53
55
 
54
56
  Deletion is **existence-checked and idempotent** — a not-found response is treated as
55
57
  success. This tolerates the GitHub integration auto-deleting the preview branch on PR
@@ -93,7 +95,7 @@ or auto-created by the GitHub integration — both paths use the same branch nam
93
95
  | Role | Skill |
94
96
  |---|---|
95
97
  | Create (lazy) | `cbp-supabase-migrate` (Step 2.3) |
96
- | Delete | `cbp-checkpoint-end`, `cbp-git-worktree-remove`, `cbp-ship-main` |
98
+ | Delete | `cbp-checkpoint-end`, `cbp-standalone-task-complete`, `cbp-git-worktree-remove`, `cbp-ship-main` |
97
99
  | PR gate | `cbp-supabase-branch-check` |
98
100
 
99
101
  Each skill in the Skill Map above carries an inline back-reference to this rule at its create or teardown step.
@@ -38,6 +38,24 @@ Write to `/tmp/cbp-ship-main-body.md`:
38
38
  - /cbp-checkpoint-check passed
39
39
  ```
40
40
 
41
+ ### Step 2.5: Supabase Branch Pre-Merge Gate
42
+
43
+ **PR-existence pre-check** — `codebyplan ship` (Step 3) is what pushes the branch and creates the PR, so on the FIRST ship of a branch no PR exists yet and a `pre_merge` gate would self-defeatingly block the very step that creates it. Probe first:
44
+
45
+ ```bash
46
+ PR_EXISTS=$(gh pr list --head "$(git branch --show-current)" --json number --jq 'length' 2>/dev/null || echo 0)
47
+ ```
48
+
49
+ - `PR_EXISTS` is `0` → skip this gate and proceed directly to Step 3 with a one-line note: `Supabase pre-merge gate skipped (no PR yet) — the generic check-poll inside codebyplan ship gates Supabase Preview as a required check.`
50
+ - `PR_EXISTS` ≥ `1` → run the gate: invoke the `cbp-supabase-branch-check` skill with `--mode pre_merge --target production` and parse the fenced JSON block it emits (`status`, `reason`, optional `failed_step` / `log_excerpt`).
51
+
52
+ Gate dispositions:
53
+
54
+ - `status: "passed"` or `status: "skipped"` → proceed to Step 3.
55
+ - `status: "blocked"` or `status: "pending_pr"` → surface `reason` (plus `failed_step` and `log_excerpt` when present) and STOP — do NOT invoke `codebyplan ship`.
56
+
57
+ **Dual-gate note**: this dedicated gate adds DB-failure diagnostics (`failed_step`, `log_excerpt` pulled from Supabase logs) that the generic check-poll inside `codebyplan ship` cannot produce. The generic poll (`pollChecks` → `evaluateChecks` in `src/lib/ship.ts`, gh bucket model) still runs after PR creation and gates Supabase Preview as one required check among all checks — the two gates are complementary, not redundant.
58
+
41
59
  ### Step 3: Invoke `codebyplan ship`
42
60
 
43
61
  ```bash
@@ -53,7 +71,7 @@ Pass `--dry-run` through if the skill was invoked with a dry-run arg.
53
71
 
54
72
  Parse JSON from Step 3. Report `pr_url`, `merge_commit`, `branch_deleted`. If `checks_failed: true`, surface `checks_failure_reason` and stop.
55
73
 
56
- > **gh false-negative workaround.** `codebyplan ship` can report `checks_failed: true` when the underlying `gh` query reads a stale/mismatched check field (it queries `conclusion`/`state` and the GitHub API can lag). Before treating the stop as final, verify the real status: `gh pr checks <PR> --watch`. If every required check is green, merge manually with `gh pr merge <PR> --merge` — add `--admin` ONLY to escape a transient secondary-rate-limit loop, never to bypass a genuinely-failing gate. Never auto-merge silently on a `checks_failed` report; this verification is a manual decision.
74
+ > **gh false-negative workaround.** `codebyplan ship` can report `checks_failed: true` when the underlying `gh` query reads a stale/mismatched check field (the poller queries the gh `bucket` field — `pass|fail|pending|skipping|cancel` — and fail-safe-blocks anything outside `pass`/`skipping`, so an API lag or an unrecognized bucket reads as a failure). Before treating the stop as final, verify the real status: `gh pr checks <PR> --watch`. If every required check is green, merge manually with `gh pr merge <PR> --merge` — add `--admin` ONLY to escape a transient secondary-rate-limit loop, never to bypass a genuinely-failing gate. Never auto-merge silently on a `checks_failed` report; this verification is a manual decision. (A `checks_failed` at this stage most likely pertains to a non-Supabase-Preview check — Supabase Preview was already gated in Step 2.5 when a PR pre-existed. If `gh pr checks <PR> --watch` shows Supabase Preview itself failing, investigate via `cbp-supabase-branch-check`'s `failed_step`/`log_excerpt` diagnostics before treating it as a false negative.)
57
75
 
58
76
  If `bumps[]` is present with any non-skipped entry, surface a **Version bumps** line per package — `<name>: <currentVersion> → <nextVersion>` — so the user sees what this PR will publish on merge.
59
77
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  scope: repo-only:codebyplan
3
3
  name: cbp-standalone-task-complete
4
- description: Complete a standalone task — merge feat branch and mark done
4
+ description: Complete a standalone task — ship feat branch to production via PR and mark done
5
5
  argument-hint: [task] # e.g. `45` (standalone TASK-45)
6
6
  effort: xhigh
7
7
  ---
@@ -125,24 +125,60 @@ Skip only when nothing was committed AND `/cbp-merge-main` reported already-up-t
125
125
 
126
126
  `update_standalone_task(task_id, context: { ...existing, files_changed: aggregated_files })`.
127
127
 
128
- ### Step 7: Standalone Task Branch Merge
128
+ ### Step 7: Standalone Task Branch Ship
129
129
 
130
130
  Only when current branch matches `feat/standalone-TASK-*`:
131
131
 
132
- 1. Read `.codebyplan/git.json` `branch_config.production` (default: `main`). Store as `PRODUCTION`.
133
- 2. `git checkout {PRODUCTION}`
134
- 3. `git merge {feat-branch} --no-ff -m "Merge {feat-branch}: {task title}"`
135
- 4. `git push origin {PRODUCTION}`
136
- 5. Delete feat branch local: `git branch -d {feat-branch}`
137
- 6. Delete feat branch remote: `git push origin --delete {feat-branch}`
132
+ #### Step 7.1 Compose PR body
138
133
 
139
- If merge has conflicts, stop immediately and ask the user to resolve. Do not delete the feat branch until the merge succeeds and is pushed.
134
+ Write `/tmp/cbp-ship-body-standalone-{N}.md`:
140
135
 
141
- If current branch is not `feat/standalone-TASK-*`, skip this step.
136
+ ```markdown
137
+ ## Summary
138
+
139
+ {standalone_task.title}
140
+
141
+ Standalone TASK-{N}
142
+
143
+ ## Test Plan
144
+
145
+ - All rounds passed testing-qa
146
+ - /cbp-standalone-task-check passed
147
+ ```
148
+
149
+ #### Step 7.2 — Invoke `codebyplan ship`
150
+
151
+ ```bash
152
+ codebyplan ship --body-file /tmp/cbp-ship-body-standalone-{N}.md --json
153
+ ```
154
+
155
+ `codebyplan ship` patch-bumps every changed workspace package and commits `chore(release): bump versions` on the feat branch BEFORE creating the PR, so the bump rides this same feat→main PR. Pass `--no-bump` for infra/doc-only standalone work where a version bump is not appropriate.
156
+
157
+ `codebyplan ship` pushes the feat branch, gets-or-creates the PR, polls required checks (including Supabase Preview) via the gh bucket model (`pollChecks` → `evaluateChecks` — pass|fail|pending|skipping|cancel; only pass/skipping are non-blocking), merges with `gh pr merge --merge`, checks out the base branch, and deletes the feat branch.
158
+
159
+ **On `checks_failed: true`**: surface `checks_failure_reason` and STOP — do NOT proceed to Step 7.5 (`complete_standalone_task` is never called on a failed ship).
160
+
161
+ > **gh false-negative workaround.** `codebyplan ship` can report `checks_failed: true` when the underlying `gh` query reads a stale/mismatched check field. Before treating the stop as final, verify with `gh pr checks <PR> --watch`. If every required check is genuinely green, merge manually with `gh pr merge <PR> --merge`. Never auto-merge silently on a `checks_failed` report — this verification is a manual decision.
162
+
163
+ Parse the JSON output and store: `pr_url`, `merge_commit`, `branch_deleted`, `feat_branch`, `checks_failed`, `checks_failure_reason`, `bumps[]`.
164
+
165
+ #### Step 7.3 — Supabase preview-branch teardown
166
+
167
+ > Lifecycle contract: see [[supabase-branch-lifecycle]].
168
+
169
+ When `branch_deleted === true` in the ship JSON:
170
+
171
+ - Read `FEAT_BRANCH` from the `feat_branch` field in the ship JSON — NOT from `git branch --show-current`. By the time Step 7.3 runs, `codebyplan ship` has already checked out the base branch, so the live branch is the base, not the feat branch.
172
+ - Call `mcp__supabase__list_branches` with `project_id: rrvtrumtkhrsbhcyrwvf`.
173
+ - Scan the returned list for an entry whose `name` exactly equals `FEAT_BRANCH`.
174
+ - If found: call `mcp__supabase__delete_branch` with its `branch_id`. Report the outcome.
175
+ - If not found: no-op silently — the GitHub integration may have already removed the preview branch on PR close; not-found is success, NOT an error.
176
+ - If the `list_branches` call itself fails (network, auth, or non-success response): emit a non-blocking warning that the Supabase preview branch for `FEAT_BRANCH` may still exist and should be verified in the dashboard. Never treat an API failure as a not-found success.
177
+ - Never delete the parent project `rrvtrumtkhrsbhcyrwvf` itself or any persistent/production branch.
142
178
 
143
179
  ### Step 7.5: Complete Standalone Task
144
180
 
145
- Note: `complete_standalone_task` is called only after the branch merge succeeds — the DB completion record reflects work that has landed in production.
181
+ Note: `complete_standalone_task` is called only after `codebyplan ship` succeeds (no `checks_failed`) — the DB completion record reflects work that has landed in production.
146
182
 
147
183
  Resolve caller worktree: `CALLER_WT=$(npx codebyplan resolve-worktree 2>/dev/null)`.
148
184
 
@@ -168,7 +204,10 @@ Apply the `cleanup` skill inline to remove orphan references to deleted/modified
168
204
  **Rounds**: [N] completed
169
205
  **Files**: [N] changed
170
206
  **Commit**: [hash]
171
- **Branch merged**: [feat-branch] → {PRODUCTION}
207
+ **PR**: [pr_url]
208
+ **Merge commit**: [merge_commit]
209
+ **Branch deleted**: [branch_deleted]
210
+ **Version bumps**: [<name>: <current> → <next> per package, or "none"]
172
211
  **Warnings**: [any QA / file-approval warnings from Step 3, or "none"]
173
212
  ```
174
213
 
@@ -187,7 +226,7 @@ Do NOT use AskUserQuestion for routing. Do NOT use the Skill tool to auto-trigge
187
226
  ## Key Rules
188
227
 
189
228
  - **`caller_worktree_id` is REQUIRED** for `complete_standalone_task`
190
- - **Branch merge lives here** (not in checkpoint-end) — standalone tasks self-ship to production
229
+ - **Branch shipping lives here** (not in checkpoint-end) — standalone tasks self-ship to production via `codebyplan ship`
191
230
  - **Single-directive routing** — no menus, no auto-triggers via Skill tool
192
231
  - **No checkpoint** — never check `checkpoint_id`, always treat task as standalone
193
232
  - **Never skippable prerequisites** — check_verdict READY + task_testing_output all_passed required
@@ -196,6 +235,7 @@ Do NOT use AskUserQuestion for routing. Do NOT use the Skill tool to auto-trigge
196
235
 
197
236
  - **Triggered by**: `/cbp-standalone-task-testing` emits directive (user runs it manually after seeing directive)
198
237
  - **Chain**: `/cbp-standalone-task-check` → `/cbp-standalone-task-testing` → `/cbp-standalone-task-complete`
238
+ - **Delegates to**: `codebyplan ship` CLI (Step 7 — PR creation, check polling, merge, branch cleanup)
199
239
  - **Reads**: MCP `get_current_standalone_task`, `get_standalone_tasks`, `get_standalone_rounds`
200
240
  - **Writes**: MCP `update_standalone_task`, `complete_standalone_task`
201
241
  - **Uses skills (inline, no sub-agent)**: `cleanup` (if deletions), `migration` (if exports renamed)
@@ -57,7 +57,7 @@ Invalid --mode value: <value>. Valid values: pre_pr_create, pre_merge.
57
57
 
58
58
  Infer `TARGET` when absent:
59
59
  - `pre_pr_create` → `integration`
60
- - `pre_merge` → detect via `gh pr view --json baseRefName --jq '.baseRefName'`; fallback to `integration` if no PR is open.
60
+ - `pre_merge` → detect via `gh pr view --json baseRefName --jq '.baseRefName'`; fallback to `integration` if no PR is open. Production-ship callers (e.g. `cbp-ship-main` Step 2.5) should pass `--target production` explicitly rather than rely on auto-detect.
61
61
 
62
62
  ## Step 1 — Read DB Paths Config
63
63
 
@@ -339,5 +339,6 @@ Both emit `status: passed` so callers proceed; the `reason` differs for traceabi
339
339
 
340
340
  ## Integration
341
341
 
342
- **Callers**: `/cbp-ship-main` invokes this skill pre-merge (mode=`pre_merge`, target=`production`, no override).
342
+ **Callers**: `cbp-ship-main` Step 2.5 invokes this skill pre-merge (`--mode pre_merge --target production`, only when a PR already exists for the branch); the caller proceeds on `passed` (Supabase Preview check green — including the CI-level `skipping` bucket, which Step 8 maps to `passed`) and `skipped` (no DB-path changes detected — the gate did not apply), and stops on `blocked`/`pending_pr`. Note: `status: "skipped"` is NOT the CI `skipping` bucket — the two are distinct layers.
343
+ **Canonical bucket contract**: the gh-checks bucket vocabulary used in Step 6 — `pass|fail|pending|skipping|cancel` — is the single canonical contract shared with `evaluateChecks()` in `packages/codebyplan-package/src/lib/ship.ts` (the generic poller inside `codebyplan ship`). Only `pass`/`skipping` are non-blocking, `pending` waits, and every other disposition blocks (fail-safe). The two pollers MUST NOT drift — any change to this enum or its dispositions must land in both places.
343
344
  **Tools used**: `mcp__supabase__list_branches` for project_ref resolution; `mcp__supabase__get_logs` for failure diagnostics; `gh pr checks` for status polling; `supabase --experimental branches get` as CLI fallback.