Epic: Make author workflows transactional and safe for multiple LLM clients #887

Open
opened 2026-07-24 21:09:41 -05:00 by jcwalker3 · 1 comment
Owner

Problem

Author workflows are a chain of independently-failing operations with no transaction boundary. Every stage keeps its own state (assignment, workflow lease, keyed lock, /tmp pointer file, generation counter, branch, worktree), and those stores are allowed to contradict one another while the gate layer still reports safe_next_action: proceed. When any single stage fails, the run leaves durable, contradictory state that the next worker — often a different LLM client — cannot interpret or recover from without operator repair.

Observed consequences, all reproduced on live runs:

  • Test suites mutated production workflow state (lock generation counters, /tmp/gitea_issue_lock.json, the global current-issue pointer).
  • preflight_order_violation fires whenever any call — including read-only ones — lands between capability resolution and the intended mutation, so correctness depends on prompt-level instructions to emit two adjacent tool calls.
  • Ownership records disagreed with each other while still reporting proceed.
  • Publish / PR-create / reviewer-handoff / lease-retire are four separate fragile steps, so interruption between any two strands the branch.
  • One transient dirty-checkout observation permanently blocked a run whose immediate diff was empty.
  • A resolved commit_files capability was followed by shell git add / git commit, bypassing the native path entirely.
  • Failed gates prohibited posting the diagnostic handoff, so the failure left no durable record for later workers.

Scope

Eight children: five P0 (correctness and isolation), three P1 (stability, enforcement, observability).

Priority Child
P0 Isolate tests from live workflow state
P0 Replace capability-call adjacency with consumable mutation grants
P0 Unify author ownership and add fenced recovery
P0 Add atomic author finalization
P0 Break the author worktree bootstrap deadlock
P1 Stabilize transient dirty-checkout verification
P1 Enforce native MCP commits
P1 Preserve failure reporting after hard stops

Child issue numbers are linked in a follow-up comment on this issue.

Epic completion gate

Do not restart unattended looping until all of the following hold:

  • All P0 children are closed.
  • The full test suite provably cannot mutate live workflow state.
  • Two different LLM clients each complete a supervised end-to-end author canary (allocate -> lock -> commit -> publish -> PR -> handoff -> retire).
  • No call-adjacency instructions are required in any prompt or skill.
  • No run depends on lease expiry, generation omission, manual lock-file editing, shell publication, or operator repair.
  • Every failure produces a durable diagnostic record discoverable by the next worker.

Non-goals

  • Redesigning the reviewer or merger role chains.
  • Replacing the MCP transport or role-namespace model.
  • Changing Gitea-side branch protection.

Duplicate verdict

No existing epic covers this scope. Issue #820 is the control-plane architecture program and is a different scope. Verified against a full scan of open issues at master ccde9e8f1183bc9a6672393a9923f304086fb874.

## Problem Author workflows are a chain of independently-failing operations with no transaction boundary. Every stage keeps its own state (assignment, workflow lease, keyed lock, `/tmp` pointer file, generation counter, branch, worktree), and those stores are allowed to contradict one another while the gate layer still reports `safe_next_action: proceed`. When any single stage fails, the run leaves durable, contradictory state that the next worker — often a different LLM client — cannot interpret or recover from without operator repair. Observed consequences, all reproduced on live runs: - Test suites mutated production workflow state (lock generation counters, `/tmp/gitea_issue_lock.json`, the global current-issue pointer). - `preflight_order_violation` fires whenever any call — including read-only ones — lands between capability resolution and the intended mutation, so correctness depends on prompt-level instructions to emit two adjacent tool calls. - Ownership records disagreed with each other while still reporting proceed. - Publish / PR-create / reviewer-handoff / lease-retire are four separate fragile steps, so interruption between any two strands the branch. - One transient dirty-checkout observation permanently blocked a run whose immediate diff was empty. - A resolved `commit_files` capability was followed by shell `git add` / `git commit`, bypassing the native path entirely. - Failed gates prohibited posting the diagnostic handoff, so the failure left no durable record for later workers. ## Scope Eight children: five P0 (correctness and isolation), three P1 (stability, enforcement, observability). | Priority | Child | | -------- | ----- | | P0 | Isolate tests from live workflow state | | P0 | Replace capability-call adjacency with consumable mutation grants | | P0 | Unify author ownership and add fenced recovery | | P0 | Add atomic author finalization | | P0 | Break the author worktree bootstrap deadlock | | P1 | Stabilize transient dirty-checkout verification | | P1 | Enforce native MCP commits | | P1 | Preserve failure reporting after hard stops | Child issue numbers are linked in a follow-up comment on this issue. ## Epic completion gate Do not restart unattended looping until all of the following hold: - All P0 children are closed. - The full test suite provably cannot mutate live workflow state. - Two different LLM clients each complete a supervised end-to-end author canary (allocate -> lock -> commit -> publish -> PR -> handoff -> retire). - No call-adjacency instructions are required in any prompt or skill. - No run depends on lease expiry, generation omission, manual lock-file editing, shell publication, or operator repair. - Every failure produces a durable diagnostic record discoverable by the next worker. ## Non-goals - Redesigning the reviewer or merger role chains. - Replacing the MCP transport or role-namespace model. - Changing Gitea-side branch protection. ## Duplicate verdict No existing epic covers this scope. Issue #820 is the control-plane architecture program and is a different scope. Verified against a full scan of open issues at master `ccde9e8f1183bc9a6672393a9923f304086fb874`.
Author
Owner

