LearnNewsExamplesServices
Frontmatter
id14144
titleMaintenance-backpressure can indefinitely defer githubWorkflowSync during long re-embeds
stateClosed
labels
enhancementepicaiarchitecture
assigneesneo-opus-ada
createdAtJun 26, 2026, 10:46 PM
updatedAtJun 28, 2026, 1:26 AM
githubUrlhttps://github.com/neomjs/neo/issues/14144
authorneo-opus-ada
commentsCount5
parentIssuenull
subIssues
14185 Lease-service: maxActiveHoldMs fairness bound + wire shouldYieldHeavyMaintenanceLease for holders
14186 kbSync embedViaShadowSwap: between-batch heavy-lease yield-point (torn-read-free via #14146 resume)
subIssuesCompleted2
subIssuesTotal2
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtJun 28, 2026, 1:26 AM

Maintenance-backpressure can indefinitely defer githubWorkflowSync during long re-embeds

Closed v13.1.0/archive-v13-1-0-chunk-7 enhancementepicaiarchitecture
neo-opus-ada
neo-opus-ada commented on Jun 26, 2026, 10:46 PM

[EPIC re-scope — 2026-06-27] Originally a picker/config-defer fix; the descriptor V-B-A (see the correction comment) re-scoped it to heavy-maintenance lease fairness. Co-shaped with @neo-opus-grace.

Problem

githubWorkflowSync (and any starved heavy task) can be deferred indefinitely when a single heavy task holds the heavy-maintenance lease continuously — e.g. a one-time full KB re-embed (#14069/#14071) held the lease ~20h, staling the sandman handoff. The serialization is justified (githubWorkflowSync WRITES resources/content/ that kbSync EMBEDS — concurrent = torn read), so the fix is NOT to bypass the lease but to make a long HOLD yield fairly.

Intended solution — time-driven cooperative lease-yielding

A long-held lease yields at safe checkpoints so starved heavy tasks interleave, then the yielder re-acquires + resumes. Two composable parts (linked subs carry the ACs):

  • Lease-service side: a maxActiveHoldMs reactive fairness bound + the (already-built, currently-unconsumed) shouldYieldHeavyMaintenanceLease primitive (HeavyMaintenanceLeaseService.mjs:121) wired for holders to consult via a thin service method. Decision: time-driven, not waiter-driven — there is no waiter registry (deferred tasks just read the lease + self-defer); adding waiter-detection = new machinery on every deferred task, and the time-bound is the fairness backstop regardless.
  • kbSync yield-point side: embedViaShadowSwap releases the lease between batches on the yield-trigger; #14146's resume-marker + the preserve-not-promote shadow make the release-window torn-read-free — the live collection is untouched until the final atomic promote, so githubWorkflowSync writes resources/content/ freely during the yield, and kbSync re-reads the updated corpus on resume.

Builds directly on #14146 (resumable kbSync) + #14161 (shadow-swap resume). The yield substrate (shouldYieldHeavyMaintenanceLease + acquire/releaseHeavyMaintenanceLeaseSync) already exists — this epic wires it.

Avoided traps

  • NOT a picker force-run — defeated by syncGithubWorkflow.mjs's own withHeavyMaintenanceLease self-defer (the script self-defers on the held lease regardless of the picker).
  • NOT de-leasing githubWorkflowSync — the resources/content/ write-vs-embed conflict is real; the lease serialization is correct.

🤖 Epic re-scoped by Ada (@neo-opus-ada · Claude Opus 4.8, Claude Code). Co-shaped with @neo-opus-grace (she owns the kbSync yield-point sub; Ada owns the lease-service sub).

tobiu referenced in commit b703c66 - "feat(ai): wire heavy-maintenance lease cooperative-yield mechanism (#14144) (#14261) on Jun 27, 2026, 8:01 PM
tobiu referenced in commit 07549a7 - "feat(ai): kbSync cooperative heavy-maintenance-lease yield-point (#14186) (#14273) on Jun 28, 2026, 1:22 AM