LearnNewsExamplesServices
Frontmatter
id13155
titleFleet Manager: repo-provisioning executor (clone / reuse / never-clobber)
stateClosed
labels
enhancementaiarchitecture
assigneesneo-opus-ada
createdAtJun 14, 2026, 1:44 AM
updatedAtJun 14, 2026, 2:05 AM
githubUrlhttps://github.com/neomjs/neo/issues/13155
authorneo-opus-ada
commentsCount0
parentIssue13015
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtJun 14, 2026, 2:05 AM

Fleet Manager: repo-provisioning executor (clone / reuse / never-clobber)

Closed v13.1.0/archive-v13-1-0-chunk-2 enhancementaiarchitecture
neo-opus-ada
neo-opus-ada commented on Jun 14, 2026, 1:44 AM

Context

Sub-leaf of #13015 (FM MVP) — the third and final leaf of the read → decide → act repo-provisioning trio: #13145 / PR #13146 derives the path (the "where"), #13148 / PR #13149 inspects the checkout state (the "what's there" → a provisioningAction of clone / reuse / conflict), and this leaf executes that action — materializing the managed checkout under the hood, the operator's "repos managed under the hood."

The Problem

The inspector returns a provisioningAction but does not act. The executor must: clone into an absent / empty path; reuse an existing valid checkout as-is (no reclone — path stability is load-bearing for the path-keyed auto-memory); and on a conflict (a foreign occupant, including a symlink) refuse — never clobber. The git clone is a side effect (subprocess + network), so the leaf needs a test seam so the clone / reuse / conflict contract is unit-testable without a real remote.

The Architectural Reality

  • ai/services/fleet/provisionAgentRepo.mjs (Brain side, beside deriveAgentRepoPath / inspectAgentRepo / FleetLifecycleService).
  • Follows FleetLifecycleService's default-real + injectable seam idiom: the clone executor defaults to a real child_process git clone but is injectable (a cloneRepo parameter), so the spec asserts the contract with a recording stub — no git binary / network in tests. This is the exact pattern FleetLifecycleService.spawnFn (defaulting to child_process.spawn) and its spawn-stub spec already use.
  • Decoupled: takes the resolved repoPath + the inspector's provisioningAction (does not import the sibling leaves) — single responsibility; the composing "ensure" orchestrator (a later step) wires derive → inspect → provision.

The Fix

export async function provisionAgentRepo({repoPath, cloneUrl, provisioningAction, cloneRepo}){repoPath, action, cloned}:

  • provisioningAction: 'clone' → require a non-empty cloneUrl; await cloneRepo(cloneUrl, repoPath); return {action: 'cloned', cloned: true}.
  • 'reuse' → no-op (the checkout already exists); return {action: 'reused', cloned: false}.
  • 'conflict' → throw (never clobber a foreign occupant).
  • unknown action / invalid inputs → throw.
  • cloneRepo defaults to a real git clone (git clone -- <url> <dest> via execFile); injectable for tests.

Acceptance Criteria

  • provisionAgentRepo({repoPath, cloneUrl, provisioningAction, cloneRepo}); async; the default cloneRepo performs a real git clone.
  • 'clone' invokes cloneRepo(cloneUrl, repoPath) exactly once and reports cloned: true; requires a non-empty cloneUrl (throws otherwise).
  • 'reuse' does NOT invoke cloneRepo and reports cloned: false (no reclone of an existing checkout).
  • 'conflict' throws and does NOT invoke cloneRepo (never clobber).
  • Unknown action, and non-string / empty / non-absolute repoPath, throw.
  • Unit spec test/playwright/unit/ai/provisionAgentRepo.spec.mjs injects a recording cloneRepo stub (no git binary), covering each branch; green under the custom unit config.

Out of Scope

  • The composing derive → inspect → provision orchestrator (a later leaf).
  • Repair of a wrong-remote checkout (a later refinement, once the inspector adds remote-match).
  • Credential / PAT injection into the clone URL — the registry's resolveCredential boundary; the caller supplies the already-resolved cloneUrl.

Decision Record impact

none — a new Brain-side helper consistent with the existing fleet-service conventions.

Related

  • Parent #13015; grandparent #13012. Siblings: #13145 / PR #13146 (derive), #13148 / PR #13149 (inspect). Pattern precedent: FleetLifecycleService's injectable spawnFn seam + its spawn-stub spec (the subprocess test idiom).

Live latest-open sweep: checked latest open issues + a provision / clone / ensure-repo scan at 2026-06-13T23:42Z; no equivalent found.

Release classification: post-release (Fleet Manager product line; nothing v13.x-blocking).

Origin Session ID: 4c598c8f-d8a7-4288-9420-e825a45d310e