Context
Operator friction report (2026-07-21): agents are no longer supposed to invoke sync_all manually — it is orchestrator territory. Empirical anchor from the same evening: an agent (Iris) called it twice (20:57Z, 21:00Z) pushing a ticket-body edit; both calls timed out at the MCP boundary (MCP error -32001). gh issue edit --body-file did the same push in ~1s.
Amended 2026-07-22T00:2xZ per Euclid's intake (needs-narrowing + needs-contract-alignment, comment on this ticket): two foundational runtime claims in the original body were false and are corrected below; the three-edit doc fix is replaced by the MCP-surface contract decision + Contract Ledger.
The Problem
The substrate contradicts itself about who may call sync_all, and the agent-facing surface recruits exactly the wrong behavior:
- The live tool-selection description is only "Sync GitHub Issues & Releases" (this server uses
compactToolDescriptions: true; /sync-all has no x-neo-tool-summary) — the misleading first-selection affordance sits in the compact line, not just the lazy handbook.
openapi.yaml update_issue_relationship Workflow step 3: "Run sync_all…" — and McpServerListToolsSmoke.spec.mjs:613 positively LOCKS that stale instruction as expected test content.
.agents/skills/ticket-create/references/ticket-create-workflow.md §10 routes body edits through sync_all.
.agents/skills/pull-request/references/pull-request-workflow.md:86 + sync-all-constraints.md teach agents to switch to dev and invoke the tool; .agents/skills/create-skill/references/skill-authoring-guide.md:107 uses that stale rule as its Map-vs-Atlas example.
learn/agentos/tooling/TroubleshootingToolCalls.md:41, learn/agentos/GitHubWorkflow.md:73,90, learn/benefits/ArchitectureOverview.md:258, and syncGithubWorkflow.mjs:16-31 all present it as agent-callable.
toolService.mjs:338,366's own guard remediation names the wrong owner (PrimaryRepoSyncService) — part of the bug, not the source of truth.
The Architectural Reality (corrected per Euclid, live 1d7fa14474)
- The scheduled owner is
githubWorkflowSync (taskDefinitions.mjs:366-371 → ai/scripts/maintenance/syncGithubWorkflow.mjs), NOT PrimaryRepoSyncService (the separate primary-dev-sync lane, taskDefinitions.mjs:410-414). PR #13684 merged the local-only scheduler lane 2026-06-21.
- The MCP handler and the scheduled CLI resolve to the same
SyncService.runFullSync() entry (toolService.mjs:373; syncGithubWorkflow.mjs:18-31,90-92) — and both perform phase-2 graph ingestion (SyncService.mjs:371-380). The original "daemon does more" claim was false.
- The real collision: the CLI wrapper acquires
withHeavyMaintenanceLease (syncGithubWorkflow.mjs:84-93), while the MCP mapping calls runFullSync() behind only the dev-branch guard (toolService.mjs:352-373) — the manual MCP path bypasses the shared heavy-maintenance lease and is request-timeout-prone (tonight's -32001 symptoms).
- Freshness consequence stands:
resources/content/** reflects the last completed scheduled run and can lag hours; live gh/MCP access is the only fresh source.
- ADR framing:
adr-aligned — ADR 0014's local-only scheduler taxonomy via PR #13684; ADR 0004 constrains the repair to preserve an operator/canonical rebuild path (do not eliminate the primitive).
The Fix (contract decision — recommendation per Euclid's intake, ratified here)
Remove sync_all from the agent MCP surface; retain npm run ai:sync-github-workflow as the operator/canonical rebuild entry point. (Fallback if removal is rejected: an explicit server-side authorization/projection contract — changing extended to admin alone does not constrain an unprojected full developer/operator server.)
- Deregister
/sync-all from the agent-visible tool surface (or project it away for agent identities); the scheduled githubWorkflowSync lane remains the only canonical invoker.
- Fix the stale guard remediation text in
toolService.mjs:338,366 (owner = githubWorkflowSync).
- Repair the stale guidance chain:
update_issue_relationship step 3 (+ the McpServerListToolsSmoke.spec.mjs:613 lock), ticket-create-workflow.md §10 (route body edits through gh issue edit), retire pull-request/references/sync-all-constraints.md + its pull-request-workflow.md:86 route, update the create-skill example, and align TroubleshootingToolCalls.md:41, GitHubWorkflow.md:73,90, ArchitectureOverview.md:258, syncGithubWorkflow.mjs:16-31 header docs. Do NOT touch accepted ADR 0004's historical text.
- Substrate economy: the retirement of
sync-all-constraints.md nets a reduction in agent-loaded instruction surface (no second "never call" layer).
Contract Ledger Matrix
| Contract |
Source of Authority |
Required Behavior |
Fallback / Evidence |
| Scheduled lane |
githubWorkflowSync → syncGithubWorkflow.mjs → SyncService.runFullSync() |
sole canonical invoker; holds withHeavyMaintenanceLease |
taskDefinitions + CLI wrapper stay unchanged |
sync_all MCP surface |
tool registration + compact description |
not visible/callable to agent identities (or explicit authorization projection) |
negative dispatch test; smoke spec updated |
update_issue_relationship freshness guidance |
openapi handbook + smoke spec |
names the scheduled lane + live-API reads; no manual sync instruction |
spec expectation updated |
| Guard remediation text |
toolService.mjs:338,366 |
names githubWorkflowSync |
grep shows zero PrimaryRepoSyncService remnants in remediation |
| Skill/guide surfaces |
the 8 files above |
retired or corrected; sync-all-constraints.md removed |
create-skill example updated; no Map-layer bloat added |
| Operator rebuild path |
npm run ai:sync-github-workflow |
retained (ADR 0004) |
unchanged CLI entry |
Acceptance Criteria
Out of Scope
- Changing daemon scheduling, the
#11503 lease, SyncService.runFullSync(), or phase-2 ingestion.
- Diagnosing tonight's MCP
-32001 timeouts beyond recording them.
list_issues staleness (#15603 owns that tool).
- Accepted ADR 0004 text (historical record).
Avoided Traps / Gold Standards Rejected
- Warning-only contract (the original three-edit doc fix) — leaves the forbidden operation callable; the compact list line stays misleading.
extended→admin relabel as the constraint — does not constrain an unprojected full developer/operator server.
- Preserving
sync-all-constraints.md + adding a second "never call" layer — substrate bloat; retire instead.
- Rewriting ADR 0004 history — the repair preserves the operator/canonical rebuild primitive.
Related
#13684 (merged scheduler lane — the successor that reframed ownership), #8408 (pre-daemon description tuning), #11503 (heavy-maintenance lease)
- #15603 (sibling:
list_issues staleness), #15660 (the evening's timeout reproducer)
- Origin Session ID: eb9be68e-9401-4ecd-9762-ef519b4091ed
Sweeps: live latest-open sweep at 2026-07-21T21:05Z (no equivalent); KB semantic (#8408/#11503/#12065 context, no dup); mailbox in-flight clean. Euclid's intake corrections absorbed 2026-07-22T00:2xZ.
Retrieval Hint: "sync_all agent MCP surface removal githubWorkflowSync heavy-maintenance lease bypass"; anchors toolService.mjs:338,366,373, syncGithubWorkflow.mjs:84-93, McpServerListToolsSmoke.spec.mjs:613.
Context
Operator friction report (2026-07-21): agents are no longer supposed to invoke
sync_allmanually — it is orchestrator territory. Empirical anchor from the same evening: an agent (Iris) called it twice (20:57Z, 21:00Z) pushing a ticket-body edit; both calls timed out at the MCP boundary (MCP error -32001).gh issue edit --body-filedid the same push in ~1s.Amended 2026-07-22T00:2xZ per Euclid's intake (needs-narrowing + needs-contract-alignment, comment on this ticket): two foundational runtime claims in the original body were false and are corrected below; the three-edit doc fix is replaced by the MCP-surface contract decision + Contract Ledger.
The Problem
The substrate contradicts itself about who may call
sync_all, and the agent-facing surface recruits exactly the wrong behavior:compactToolDescriptions: true;/sync-allhas nox-neo-tool-summary) — the misleading first-selection affordance sits in the compact line, not just the lazy handbook.openapi.yamlupdate_issue_relationshipWorkflow step 3: "Runsync_all…" — andMcpServerListToolsSmoke.spec.mjs:613positively LOCKS that stale instruction as expected test content..agents/skills/ticket-create/references/ticket-create-workflow.md§10 routes body edits throughsync_all..agents/skills/pull-request/references/pull-request-workflow.md:86+sync-all-constraints.mdteach agents to switch todevand invoke the tool;.agents/skills/create-skill/references/skill-authoring-guide.md:107uses that stale rule as its Map-vs-Atlas example.learn/agentos/tooling/TroubleshootingToolCalls.md:41,learn/agentos/GitHubWorkflow.md:73,90,learn/benefits/ArchitectureOverview.md:258, andsyncGithubWorkflow.mjs:16-31all present it as agent-callable.toolService.mjs:338,366's own guard remediation names the wrong owner (PrimaryRepoSyncService) — part of the bug, not the source of truth.The Architectural Reality (corrected per Euclid, live
1d7fa14474)githubWorkflowSync(taskDefinitions.mjs:366-371→ai/scripts/maintenance/syncGithubWorkflow.mjs), NOTPrimaryRepoSyncService(the separateprimary-dev-synclane,taskDefinitions.mjs:410-414). PR#13684merged the local-only scheduler lane 2026-06-21.SyncService.runFullSync()entry (toolService.mjs:373;syncGithubWorkflow.mjs:18-31,90-92) — and both perform phase-2 graph ingestion (SyncService.mjs:371-380). The original "daemon does more" claim was false.withHeavyMaintenanceLease(syncGithubWorkflow.mjs:84-93), while the MCP mapping callsrunFullSync()behind only the dev-branch guard (toolService.mjs:352-373) — the manual MCP path bypasses the shared heavy-maintenance lease and is request-timeout-prone (tonight's-32001symptoms).resources/content/**reflects the last completed scheduled run and can lag hours; livegh/MCP access is the only fresh source.adr-aligned— ADR 0014's local-only scheduler taxonomy via PR#13684; ADR 0004 constrains the repair to preserve an operator/canonical rebuild path (do not eliminate the primitive).The Fix (contract decision — recommendation per Euclid's intake, ratified here)
Remove
sync_allfrom the agent MCP surface; retainnpm run ai:sync-github-workflowas the operator/canonical rebuild entry point. (Fallback if removal is rejected: an explicit server-side authorization/projection contract — changingextendedtoadminalone does not constrain an unprojected full developer/operator server.)/sync-allfrom the agent-visible tool surface (or project it away for agent identities); the scheduledgithubWorkflowSynclane remains the only canonical invoker.toolService.mjs:338,366(owner =githubWorkflowSync).update_issue_relationshipstep 3 (+ theMcpServerListToolsSmoke.spec.mjs:613lock),ticket-create-workflow.md§10 (route body edits throughgh issue edit), retirepull-request/references/sync-all-constraints.md+ itspull-request-workflow.md:86route, update thecreate-skillexample, and alignTroubleshootingToolCalls.md:41,GitHubWorkflow.md:73,90,ArchitectureOverview.md:258,syncGithubWorkflow.mjs:16-31header docs. Do NOT touch accepted ADR 0004's historical text.sync-all-constraints.mdnets a reduction in agent-loaded instruction surface (no second "never call" layer).Contract Ledger Matrix
githubWorkflowSync→syncGithubWorkflow.mjs→SyncService.runFullSync()withHeavyMaintenanceLeasesync_allMCP surfaceupdate_issue_relationshipfreshness guidancetoolService.mjs:338,366githubWorkflowSyncPrimaryRepoSyncServiceremnants in remediationsync-all-constraints.mdremovednpm run ai:sync-github-workflowAcceptance Criteria
sync_allis no longer agent-visible/agent-callable on the MCP surface (or the explicit authorization projection exists); negative test proves rejection.update_issue_relationship+ smoke spec carry the scheduled-lane guidance; zero manual-sync instructions remain in agent-facing surfaces (implementation grep).ticket-create§10 routes body edits throughgh issue edit;sync-all-constraints.mdretired; create-skill example updated.githubWorkflowSync;npm run ai:sync-github-workflowdocumented as the operator/canonical path.Out of Scope
#11503lease,SyncService.runFullSync(), or phase-2 ingestion.-32001timeouts beyond recording them.list_issuesstaleness (#15603owns that tool).Avoided Traps / Gold Standards Rejected
extended→adminrelabel as the constraint — does not constrain an unprojected full developer/operator server.sync-all-constraints.md+ adding a second "never call" layer — substrate bloat; retire instead.Related
#13684(merged scheduler lane — the successor that reframed ownership),#8408(pre-daemon description tuning),#11503(heavy-maintenance lease)list_issuesstaleness), #15660 (the evening's timeout reproducer)Sweeps: live latest-open sweep at 2026-07-21T21:05Z (no equivalent); KB semantic (
#8408/#11503/#12065context, no dup); mailbox in-flight clean. Euclid's intake corrections absorbed 2026-07-22T00:2xZ.Retrieval Hint: "sync_all agent MCP surface removal githubWorkflowSync heavy-maintenance lease bypass"; anchors
toolService.mjs:338,366,373,syncGithubWorkflow.mjs:84-93,McpServerListToolsSmoke.spec.mjs:613.