Files
fusion/docs/workflow-policy-ownership-map.md
gsxdsm 6ee20d9817 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>
2026-07-28 17:15:16 -07:00

12 KiB
Raw Blame History

Workflow Policy Ownership Map

Purpose

This map is the U1 characterization artifact for moving merge, retry, scheduling, and recovery policy into workflow IR/runtime. It classifies current production branches before code is deleted or moved so later cutover work can prove that no legacy engine control path was left unowned.

Ownership Categories

  • substrate: engine/core mechanics that remain below workflow policy.
  • workflow-policy: decisions that must be represented by workflow nodes, workflow node state, or workflow recovery events.
  • capability: operations invoked by workflow nodes while still using shared guard services.
  • compat-projection: legacy task fields or records that may remain as derived summaries during migration.
  • delete-after-cutover: branches that should disappear once workflow parity is authoritative.

Catalog

Surface Current source Current owner Target owner Disposition
Auto-merge queue enqueue and dequeue packages/engine/src/project-engine.ts ProjectEngine merge queue workflow merge work items and merge-gate nodes workflow-policy, delete-after-cutover
In-review handoff delay and startup sweep packages/engine/src/project-engine.ts task:moved listener plus in-review scan workflow completion handoff node creates merge work workflow-policy
Manual onMerge requests packages/engine/src/project-engine.ts engine public merge queue entry point explicit human/manual workflow event that wakes merge node workflow-policy, capability
Merge request shadow contract packages/core/src/store.ts, packages/engine/src/project-engine.ts, packages/engine/src/merger.ts store record plus shadow parity branches workflow work-item state or compatibility projection compat-projection
Merge checkout, integration, conflict resolution, squash, finalize packages/engine/src/merger.ts, packages/engine/src/merger-ai.ts, packages/engine/src/merger-integration-worktree.ts merger lifecycle procedures workflow merge node capabilities calling guard services capability
Branch-group member integration and group promotion packages/engine/src/group-merge-coordinator.ts, packages/engine/src/merge-trait.ts, packages/engine/src/merger-integration-worktree.ts group coordinator and merger helpers branch-group workflow subgraph with separate member and promotion nodes workflow-policy, capability
Merge target and auto-merge eligibility guards packages/core/src/task-merge.ts shared helper used by engine paths shared guard service called by workflow nodes substrate
Dependency satisfaction treats in-review as satisfied packages/engine/src/scheduler.ts, packages/core/src/task-merge.ts scheduler/task helper lifecycle interpretation workflow completion handoff state and compatibility projection workflow-policy, compat-projection
Active scope leases include unmerged in-review worktrees packages/engine/src/scheduler.ts scheduler overlap policy workflow work leases plus repository guard services workflow-policy, substrate
PR monitor starts/stops from in-review transitions packages/engine/src/scheduler.ts scheduler task-move listener workflow PR/watch nodes or workflow events workflow-policy
Generic agent capacity, routing, claim, and lease mechanics packages/engine/src/scheduler.ts scheduler scheduler substrate claiming runnable workflow work substrate
Executor retry storm cap packages/engine/src/__tests__/executor-retry-storm.test.ts, packages/engine/src/project-engine.ts engine retry counters and execution loop workflow node retry policy plus runtime substrate guard workflow-policy, substrate
Generic backoff helpers packages/engine/src/retry-with-backoff.ts, packages/engine/src/rate-limit-retry.ts helper functions reusable substrate helper called by retry nodes substrate
Transient merge error classification packages/engine/src/transient-merge-error-classifier.ts helper used by merger/self-healing merge-node classification input, not route owner substrate
Task-level retry summary fields packages/core/src/retry-summary.ts, packages/core/src/manual-retry-reset.ts task metadata and reset patch compatibility projection from workflow node/run retry state compat-projection
Manual retry reset packages/core/src/manual-retry-reset.ts, dashboard/API callers task metadata patch workflow event clearing targeted failed node retry state workflow-policy, compat-projection
Recover mergeable in-review tasks packages/engine/src/self-healing.ts self-healing directly re-enqueues merge workflow recovery event wakes merge node workflow-policy, delete-after-cutover
Completion handoff limbo recovery packages/engine/src/self-healing.ts self-healing re-emits auto-merge handoff workflow recovery event or idempotent handoff node wake workflow-policy
Transient merge failure recovery packages/engine/src/self-healing.ts self-healing resets merge retries and re-enqueues merge-node retry policy and retry-after work item workflow-policy, delete-after-cutover
Stale merge status recovery packages/engine/src/self-healing.ts self-healing clears status and may enqueue merge workflow recovery event plus merge work reconciliation workflow-policy
Already-landed and no-op finalization packages/engine/src/self-healing.ts, packages/engine/src/merger.ts self-healing/merger lifecycle paths workflow recovery/finalize nodes with repository guard services workflow-policy, capability
Backward in-review recovery paths packages/engine/src/self-healing.ts, docs/self-healing-backward-move-audit.md proof-gated self-healing mutations workflow recovery nodes; engine only emits facts workflow-policy, delete-after-cutover
Workflow runtime execution facade packages/engine/src/workflow-task-runtime.ts, packages/engine/src/workflow-graph-executor.ts runtime executes graph nodes remains workflow runtime owner substrate, workflow-policy
Built-in default workflow definitions packages/core/src/builtin-coding-workflow-ir.ts, packages/core/src/builtin-stepwise-coding-workflow-ir.ts, packages/core/src/builtin-pr-workflow-ir.ts partial lifecycle expression authoritative source for default scheduling, retry, merge, and recovery regions workflow-policy
Dashboard task-card merge/retry/stall badges packages/dashboard/app/components/TaskCard.tsx task fields and legacy classifications workflow run/work-item projection first, legacy fields second compat-projection
Reliability and diagnostics surfaces docs/diagnostics.md, dashboard reliability views self-healing and engine status strings workflow-native recovery and held-work reasons compat-projection

Non-Bypassable Guard Services

These remain centralized and are called by workflow node capabilities before mutating git state:

  • File-scope and squash overlap checks.
  • Branch target and branch-group target validation.
  • Worktree ownership and lease checks.
  • Auto-merge processing gate, including autoMerge:false terminal-until-human 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 except a workflow merge node or an explicit human/manual API that records an equivalent workflow event.
  • Scheduler may claim runnable workflow work, apply capacity/routing/leases, and monitor PR/watch substrate events; it must not infer merge eligibility, retry routing, or task lifecycle advancement from task columns.
  • SelfHealingManager may publish typed recovery facts and reconcile metadata; it must not directly requeue, pause, fail, unpause, or move merge/retry tasks except through guarded workflow primitives.
  • Task-level retry and merge fields are compatibility summaries. Workflow run/node/work-item state is the policy authority.