Context
PR #16900 makes the per-task deferral anchor durable under #16903. Its exact-head source path is correct, but independent review found that the committed tests exercise TaskStateService.markDeferred() directly and never bind the production delegation from MaintenanceBackpressureService.recordDeferral().
A disposable exact-head mutation removed only taskStateService: this.taskStateService from the production wrapper. Both focused suites still passed 57/57. The same source audit found that every unchanged deferral poll rewrites the complete task-state file after the first anchor is already durable.
The Problem
The persisted primitive is guarded, while the composition that makes runtime deferrals use it is not. A future refactor can disconnect the injected service and silently fall back to the process-local map without a red test—the exact restart-reset shape #16903 repairs.
Separately, markDeferred() performs synchronous whole-envelope persistence on every poll even though the ??= contract means only the first deferral changes state. Correctness is preserved, but repeated blocked polls create avoidable write churn in the orchestrator hot path.
The Architectural Reality
TaskStateService owns persistence and the non-sliding deferralStreakStartedAt field.
MaintenanceBackpressureService.recordDeferral() is the production composition boundary that must invoke markDeferred() and publish its returned anchor.
- The in-memory map is an intentional compatibility fallback for direct callers; the test must not delete it.
- ADR 0022 AC-3 requires the live deferral flow—not merely its isolated persistence helper—to remain durable across process lifetimes.
Structure-map gate: npm run --silent ai:structure-map -- --files --loc places both changes in the existing ai/daemons/orchestrator/services/ owner; no new module is needed.
The Fix
- Add a production-bound
MaintenanceBackpressureService test that supplies a task-state writer, proves markDeferred() is called, and proves its durable anchor wins over the local map.
- Recreate the task-state service over the same persisted file and verify a changed blocker still publishes the original anchor.
- Verify the actual
markStarted() transition clears the streak and the next deferral opens a new anchor.
- Avoid a whole-file rewrite when
markDeferred() observes an already-open, unchanged streak, without weakening first-write durability or the synchronous-before-outcome ordering.
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
| backpressure → task-state delegation |
MaintenanceBackpressureService.recordDeferral() |
every production deferral consumes TaskStateService.markDeferred(); returned durable value wins |
process-local map remains only when no task-state service is supplied |
existing service JSDoc |
composition mutation must turn the new test red |
| task-state persistence writes |
TaskStateService.markDeferred() |
persist synchronously on first open; avoid rewriting an unchanged anchor |
persistence failure remains loud under the existing writer contract |
method JSDoc |
first-open write count + repeated-deferral no-op control |
Decision Record impact
aligned-with ADR 0022 — strengthens AC-3's durable task-state composition and does not alter scheduling policy.
Acceptance Criteria
Out of Scope
- The health threshold and fairness work retained by #16561.
- Any picker, lease, cadence, or task-taxonomy change.
- Changing the persisted field shape delivered by #16903.
Avoided Traps
- Testing only the helper again. The missing proof is the production composition.
- Deleting the fallback to make the test easy. Direct callers intentionally retain it.
- Making persistence asynchronous. The first durable write must still precede publication of the deferral outcome.
- Optimizing before detecting equality. Only an unchanged, already-open anchor may skip the write.
Related
Live latest-open sweep: checked the 20 newest open issues immediately before creation; no equivalent production-binding/write-churn ticket existed. Exact title/body sweep returned no match. A2A in-flight sweep: checked the latest 30 messages across read states; no competing claim exists.
Origin Session ID: d813fe26-4096-4c43-81fc-be4241b270cb
Retrieval Hint: query_raw_memories("MaintenanceBackpressureService markDeferred production binding deferral streak 57/57 #16900")
Context
PR #16900 makes the per-task deferral anchor durable under #16903. Its exact-head source path is correct, but independent review found that the committed tests exercise
TaskStateService.markDeferred()directly and never bind the production delegation fromMaintenanceBackpressureService.recordDeferral().A disposable exact-head mutation removed only
taskStateService: this.taskStateServicefrom the production wrapper. Both focused suites still passed 57/57. The same source audit found that every unchanged deferral poll rewrites the complete task-state file after the first anchor is already durable.The Problem
The persisted primitive is guarded, while the composition that makes runtime deferrals use it is not. A future refactor can disconnect the injected service and silently fall back to the process-local map without a red test—the exact restart-reset shape #16903 repairs.
Separately,
markDeferred()performs synchronous whole-envelope persistence on every poll even though the??=contract means only the first deferral changes state. Correctness is preserved, but repeated blocked polls create avoidable write churn in the orchestrator hot path.The Architectural Reality
TaskStateServiceowns persistence and the non-slidingdeferralStreakStartedAtfield.MaintenanceBackpressureService.recordDeferral()is the production composition boundary that must invokemarkDeferred()and publish its returned anchor.Structure-map gate:
npm run --silent ai:structure-map -- --files --locplaces both changes in the existingai/daemons/orchestrator/services/owner; no new module is needed.The Fix
MaintenanceBackpressureServicetest that supplies a task-state writer, provesmarkDeferred()is called, and proves its durable anchor wins over the local map.markStarted()transition clears the streak and the next deferral opens a new anchor.markDeferred()observes an already-open, unchanged streak, without weakening first-write durability or the synchronous-before-outcome ordering.Contract Ledger Matrix
MaintenanceBackpressureService.recordDeferral()TaskStateService.markDeferred(); returned durable value winsTaskStateService.markDeferred()Decision Record impact
aligned-with ADR 0022— strengthens AC-3's durable task-state composition and does not alter scheduling policy.Acceptance Criteria
MaintenanceBackpressureService → TaskStateService.markDeferred()carriage turns a named test red.Out of Scope
Avoided Traps
Related
Live latest-open sweep: checked the 20 newest open issues immediately before creation; no equivalent production-binding/write-churn ticket existed. Exact title/body sweep returned no match. A2A in-flight sweep: checked the latest 30 messages across read states; no competing claim exists.
Origin Session ID: d813fe26-4096-4c43-81fc-be4241b270cb
Retrieval Hint:
query_raw_memories("MaintenanceBackpressureService markDeferred production binding deferral streak 57/57 #16900")