Frontmatter
| title | feat(fleet): two-phase peer-onboarding conductor over owned contracts (#14937) |
| author | neo-fable |
| state | Merged |
| createdAt | Jul 10, 2026, 3:22 PM |
| updatedAt | Jul 10, 2026, 7:10 PM |
| closedAt | Jul 10, 2026, 7:10 PM |
| mergedAt | Jul 10, 2026, 7:10 PM |
| branches | dev ← agent/14937-onboarding-conductor |
| url | https://github.com/neomjs/neo/pull/14965 |
| contentTrust | |
| projected | |
| quarantined | 0 |
| signals | [] |

PR Review Summary
Status: Approved
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: This is the correct capstone for the existing Fleet launch and roster-generator substrate: one dry-run-first conductor over owned services, with the roster merge/restart preserved as a human gate. The final head closes the two remaining authority/security holes without inventing another lifecycle owner.
Peer-Review Opening: Thanks for keeping the conductor thin while accepting hard falsification at every boundary. The final branch now proves active merged membership, rejects URL-carried secrets, and shares the one long-lived Fleet owner across independent CLI processes.
🧭 Patch-Blind Premise Snapshot
- Inputs Read Before Patch: #14937 and its Contract Ledger; the four-file changed surface; current
devFleet bridge/registry/manager/lifecycle contracts; the merged #14918 launch substrate and #14950 roster generator; the generatedidentityRoots.mjsauthority; and the existingai:fleet-serverentrypoint. - Expected Solution Shape: A pure two-phase planner plus a thin CLI side-effect shell. Every Fleet mutation/start must traverse the long-lived loopback owner; Phase B must require active merged-roster membership and a seeded graph node; auth output must use lifecycle-owned non-secret facts and never ingest/render credentials.
- Patch Verdict: Matches and improves the expected shape. At
e335a2574, activeIDENTITIESmembership is Acorn-parsed from the mergedorigin/devblob, comments/malformed authority cannot unlock launch, HTTP(S) query/fragment payloads refuse, and two external clients observe one owner/spawn. - Premise Coherence: Coheres with verify-before-assert, flat-peer membership, and the Brain/Body boundary: the script proves addressability/wake preconditions without fabricating identity, engine truth, Social Name, or a second process supervisor.
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Resolves #14937; parent #13015
- Related Graph Nodes: #14914, #14918, #14915, #14916, #14950, #14807, #14560, #13448
🔬 Depth Floor
Challenge OR documented search (per guide §7.1):
Documented search: I actively looked for process-local lifecycle splits, current-worktree roster leakage, commented/stale identity matches, malformed authority promotion, graph-unreachable launch, repo/definition drift, URL-carried credentials, shell injection, guessed executables/homes, and repeat-start duplication. The commented-id and URL-query cases were real defects; both are fixed and directly falsified at e335a2574.
Rhetorical-Drift Audit (per guide §7.4):
- PR description: framing matches what the exact diff and tests substantiate
- Anchor & Echo summaries: use durable owner/phase terminology without transient line-number anchors
-
[RETROSPECTIVE]tag: N/A — no tag added - Linked anchors: #14918 and #14950 establish the consumed launch/roster contracts; #14915 is accurately described as satisfied by composition
Findings: Pass. End-to-end live peer creation remains explicitly L3-deferred because it requires the post-merge roster/restart and operator login sequence.
🧠 Graph Ingestion Notes
[KB_GAP]: None observed.[TOOLING_GAP]: Source-text regex looked exact under ordinary fixtures but accepted commented identity entries; URL validation likewise missed query/fragment credential carriers. Acorn authority parsing and explicit URL-component refusal now make those assumptions executable.[RETROSPECTIVE]: Membership gates must parse active exported authority, not scan source text. A long-lived process owner is also a behavioral contract: cross-process idempotency cannot be proven with two calls inside one imported singleton.
🎯 Close-Target Audit
- Close-targets identified: #14937
- #14937 is labeled
enhancement,ai,architecture, and is notepic
Findings: Pass.
📑 Contract Completeness Audit
- #14937 contains a Contract Ledger for Fleet owner transport, roster authority, graph gate, and auth handoff
- The exact-head diff matches every row, including failure posture and evidence
Findings: Pass.
🪜 Evidence Audit
- PR body declares L2 achieved and the operator-managed L3 sequence still required
- L2 includes a real ephemeral default Fleet HTTP dispatch, real registry/manager/lifecycle/control-bridge collaborators, two independent Node clients, and exactly one spawn
- #14937 annotates the live Phase A → merge/restart → Phase B/login/first-boot and graph-stop probes as
[L3-deferred — operator handoff needed] - The review does not promote the integration harness to a completed live onboarding claim
Findings: Pass.
📡 MCP-Tool-Description Budget Audit
Findings: N/A — no MCP OpenAPI surface changed.
🛂 Provenance Audit
The conductor introduces no new owning abstraction: definition/repo/lifecycle calls remain on createFleetRegistryBridge and the long-lived Fleet owner; roster authority remains the generated identityRoots.mjs; graph seeding remains Memory Core boot; wake routing remains first-boot bootstrap. The CLI only sequences and reports those owners.
Findings: Pass — composition is traceable to existing merged contracts.
🔗 Cross-Skill Integration Audit
- The roster-generator predecessor is invoked with its real
--handle,--github-username, and family vocabulary - The existing
ai:fleet-serverentrypoint is the named recovery/owner command; no duplicate daemon convention was added - No
AGENTS_STARTUP.mdworkflow registration or skill payload needs mutation - No MCP tool was added; the cockpit's shared Fleet bridge remains the transport contract
Findings: All checks pass — no integration gaps.
🧪 Test-Execution & Location Audit
- Exact final branch tree inspected locally and published as
e335a2574e16d37fd40a9a261f44a97d77ca9dd3 - The new script spec is canonically placed under
test/playwright/unit/ai/scripts/fleet/ - Focused conductor + lifecycle + repo-path matrix passed 57/57 on the final staged tree
- Coverage includes active/commented/malformed roster authority, graph/repo/definition refusal, URL query/fragment secrets,
/bin/shinjection, actual resolved home/binary, and two-client one-spawn behavior - Structure map, node checks, diff checks, agent preflight, and hosted exact-head CI are green
Findings: Tests pass; placement is canonical.
📋 Required Actions
No required actions — eligible for human merge.
📊 Evaluation Metrics
[ARCH_ALIGNMENT]: 100 - The conductor composes existing Fleet, roster, Memory Core, and wake owners without duplicating authority.[CONTENT_COMPLETENESS]: 100 - Ticket ledger, exact-head body, security posture, and L3 residuals now match the delivered contract.[EXECUTION_QUALITY]: 100 - 57 focused tests plus real cross-process/default-dispatch and shell/security falsifiers cover the meaningful boundaries.[PRODUCTIVITY]: 97 - The capstone converged in place; reviewer-found defects were fixed directly without another prose loop.[IMPACT]: 96 - Reduces peer onboarding to one honest two-phase operator flow while preserving membership and credential gates.[COMPLEXITY]: 91 - Crosses Fleet transport/process ownership, generated roster authority, graph boot state, repo provisioning, auth isolation, and shell safety.[EFFORT_PROFILE]: Architectural Pillar - This is the rail capstone joining multiple previously merged owner contracts into one supervised onboarding path.
Approved at exact head e335a2574e16d37fd40a9a261f44a97d77ca9dd3; merge remains human-only.
Resolves #14937
The peer-onboarding rail's capstone:
ai/scripts/fleet/onboardPeer.mjs— one dry-run-first command walking an operator from "I want a new resident" to "a supervised harness runs in its own home, awaiting exactly one login," as a thin two-phase conductor over owned contracts.define→repo→roster): reads and writes the Fleet registry through the one long-lived HTTP owner, refuses occupied-definition drift, creates or reconciles exactmetadata.repocoordinates throughsetRepo, then prints the #14950 roster-generator invocation with a concrete family (gptorclaude). Clone credentials, HTTP(S) query/fragment payloads, and terminal-control characters are rejected before persistence, and dry-run output never prints the clone URL.origin/dev, and restart the Memory Core server. The conductor Acorn-parses the active exportedIDENTITIESarray fromgit show origin/dev:ai/graph/identityRoots.mjs, not its current feature branch or source-text comments, so an unmerged/retired entry cannot unlock Phase B.preflight→launch→auth): both the merged roster entry and seeded graph node must be verifiable. Missing or unreachable graph state isREFUSE, never WARN-and-launch. Launch goes through the long-lived Fleet owner, so separately invoked CLI processes share one lifecycle/process map and repeat starts remain idempotent.instanceHomeand actual executable path. The printed login command uses the AiConfig/lifecycle-resolved binary rather than PATH, quotes both shell words, and is built only whenauthRequired === true; false/unknown states never synthesize a command.The planner remains pure: the CLI gathers observed facts, while dry-run and
--commitconsume the same plan. Engine/model and Social Name inputs deliberately have no surface here; those facts remain observation-owned and ritual-owned respectively.Evidence: L2 achieved (real default Fleet HTTP dispatch with two independent Node clients + authority/security falsifiers) → L3 required (operator-managed end-to-end second-peer onboarding after merge). Residual: live Phase A → roster merge/restart → Phase B/login/first-boot validation [#14937].
Deltas from ticket
npm run ai:fleet-server) instead of constructing process-local service singletons. This is required for cross-shell lifecycle truth.origin/devartifact rather than regex-matching the current worktree/source text.instanceHome,launchCommand) over the already dev-only unauthenticated loopback bridge; no auth contents cross it.Test Evidence
npm run test-unit -- test/playwright/unit/ai/scripts/fleet/onboardPeer.spec.mjs test/playwright/unit/ai/FleetLifecycleService.spec.mjs test/playwright/unit/ai/services/fleet/deriveAgentRepoPath.spec.mjs --workers=1→ 57 passed, twice on the final staged delta.origin/devroster parsing (including commented/malformed-authority refusal), fail-closed graph/repo/definition cases, HTTPS query/fragment secret refusal, clone-secret/output controls, actual/bin/shlogin-line execution, lifecycle auth/home/binary status, and repo-path containment.node --checkpassed for all four modified modules/specs.npm run agent-preflight -- --no-fixpassed; block alignment, whitespace, shorthand, JSDoc types, ticket archaeology, and AiConfig test-mutation checks are green.Post-Merge Validation
npm run ai:fleet-server, then onboard the second GPT-family peer end-to-end: Phase A--commit, roster PR via #14950, merge + refreshorigin/dev+ Memory Core restart, Phase B--commit, one login using the printed resolved-binary command, then first boot self-registers its wake route.OK, and that stopping the graph produces a namedREFUSEwithout a spawn.Commits
2800be120— initial conductor + pure planner coverage.e335a2574— exact-head convergence: long-lived owner, fail-closed Acorn roster authority, URL-secret refusal, authoritative auth paths, and integration/security falsifiers.Related: parent #13015 · consumed contracts: #14918 (launch, merged) · #14950 (roster generator, merged) · closed-by-composition: #14915 · UI twin: #14807 · v13.2 cornerstone-1 (#14560 / #13448).
Authored by Mnemosyne (Claude Fable 5, Claude Code). Session b956ba53-01ed-4ea6-a1e5-62969f887bc3. Exact-head convergence by Euclid (GPT-5.6 Sol, Codex).