docs(U9): correct merge-stack slice statuses to measured wiring state (#2504)

**U9, PR2.** Docs-only, no changeset (AGENTS.md: internal docs).

## Why

All seven slices in `docs/plans/workflow-owned-merge-stack/` were marked
`draft-stack-handoff` — accurate when drafted 2026-06-09, wrong now. **A
worker picking up this stack cold would have re-implemented S04, which
has already landed.** I nearly did.

## Measured, against `main @ 46f35323c`

| Slice | Was | Now | Evidence |
|---|---|---|---|
| S02 projection | draft | `landed-unwired` |
`projectMergeRequestToWorkflowWorkItem` implemented, **0 production
callers** |
| S03 scheduler claim | draft | `landed-unwired` |
`claimDueWorkflowWorkItem` implemented; its only caller is S05's
processor, itself unwired |
| S04 IR regions | draft | **`landed`** | `merge-gate`, `merge-retry`,
`manual-merge-hold`, `merge-attempt`, `recovery-router` present in the
coding IR |
| S05 runtime driver | draft | `landed-unwired` | `runWorkItem` /
`processDueWorkflowWorkItem` implemented, exported from `index.ts`, **0
production callers** |
| S06/S07/S08 | draft | `not-started` | merge still runs through
`merger.ts` + the live `ProjectEngine.mergeQueue` pump |

## The finding that changes U9's sequencing

`WorkflowWorkItemKind` is `task | merge | retry | manual-hold |
recovery`. The only live pump —
`InProcessRuntime.drainWorkflowContinuations` — filters `kinds:
["task"]`. The generic processor that would claim the other four kinds
has **no production caller**.

So the entire merge-lane work-item vocabulary is dormant: **zero
writers, zero readers.**

**I checked whether this is a live bug and it is not.** Nothing in
production writes a non-`task` kind — the only two writers
(`plan-review-continuation.ts`, `workflow-column-boundary-hooks.ts`)
both go through `replaceActiveTaskWorkflowContinuation`. Nothing is
stranded today. I'd rather say that plainly than let a scary-sounding
finding stand unqualified.

But it produces a hard ordering constraint, now recorded in S07:

> **S07 must not land before S03/S05 are actually driven.** S07 is the
slice that starts writing `merge`-kind work items. If it lands first,
those items are created and never claimed — a card that reaches the
merge boundary and silently stops.

This also reframes U9's job on S02/S03/S05: **wire them, don't build
them.**

## Scope discipline

Docs-only — `git diff --stat` is 9 files, all under `docs/`. No
production code, no tests, no behavior. `pnpm lint` clean.

I also fixed the three parent-plan lines asserting the slices are "all
still `draft-stack-handoff`", and the four landed slices' Stack Role
paragraphs that would otherwise contradict their own new Measured State
block. Leaving those stale would recreate exactly the defect this PR
fixes.

Related: #2494 pins the S04 caveat — the IR regions are declared but
their config is read by nothing.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **Documentation**
- Updated workflow-owned merge planning documents with current
implementation and wiring statuses.
- Added measured wiring details showing which workflow capabilities are
active, implemented but unused, or not started.
- Clarified sequencing requirements to ensure merge processing is not
enabled before prerequisite workflow paths are operational.
- Corrected slice metadata and references to reflect the latest measured
state.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-07-28 17:15:16 -07:00
committed by GitHub
parent 46f35323cf
commit 6ee20d9817
9 changed files with 145 additions and 31 deletions

View File

@@ -102,7 +102,7 @@ The durable substrate already exists (`workflow_work_items` with leases and stat
Triage discovers and seeds; the executor supplies primitives and node runners; the reviewer and merger expose capabilities. Node behavior moves to runners, policy moves to the IR. The vocabulary for this already exists in `CONCEPTS.md` — Workflow Runtime Primitive, Node Runner, Workflow Service — so this is completing a stated architecture, not inventing one.
**KTD-5. Adopt the existing workflow-owned merge design; do not redesign it.**
`docs/plans/2026-06-09-003-refactor-workflow-owned-merge-full-migration-slices-plan.md` (status `active`) already specifies the merge lane's target state and slices it S02–S08 in `docs/plans/workflow-owned-merge-stack/` — all still `draft-stack-handoff`. Its target state ("workflow IR/runtime owns merge policy, retry policy, scheduling policy, recovery routing, and git operation flow; the engine keeps substrate") is exactly this program's R4 for the merge lane. U9 sequences and lands those slices rather than authoring a parallel design.
`docs/plans/2026-06-09-003-refactor-workflow-owned-merge-full-migration-slices-plan.md` (status `active`) already specifies the merge lane's target state and slices it S02–S08 in `docs/plans/workflow-owned-merge-stack/`. **Their statuses were corrected 2026-07-28** after a U9 pre-flight audit: S04 has LANDED, S02/S03/S05 are implemented but have zero production callers, and only S06–S08 are genuinely not started. Its target state ("workflow IR/runtime owns merge policy, retry policy, scheduling policy, recovery routing, and git operation flow; the engine keeps substrate") is exactly this program's R4 for the merge lane. U9 sequences and lands those slices rather than authoring a parallel design.
**KTD-6. Delete the parity machinery rather than update it — but only what is provably dead.**
`isWorkflowColumnsEnabled` returns a literal `true` with 8 live branches reading it. `workflow-parity.ts` asserts the default workflow's adjacency equals the legacy `VALID_TRANSITIONS`; once the default deliberately diverges, that assertion is not stale — it is wrong, and updating it would re-encode the shape we chose to break. Both are safe deletions.
@@ -470,7 +470,7 @@ The measurable goal is that the executor stops deciding *what happens next* —
**Files:** `packages/engine/src/merger.ts`, `packages/engine/src/merger-ai.ts`, `packages/engine/src/reviewer.ts`, `packages/engine/src/merge-trait.ts`, `packages/engine/src/auto-merge-finalization.ts`, `packages/engine/src/pr-nodes.ts`, plus the merge/review test suites
**Approach:** Adopt `docs/plans/2026-06-09-003-refactor-workflow-owned-merge-full-migration-slices-plan.md` and its S02–S08 slices (`docs/plans/workflow-owned-merge-stack/`, all `draft-stack-handoff`) rather than authoring a parallel design (KTD-5). Sequence them behind U8 so the merge lane converts onto an executor that is already substrate. The reviewer follows the same shape as the planning service: a capability the graph's review nodes call.
**Approach:** Adopt `docs/plans/2026-06-09-003-refactor-workflow-owned-merge-full-migration-slices-plan.md` and its S02–S08 slices (`docs/plans/workflow-owned-merge-stack/`) rather than authoring a parallel design (KTD-5). **Re-measure before sequencing:** S04 landed and S02/S03/S05 are built-but-undriven, so U9's job on those is to WIRE them, not to build them — see `docs/workflow-policy-ownership-map.md` → "Measured Wiring State". Sequence them behind U8 so the merge lane converts onto an executor that is already substrate. The reviewer follows the same shape as the planning service: a capability the graph's review nodes call.
**S1 prerequisite — already landed.** *(PR #2463 review — greptile P1.)* S02 and S03 declare a direct dependency on S1 (workflow work-item schema + store API), and every later slice depends on it transitively. S1 is **in main**: the schema ships in `packages/core/src/postgres/migrations/0031_workflow_task_continuations.sql` and the store API (`listDueWorkflowWorkItems`, `acquireWorkflowWorkItemLease`, `transitionWorkflowWorkItem`, `replaceActiveTaskWorkflowContinuation`) is live and already drives the plan-review continuation path. Verify this at the start of U9 rather than assuming it — if any slice reaches for a store method that does not exist, land that gap as S1-completion work before continuing.
@@ -614,7 +614,7 @@ The measurable goal is that the executor stops deciding *what happens next* —
- `docs/solutions/architecture-patterns/workflow-node-column-placement-and-graph-entry-contract.md` — the entry contract, the plan-in-place chain, and the measured failure table from three reverted attempts.
- `docs/plans/2026-07-21-001-fix-truthful-workflow-lifecycle-plan.md` — the five-column contract and suspend/resume protocol. Its R18 deferred "migrating `builtin:coding` node placement"; this plan is that deferred work.
- `docs/plans/2026-06-09-003-refactor-workflow-owned-merge-full-migration-slices-plan.md` (`status: active`) and `docs/plans/workflow-owned-merge-stack/` S02–S08 (all `draft-stack-handoff`) — the merge lane's existing target state and slices, adopted by U9 per KTD-5.
- `docs/plans/2026-06-09-003-refactor-workflow-owned-merge-full-migration-slices-plan.md` (`status: active`) and `docs/plans/workflow-owned-merge-stack/` S02–S08 (statuses corrected 2026-07-28; see each slice's Measured State block) — the merge lane's existing target state and slices, adopted by U9 per KTD-5.
- `CONCEPTS.md` — Column, Column Trait, Hold, Slot, Workflow Runtime Primitive, Node Runner, Workflow Service. The Task entry enumerating the six legacy columns needs updating in U12.
- `STRATEGY.md` — the orchestration-layer approach; a workflow that actually drives the lifecycle is the product claim this program makes true.
- Session measurement (2026-07-26): 82 column guards, 43 column writes, 59 dashboard literals; `isWorkflowColumnsEnabled` returns a literal `true` with 8 live branches; `workflow-parity.ts` asserts equality with the legacy transition graph; lane service sizes as tabulated in Problem Frame.

View File

@@ -1,7 +1,8 @@
---
title: "S02: merge request projection onto work items"
type: refactor
status: draft-stack-handoff
status: landed-unwired
measured_against: "main @ 46f35323c (2026-07-28)"
date: 2026-06-09
slice: S02
milestone: "Foundation"
@@ -11,11 +12,18 @@ stack_base: feature/workflow-owned-merge-retry-scheduling-plan
# S02: merge request projection onto work items
## Measured State (2026-07-28, U9 pre-flight)
`projectMergeRequestToWorkflowWorkItem` is implemented in `packages/core/src/task-store/workflow-workitems-ops.ts` and has **zero production callers**. The projection exists; nothing invokes it.
Status corrected from `draft-stack-handoff`, which was accurate when drafted on
2026-06-09 and is not now. See `docs/workflow-policy-ownership-map.md` →
"Measured Wiring State" for the whole-stack table.
## Stack Role
This draft PR reserves the S02 review slot in the workflow-owned merge,
retry, scheduling, and recovery migration stack. It is intentionally a handoff
artifact, not the completed implementation for this slice.
This slot was drafted 2026-06-09 as a handoff artifact. It is **no longer**
only that — see the Measured State block above for what has actually landed.
## Milestone

View File

@@ -1,7 +1,8 @@
---
title: "S03: generic scheduler claim path"
type: refactor
status: draft-stack-handoff
status: landed-unwired
measured_against: "main @ 46f35323c (2026-07-28)"
date: 2026-06-09
slice: S03
milestone: "Foundation"
@@ -11,11 +12,18 @@ stack_base: feature/workflow-owned-merge-s02-merge-request-projection
# S03: generic scheduler claim path
## Measured State (2026-07-28, U9 pre-flight)
`claimDueWorkflowWorkItem` is implemented in `packages/engine/src/workflow-work-scheduler.ts` and wired into `workflow-work-processor.ts` — but that processor has **zero production callers**, so the claim path never runs.
Status corrected from `draft-stack-handoff`, which was accurate when drafted on
2026-06-09 and is not now. See `docs/workflow-policy-ownership-map.md` →
"Measured Wiring State" for the whole-stack table.
## Stack Role
This draft PR reserves the S03 review slot in the workflow-owned merge,
retry, scheduling, and recovery migration stack. It is intentionally a handoff
artifact, not the completed implementation for this slice.
This slot was drafted 2026-06-09 as a handoff artifact. It is **no longer**
only that — see the Measured State block above for what has actually landed.
## Milestone

View File

@@ -1,7 +1,8 @@
---
title: "S04: built-in merge retry recovery IR regions"
type: refactor
status: draft-stack-handoff
status: landed
measured_against: "main @ 46f35323c (2026-07-28)"
date: 2026-06-09
slice: S04
milestone: "Gate A"
@@ -11,11 +12,18 @@ stack_base: feature/workflow-owned-merge-s03-generic-scheduler-claim
# S04: built-in merge retry recovery IR regions
## Measured State (2026-07-28, U9 pre-flight)
The merge/retry/manual-hold/branch-group/recovery regions are **present** in `packages/core/src/builtin-coding-workflow-ir.ts` (`merge-gate`, `merge-retry`, `manual-merge-hold`, `merge-attempt`, `recovery-router`). Do not re-implement. Caveat: the declared node *config* (`maxAttempts`, `release`, `maxReworkCycles`) is read by nothing — pinned by `u9-merge-region-node-config-authority.test.ts` in the merge gate.
Status corrected from `draft-stack-handoff`, which was accurate when drafted on
2026-06-09 and is not now. See `docs/workflow-policy-ownership-map.md` →
"Measured Wiring State" for the whole-stack table.
## Stack Role
This draft PR reserves the S04 review slot in the workflow-owned merge,
retry, scheduling, and recovery migration stack. It is intentionally a handoff
artifact, not the completed implementation for this slice.
This slot was drafted 2026-06-09 as a handoff artifact. It is **no longer**
only that — see the Measured State block above for what has actually landed.
## Milestone

View File

@@ -1,7 +1,8 @@
---
title: "S05: runtime work-item driver"
type: refactor
status: draft-stack-handoff
status: landed-unwired
measured_against: "main @ 46f35323c (2026-07-28)"
date: 2026-06-09
slice: S05
milestone: "Runtime"
@@ -11,11 +12,18 @@ stack_base: feature/workflow-owned-merge-s04-builtin-ir-regions
# S05: runtime work-item driver
## Measured State (2026-07-28, U9 pre-flight)
`WorkflowTaskRuntime.runWorkItem` and `processDueWorkflowWorkItem` are implemented; the processor is exported from `packages/engine/src/index.ts` and has **zero production callers**. The only live pump, `InProcessRuntime.drainWorkflowContinuations`, filters `kinds: ["task"]` and does not use this path.
Status corrected from `draft-stack-handoff`, which was accurate when drafted on
2026-06-09 and is not now. See `docs/workflow-policy-ownership-map.md` →
"Measured Wiring State" for the whole-stack table.
## Stack Role
This draft PR reserves the S05 review slot in the workflow-owned merge,
retry, scheduling, and recovery migration stack. It is intentionally a handoff
artifact, not the completed implementation for this slice.
This slot was drafted 2026-06-09 as a handoff artifact. It is **no longer**
only that — see the Measured State block above for what has actually landed.
## Milestone

View File

@@ -1,7 +1,8 @@
---
title: "S06: git and merge capability extraction"
type: refactor
status: draft-stack-handoff
status: not-started
measured_against: "main @ 46f35323c (2026-07-28)"
date: 2026-06-09
slice: S06
milestone: "Runtime"
@@ -11,11 +12,18 @@ stack_base: feature/workflow-owned-merge-s05-runtime-work-item-driver
# S06: git and merge capability extraction
## Measured State (2026-07-28, U9 pre-flight)
Merge still runs through `packages/engine/src/merger.ts` (11,273 lines). `workflow-merge-nodes.ts` is a 76-line shim over the `requestMerge` primitive, not the capability extraction this slice describes.
Status corrected from `draft-stack-handoff`, which was accurate when drafted on
2026-06-09 and is not now. See `docs/workflow-policy-ownership-map.md` →
"Measured Wiring State" for the whole-stack table.
## Stack Role
This draft PR reserves the S06 review slot in the workflow-owned merge,
retry, scheduling, and recovery migration stack. It is intentionally a handoff
artifact, not the completed implementation for this slice.
Not started. Merge still runs through `merger.ts`; this slot remains the plan of
record for extracting those procedures into workflow node capabilities.
## Milestone

View File

@@ -1,7 +1,8 @@
---
title: "S07: completion handoff creates merge work"
type: refactor
status: draft-stack-handoff
status: not-started
measured_against: "main @ 46f35323c (2026-07-28)"
date: 2026-06-09
slice: S07
milestone: "Runtime"
@@ -11,11 +12,18 @@ stack_base: feature/workflow-owned-merge-s06-git-merge-capabilities
# S07: completion handoff creates merge work
## Measured State (2026-07-28, U9 pre-flight)
**Ordering constraint (corrected 2026-07-28 after PR #2504 review).** The writer already exists: `createCompletionHandoffWorkflowWork` writes `merge`/`manual-hold` items from the live handoff-to-review path, and nothing claims or reconciles them, so they accumulate non-terminal today. That is benign — the legacy `ProjectEngine.mergeQueue` still drives the actual merge. What this slice changes is making those items **authoritative**. Landing it before S03/S05 are driven converts a benign row leak into cards that reach the merge boundary and stop. S07 must not land before S03/S05 are driven, and the pre-existing unclaimed rows need a reconcile/backfill decision as part of this slice.
Status corrected from `draft-stack-handoff`, which was accurate when drafted on
2026-06-09 and is not now. See `docs/workflow-policy-ownership-map.md` →
"Measured Wiring State" for the whole-stack table.
## Stack Role
This draft PR reserves the S07 review slot in the workflow-owned merge,
retry, scheduling, and recovery migration stack. It is intentionally a handoff
artifact, not the completed implementation for this slice.
Not started, and gated on S03/S05 actually being driven — see the corrected
ordering constraint above. This slot remains the plan of record.
## Milestone

View File

@@ -1,7 +1,8 @@
---
title: "S08: workflow-owned merge queue processing"
type: refactor
status: draft-stack-handoff
status: not-started
measured_against: "main @ 46f35323c (2026-07-28)"
date: 2026-06-09
slice: S08
milestone: "Gate B"
@@ -11,11 +12,18 @@ stack_base: feature/workflow-owned-merge-s07-completion-handoff-merge-work
# S08: workflow-owned merge queue processing
## Measured State (2026-07-28, U9 pre-flight)
`ProjectEngine.mergeQueue` + `drainMergeQueue` remain the live merge pump.
Status corrected from `draft-stack-handoff`, which was accurate when drafted on
2026-06-09 and is not now. See `docs/workflow-policy-ownership-map.md` →
"Measured Wiring State" for the whole-stack table.
## Stack Role
This draft PR reserves the S08 review slot in the workflow-owned merge,
retry, scheduling, and recovery migration stack. It is intentionally a handoff
artifact, not the completed implementation for this slice.
Not started. `ProjectEngine.mergeQueue` + `drainMergeQueue` remain the live merge
pump; this slot remains the plan of record for replacing them.
## Milestone

View File

@@ -62,6 +62,64 @@ mutating git state:
semantics and the shared-branch member integration exception.
- Run-audit correlation for git operations and recovery facts.
## Measured Wiring State (2026-07-28, U9 pre-flight)
The S02–S08 substrate is further along than the slice docs claim, but a large part
of it is **built and not driven**. Measured against `main` at `46f35323c`. Recorded
here because "the code exists and its tests pass" reads as landed, and for four of
these that is not the same as running.
| Capability | Implementation | Production callers | Reality |
|---|---|---|---|
| S1 work-item schema + store API | `0031_workflow_task_continuations.sql`, `store.ts` | live | **Wired.** Drives the plan-review continuation path. |
| S02 merge-request projection | `projectMergeRequestToWorkflowWorkItem` | **none** | Built, never invoked. |
| S03 generic scheduler claim | `claimDueWorkflowWorkItem` (`workflow-work-scheduler.ts`) | only the S05 processor, which is itself unwired | Built, never invoked. |
| S04 built-in IR merge regions | `merge-gate`, `merge-retry`, `manual-merge-hold`, `merge-attempt`, `recovery-router` in the coding IR | n/a — declarations | **Landed.** Node *config* is unread; see `u9-merge-region-node-config-authority.test.ts`. |
| S05 runtime work-item driver | `WorkflowTaskRuntime.runWorkItem`, `processDueWorkflowWorkItem` | **none** (exported from `index.ts` only) | Built, never invoked. |
| S06 git/merge capabilities | — | — | Not started. Merge runs through `merger.ts`. |
| S07 completion handoff creates merge work | — | — | Not started. |
| S08 workflow-owned merge processing | — | — | Not started. `ProjectEngine.mergeQueue` is the live pump. |
**The consequence that matters for U9.** `WorkflowWorkItemKind` is
`task | merge | retry | manual-hold | recovery`. The only live pump is
`InProcessRuntime.drainWorkflowContinuations`, and it filters `kinds: ["task"]`.
The generic processor that would claim the other four kinds
(`processDueWorkflowWorkItem`) has no production caller.
**Non-`task` work items are already being written, and nothing claims them.**
`createCompletionHandoffWorkflowWork` (`workflow-workitems-ops.ts:68`) writes
`kind: "merge"` when auto-merge is on and `kind: "manual-hold"` when it is off. It
is called from the LIVE handoff-to-review path (`moves.ts:438` and `:1150`), inside
the move transaction. The kind is computed into a variable
(`autoMerge ? "merge" : "manual-hold"`), which is why a literal grep for
`kind: "merge"` finds nothing — an earlier revision of this section wrongly
concluded there were zero writers on exactly that basis.
So the current state is:
| | State |
|---|---|
| Writers of `merge` / `manual-hold` | **Live** — every task that reaches review writes one |
| Claimers | **None** — the only pump filters `kinds: ["task"]` |
| Reconcilers | **None** — self-healing's continuation check also filters `kinds: ["task"]` (`self-healing.ts:6575`) |
| Only terminalization | The NEXT `createCompletionHandoffWorkflowWork` for the same task cancels prior ones as `superseded-by-completion-handoff` |
These rows therefore **accumulate in a non-terminal state** (`runnable` /
`manual-required`), one per task that reaches review, cleared only if that same task
hands off again.
**This does not stall any merge.** The actual merge is enqueued by
`enqueueMergeQueueInTransaction` in the same transaction, and the legacy
`ProjectEngine.mergeQueue` pump still drives it. The work items are parallel
bookkeeping that nothing consumes yet — accumulating dead rows, not stuck cards.
**What this means for S07.** S07 does not introduce the writer; the writer is
already here. What S07 changes is making those items *authoritative* for the merge
lane. Until the generic pump (S03/S05) is actually driven, promoting these rows from
bookkeeping to authority converts a benign row leak into cards that reach the merge
boundary and stop. **S07 must not land before S03/S05 are driven** — and the
pre-existing unclaimed rows need a reconcile/backfill decision as part of that work.
## Deletion Gates
- No production caller may start checkout, branch integration, squash, or finalize