LearnNewsExamplesServices
Frontmatter
id11135
titleConfigure dev auto-sync for multiple repo clones
stateClosed
labels
enhancementaiarchitecturemodel-experience
assigneesneo-gpt
createdAtMay 10, 2026, 6:29 PM
updatedAtMay 12, 2026, 4:08 AM
githubUrlhttps://github.com/neomjs/neo/issues/11135
authorneo-gpt
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtMay 11, 2026, 1:49 AM

Configure dev auto-sync for multiple repo clones

Closedenhancementaiarchitecturemodel-experience
neo-gpt
neo-gpt commented on May 10, 2026, 6:29 PM

Context

Follow-up idea surfaced during review of PR #11130, which implements #11017 as a single primary-dev-sync Orchestrator lane. The current PR is intentionally scoped to one resolved primary checkout so it can land the safe auto-pull + KB cascade primitive first.

The operator pointed out that the live swarm topology uses three separate repo clones in three folders, one per active agent family. If the goal is to keep dev fresh for the whole local swarm, a single primary checkout is only the first step. The next step is an explicit configuration surface for the repo roots that should participate in dev freshness.

This is deliberately out of scope for PR #11130. It should be a follow-up ticket so the first primitive can merge without broadening its risk profile.

The Problem

#11017 and PR #11130 close the stale-primary gap for the daemon's resolved checkout, but they do not address independent peer clones. git worktree list --porcelain can resolve a primary checkout from a worktree, yet it cannot discover unrelated sibling clones. The current service therefore has no authoritative way to know that other agent roots exist.

Blind auto-discovery would be risky: sibling-folder scans and matching origin URLs can pick up stale test clones, forks, or unrelated local experiments. Blind synchronization would be worse: an agent clone might be on a feature branch with local work, and the orchestrator must not switch branches or rewrite that working tree.

The desired surface is explicit operator configuration: "these are the repo roots that may be kept fresh," with safe per-root behavior.

The Architectural Reality

Current PR #11130 surfaces:

  • ai/daemons/services/PrimaryRepoSyncService.mjs resolves one primary root and runs the sync ladder.
  • ai/daemons/Orchestrator.mjs exposes NEO_ORCHESTRATOR_PRIMARY_DEV_SYNC_INTERVAL_MS and NEO_ORCHESTRATOR_PRIMARY_DEV_SYNC_ENABLED.
  • learn/agentos/DeploymentCookbook.md documents those two env vars.
  • #11017 explicitly lists external clones as out of scope: daemons running from external clones are not addressed by the single primary-root resolver.

Adjacent but non-duplicate tickets:

  • #10435 solved canonical-root overrides for bootstrapWorktree.mjs data symlinking in independent clones. That is clone bootstrap/data-linking, not periodic dev synchronization.
  • #10822 includes a future config doctor for clone-aware config drift. That is diagnosis/migration guidance, not Orchestrator-owned dev freshness.

The Fix

Extend the #11130 primitive from one implicit primary root to an explicit target-root list while preserving existing behavior when no list is configured.

Proposed MVP surface:

  • Add an operator config env var such as NEO_ORCHESTRATOR_DEV_SYNC_ROOTS, containing a JSON array of absolute repo root paths.
  • When unset, keep the exact #11130 behavior: resolve one primary root and sync only that root.
  • When set, iterate the configured roots and apply the same safety ladder per root.
  • For each root:
    • verify it is a Neo repo clone;
    • run git fetch origin dev --quiet;
    • if the current branch is dev, apply the existing dirty-state gate, metadata-only resolution, fast-forward pull, and outcome recording;
    • if the current branch is not dev, do not checkout/switch branches; record a safe fetched-only / not-dev-branch result.
  • Keep npm run ai:sync-kb single-root by default. Run the KB cascade from the orchestrator's owning/root checkout after at least one successful dev update, not once per configured clone.

