Files
fusion/packages/engine
gsxdsm cf6133da8b consolidate/e2e — E2E evidence: already-finalized terminal roles (real merge entry, no git) + ledger corrections (#2648)
Consolidation branch for the E2E-evidence worker. Two commits, both
engine test/comment only — **no production code, census unchanged**.

## Census (the authoritative instrument)

`node scripts/lifecycle-column-census.mjs` on this branch: **triage 10,
total 784** — identical to its base.
`lifecycle-column-census-ast.test.ts` and
`lifecycle-column-census.test.ts` pass (15). This PR neither shrinks nor
grows the backlog; it is evidence.

## What it contains, file by file

| file | change |
|---|---|
|
`packages/engine/src/__tests__/workflow-already-finalized-live-e2e.pg.test.ts`
| **new** — 3 cases, live PG store + real `runAiMerge` |
| `packages/engine/src/__tests__/workflow-lifecycle-live-e2e.pg.test.ts`
| comment only — retires two unproven-ledger entries |

## The evidence: `isAlreadyFinalizedColumn` never needed the real-git
lane

My unproven-sites ledger listed it as requiring a git harness because it
is module-private inside `runAiMerge`. Reading the function instead of
costing the lane: `runAiMerge` reaches it after only `store.getTask`, a
pure workspace assert, and a pure branch resolve — **before** the merge
blocker, settings, and any branch sync. `projectRootDir` is never
touched on that path, and the short-circuit returns a `noOp` rather than
throwing. Reachable through the real public entry point with no
repository at all.

### Why two cases and not one

The guard resolves terminal columns **per role**:

```ts
terminal = [lifecycle.complete ?? "done", lifecycle.archived ?? "archived"]
```

#2471's P1 caught the first cut replacing the whole legacy **pair** as
soon as *any* terminal role resolved — a workflow declaring `complete`
but no `archived` collapsed to one element, silently lost the archived
short-circuit, and an archived card then threw *"must be in
'in-review'"* for a card whose real state was "already done, nothing to
do".

A per-set rule passes for whichever role **is** declared and fails the
other, so a single case cannot tell the two rules apart. The shared
fixture declares `complete` (renamed `shipped`) and **no** `archived`,
so it is exactly that partially-declared shape — resolved half and
fallback half live on one board.

Mutation-verified, each killing only its own case:

| mutation | kills |
|---|---|
| per-**set** replacement (the #2471 defect) | the legacy-`archived`
fallback case |
| legacy pair only (conversion reverted) | the renamed-`shipped` case |

Plus a differential: a renamed **review** card must not report
already-finalized. Without it both cases above would pass for a guard
that finalizes everything — turning every merge into a silent no-op, the
worst failure this function has.

Evidence strength is stated in the file header rather than overclaimed:
this reads a returned **decision**, not a persisted row, so it proves
the renamed board resolves and short-circuits — not that a card moves.

## Ledger corrections (comment only)

Two entries retired, both wrong the same way — each stated a **lane
cost** as if it were an impossibility:

- `columnIsIntakeOrHold` — "consumers are dashboard-side" is true and
irrelevant; its one consumer is an exported pure function. Proven on
merged and renamed boards by work already merged in #2631.
- `register-task-workflow-routes.ts` — "standing up the route shell is
mock-the-world" was false; `createApiRoutes` + `test-request.js` is this
repo's established convention with ten existing suites for that file.
Covered by its owner in #2614.

Counting this PR's own subject, that is **seven** wrong lane-cost
inferences in that ledger. The rule it keeps violating is unchanged and
now recorded in the file: read what the FUNCTION touches before costing
a lane for it.

## Verification

`pnpm test:gate` exit 0 (695), `pnpm lint` exit 0, engine typecheck
clean, 28 tests green across the AST ratchet and the three
merged-board/planner-lane/already-finalized families.

## Not in scope here

The `performWorkflowRerunBounce` E2E. The harness exists (`new
TaskExecutor(store, "/tmp/test", {})`), but `executor.ts:4305` gates the
rebound on the legacy `in-progress`/`in-review` pair while resolving its
target by role — so on a renamed board the bounce never fires and the
resolved target is unreachable. An E2E asserting today's behaviour would
cement that. It is executor.ts's owner's fix; evidence should follow it.
Detail in #2632's thread.

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 00:27:30 -07:00
..
2026-07-26 18:11:47 -07:00