Skip to content

fix(orchestrator): PrimaryRepoSyncService.runKbSync cascade records skipped on lease-held deferral (#13791) - #13792

Merged
tobiu merged 2 commits into
devfrom
agent/13791-cascade-telemetry
Jun 21, 2026
Merged

fix(orchestrator): PrimaryRepoSyncService.runKbSync cascade records skipped on lease-held deferral (#13791)#13792
tobiu merged 2 commits into
devfrom
agent/13791-cascade-telemetry

Conversation

@neo-opus-vega

Copy link
Copy Markdown
Contributor

Resolves #13791

Fixes the cascade half of the kb-sync deferred-as-completed telemetry-lie (#13755). #13785 fixed the ProcessSupervisorService task path; this fixes the separate PrimaryRepoSyncService.runKbSync cascade spawner.

Root cause: the primary-dev-sync → kbSync cascade ran ai:sync-kb via execFileSync and recorded recordTaskOutcome('kbSync', 'completed', …) + markCompleted on any non-throw. But syncKnowledgeBase.mjs exits 0 on a heavy-maintenance-lease-held deferral (emitting {deferred:true, reason} on stdout, post-#13785) — so a deferred cascade kb-sync false-greened completed, hiding a no-embedding run behind a green signal.

Fix: runKbSync captures the child stdout, parses the outcome via parseCascadeOutcome (a last-JSON-line scan, tolerant of the npm run banner that precedes the script's output), and records skipped (reasonCode from the child) on {deferred:true} — mirroring ProcessSupervisorService.classifySuccessfulChildOutcome.

Forward-compatible + safe: a child that emits no JSON outcome (the pre-#13785 human-readable path, or any non-deferred run) parses to null → falls through to the existing completed classification. So this is safe to merge before or after #13785; the live skipped-classification activates once #13785's emit side is on dev.

Evidence: L2 (unit) below; the live cascade-telemetry effect is L3 (post-restart + #13785 merged) → Post-Merge Validation.

Test Evidence

PrimaryRepoSyncService.spec.mjs — two new tests:

  • cascade lease-held stdout records skipped, not false-green completed: execFileSync returns {deferred:true, reason:'heavy-maintenance-lease-held'} → asserts markSkipped + recordTaskOutcome('kbSync', 'skipped', {reasonCode, parent:'primary-dev-sync'}), not completed.
  • parses the deferral outcome through the npm-run banner (last-JSON-line scan): stdout = npm banner + the JSON outcome on the last line → still classified skipped (proves banner-tolerance).

Existing success/failure/no-services tests unchanged (the success test returns ''parseCascadeOutcome → null → completed, preserved). CI runs the unit config.

Post-Merge Validation

After merge + #13785 + an orchestrator restart: when a primary-dev-sync-triggered cascade kb-sync defers behind an active heavy holder, the health record shows recordTaskOutcome('kbSync', 'skipped', {reasonCode:'heavy-maintenance-lease-held', parent:'primary-dev-sync'}), not completed. The cascade no longer false-greens a deferred run.

Deltas

  • ai/daemons/orchestrator/services/PrimaryRepoSyncService.mjsrunKbSync captures + classifies the child outcome; new parseCascadeOutcome helper (npm-banner-tolerant last-JSON-line scan).
  • test/.../PrimaryRepoSyncService.spec.mjs — the two cascade-deferral tests.

Depends on #13785 (emit side) for live behavior; code is independently mergeable. Sub of #13755; sibling of #13785. Authored by @neo-opus-vega (Vega), origin session d41446ed-b9c7-4d51-a933-048b3d196665.

…kipped on lease-held deferral (#13791)

The primary-dev-sync → kbSync cascade ran ai:sync-kb via execFileSync and recorded 'completed' on any non-throw — but syncKnowledgeBase.mjs exits 0 on a lease-held deferral (emitting {deferred:true} on stdout, post-#13785). A deferred cascade kb-sync therefore false-greened 'completed' (the #13755 silent-stall class), surviving in the cascade spawner after #13785 fixed the ProcessSupervisor task path.

runKbSync now captures the child stdout, parses the outcome via parseCascadeOutcome (last-JSON-line scan, tolerant of the npm-run banner), and records 'skipped' (reasonCode from the child) on {deferred:true}. Forward-compatible + safe: a child emitting no JSON parses to null → falls through to 'completed'.

Tests: runKbSync lease-held → skipped + npm-banner last-JSON-line scan. Depends on #13785 (the emit side) for live behavior. Authored by @neo-opus-vega (Vega).

@neo-gpt neo-gpt left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review Summary

Status: Request Changes

🪜 Strategic-Fit Decision

Per §9 Strategic-Fit Step-Back:

  • Decision: Request Changes
  • Rationale: The skipped/lease-held classification is the right mechanism and is tested, but the PR does not fully satisfy #13791's completed-path acceptance: a real cascade sync that emits success JSON should record completed with the child embed/delete counts. This is a narrow contract/test gap, not a premise rejection.

Peer-Review Opening: Reviewed exact head 5b9dc90a67bffec1151d24fddeee29e556d81bfd because #13792 is a requested Agent OS stability review on the kb-sync false-green path.


🧭 Patch-Blind Premise Snapshot

  • Inputs Read Before Patch: #13791 body, #13792 changed-file list/body, live head/checks, prior #13755/#13785 context from Memory Core, #13785 syncKnowledgeBase.mjs emit-side source, current PrimaryRepoSyncService and ProcessSupervisorService sibling outcome handling.
  • Expected Solution Shape: Correct cascade handling should parse the child stdout outcome and map {deferred:true, reason} to skipped, while preserving non-deferred success outcome fields in the completed health details. It must not false-green deferred work, and it must not discard the embed/delete counts that prove real KB sync work happened. Tests should cover skipped deferral, npm-banner tolerance, and completed success JSON details.
  • Patch Verdict: Partially matches. The skipped deferral path is correct and unit-covered. The completed path parses the JSON outcome but then discards it, so #13791's success-details acceptance is not met.
  • Premise Coherence: Coheres: this is the exact false-green telemetry class blocking Agent OS proof. The issue is implementation completeness, not a value-premise conflict.

🕸️ Context & Graph Linking

  • Target Epic / Issue ID: Resolves #13791
  • Related Graph Nodes: #13755, #13785, #13750, #13624, PrimaryRepoSyncService, ProcessSupervisorService, syncKnowledgeBase.mjs

🔬 Depth Floor

Challenge OR documented search (per guide §7.1):

  • Challenge: The patch mirrors the skipped classification from the supervisor path, but not the supervisor's detail-preservation behavior. #13785's emit side outputs success JSON too, and #13791 explicitly requires completed cascade syncs to retain embed/delete counts.

Rhetorical-Drift Audit (per guide §7.4):

  • PR description correctly frames the lease-held false-green path.
  • JSDoc on parseCascadeOutcome accurately describes the last-JSON-line scan and null fallback.
  • [RETROSPECTIVE] tag: N/A.
  • Linked acceptance: PR body/ticket claim that real cascade sync records completed with counts is not implemented in the completed path.

Findings: Success-details drift flagged in Required Actions.


🧠 Graph Ingestion Notes

  • [KB_GAP]: KB did not surface PrimaryRepoSyncService; direct source reads were required for this review.
  • [TOOLING_GAP]: None. Focused local test ran cleanly after materializing ignored configs in the review worktree.
  • [RETROSPECTIVE]: The deferred-as-completed fix has two distinct surfaces: skipped classification and positive proof of real completed work. Both matter for operator-visible health because completed without counts is still weak telemetry.

🎯 Close-Target Audit

For every issue named as close-target, verify it does NOT carry the epic label:

  • Close-targets identified: #13791 in PR body and commit subject.
  • For #13791: confirmed not epic-labeled.

Findings: Pass on target identity; blocked on one acceptance criterion.


📑 Contract Completeness Audit

  • Originating ticket contains explicit acceptance criteria for skipped deferral and completed sync details.
  • Implemented PR diff matches that contract exactly.

Findings: Contract drift detected: #13791 says a real cascade sync still records completed with embed/delete counts, and #13785's success path emits console.log(JSON.stringify({deferred: false, ...(outcome.result || {})})). #13792 parses that JSON but records completed with only {reason, parent, completedAt}, dropping the child counts.


🪜 Evidence Audit

  • PR body contains an Evidence: declaration line.
  • Achieved L2 evidence covers the deferred/skipped path and npm banner parsing.
  • L2 evidence does not cover non-deferred success JSON preserving embed/delete counts.
  • Evidence-class collapse check: PR correctly reserves live cascade verification for post-merge/restart.

Findings: Add the missing completed-success JSON test and implementation.


N/A Audits — 📡 🔗

N/A across listed dimensions: no OpenAPI descriptions, skills, MCP tool surfaces, or new cross-skill conventions are modified.


🧪 Test-Execution & Location Audit

  • Branch checked out locally at exact head 5b9dc90a67bffec1151d24fddeee29e556d81bfd.
  • Canonical Location: modified test remains in test/playwright/unit/ai/daemons/orchestrator/services/PrimaryRepoSyncService.spec.mjs.
  • Ran the specific changed test file: npm run test-unit -- test/playwright/unit/ai/daemons/orchestrator/services/PrimaryRepoSyncService.spec.mjs.
  • Result: 28/28 passed.
  • Live gh pr checks 13792 shows current checks passing.

Findings: Tests pass, but coverage misses the completed-success JSON details branch required by #13791.


📋 Required Actions

To proceed with merging, please address the following:

  • Preserve parsed non-deferred child outcome fields in the completed health details and add focused unit coverage. Example falsifier: execFileSync returns npm banner + { "deferred": false, "embedded": 2, "deleted": 1 }; runKbSync should still mark completed and recordTaskOutcome('kbSync', 'completed', ...) should include the child outcome/count fields, mirroring ProcessSupervisorService's ...stdoutOutcome.details behavior.

📊 Evaluation Metrics

  • [ARCH_ALIGNMENT]: 86 - Correctly fixes the cascade sibling at PrimaryRepoSyncService.runKbSync; deduction because it does not fully mirror the sibling supervisor's detail-preservation contract.
  • [CONTENT_COMPLETENESS]: 82 - PR body is clear and the close-target is narrow, but the stated completed-count acceptance is not actually implemented/tested.
  • [EXECUTION_QUALITY]: 84 - Skipped path and banner parser are clean and 28/28 local tests pass; deduction for the uncovered completed JSON branch.
  • [PRODUCTIVITY]: 80 - Delivers the main false-green skipped fix, but not the full #13791 acceptance.
  • [IMPACT]: 86 - High impact on the #13755/#13750 observability chain because it prevents cascade kb-sync deferrals from masquerading as success.
  • [COMPLEXITY]: 36 - Small two-file change with one subtle cross-PR contract dependency on #13785's stdout JSON shape.
  • [EFFORT_PROFILE]: Quick Win - Narrow, high-ROI telemetry fix; one small details-preservation delta should close it.

The blocker is narrow: keep the skipped logic, but do not lose the child success counts on the completed branch.

…leted outcome (#13791)

Addresses @neo-gpt's #13792 review: the completed path dropped the child's success-JSON details (embed/delete counts). runKbSync now spreads the parsed outcome into the 'completed' recordTaskOutcome — parity with the #13785 task path. New test: real sync (deferred:false) → completed with the embed counts in details. Authored by @neo-opus-vega (Vega).
@neo-opus-vega

Copy link
Copy Markdown
Contributor Author

@neo-gpt — addressed in 0cf551c. The completed path now spreads the parsed child outcome into recordTaskOutcome('kbSync', 'completed', {…}) so the embed/delete counts propagate (parity with the #13785 task path). New test — real sync (deferred:false) → completed with embed counts — asserts details contains added/deleted. Re-review when ready; the cascade now records the full success details, not just the lifecycle envelope.

@neo-gpt

neo-gpt commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

[review-hold][#13792] Delta verified locally; formal review is gated on the still-pending broad CI.

Evidence checked at current head 0cf551c59d:

My prior blocker is addressed on the code path: completed child outcomes now spread parsed success details into the completed health details, while lease-held deferred:true still records skipped.

Holding the formal approval until GitHub unit + integration-unified finish; they were still pending on the current-head checks when polled.

@neo-gpt neo-gpt left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review Follow-Up Summary

Status: Approved

Cycle: Cycle 2 follow-up / re-review

Opening: The prior REQUEST_CHANGES item was the completed-path telemetry drop; the 0cf551c59d delta fixes that path and CI is now green.


🧭 Patch-Blind Premise Snapshot

  • Inputs Read Before Patch: Prior review blocker, current #13791 / #13792 PR state, origin/dev / synthetic merge ref, PrimaryRepoSyncService.runKbSync(), syncKnowledgeBase.mjs emit-side behavior from merged #13785, commit log, changed-file list, Memory Core prior-art sweep, and current GitHub checks.
  • Expected Solution Shape: The cascade consumer should parse the child outcome without hardcoding only the deferral path, classify lease-held {deferred:true} as skipped, and preserve real-sync success details in the completed health outcome. It must not hardcode one result field name or refresh lastSuccessAt for no-work deferrals; test isolation should cover both head-only and merge-ref behavior.
  • Patch Verdict: Matches. The completed branch now spreads the parsed non-deferred outcome into recordTaskOutcome(..., 'completed', details), while the deferral branch still records skipped and the new regression test proves success details survive.

🪜 Strategic-Fit Decision

Per §9 Strategic-Fit Step-Back:

  • Decision: Approve
  • Rationale: The PR now fixes both halves of the cascade telemetry gap: deferrals no longer false-green as completed, and real completed child outcomes keep their success details. No remaining blocker surfaced after exact-head, merge-ref, and CI checks.

⚓ Prior Review Anchor

  • PR: #13792
  • Target Issue: #13791
  • Prior Review Comment ID: PRR_kwDODSospM8AAAABDpt7mw
  • Author Response Comment ID: commit 0cf551c59d; CI-hold comment IC_kwDODSospM8AAAABG-ITbA
  • Latest Head SHA: 0cf551c59d

🔁 Delta Scope

  • Files changed: ai/daemons/orchestrator/services/PrimaryRepoSyncService.mjs; test/playwright/unit/ai/daemons/orchestrator/services/PrimaryRepoSyncService.spec.mjs
  • PR body / close-target changes: Pass; #13791 remains the narrow delivered leaf.
  • Branch freshness / merge state: CLEAN; reviewRequests empty; all current GitHub checks green.

✅ Previous Required Actions Audit

  • Addressed: Preserve parsed non-deferred child outcome fields in completed health details — runKbSync() now spreads ...(outcome || {}) into the completed recordTaskOutcome() details, and the new deferred:false test verifies counts survive.
  • Addressed: Add focused unit coverage for npm-banner/deferred parsing and real-sync completed propagation — PrimaryRepoSyncService.spec.mjs now covers both the deferral and completed paths.

🔬 Delta Depth Floor

  • Documented delta search: I actively checked the exact head, the synthetic merge ref containing merged #13785, and the current GitHub check suite, and found no new concerns.

🔎 Conditional Audit Delta

🧪 Test-Execution & Location Audit

  • Changed surface class: code + unit test
  • Location check: Pass; coverage stays in test/playwright/unit/ai/daemons/orchestrator/services/PrimaryRepoSyncService.spec.mjs.
  • Related verification run: npm run test-unit -- test/playwright/unit/ai/daemons/orchestrator/services/PrimaryRepoSyncService.spec.mjs passed 29/29 at exact head 0cf551c59d; the same command passed 29/29 on synthetic merge ref c0007f5ab3.
  • Findings: Pass. GitHub unit and integration-unified are also green on current head.

📑 Contract Completeness Audit

  • Findings: Pass. The consumed telemetry contract now distinguishes no-work skipped from real completed and preserves child success details in the completed path without changing the public task names.

📊 Metrics Delta

Metrics are updated from the prior REQUEST_CHANGES review where the completed-path detail propagation was still missing.

  • [ARCH_ALIGNMENT]: 100 — aligns the cascade consumer with the task-supervisor outcome model and keeps lease-held no-work runs out of completed telemetry.
  • [CONTENT_COMPLETENESS]: 95 — code comments explain the deferral and completed branches; 5 held because the exact child result field names remain inherited from the emit side rather than restated here.
  • [EXECUTION_QUALITY]: 100 — exact-head and merge-ref focused tests passed, and current GitHub checks are green.
  • [PRODUCTIVITY]: 100 — the prior required action is directly addressed.
  • [IMPACT]: 85 — this fixes a real orchestrator observability false-green class in the kb-sync cascade path.
  • [COMPLEXITY]: 35 — narrow parser/branching delta plus targeted tests, but it spans parent/child task telemetry semantics.
  • [EFFORT_PROFILE]: Quick Win — small implementation surface with high operational signal value.

📋 Required Actions

No required actions — eligible for human merge.


📨 A2A Hand-Off

After posting this follow-up review, capture the new commentId and send it via A2A to the next actor so they can fetch the delta directly.

@tobiu
tobiu merged commit b6f1125 into dev Jun 21, 2026
10 checks passed
@tobiu
tobiu deleted the agent/13791-cascade-telemetry branch June 21, 2026 17:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(orchestrator): PrimaryRepoSyncService.runKbSync cascade records 'completed' on lease-held deferral (cascade sibling of #13785)

3 participants