Tags: kamp-us/phoenix
Tags
fix(ship-it): never park a `--auto` merge intent — clear it on every … …path that does not enqueue (#3723) (#3774) * fix(ship-it): never park a `--auto` merge intent — clear it on every path that does not enqueue (#3723) A `gh pr merge --auto` left armed by an earlier or interrupted ship-it run survives a rebase + re-review and fires the instant a fresh control-plane approval lands, so GitHub enqueues a §CP PR *before* the ship-it run that asserts the machine gates has started (PR #3700: `added_to_merge_queue` one second after the approving review). The approval requirement still holds — the defect is ordering: the current-head verdicts, the SHA-bound run-evidence bundle, the leak scan and the unresolved-thread check can all be skipped at the decisive instant. The enqueue primitive is unchanged. What is added is a lifecycle invariant (ADR 0198): an armed merge intent may exist only between a fully-gated Step-4 enqueue and the queue accepting the PR. Four mandated sites clear it — run start (catches the interrupted run), every STOP/refusal, a merge-queue ejection, and a post-reconcile enqueue that never took effect. A live queue entry is never disturbed, and a repo with no merge queue keeps its legitimate armed auto-merge. - new `pipeline-cli merge-intent disarm`: the branch in a pure, unit-tested core; the `gh` IO in a service that verifies the clear by re-reading `auto_merge` (the `--disable-auto` exit code is non-zero both when it fails and when nothing was armed, so it cannot carry the guarantee). Fail-closed: an unreadable arm state disarms, an unprovable clear exits 1. - ship-it: guard 6 + the invariant section, the four sites wired in, and a refusal ledger that names an uncleared intent instead of reporting a clean stop. Fixes #3723 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(merge-intent): key the pre-queue exemption on the base branch's regime, fail closed on the probe Repairs the three current-head FAIL verdicts on PR #3774. The `post-enqueue` exemption keyed on `everQueued`, a per-PR fact — but the property it is for ("this repo has no merge queue, so `--auto` IS the enqueue mechanism") is a property of the base branch. Under a merge queue every PR on its FIRST enqueue attempt has no queue history, so the exemption fired exactly where the parked intent lives: arm at Step 4, no queue acceptance inside the reconcile budget, reconcile -> pending -> keep, run ends with the arm outliving it. Now the predicate is a `merge_queue` rule on `GET /repos/{repo}/rules/branches/{branch}`. Same root closed the fail-open path: the regime read recovers every fault to `queueGoverned: true`, so an unreadable probe can never reach the keep. `readQueue` split into `readQueued` (live membership, unchanged reasoning) and `readQueueGoverned`. ship-it/SKILL.md: `disarm_intent preflight` is now wired at Step 0 on the line after `PR=` (previously it appeared only in the preamble block, which runs before $PR/$REPO exist — so the site that catches the interrupted run was never called). The Site-2 enumeration now leads with the rule and names the paths it omitted (Step 2 guard 1's FAIL stop, Step 1's draft/closed/no-linked-issue), and those sites plus the three prose-wired ones use the coded `|| INTENT_UNCLEARED=1` form so a failed disarm always reaches the refusal ledger. ADR 0198 rewritten (immutable-once-landed, so before merge): the Consequences no longer claim the approval is inert for a never-yet-queued PR, the Decision separates "a repo with no queue" from "a PR the queue has not governed", and the fail-closed section covers both reads. Number 0198 kept. Comment discipline: `merge-intent.ts` and `command.ts` docblocks collapsed to pointers; the README's why and `decideMergeIntent`'s precedence docblock kept. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
docs(adr): 0197 — crew rendezvous is per-repo canonical, keyed on the… … shared git dir (#3747) Records the founder ruling on #3626: Option B (per-repo canonical rendezvous); machine-global is out, since the crew will run across many repos on one machine. The load-bearing constraint: `canonical` resolves to the main checkout's shared git dir (`--git-common-dir`), never a worktree's `--show-toplevel` — write-code runs in isolation:worktree and each worktree has a distinct toplevel, so keying on it would re-create the cwd-split bug. Closes #3626 Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
feat(epic-ledger,repo): repo-agnostic gate (#408) + @kampus scope rep… …o-wide (#404) (#413) #408 — epic-ledger gate no longer hardcodes kamp-us/phoenix. The target repo is resolved once at the Github layer build (ADR 0062 §1): CLAUDE_PIPELINE_REPO → GITHUB_REPOSITORY → `gh repo view`, captured in the closure for all 5 URL builders. Fails RepoResolutionError when nothing resolves — never a silent phoenix default. Bumps the package to 0.1.2; adds resolution-order test coverage. #404 — renames the remaining 6 @phoenix/* packages (web, dashboard, fate-effect, leak-guard, crabbox-manifest, infra) and every live reference to the @kampus/* scope, so the repo speaks one scope (epic-ledger was already @kampus from #366). Pure rename, no behavior change: worker/stack names are string literals decoupled from package names. Only historical ADR prose in .decisions/** keeps @phoenix/. Fixes #404 Fixes #408 Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
fix(epic-ledger): ship compiled ESM dist, not raw .ts (fixes #405) (#407 ) Published @kampus/epic-ledger@0.1.0 shipped bin/exports pointing at ./src/*.ts with files:["src"] and no build, so any consumer under node_modules crashed with ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING (Node won't strip TS types under node_modules). The package now compiles src/ → ESM dist/ and ships dist only. - add tsconfig.build.json (extends tsconfig.json): noEmit:false, rootDir/outDir, declaration + maps, rewriteRelativeImportExtensions (.ts imports → .js in emit), excludes tests + fixtures. tsc emit keeps runtime deps external (no bundling). - package.json: bin → ./dist/bin.js, exports → {types,import} dist, main/module/types → dist, files → ["dist"]; add build + prepublishOnly scripts; bump 0.1.0 → 0.1.1 (0.1.0 is published-immutable). The in-repo `gate` script stays node src/bin.ts. - publish workflow: explicit build step before npm publish. Version-guard unchanged; it now expects tag epic-ledger-v0.1.1 ↔ package.json 0.1.1. dist/bin.js keeps the shebang and runs clean; npm-pack→install→run from node_modules no longer hits the type-stripping error. In-repo node src/bin.ts --help still works. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>