Context
Sub of #13755 (orchestrator heavy-lease: deferred/held runs log as 'completed'). GPT's #13755 epic-review flagged the kb-sync / PrimaryRepoSyncService child-outcome propagation surface as needing an explicit native sub rather than remaining comment-only. This is that sub — the C.2 (child→orchestrator outcome channel) pattern applied to kbSync, the sibling of #13777/#13778 (miniSummary).
The Problem
kbSync spawns ai/scripts/maintenance/syncKnowledgeBase.mjs, which runs the sync under withHeavyMaintenanceLease. When the lease is held by another task, withHeavyMaintenanceLease returns a deferred outcome (previousStatus: 'held' / the inherited-token-stale marker), and the child exits 0 — but it prints only human-readable console.log status lines, NOT a structured outcome JSON. ProcessSupervisorService therefore records completed + refreshes lastSuccessAt for a run that did NO embedding. This is the documented #13755 root: kb-sync deferred 502× with a 4-day embedding gap (06-17→06-20), every "completed successfully" line a deferral-masked-as-completion.
Same false-green class #13778 fixed for memory-summary-backfill — but kbSync needs BOTH halves (miniSummary's child already emitted structured JSON; kbSync's does not).
The Architectural Reality
ai/scripts/maintenance/syncKnowledgeBase.mjs — runs KB_DatabaseService.syncDatabase() under withHeavyMaintenanceLease; captures outcome locally but does not emit it as JSON.
withHeavyMaintenanceLease (HeavyMaintenanceLeaseService.mjs) returns previousStatus on deferral (the #13764 marker) + the task result on success.
ProcessSupervisorService.classifySuccessfulChildOutcome (#13778) already maps a child's structured outcome → completed/skipped, but only memory-summary-backfill opts in (captureStdoutJson).
The Fix (2 halves, mirroring #13777/#13778)
- Child-emit:
syncKnowledgeBase.mjs prints a structured outcome JSON on stdout — {deferred: true, reason: <previousStatus>} when the lease was held / inherited-token-stale; {embedded, deleted, ...} on real work.
- Supervisor-capture: add
captureStdoutJson: true to the kbSync task definition + extend classifySuccessfulChildOutcome so a deferred/no-embedding kbSync outcome records skipped (does NOT refresh lastSuccessAt), not completed.
Acceptance Criteria
Out of Scope
- The PrimaryRepoSyncService child-outcome (GPT named it alongside kb-sync; if it has the same surface, a separate sibling sub).
- The within-day fairness reducing kbSync deferrals (#13780) + the time-of-day batching (#13782) — those reduce the deferrals; this makes the deferrals OBSERVABLE.
Related
- Parent: #13755 (heavy-lease deferred-as-completed epic)
- Pattern siblings: #13777 / #13778 (miniSummary child-outcome)
- Lease marker: #13764 (
withHeavyMaintenanceLease previousStatus)
Live latest-open sweep: checked latest 30 open issues 2026-06-21; no existing kb-sync child-outcome capture sub.
Origin Session ID: 80932414-00dc-4d2e-96e6-d0bcf1529733
Retrieval Hint: "kb-sync child-outcome capture deferred skipped syncKnowledgeBase false-green C.2"
Context
Sub of #13755 (orchestrator heavy-lease: deferred/held runs log as 'completed'). GPT's #13755 epic-review flagged the kb-sync / PrimaryRepoSyncService child-outcome propagation surface as needing an explicit native sub rather than remaining comment-only. This is that sub — the C.2 (child→orchestrator outcome channel) pattern applied to
kbSync, the sibling of #13777/#13778 (miniSummary).The Problem
kbSyncspawnsai/scripts/maintenance/syncKnowledgeBase.mjs, which runs the sync underwithHeavyMaintenanceLease. When the lease is held by another task,withHeavyMaintenanceLeasereturns a deferred outcome (previousStatus: 'held'/ the inherited-token-stale marker), and the child exits 0 — but it prints only human-readableconsole.logstatus lines, NOT a structured outcome JSON.ProcessSupervisorServicetherefore recordscompleted+ refresheslastSuccessAtfor a run that did NO embedding. This is the documented #13755 root: kb-sync deferred 502× with a 4-day embedding gap (06-17→06-20), every "completed successfully" line a deferral-masked-as-completion.Same false-green class #13778 fixed for
memory-summary-backfill— but kbSync needs BOTH halves (miniSummary's child already emitted structured JSON; kbSync's does not).The Architectural Reality
ai/scripts/maintenance/syncKnowledgeBase.mjs— runsKB_DatabaseService.syncDatabase()underwithHeavyMaintenanceLease; capturesoutcomelocally but does not emit it as JSON.withHeavyMaintenanceLease(HeavyMaintenanceLeaseService.mjs) returnspreviousStatuson deferral (the #13764 marker) + the task result on success.ProcessSupervisorService.classifySuccessfulChildOutcome(#13778) already maps a child's structured outcome → completed/skipped, but onlymemory-summary-backfillopts in (captureStdoutJson).The Fix (2 halves, mirroring #13777/#13778)
syncKnowledgeBase.mjsprints a structured outcome JSON on stdout —{deferred: true, reason: <previousStatus>}when the lease was held / inherited-token-stale;{embedded, deleted, ...}on real work.captureStdoutJson: trueto thekbSynctask definition + extendclassifySuccessfulChildOutcomeso a deferred/no-embedding kbSync outcome recordsskipped(does NOT refreshlastSuccessAt), notcompleted.Acceptance Criteria
skipped(notcompleted);lastSuccessAtnot refreshed.completed+ the embedded/deleted counts.Out of Scope
Related
withHeavyMaintenanceLeasepreviousStatus)Live latest-open sweep: checked latest 30 open issues 2026-06-21; no existing kb-sync child-outcome capture sub.
Origin Session ID: 80932414-00dc-4d2e-96e6-d0bcf1529733
Retrieval Hint: "kb-sync child-outcome capture deferred skipped syncKnowledgeBase false-green C.2"