LearnNewsExamplesServices
Frontmatter
id14535
titleFleet registryBridge: setRepo verb + registry partial-update (FM Lane C)
stateClosed
labels
enhancementaiarchitecture
assigneesneo-opus-ada
createdAtJul 3, 2026, 8:24 AM
updatedAtJul 3, 2026, 1:03 PM
githubUrlhttps://github.com/neomjs/neo/issues/14535
authorneo-opus-ada
commentsCount2
parentIssue13015
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[ ] 13448 Epic: the harness-UI definition — the v13.1 fleet cockpit (keeper views · nav · human/agent caps)
closedAtJul 3, 2026, 1:03 PM

Fleet registryBridge: setRepo verb + registry partial-update (FM Lane C)

Closed v13.1.0/archive-v13-1-0-chunk-8 enhancementaiarchitecture
neo-opus-ada
neo-opus-ada commented on Jul 3, 2026, 8:24 AM

Context

The operator reframed the Fleet Manager cockpit (2026-07-02, relayed via @neo-opus-grace): "the team can control it and it enables the team — session-sunset → restart your harness." So the cockpit (#13448, Grace's Lane B) is a control surface, not observe-only. This leaf delivers the per-agent repo control verb — setRepo — plus the registry partial-update primitive it needs.

Scope refined during implementation (2026-07-03): this ticket originally paired setRepo with setWakeEnabled. Deep V-B-A showed the two split by AUTHORITY: setRepo is fleet authority (own-registry mutation, like defineAgent) and ships here; setWakeEnabled is control-plane authorized (toggling another agent's wake is a privilege boundary via WakeSubscriptionService's context-owner scoping) and moved to #14537 (blocked_by #14477). Ticket re-scoped to setRepo.

The Problem

FLEET_WIRE_METHODS (src/ai/fleet/fleetWireMethods.mjs) exposed defineAgent · listAgents · getAgent · startAgent · stopAgent · restartAgent · removeAgent · fleetStatus — no way for the cockpit to set an agent's working repo. And the registry had defineAgent (full create-or-replace upsert) but no narrow partial-update, so one facet couldn't be mutated without re-supplying the whole definition.

The Architectural Reality

  • ai/services/fleet/FleetManager.mjs is the Brain-side thin facade; each verb composes a collaborator.
  • startAgentProvisioned.mjs:54 already honors agent.metadata.repo = {cloneUrl, repoSlug} — it clone-or-reuses that repo and pins the harness cwd to the checkout. So setting metadata.repo is functional end-to-end; no new provisioning consumer is needed.
  • The app↔fleet wire (dispatchFleetRequest.mjs:30) forwards a single params argument, so a pane-reachable verb must take ONE payload object — mirroring defineAgent.
  • FleetControlBridge is the pane-reachable capability allowlist; createFleetRegistryBridge generates the client bridge from FLEET_WIRE_METHODS, and dispatchFleetRequest is the server-side choke-point enforcing the same list.

The Fix

  • FleetRegistryService.updateAgent(id, patch) — partial-merge (merges metadata, preserves other fields + createdAt + credential; null on unknown id). Non-destructive.
  • FleetManager.setRepo({id, cloneUrl, repoSlug}) — single-payload, wire-compatible; delegates to updateAgent setting metadata.repo = {cloneUrl, repoSlug}. Non-destructive (mirrors removeAgent).
  • FleetControlBridge.setRepo(payload) + FLEET_WIRE_METHODS += setRepo — pane-reachable, both wire ends + the dispatch choke-point updated.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
FLEET_WIRE_METHODS += setRepo operator control-plane reframe; the app↔fleet wire SSOT pane-reachable setRepo on both wire ends (createFleetRegistryBridge gen + dispatchFleetRequest enforce) none — off-list rejected fleetWireMethods JSDoc dispatchFleetRequest.spec allowlist + routing tests
FleetControlBridge.setRepo(payload) FleetControlBridge capability allowlist single-params payload → FleetManager.setRepo none — fail-closed JSDoc FleetControlBridge.spec
FleetManager.setRepo({id, cloneUrl, repoSlug}) FleetManager facade; startAgentProvisioned metadata.repo contract sets metadata.repo = {cloneUrl, repoSlug} via updateAgent; provisioner honors it none — fail-closed; null on unknown id JSDoc FleetManager.spec
FleetRegistryService.updateAgent(id, patch) new registry primitive partial-merge metadata + modelProvider, preserve rest; null on unknown none JSDoc FleetRegistryService.spec

Decision Record impact

aligned-with ADR-0026 — a fleet-authority operator-UI control verb on the client bridge, the OTHER side of the control-plane/diagnostics R3 seam from the #14477/#14501 daemon-core actuator. No ADR authority change.

Acceptance Criteria

  • FleetRegistryService.updateAgent(id, patch) partial-merges metadata, preserves other fields, returns null on unknown id — unit spec.
  • FleetManager.setRepo({id, cloneUrl, repoSlug}) is single-payload (wire-compatible), sets metadata.repo = {cloneUrl, repoSlug}, omits unset coords — unit spec.
  • setRepo added to FLEET_WIRE_METHODS; dispatchFleetRequest allowlist + routing tests confirm the choke-point routes it to the injected bridge without opening resolver seams.
  • FleetControlBridge.setRepo(payload) exposed on the capability allowlist; the secret-omission boundary still holds.
  • No re-resolution of managedRoot / re-wiring of singletons in the new methods (facade discipline).

Out of Scope

  • setWakeEnabled — moved to #14537 (blocked_by #14477; control-plane authorized).
  • setHookEnabled — deferred (Grace's #14439/#14481 stop-hook revert per #14501 OQ2).
  • The #14477/#14501 daemon-core restart actuator — separate control-plane/ off-bridge surface.
  • The cockpit UI#13448 (Lane B) consumes registryBridge.setRepo.
  • data-dir per-agent override — the checkout path is managedRoot-derived (not a per-agent metadata.repo field); out of scope for this verb.

Related

#13015 (parent — FM MVP / Lane C) · #13448 (Lane B cockpit — blocked_by this) · #14537 (setWakeEnabled split-out) · #14477 / #14501 (control-plane authority) · PR #14536 · ai/services/fleet/FleetManager.mjs · startAgentProvisioned.mjs

Origin Session ID: 29018efb-2edf-4172-902d-0fe42d4b0c11 Retrieval Hint: "Fleet setRepo single payload metadata.repo updateAgent FLEET_WIRE_METHODS wire-compatible"

tobiu referenced in commit f598290 - "feat(fleet): setRepo control verb + registry updateAgent (#14535) (#14536) on Jul 3, 2026, 1:03 PM
tobiu closed this issue on Jul 3, 2026, 1:03 PM