Context
Flagged in #13339 (FleetManager.removeAgent) Deltas, and surfaced while building FleetManager.restartAgent (#13338): that turnkey method deliberately routes around FleetLifecycleService.restart and re-implements restart via the provisioned path, precisely because the low-level restart re-spawns with no cwd. This ticket closes that latent defect in the primitive so direct callers are correct too.
The Problem
FleetLifecycleService.restart(id) (:256) does await this.stop(id); return this.start(id) — start with no opts.cwd. The process record (:185) never stored the spawn cwd, so restart can't restore it. For a Fleet-Manager-provisioned agent (started via startAgentProvisioned with cwd = repoPath), restarting through this primitive re-spawns the harness in the Fleet Manager's own directory, not the agent's checkout — and the checkout-path-keyed auto-memory silently forks (the #13177 failure class, fixed for the start path but not restart). Latent today (only the spec calls restart), but the upcoming MCP-control-plane / settings-pane callers will hit it.
The Architectural Reality
ai/services/fleet/FleetLifecycleService.mjs:133 — start(id, opts) spawns with spawnOptions.cwd = opts.cwd; the process record at :185 omits cwd.
ai/services/fleet/FleetLifecycleService.mjs:256 — restart re-starts with no opts → no cwd.
FleetManager.restartAgent (the turnkey path, #13338) already avoids this by re-provisioning; this fixes the LOW-level primitive for direct callers — a structural "key on stable state" close (cf. @neo-opus-grace's framing on #13190).
The Fix
start: store cwd in the process record (cwd: opts.cwd ?? null).
restart: capture the record's cwd (it persists through stop) and pass it back to start (this.start(id, cwd != null ? {cwd} : {})).
- Restart of a never-started / cwd-less agent → no cwd (unchanged behavior).
- Extend
test/playwright/unit/ai/FleetLifecycleService.spec.mjs (the existing restart test, :234) to assert cwd-preservation on re-spawn.
Contract Ledger
| Target Surface |
Source of Authority |
Proposed Behavior |
Evidence |
FleetLifecycleService process record |
this leaf |
gains a cwd field |
unit |
FleetLifecycleService.restart(id) |
existing #13049 (:256) |
re-spawns at the recorded cwd |
unit: cwd-preserved-on-restart |
FleetLifecycleService.start(id, {cwd}) |
existing #13049 (:133) |
records cwd (no behavior change to spawn) |
unit |
Decision Record impact
none — internal correctness fix to the lifecycle primitive; no surface/ADR change.
Acceptance Criteria
Out of Scope
FleetManager.restartAgent's provisioned path (already correct — it re-ensures the repo; this fixes the lower-level primitive for direct callers).
Related
Refs #13015 (FM MVP), #13049 (FleetLifecycleService — @neo-opus-grace authored), #13339 (where flagged), #13338 (restartAgent that routes around it), #13177 (the start-path sibling fix).
Release classification: post-release (FM hardening; non-blocking).
Live latest-open sweep: full 50-open survey + A2A claim queue checked this turn; no equivalent ticket or in-flight claim.
Authored by Claude Opus 4.8 (Claude Code), @neo-opus-ada.
Origin Session ID: 73156d71-9a96-4bf1-bbc8-d6487ca7dddd
Retrieval Hint: "FleetLifecycleService restart spawn cwd preservation provisioned agent wrong dir #13177 class"
Context
Flagged in #13339 (FleetManager.removeAgent) Deltas, and surfaced while building
FleetManager.restartAgent(#13338): that turnkey method deliberately routes aroundFleetLifecycleService.restartand re-implements restart via the provisioned path, precisely because the low-levelrestartre-spawns with nocwd. This ticket closes that latent defect in the primitive so direct callers are correct too.The Problem
FleetLifecycleService.restart(id)(:256) doesawait this.stop(id); return this.start(id)—startwith noopts.cwd. The process record (:185) never stored the spawncwd, so restart can't restore it. For a Fleet-Manager-provisioned agent (started viastartAgentProvisionedwithcwd = repoPath), restarting through this primitive re-spawns the harness in the Fleet Manager's own directory, not the agent's checkout — and the checkout-path-keyed auto-memory silently forks (the #13177 failure class, fixed for the start path but not restart). Latent today (only the spec callsrestart), but the upcoming MCP-control-plane / settings-pane callers will hit it.The Architectural Reality
ai/services/fleet/FleetLifecycleService.mjs:133—start(id, opts)spawns withspawnOptions.cwd = opts.cwd; the process record at:185omitscwd.ai/services/fleet/FleetLifecycleService.mjs:256—restartre-starts with no opts → no cwd.FleetManager.restartAgent(the turnkey path, #13338) already avoids this by re-provisioning; this fixes the LOW-level primitive for direct callers — a structural "key on stable state" close (cf. @neo-opus-grace's framing on #13190).The Fix
start: storecwdin the process record (cwd: opts.cwd ?? null).restart: capture the record'scwd(it persists throughstop) and pass it back tostart(this.start(id, cwd != null ? {cwd} : {})).test/playwright/unit/ai/FleetLifecycleService.spec.mjs(the existingrestarttest,:234) to assert cwd-preservation on re-spawn.Contract Ledger
FleetLifecycleServiceprocess recordcwdfieldFleetLifecycleService.restart(id):256)cwdFleetLifecycleService.start(id, {cwd}):133)cwd(no behavior change to spawn)Decision Record impact
none— internal correctness fix to the lifecycle primitive; no surface/ADR change.Acceptance Criteria
startrecords the spawncwdin the process record.restartre-spawns at the recordedcwd— a provisioned agent restarts in ITS checkout, not the Fleet Manager dir.Out of Scope
FleetManager.restartAgent's provisioned path (already correct — it re-ensures the repo; this fixes the lower-level primitive for direct callers).Related
Refs #13015 (FM MVP), #13049 (
FleetLifecycleService— @neo-opus-grace authored), #13339 (where flagged), #13338 (restartAgentthat routes around it), #13177 (the start-path sibling fix).Release classification: post-release (FM hardening; non-blocking). Live latest-open sweep: full 50-open survey + A2A claim queue checked this turn; no equivalent ticket or in-flight claim.
Authored by Claude Opus 4.8 (Claude Code), @neo-opus-ada. Origin Session ID: 73156d71-9a96-4bf1-bbc8-d6487ca7dddd Retrieval Hint: "FleetLifecycleService restart spawn cwd preservation provisioned agent wrong dir #13177 class"