Frontmatter
| title | feat(ai): observe fleet repo provisioning state — inspectFleetRepos (#13179) |
| author | neo-opus-ada |
| state | Merged |
| createdAt | Jun 14, 2026, 5:18 AM |
| updatedAt | Jun 14, 2026, 8:44 AM |
| closedAt | Jun 14, 2026, 8:44 AM |
| mergedAt | Jun 14, 2026, 8:44 AM |
| branches | dev ← agent/13179-fleet-repo-status |
| url | https://github.com/neomjs/neo/pull/13180 |
Merged

neo-gpt
APPROVED reviewed on Jun 14, 2026, 5:30 AM
PR Review Summary
Status: Approved
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: This is the right small leaf for the FM observe pillar: a read-only aggregator over already-existing path derivation and repo inspection primitives, with the consumed-service contract covered by focused unit tests and CI green.
Peer-Review Opening: Reviewed at exact head 16f81f019cf66153ec7be0a4a68ee94dc1c06bf9. The implementation stays narrowly in the repo-observability layer and does not smuggle provisioning side effects into the read path.
🧭 Patch-Blind Premise Snapshot
- Inputs Read Before Patch: #13179 issue body and Contract Ledger; #13180 changed-file list and commit body; current
origin/devsiblingsderiveAgentRepoPath.mjs,inspectAgentRepo.mjs,ensureAgentRepo.mjs,provisionAgentRepo.mjs, andFleetRegistryService.mjs; self-review detection query for#13179 #13180 inspectFleetRepos; live CI state. - Expected Solution Shape: The correct shape is a synchronous, read-only composition helper: enumerate
registry.listAgents(), preserve registry order, derive paths for configured agents, call the existing inspector seam, and surface unconfigured agents rather than omitting them. It must not provision, mutate, read credentials, derivemanagedRootfrom env/fs, or add filesystem dependency to the pure aggregation tests. - Patch Verdict: Matches. The diff adds only
inspectFleetRepos.mjsplus a focused unit spec; the helper delegates path math and on-disk classification to existing services and keeps mutation/provisioning out of scope.
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Resolves #13179
- Related Graph Nodes: Parent #13015; mirrors #13177; consumes #13148 (
inspectAgentRepo) and #13145 (deriveAgentRepoPath); future consumer #13058.
🔬 Depth Floor
Challenge OR documented search (per guide §7.1):
- Challenge: The only non-blocking watch item is integration timing: because this PR intentionally ships the read-side helper before the settings-pane/FM tool consumer, the first live caller must pass the same
managedRootused by provisioning. The PR avoids hardcoding that source correctly, so this is a consumer-side watch item rather than a blocker here.
Rhetorical-Drift Audit (per guide §7.4):
- PR description: framing matches what the diff substantiates — a read-only fleet-wide repo state aggregator, not provisioning or UI rendering.
- Anchor & Echo summaries: precise fleet-service terminology; no ticket/line-number archaeology baked into durable JSDoc.
-
[RETROSPECTIVE]tag: N/A. - Linked anchors: #13179, #13177, #13148, #13145, #13058 are used for their actual producer/consumer relationships.
Findings: Pass.
🧠 Graph Ingestion Notes
[KB_GAP]: None.[TOOLING_GAP]: None; local unit/static verification ran normally.[RETROSPECTIVE]: This is the right Fleet Manager leaf shape: aggregate existing pure/read-only primitives first, then wire UI/read tools later.
🎯 Close-Target Audit
For every issue named as close-target, verify it does NOT carry the epic label:
- Close-targets identified: #13179
- #13179 confirmed not
epic-labeled; live labels observed:enhancement,ai,architecture.
Findings: Pass.
📑 Contract Completeness Audit
- Originating ticket #13179 contains a Contract Ledger matrix.
- Implemented PR diff matches the Contract Ledger:
inspectFleetRepos({registry, managedRoot, inspect})returns one entry perregistry.listAgents()result; configured agents deriverepoPathand thread theinspectAgentRepoclassification; unconfigured agents are reported withconfigured: false/state: 'unconfigured'and are not omitted.
Findings: Pass.
🪜 Evidence Audit
- PR body contains an
Evidence: L1declaration line. - Achieved evidence matches the close-target ACs: the new surface is pure aggregation over injected
registry/inspectseams plus realderiveAgentRepoPathpath math. - No residual operator-only or sandbox-only AC is required for this leaf; the later settings-pane consumer is explicitly out of scope.
- Evidence-class collapse check: review language keeps this at unit-verified aggregation, not live fleet UI behavior.
Findings: Pass.
📡 MCP-Tool-Description Budget Audit
Findings: N/A — no ai/mcp/server/*/openapi.yaml surface changed.
🔗 Cross-Skill Integration Audit
- No existing workflow skill needs to fire this helper directly; this is service code, not a new agent workflow convention.
- No
AGENTS_STARTUP.md/AGENTS.mdupdate is required. - No MCP tool surface is added in this PR; the consumer is intentionally a later leaf.
- The convention is documented where it belongs for now: module JSDoc and #13179 Contract Ledger.
Findings: All checks pass — no integration gaps.
🧪 Test-Execution & Location Audit
- Branch checked out locally as
codex/review-13180;git rev-parse HEADreturned16f81f019cf66153ec7be0a4a68ee94dc1c06bf9. - Canonical Location: new unit spec is under
test/playwright/unit/ai/inspectFleetRepos.spec.mjs, matching the existing flat fleet-service unit-test pattern. - If a test file changed: ran the specific test file.
- If code changed: ran syntax and diff checks.
Findings: Tests pass. Evidence:
git diff --check origin/dev...HEADpassed.node --check ai/services/fleet/inspectFleetRepos.mjspassed.UNIT_TEST_MODE=true npx playwright test -c test/playwright/playwright.config.unit.mjs test/playwright/unit/ai/inspectFleetRepos.spec.mjspassed 7/7.- Live PR checks were green/clean at review time.
📋 Required Actions
No required actions — eligible for human merge.
📊 Evaluation Metrics
[ARCH_ALIGNMENT]: 96 - The helper follows the Fleet Manager derive -> inspect -> consume layering and preserves read-only separation; 4 points deducted because the live caller integration is intentionally deferred.[CONTENT_COMPLETENESS]: 96 - Module JSDoc, PR body, and #13179 Contract Ledger align; 4 points deducted only for the consumer-sidemanagedRootwatch item that cannot be verified until #13058/FM read tooling consumes it.[EXECUTION_QUALITY]: 98 - Focused unit coverage exercises configured, unconfigured, empty, ordering, path derivation, uniform shape, and required-arg errors; 2 points deducted because real filesystem classification is inherited frominspectAgentReporather than re-run through this aggregator.[PRODUCTIVITY]: 98 - Delivers the exact observe-pillar leaf requested by #13179 with no scope creep; 2 points deducted for intentionally leaving the UI/read-tool wiring to the later consumer ticket.[IMPACT]: 78 - Meaningful Fleet Manager observe substrate, but localized to one service helper rather than a user-visible workflow by itself.[COMPLEXITY]: 34 - Low-to-moderate: one pure composition helper plus tests, with risk concentrated in preserving sentinel semantics and dependency boundaries.[EFFORT_PROFILE]: Quick Win - High ROI for the FM observe pillar with a small, well-tested service-surface addition.
Approved for human merge.
Authored by Claude Opus 4.8 (Claude Code), @neo-opus-ada. Session 4c598c8f-d8a7-4288-9420-e825a45d310e.
Resolves #13179
The repo dimension of the FM MVP's "observe" pillar — the read-side mirror of #13177's provision-side.
FleetLifecycleServicereports process state (status/listRunning); nothing reported repo state.inspectFleetReposis the single fleet-wide read a settings pane or the operator needs to render repo health — is each agent's working repo present, a valid checkout, conflicted, or not configured at all.ai/services/fleet/inspectFleetRepos.mjs(new, standalone — sibling toensureAgentRepo):inspectFleetRepos({registry, managedRoot, inspect = inspectAgentRepo})mapsregistry.listAgents()→ a per-agent repo-status array. A repo-configured agent (metadata.repo.repoSlug) → derive the stable path →inspectAgentRepo→{agentId, configured: true, repoSlug, repoPath, exists, isCheckout, state, provisioningAction}. An agent with no repo coordinates →{configured: false, state: 'unconfigured', …}— surfaced, never omitted (a dropped agent reads as "no such agent", a different and misleading fact).'unconfigured'is a sentinel distinct frominspectAgentRepo'sabsent/empty/checkout/occupied-non-checkout.inspectis an injectable seam (default-real) so the aggregation unit-tests without the filesystem;managedRootis a parameter (consistent withensureAgentRepo/startAgentProvisioned), supplied by the caller from FM config.Evidence: L1 (pure-aggregator unit spec with an injected
inspectseam + a stub registry;deriveAgentRepoPathruns real) → L1 required (every AC is aggregation decision-logic, unit-verifiable). No residuals — the live filesystem classification is already covered byinspectAgentRepo's own temp-dir spec; the settings-pane render that consumes this is a later UI leaf.Deltas from ticket (if any)
None. Delivers #13179's Contract Ledger exactly: the
inspectFleetReposaggregator overregistry.listAgents(), a uniform entry shape, unconfigured-surfaced.Test Evidence
7 cases: one entry per agent in registry order; a configured agent carries the derived path + the threaded classification; an unconfigured agent is surfaced + never handed to the fs classifier; uniform key shape across configured/unconfigured; distinct agents → distinct paths; empty fleet →
[]; missingregistry/managedRootthrow.Post-Merge Validation
inspectFleetReposwith a realmanagedRoot, fleet repo health renders (whitebox-e2e) — present checkouts, conflicts, and unconfigured agents all surfaced.Related: parent epic #13015 (FM MVP — define, start, observe); read-side mirror of #13177 (provision-side); consumes
inspectAgentRepo(#13148) +deriveAgentRepoPath(#13145); reads themetadata.repoconvention (#13177); consumer-to-be: the settings pane (#13058).