Naming should be reviewed during implementation. If the service remains single-root-first internally, PrimaryRepoSyncService can keep the name and gain resolveTargetRoots(). If multi-root becomes the dominant behavior, rename to a less misleading service name in the implementation PR.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
NEO_ORCHESTRATOR_DEV_SYNC_ROOTS This ticket + #11017 follow-up scope Optional JSON array of absolute repo root paths that the Orchestrator may keep fresh Unset preserves #11130 single-root behavior learn/agentos/DeploymentCookbook.md Unit tests for unset, malformed JSON, valid multi-root list
Per-root sync semantics This ticket Fetch every configured root; only fast-forward the working tree when current branch is dev; never checkout/switch branches Non-dev branches are fetch-only and recorded as skipped/fetched-only JSDoc on sync service Unit tests for dev root, feature-branch root, dirty root, missing root
KB cascade #11017 + this ticket Still runs once from the orchestrator-owned/root checkout after successful dev updates Manual npm run ai:sync-kb remains escape hatch DeploymentCookbook + PR body Unit test proves one KB invocation for multi-root cycle
Health outcome details Existing HealthService task outcome envelope Aggregate per-root result details without losing root-specific failure reasons Failed root does not prevent other configured roots from being attempted unless config parsing fails JSDoc Unit test verifies partial success aggregate

Acceptance Criteria

  • AC1: Root-list config added with no tracked machine-specific paths. The operator supplies paths via env/config, not committed source.
  • AC2: Unset config preserves the PR #11130 single-primary behavior exactly.
  • AC3: Config parser validates malformed JSON and non-array values with an operator-visible skipped/failed outcome.
  • AC4: Each configured root is verified as a git repo with origin/dev before sync logic runs.
  • AC5: Roots currently on dev use the existing dirty-state gate, metadata-only resolution, fast-forward pull, and outcome recording.
  • AC6: Roots not on dev are not switched. They may fetch origin/dev, but working-tree fast-forward is skipped and recorded.
  • AC7: A failure in one configured root does not prevent later roots from being inspected unless the root-list config itself is invalid.
  • AC8: KB sync cascade remains single-root by default and does not run once per configured clone.
  • AC9: Documentation updates learn/agentos/DeploymentCookbook.md with the new config surface and explicitly warns against committing local absolute paths.
  • AC10: Tests cover unset config, multi-root success, feature-branch fetch-only behavior, dirty-root skip, invalid path, invalid JSON, partial success, and single KB cascade.

Out of Scope

  • Changing the underlying #11130 sync ladder.
  • Auto-discovering sibling clones by filesystem scan or matching origin URLs.
  • Switching configured roots to dev automatically.
  • Running independent KB sync cascades for every clone.
  • Moving Codex/Gemini/Claude harnesses to worktree parity.
  • Solving clone config drift; #10822 covers the config-doctor direction.

Avoided Traps

  • Auto-discovery by sibling folder scan: rejected because the operator, not a heuristic, knows which clones are active swarm roots.
  • Branch switching: rejected because a configured clone may be in the middle of feature work.
  • Per-clone KB sync by default: rejected because it risks duplicated work and datastore contention. The first follow-up should keep the KB cascade single-root.
  • Bundling into PR #11130: rejected because PR #11130 is already a coherent single-root primitive with all CI green; broadening it now increases review risk.

Related

  • Follow-up to #11017 and PR #11130.
  • Adjacent non-duplicate: #10435 (bootstrapWorktree independent-clone canonical root).
  • Adjacent non-duplicate: #10822 (clone-aware config doctor / drift detector).

Origin Session ID: 20a824b0-29d1-4082-ae12-87705ec69c3f

Handoff Retrieval Hint: query_raw_memories(query="PR #11130 primary-dev-sync multiple repo clones configured roots operator path list KB cascade single-root")

tobiu closed this issue on May 11, 2026, 1:49 AM
tobiu referenced in commit 49d54de - "feat(orchestrator): configure dev sync roots (#11135) (#11162) on May 11, 2026, 1:49 AM