Context
Operator observed ProcessSupervisor logs for github workflow sync showing periodic-sync:1800000 and flagged that the sync feels like it runs every 10-20 minutes. The live task is expensive: the operator notes the GitHub workflow sync is roughly a 20-minute task duration, so a 30-minute start-to-start cadence leaves only about 10 minutes of quiet time.
Release classification: post-release/agent-OS stability; not a v13 release-board blocker by itself.
Live latest-open sweep: checked latest 20 open issues at 2026-06-21T23:41Z; no equivalent completion-cooldown/cadence ticket found. Related tickets present: #13626 wired the scheduled task, #13750 diagnosed Golden Path freeze/sync interaction, and #13624 covers the broader orchestrator heavy-maintenance drain issue.
A2A in-flight sweep: checked latest 30 A2A messages at 2026-06-21T23:41Z; no competing lane-claim or lane-intent for this exact cadence fix.
The Problem
githubWorkflowSync is currently configured as a 30-minute periodic task, but the scheduler measures that cadence from lastRunAt, which is recorded at task start. For a task that runs around 20 minutes, the effective quiet time after completion is about 10 minutes:
- start at T+0m
- complete around T+20m
- eligible again at T+30m
- quiet after completion: roughly 10m
That is too aggressive for a heavyweight GitHub content sync and contributes to local resource drain while the orchestrator is already under heavy-maintenance pressure.
The Architectural Reality
ai/config.mjs and ai/config.template.mjs set githubWorkflowSyncMs to 30 * 60 * 1000 via NEO_ORCHESTRATOR_GITHUB_WORKFLOW_SYNC_INTERVAL_MS.
ai/daemons/orchestrator/scheduling/registry.mjs makes githubWorkflowSync due when now - state.githubWorkflowSync.lastRunAt >= intervals.githubWorkflowSync.
ai/daemons/orchestrator/services/TaskStateService.mjs sets lastRunAt = Date.now() in markStarted(), while lastSuccessAt is only written in markCompleted() / markReady().
- The Knowledge Base confirms #13626 documented this as
intervalMs > 0 && now - lastRunAt >= intervalMs; no separate completion cooldown exists for this lane.
The Fix
- Increase the default
githubWorkflowSyncMs from 30 minutes to 2 hours. Keep the env var override intact so local operators can choose 1 hour if desired.
- Change the
githubWorkflowSync due calculation to prefer a terminal timestamp (lastSuccessAt or lastErrorAt) over lastRunAt so the cadence is effectively finish-to-start for this expensive child task.
- Preserve bootstrap behavior: if no terminal timestamp exists, fall back to
lastRunAt and then 0.
- Add focused scheduler tests proving:
- a completed 20-minute run is not due 30 minutes after start when the completion timestamp is only 10 minutes old;
- the task becomes due after the configured completion cooldown elapses;
- failed terminal timestamps also cool down the retry loop.
- Update the config default test from 30 minutes to 2 hours.
Contract Ledger
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
orchestrator.intervals.githubWorkflowSyncMs |
ai/config.template.mjs, ai/config.mjs, config template unit test |
default 2 hours |
NEO_ORCHESTRATOR_GITHUB_WORKFLOW_SYNC_INTERVAL_MS may override |
config source + test |
focused config unit assertion |
githubWorkflowSync due calculation |
ai/daemons/orchestrator/scheduling/registry.mjs |
use terminal timestamp before start timestamp |
fall back to lastRunAt / 0 for bootstrap |
scheduler unit test |
registry spec with success/failure terminal timestamps |
Decision Record impact
Aligned with ADR 0019 (config SSOT) and ADR 0022 (heavy-maintenance scheduling fairness). This narrows one heavy-maintenance lane's cadence semantics without changing the overall scheduler taxonomy.
Acceptance Criteria
Out of Scope
- Changing KB sync, primary-dev-sync, tenant-repo-sync, dream, or golden-path cadence.
- Redesigning the heavy-maintenance picker or lease semantics.
- Reworking GitHub sync content phases or incremental sync internals.
- Operator-local env override decisions beyond preserving the existing env var.
Avoided Traps
- Do not just raise the interval while keeping start-to-start semantics; long runtimes would still eat most of the quiet period.
- Do not apply completion-based cadence globally without auditing each task. Some lanes intentionally schedule from attempt/start time.
- Do not disable GitHub workflow sync entirely; #13750 shows stale graph/content sync can also derail the system.
Related
Related: #13626
Related: #13750
Related: #13624
Origin Session ID: 43e8ab91-e980-4303-b70f-898d8c4ae98e
Retrieval Hint: github workflow sync cadence start-to-start completion cooldown lastRunAt lastSuccessAt periodic-sync:1800000
Context
Operator observed
ProcessSupervisorlogs forgithub workflow syncshowingperiodic-sync:1800000and flagged that the sync feels like it runs every 10-20 minutes. The live task is expensive: the operator notes the GitHub workflow sync is roughly a 20-minute task duration, so a 30-minute start-to-start cadence leaves only about 10 minutes of quiet time.Release classification: post-release/agent-OS stability; not a v13 release-board blocker by itself.
Live latest-open sweep: checked latest 20 open issues at 2026-06-21T23:41Z; no equivalent completion-cooldown/cadence ticket found. Related tickets present: #13626 wired the scheduled task, #13750 diagnosed Golden Path freeze/sync interaction, and #13624 covers the broader orchestrator heavy-maintenance drain issue.
A2A in-flight sweep: checked latest 30 A2A messages at 2026-06-21T23:41Z; no competing lane-claim or lane-intent for this exact cadence fix.
The Problem
githubWorkflowSyncis currently configured as a 30-minute periodic task, but the scheduler measures that cadence fromlastRunAt, which is recorded at task start. For a task that runs around 20 minutes, the effective quiet time after completion is about 10 minutes:That is too aggressive for a heavyweight GitHub content sync and contributes to local resource drain while the orchestrator is already under heavy-maintenance pressure.
The Architectural Reality
ai/config.mjsandai/config.template.mjssetgithubWorkflowSyncMsto30 * 60 * 1000viaNEO_ORCHESTRATOR_GITHUB_WORKFLOW_SYNC_INTERVAL_MS.ai/daemons/orchestrator/scheduling/registry.mjsmakesgithubWorkflowSyncdue whennow - state.githubWorkflowSync.lastRunAt >= intervals.githubWorkflowSync.ai/daemons/orchestrator/services/TaskStateService.mjssetslastRunAt = Date.now()inmarkStarted(), whilelastSuccessAtis only written inmarkCompleted()/markReady().intervalMs > 0 && now - lastRunAt >= intervalMs; no separate completion cooldown exists for this lane.The Fix
githubWorkflowSyncMsfrom 30 minutes to 2 hours. Keep the env var override intact so local operators can choose 1 hour if desired.githubWorkflowSyncdue calculation to prefer a terminal timestamp (lastSuccessAtorlastErrorAt) overlastRunAtso the cadence is effectively finish-to-start for this expensive child task.lastRunAtand then0.Contract Ledger
orchestrator.intervals.githubWorkflowSyncMsai/config.template.mjs,ai/config.mjs, config template unit testNEO_ORCHESTRATOR_GITHUB_WORKFLOW_SYNC_INTERVAL_MSmay overridegithubWorkflowSyncdue calculationai/daemons/orchestrator/scheduling/registry.mjslastRunAt/0for bootstrapDecision Record impact
Aligned with ADR 0019 (config SSOT) and ADR 0022 (heavy-maintenance scheduling fairness). This narrows one heavy-maintenance lane's cadence semantics without changing the overall scheduler taxonomy.
Acceptance Criteria
githubWorkflowSyncMsdefaults to 2 hours in both materialized and template config.githubWorkflowSyncdoes not become due until the configured interval has elapsed after the latest terminal timestamp when one exists.lastRunAt/0fallback.Out of Scope
Avoided Traps
Related
Related: #13626 Related: #13750 Related: #13624
Origin Session ID: 43e8ab91-e980-4303-b70f-898d8c4ae98e
Retrieval Hint:
github workflow sync cadence start-to-start completion cooldown lastRunAt lastSuccessAt periodic-sync:1800000