Skip to content

feat: SPEC-6-5 cwd isolation (#20) — foreground cwd + userMemory opt-in - #68

Merged
rz1989s merged 9 commits into
mainfrom
feat/spec-6-5-cwd-isolation
Aug 29, 2026
Merged

rz1989s merged 9 commits into
mainfrom
feat/spec-6-5-cwd-isolation

Conversation

@rz1989s

@rz1989s rz1989s commented Aug 29, 2026

Copy link
Copy Markdown
Member

What

Foreground cwd isolation for the subagent tool — the #20 confabulation fix. A dispatch can now target a working directory (cwd), and the child's working dir + context (AGENTS.md cascade, skill discovery, memory scopes) are scoped to it instead of always inheriting the session cwd. Also makes the global cross-project user-memory scope opt-in (userMemory: true, default off) — it was a cross-project memory bleed by construction.

subagent({ agent, task, cwd: "~/local-dev/getpipher/armory-fleet" })
  → child runs + reads context in the dispatch target, not the session cwd
  → widget shows ↗armory-fleet (cross-cwd glyph) + a spawn-time notify

The end-to-end chain

layer change
tool (src/tools/subagent.ts) cwd? param; resolveDispatchCwd (relative → resolve against session cwd; exists + is-dir validation, actionable error); cross-cwd onNotify; threaded to direct/retry/lifecycle-adapter spawnSubagent calls; entryCwd: resolvedCwdrunLifecycle
engine (src/engine/spawnSubagent.ts) childCwd = opts.cwd ?? opts.parentCwd threaded to RunRecord.cwd, factory.create, run:meta (+ sessionCwd: parentCwd audit on both)
lifecycle (run-lifecycle.ts, registry.ts, lifecycle-types.ts) per-lifecycle cwd? frontmatter field; precedence lifecycle.cwd ?? entryCwd; PhaseSpawnOpts.cwd threaded to each phase spawn
panel (fleet-panel.ts) Run-action 3rd cwd input step (prefilled session cwd; Enter accepts, Escape cancels); validation + cross-cwd notify + entryCwd threading
widget (widget-rows.ts) ↗<basename> glyph on cross-cwd fg runs
memory (child-loader.ts, port.ts, adapter.ts, claude-factory.ts) memoryScopesFor(cwd, { includeUser }); user? optional; adapter null-guards; both backends pass includeUser: agent.userMemory ?? false
registry (frontmatter.ts) userMemory: boolean (default false)

Breaking changes (migration notes in README)

  1. userMemory default flip — the user pseudo-scope (/__armory-fleet-user__) is no longer hydrated by default. Add userMemory: true to opt back in. TS consumers constructing AgentDef literals must include userMemory (required field).
  2. AgentDef.userMemory required — compile-time break for external TS constructors of AgentDef.

Deferred (tracked)

Verification

Closes #20 (foreground cwd isolation; bg/worktree follow-up → #62; SPEC-6-4 keeps event-bus RPC + live conversation viewer).

3rd input step (task → name → cwd) prefilled with the session cwd;
Enter accepts, Escape accepts the default. Validates the chosen cwd
(exists + dir) + surfaces cross-cwd via onNotify. Threads entryCwd to
runLifecycle + cwd:o.cwd to the spawn adapter (lifecycle cwd precedence).
No unit test — the panel interactive Run-action flow has no existing
harness; gated by the release-gate smoke + manual QA (matches existing
panel coverage: startLifecycleRun had zero unit tests pre-SPEC-6-5).
@rz1989s
rz1989s merged commit 042b2d9 into main Aug 29, 2026
1 check passed
@rz1989s
rz1989s deleted the feat/spec-6-5-cwd-isolation branch August 29, 2026 03:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

subagent tool: no cwd isolation — children inherit the session cwd, can read sibling repos + confabulate ownership

1 participant