[THREAD STATE LEDGER] Issue #887 — infrastructure coverage for the three defects required alongside this epic

What is true now:

  • Server-side decision state: server-side state changed — three infrastructure defects that sit alongside this epic now have durable trackers. #899 owns author-loop disable enforcement, #900 owns MCP daemon cohort lifecycle supervision, #689 owns deterministic namespace attachment.
  • Local verdict/state: prgs-author session, identity jcwalker3, remote prgs, repo Scaled-Tech-Consulting/Gitea-Tools. Runtime parity green throughout: daemon_start_head, local_head, current_head, and live_remote_head all a4c73766f4, mutation_safe true, restart_required false.
  • Latest known validation: read-back of #899, #900, and #689 confirms open state with valid workflow labels; the #689 edit verified read-after-write with labels, state, assignees, and milestone unchanged.

What changed:

  • #689 was promoted from a two-line incident record to the canonical deterministic-attachment tracker. Its original incident text is preserved verbatim; scope, a coverage table, nine acceptance criteria, and explicit non-goals were added. Title now names the tracker while retaining the incident provenance.
  • #899 was created as a child of #797, covering the loop-disable requirements that #804, #805, and #799 leave open: disable actually stopping a scheduled worker, no respawn after disable, refusal of author work while looping is administratively disabled, and regression for bootout plus restart and login persistence.
  • #900 was created to bound the daemon cohort population: one eligible cohort per profile and configuration, drain and reap of superseded cohorts, no accumulation across reconnects, and full cohort identity in status output.
  • Coverage assessment recorded: of the fifteen requirements across the three defects, one was already fully covered. Loop-disable status exposure is satisfied by #799 acceptance criteria for per-worker state display combined with the #797 registry field for enabled or paused state.

What is blocked:

  • Blocker classification: no blocker

Who/what acts next:

  • Next actor: author
  • Required action: implement #899, #900, and #689 as independent work units. They have different owners and different acceptance tests and must stay separate work items.
  • Do not do: do not treat #897 as lifecycle or attachment coverage, since it scopes only blocker and permission classification. Do not collapse #689 into #708, which explicitly scopes itself to Connected-versus-attached and asks not to be consolidated with transport-pinning trackers. Do not collapse #900 into #686, which is provenance detection for manually launched servers and does not bound the sanctioned cohort population.

Canonical Issue State

STATE:
open — epic children complete; adjacent infrastructure coverage now tracked

WHO_IS_NEXT:
author

NEXT_ACTION:
Implement the three infrastructure trackers independently: #899 loop-disable enforcement, #900 cohort lifecycle supervision, #689 deterministic attachment.

NEXT_PROMPT:

Role: AUTHOR
Repo: prgs / Scaled-Tech-Consulting / Gitea-Tools
Issue: one of #899, #900, #689

1. gitea_whoami + gitea_resolve_task_capability on prgs-author; bind a branches/ worktree.
2. Implement the selected tracker's acceptance criteria only; do not absorb the other two.
3. PR with Closes for that issue; stop; hand off to independent reviewer.

WHAT_HAPPENED:
A focused infrastructure-coverage audit compared the exact bodies, comments, and acceptance criteria of #686, #689, #708, #678, #669, #655, #659, and the #797 worker-management family against the fifteen requirements for loop-disable enforcement, daemon lifecycle supervision, and deterministic namespace attachment. Only one requirement was fully covered. Two trackers were created and one was extended so every remaining requirement has a durable home.

WHY:
The epic's completion gate forbids restarting unattended looping until failures are durably recorded and recoverable. That gate cannot be evaluated while loop-disable is an operator convention, daemon cohorts accumulate unbounded, and attachment to a parity-matching cohort is unverifiable.

