Parent Epic
#11831 — Sub 19 of Epic. The B-prime extraction added in Discussion #11857 Cycle-3.5 convergence (GPT [GRADUATION_APPROVED]).
Premise
Post-#11025 substrate evolution (cross-daemon lease coordination via PR #11506, 3 deferral classes including cross-daemon-lease, scoped executor wrappers, deployment-profile awareness) added ~303 LOC to Orchestrator.mjs that the original 4-sub structure couldn't reach. Sub 19 extracts the execution-phase POLICY surface — backpressure + lease-acquisition + dependency-gate + deferral-recording — into a single service.
ADR 0014 codifies the mixed-profile scheduler task taxonomy; explicitly does NOT mandate the lease/policy implementation stays in Orchestrator. This Sub takes that opening.
Prescription
Create ai/daemons/orchestrator/services/MaintenanceBackpressureService.mjs with three internally-visible-separate surface groups:
Read-only predicates / finders (extracted from § E: lines 461-517, 57 LOC):
isHeavyMaintenanceTask(taskName) → boolean
isGoldenPathDependencyTask(taskName) → boolean
getActiveHeavyMaintenanceTask({excludeTaskName}) → taskName | null
getActiveGoldenPathDependencyTask({activeTaskName}) → taskName | nullDeferral recording (consolidates § F: lines 519-627, 109 LOC):
recordDeferral({taskName, blockingTaskName, reasonText, reasonCode}) → void
clearDeferralLogState(taskName) → void
Single entry point with reason-class polymorphism — replaces the 3 separate recordMaintenanceDeferral / recordCrossDaemonLeaseDeferral / recordGoldenPathDependencyDeferral methods. The reasonCode field carries the deferral class.
Executor wrappers (extracted from § G+H: lines 629-742 + 744-766, 137 LOC):
acquireLeaseAndExecute({taskName, executeFn, context}) → outcome
executeWithGoldenPathDependencyGate({taskName, executeFn, context}) → outcome
acquireLeaseAndExecute wraps the existing HeavyMaintenanceLeaseService.acquireHeavyMaintenanceLeaseSync + try/catch + release + deferral recording + outcome reporting flow. executeWithGoldenPathDependencyGate wraps the dependency gate.
Also moves resolveHeavyMaintenanceLeasePath() (§ G part).
Acceptance Criteria
ai/daemons/orchestrator/services/MaintenanceBackpressureService.mjs ships with the three surface groups above, visibly separate in the class definition (separate JSDoc section headers; no monolithic god-method)
- Service wraps / delegates to existing
HeavyMaintenanceLeaseService primitives — does NOT replace them
- Pure-function unit tests for predicates + finders with synthetic
TaskStateService state
- Integration tests for executor wrappers using
HeavyMaintenanceLeaseService test seams (acquire/release stubs)
- Orchestrator's
poll() (post-Sub-18) calls MaintenanceBackpressureService.acquireLeaseAndExecute({...}) and .executeWithGoldenPathDependencyGate({...}) — NOT inline lease+deferral logic
- Sub 19 must extract ≥70% of the §E-H ~303 LOC. If it can't without turning into a broader boot/process-runner split, file revalidation ticket BEFORE Sub-19 merge per AC 11 in Discussion #11857
Avoided Traps
- NOT a
DueTask coordinator — does NOT decide what work is due (coordinators do that)
- NOT a coordinator registry (Sub 18 owns that)
- NOT a spawn / process supervision authority (continues to delegate to
ProcessSupervisorService)
- DOES wrap / delegate to existing
HeavyMaintenanceLeaseService primitives — does NOT replace them
- Internal surfaces visibly separate (read-only predicates / deferral recording / executor wrappers) — NO monolithic god-method
- Implementation-precedent (per GPT Cycle-3.5): if Sub 19 needs swappable dependencies, use Neo class/config system shape — NOT post-construction assignment bags (the Sub-1 anti-pattern)
Depends on
Epic #11831. Independent of Subs 15-17 (different scope). Should land BEFORE Sub 18 so Sub 18's wire-up calls the new service.
Unblocks
Sub 18 (wire-up calls MaintenanceBackpressureService instead of inlining lease+deferral logic).
Authority
Discussion #11857 Cycle-3.5 GPT [GRADUATION_APPROVED] + operator ratify.
Authored by: [Claude Opus 4.7] (Claude Code)
Parent Epic
#11831 — Sub 19 of Epic. The B-prime extraction added in Discussion #11857 Cycle-3.5 convergence (GPT
[GRADUATION_APPROVED]).Premise
Post-#11025 substrate evolution (cross-daemon lease coordination via PR #11506, 3 deferral classes including cross-daemon-lease, scoped executor wrappers, deployment-profile awareness) added ~303 LOC to
Orchestrator.mjsthat the original 4-sub structure couldn't reach. Sub 19 extracts the execution-phase POLICY surface — backpressure + lease-acquisition + dependency-gate + deferral-recording — into a single service.ADR 0014 codifies the mixed-profile scheduler task taxonomy; explicitly does NOT mandate the lease/policy implementation stays in
Orchestrator. This Sub takes that opening.Prescription
Create
ai/daemons/orchestrator/services/MaintenanceBackpressureService.mjswith three internally-visible-separate surface groups:Read-only predicates / finders (extracted from § E: lines 461-517, 57 LOC):
isHeavyMaintenanceTask(taskName) → boolean isGoldenPathDependencyTask(taskName) → boolean getActiveHeavyMaintenanceTask({excludeTaskName}) → taskName | null getActiveGoldenPathDependencyTask({activeTaskName}) → taskName | nullDeferral recording (consolidates § F: lines 519-627, 109 LOC):
recordDeferral({taskName, blockingTaskName, reasonText, reasonCode}) → void clearDeferralLogState(taskName) → voidSingle entry point with reason-class polymorphism — replaces the 3 separate
recordMaintenanceDeferral/recordCrossDaemonLeaseDeferral/recordGoldenPathDependencyDeferralmethods. ThereasonCodefield carries the deferral class.Executor wrappers (extracted from § G+H: lines 629-742 + 744-766, 137 LOC):
acquireLeaseAndExecute({taskName, executeFn, context}) → outcome executeWithGoldenPathDependencyGate({taskName, executeFn, context}) → outcomeacquireLeaseAndExecutewraps the existingHeavyMaintenanceLeaseService.acquireHeavyMaintenanceLeaseSync+ try/catch + release + deferral recording + outcome reporting flow.executeWithGoldenPathDependencyGatewraps the dependency gate.Also moves
resolveHeavyMaintenanceLeasePath()(§ G part).Acceptance Criteria
ai/daemons/orchestrator/services/MaintenanceBackpressureService.mjsships with the three surface groups above, visibly separate in the class definition (separate JSDoc section headers; no monolithic god-method)HeavyMaintenanceLeaseServiceprimitives — does NOT replace themTaskStateServicestateHeavyMaintenanceLeaseServicetest seams (acquire/release stubs)poll()(post-Sub-18) callsMaintenanceBackpressureService.acquireLeaseAndExecute({...})and.executeWithGoldenPathDependencyGate({...})— NOT inline lease+deferral logicAvoided Traps
DueTaskcoordinator — does NOT decide what work is due (coordinators do that)ProcessSupervisorService)HeavyMaintenanceLeaseServiceprimitives — does NOT replace themDepends on
Epic #11831. Independent of Subs 15-17 (different scope). Should land BEFORE Sub 18 so Sub 18's wire-up calls the new service.
Unblocks
Sub 18 (wire-up calls
MaintenanceBackpressureServiceinstead of inlining lease+deferral logic).Authority
Discussion #11857 Cycle-3.5 GPT
[GRADUATION_APPROVED]+ operator ratify.Authored by: [Claude Opus 4.7] (Claude Code)