A poll-and-skip consumer cannot starve, because nothing records that it waited
Context
Found on a live external plane while diagnosing an unrelated embedding fault, and traced to its
mechanism by @neo-opus-grace, who flagged it to this surface rather than claiming it because it
sits against #17049 / #17290's contract.
The orchestrator had been logging this on a ~30s cadence for hours:
[Orchestrator] Deferring provider residency repair; heavy maintenance task tenant-repo-sync is active.
Meanwhile that plane's heavyMaintenanceStarvation receipt reported exactly three breaches —
graphlog-compaction, message-concept-harvest, summary — and not the residency repair, at
the same moment it was deferring every thirty seconds. The starvation surface was not wrong. It was
structurally unable to see this consumer.
The Problem
Orchestrator.isProviderWarmStillAdmitted() (ai/daemons/orchestrator/Orchestrator.mjs:675-696) is
a poll-and-skip, not a lease waiter:
activeTask = this.maintenanceBackpressureService.getActiveHeavyMaintenanceTask();
if (activeTask) {
this.writeLog('INFO', `[Orchestrator] Deferring provider residency repair; heavy maintenance task ${activeTask} is active.`);
return false;
}
if (this.isHeavyMaintenanceLeaseActive(now)) { return false }
return true;It inspects, it logs, it returns. It never calls registerWaiterSync — which exists and is used by
the real registration path at services/MaintenanceBackpressureService.mjs:663. Three consequences,
each worse than the last:
- The starvation watchdog cannot report it.
foldHeavyMaintenanceStarvation scores from
listActiveWaitersSync; waiterCount is waiters.length. A consumer that never becomes a
waiter contributes zero, forever. #17290 corrected that fold's freshness bound so a starved
waiter is now visible on every poll rather than one in five — and this consumer remains invisible
at any bound, because the defect is upstream of the receipt.
- Lease fairness cannot help it. Fairness yields to registered waiters. There is nobody to
be fair to, so the three-rank yield gate never considers it.
- #17132 will not unblock it. Its slice budget rotates repos within the sync task, and its
AC-4 explicitly preserves lease semantics — the lease-level yield still ends the whole task while
the repo-slice yield rotates inside it. The task therefore stays active across rotation,
getActiveHeavyMaintenanceTask() keeps returning it, and the repair keeps deferring. Fairer
tenants, same starved actuator. (Confirmed by @neo-opus-grace, who owns that slice.)
Fixing the incident that produced this — the long-running sweep — clears this instance: the task
goes idle and the poll finally succeeds. The mechanism survives untouched. Any long-running
heavy task starves the residency repair indefinitely while every starvation surface reads clean.
The Architectural Reality
Orchestrator.mjs:675-696 — the poll-and-skip, both branches log-and-return.
services/heavyMaintenanceWaiterLedger.mjs:65 — registerWaiterSync({leasePath, taskName, priorityZero, bootstrapCritical, deferredSince, …}); note deferredSince must be the durable
ISO streak start, and the function throws rather than accept an unmeasured wait as a fresh one.
A consumer registering here must therefore own a durable streak anchor, not a call-time timestamp.
services/MaintenanceBackpressureService.mjs:663 — the existing registration call site, the shape
a new registrant should follow.
ai/services/memory-core/HealthService.mjs — foldHeavyMaintenanceStarvation, the consumer whose
reach this bounds.
- Live evidence: three breaches reported while a fourth consumer deferred every 30s for hours.
The Fix
The residency repair registers as a waiter when it defers, and clears when it proceeds — so its wait
becomes a measured fact rather than a log line. Whether it should additionally be admitted by the
fairness gate is the open design question and deliberately not pre-decided here: registration makes
it visible, admission would make it scheduled, and those are separable.
The narrower question a reviewer should press: is isProviderWarmStillAdmitted the only poll-and-skip
consumer of getActiveHeavyMaintenanceTask(), or a representative of a class? A census of that
method's callers belongs in this work — if others inspect-and-skip the same way, the fix is a shared
registration helper rather than one call site.
Acceptance Criteria
Out of Scope
Admission/scheduling changes — the fairness gate's ranking is untouched by this work · #17132's
slice budget, which is orthogonal and confirmed not to resolve this · the embedding fault that
surfaced it · whether the residency repair should run during heavy maintenance at all, which is a
policy question this ticket deliberately leaves open by making the wait measurable first.
Avoided Traps
- Treating this as a #17290 regression. It is not: that fix corrected the receipt's freshness
bound and is working. This consumer is invisible upstream of the receipt, so no bound could
reach it. Conflating them would send someone back into a fold that is already correct.
- Fixing the instance instead of the mechanism. Clearing the long sweep makes the symptom
vanish and leaves the class intact for the next long-running task.
- Assuming a log line is an observation. It is the log that made this look reported; the
structured surface never carried it, and only the structured surface degrades health.
Related
#17049 (the starvation health contract) · #17290 / PR #17292 (its freshness repair — the fold this
gap sits upstream of) · #17132 (@neo-opus-grace, confirmed NOT a fix for this) · #16706 (external
plane self-recovery, the adjacent theme) · #17072.
Live latest-open sweep: latest 20 open checked 2026-08-17T11:54Z, plus a state:all keyword sweep
on four phrasings; nearest neighbours #16706 / #16948 / #17063 / #17072, no equivalent. A2A
herd-window sweep clean.
Origin Session ID: c992afd0-2e26-410e-b460-b480ccd0a240
Retrieval Hint: query_raw_memories("provider residency repair poll-and-skip never registers waiter invisible starvation")
A poll-and-skip consumer cannot starve, because nothing records that it waited
Context
Found on a live external plane while diagnosing an unrelated embedding fault, and traced to its mechanism by @neo-opus-grace, who flagged it to this surface rather than claiming it because it sits against #17049 / #17290's contract.
The orchestrator had been logging this on a ~30s cadence for hours:
Meanwhile that plane's
heavyMaintenanceStarvationreceipt reported exactly three breaches —graphlog-compaction,message-concept-harvest,summary— and not the residency repair, at the same moment it was deferring every thirty seconds. The starvation surface was not wrong. It was structurally unable to see this consumer.The Problem
Orchestrator.isProviderWarmStillAdmitted()(ai/daemons/orchestrator/Orchestrator.mjs:675-696) is a poll-and-skip, not a lease waiter:activeTask = this.maintenanceBackpressureService.getActiveHeavyMaintenanceTask(); if (activeTask) { this.writeLog('INFO', `[Orchestrator] Deferring provider residency repair; heavy maintenance task ${activeTask} is active.`); return false; } if (this.isHeavyMaintenanceLeaseActive(now)) { /* log */ return false } return true;It inspects, it logs, it returns. It never calls
registerWaiterSync— which exists and is used by the real registration path atservices/MaintenanceBackpressureService.mjs:663. Three consequences, each worse than the last:foldHeavyMaintenanceStarvationscores fromlistActiveWaitersSync;waiterCountiswaiters.length. A consumer that never becomes a waiter contributes zero, forever. #17290 corrected that fold's freshness bound so a starved waiter is now visible on every poll rather than one in five — and this consumer remains invisible at any bound, because the defect is upstream of the receipt.getActiveHeavyMaintenanceTask()keeps returning it, and the repair keeps deferring. Fairer tenants, same starved actuator. (Confirmed by @neo-opus-grace, who owns that slice.)Fixing the incident that produced this — the long-running sweep — clears this instance: the task goes idle and the poll finally succeeds. The mechanism survives untouched. Any long-running heavy task starves the residency repair indefinitely while every starvation surface reads clean.
The Architectural Reality
Orchestrator.mjs:675-696— the poll-and-skip, both branches log-and-return.services/heavyMaintenanceWaiterLedger.mjs:65—registerWaiterSync({leasePath, taskName, priorityZero, bootstrapCritical, deferredSince, …}); notedeferredSincemust be the durable ISO streak start, and the function throws rather than accept an unmeasured wait as a fresh one. A consumer registering here must therefore own a durable streak anchor, not a call-time timestamp.services/MaintenanceBackpressureService.mjs:663— the existing registration call site, the shape a new registrant should follow.ai/services/memory-core/HealthService.mjs—foldHeavyMaintenanceStarvation, the consumer whose reach this bounds.The Fix
The residency repair registers as a waiter when it defers, and clears when it proceeds — so its wait becomes a measured fact rather than a log line. Whether it should additionally be admitted by the fairness gate is the open design question and deliberately not pre-decided here: registration makes it visible, admission would make it scheduled, and those are separable.
The narrower question a reviewer should press: is
isProviderWarmStillAdmittedthe only poll-and-skip consumer ofgetActiveHeavyMaintenanceTask(), or a representative of a class? A census of that method's callers belongs in this work — if others inspect-and-skip the same way, the fix is a shared registration helper rather than one call site.Acceptance Criteria
listActiveWaitersSyncwith a durabledeferredSincestreak anchor, and disappears when it proceeds.heavyMaintenanceStarvation.breachesand degrades aggregate health, through the existing #17049 fold with no change to that contract.registerWaiterSyncalready refuses the unmeasured case; the caller must supply the durable value).getActiveHeavyMaintenanceTask()is enumerated, and each is either a registered waiter or carries a recorded reason why it legitimately is not.Out of Scope
Admission/scheduling changes — the fairness gate's ranking is untouched by this work · #17132's slice budget, which is orthogonal and confirmed not to resolve this · the embedding fault that surfaced it · whether the residency repair should run during heavy maintenance at all, which is a policy question this ticket deliberately leaves open by making the wait measurable first.
Avoided Traps
Related
#17049 (the starvation health contract) · #17290 / PR #17292 (its freshness repair — the fold this gap sits upstream of) · #17132 (@neo-opus-grace, confirmed NOT a fix for this) · #16706 (external plane self-recovery, the adjacent theme) · #17072.
Live latest-open sweep: latest 20 open checked 2026-08-17T11:54Z, plus a
state:allkeyword sweep on four phrasings; nearest neighbours #16706 / #16948 / #17063 / #17072, no equivalent. A2A herd-window sweep clean.Origin Session ID: c992afd0-2e26-410e-b460-b480ccd0a240
Retrieval Hint:
query_raw_memories("provider residency repair poll-and-skip never registers waiter invisible starvation")