RELATED_PRS:
none

BLOCKERS:
none

VALIDATION:
Parity re-checked after every mutation and unchanged at a4c73766f4. #899 and #900 returned valid workflow label validation with exactly one type label and one status label each. #689 returned verified true with preserved_intact true and an empty mismatch list.

LAST_UPDATED_BY:
jcwalker3 / prgs-author / AUTHOR / 2026-07-24

[THREAD STATE LEDGER] Issue #887 — infrastructure coverage for the three defects required alongside this epic What is true now: - Server-side decision state: server-side state changed — three infrastructure defects that sit alongside this epic now have durable trackers. #899 owns author-loop disable enforcement, #900 owns MCP daemon cohort lifecycle supervision, #689 owns deterministic namespace attachment. - Local verdict/state: prgs-author session, identity jcwalker3, remote prgs, repo Scaled-Tech-Consulting/Gitea-Tools. Runtime parity green throughout: daemon_start_head, local_head, current_head, and live_remote_head all a4c73766f4b0cc32f7c3808688eceeb6fee74335, mutation_safe true, restart_required false. - Latest known validation: read-back of #899, #900, and #689 confirms open state with valid workflow labels; the #689 edit verified read-after-write with labels, state, assignees, and milestone unchanged. What changed: - #689 was promoted from a two-line incident record to the canonical deterministic-attachment tracker. Its original incident text is preserved verbatim; scope, a coverage table, nine acceptance criteria, and explicit non-goals were added. Title now names the tracker while retaining the incident provenance. - #899 was created as a child of #797, covering the loop-disable requirements that #804, #805, and #799 leave open: disable actually stopping a scheduled worker, no respawn after disable, refusal of author work while looping is administratively disabled, and regression for bootout plus restart and login persistence. - #900 was created to bound the daemon cohort population: one eligible cohort per profile and configuration, drain and reap of superseded cohorts, no accumulation across reconnects, and full cohort identity in status output. - Coverage assessment recorded: of the fifteen requirements across the three defects, one was already fully covered. Loop-disable status exposure is satisfied by #799 acceptance criteria for per-worker state display combined with the #797 registry field for enabled or paused state. What is blocked: - Blocker classification: no blocker Who/what acts next: - Next actor: author - Required action: implement #899, #900, and #689 as independent work units. They have different owners and different acceptance tests and must stay separate work items. - Do not do: do not treat #897 as lifecycle or attachment coverage, since it scopes only blocker and permission classification. Do not collapse #689 into #708, which explicitly scopes itself to Connected-versus-attached and asks not to be consolidated with transport-pinning trackers. Do not collapse #900 into #686, which is provenance detection for manually launched servers and does not bound the sanctioned cohort population. ## Canonical Issue State STATE: open — epic children complete; adjacent infrastructure coverage now tracked WHO_IS_NEXT: author NEXT_ACTION: Implement the three infrastructure trackers independently: #899 loop-disable enforcement, #900 cohort lifecycle supervision, #689 deterministic attachment. NEXT_PROMPT: ```text Role: AUTHOR Repo: prgs / Scaled-Tech-Consulting / Gitea-Tools Issue: one of #899, #900, #689 1. gitea_whoami + gitea_resolve_task_capability on prgs-author; bind a branches/ worktree. 2. Implement the selected tracker's acceptance criteria only; do not absorb the other two. 3. PR with Closes for that issue; stop; hand off to independent reviewer. ``` WHAT_HAPPENED: A focused infrastructure-coverage audit compared the exact bodies, comments, and acceptance criteria of #686, #689, #708, #678, #669, #655, #659, and the #797 worker-management family against the fifteen requirements for loop-disable enforcement, daemon lifecycle supervision, and deterministic namespace attachment. Only one requirement was fully covered. Two trackers were created and one was extended so every remaining requirement has a durable home. WHY: The epic's completion gate forbids restarting unattended looping until failures are durably recorded and recoverable. That gate cannot be evaluated while loop-disable is an operator convention, daemon cohorts accumulate unbounded, and attachment to a parity-matching cohort is unverifiable. RELATED_PRS: none BLOCKERS: none VALIDATION: Parity re-checked after every mutation and unchanged at a4c73766f4b0cc32f7c3808688eceeb6fee74335. #899 and #900 returned valid workflow label validation with exactly one type label and one status label each. #689 returned verified true with preserved_intact true and an empty mismatch list. LAST_UPDATED_BY: jcwalker3 / prgs-author / AUTHOR / 2026-07-24
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Scaled-Tech-Consulting/Gitea-Tools#887