Skip to content

fix(cli): squad memory opens the same governed store as squad_state - #2317

Merged
tamirdresher merged 2 commits into
github:devfrom
joslat:joslat/2316-memory-cli-same-store
Oct 26, 2026
Merged

tamirdresher merged 2 commits into
github:devfrom
joslat:joslat/2316-memory-cli-same-store

Conversation

@joslat

@joslat joslat commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

What

squad memory now opens the same governed memory store as the agents' memory.* tools in squad_state. It resolves the squad with resolveSquadState (walking up from the current folder, following worktrees and linked teams) and goes through the configured state backend. On orphan and two-layer that means the squad-state branch, not working-tree files. Outside a squad it now fails with a clear message instead of creating a stray .squad/.

Why

Closes #2316

The CLI built new LocalMemoryStore(new FSStorageProvider(), projectRoot), while squad state-mcp uses resolveSquadState(startDir) and the backend's storage. So on git backends, in linked teams, in worktrees without their own .squad and from subfolders, what an agent remembered was invisible to squad memory, and the other way round.

How

  • packages/squad-cli/src/cli/commands/memory.ts: a small exported openGovernedMemoryStore(context, startDir) builds new LocalMemoryStore(context.storage, context.paths.teamSquadDir, { rootKind: 'squad' }), the same construction createStateMcpToolRegistry hands to ToolRegistry.
    • The store is opened lazily, so squad memory help still works outside a squad.
    • The log level is read from the resolved project's config.json.
    • The start diagnostics now report startDir, the resolved projectRoot, the squad dir and the backend name.
  • docs/src/content/docs/features/memory.md: the CLI paragraph now says it opens the same store as the memory.* tools.
  • test/memory-store-resolution.test.ts builds the agents' side with the real createStateMcpToolRegistry, so the test fails if the two ever drift apart again. Three cases:
    • On the orphan backend, an agent's memory.write is found by the CLI, and a CLI write is found by memory.search. The CLI doesn't create .squad/memory/ in the working tree.
    • Run from a subfolder, the CLI finds what the agent wrote and doesn't create packages/app/.squad.
    • Outside a squad, it fails with "No .squad directory found" and creates nothing.

Not in this PR:

  • Linked teams on orphan or two-layer. They still fail, because squad_state itself can't handle that combination yet (squad_state fails on every call in a linked team with the orphan or two-layer backend #2320). Since the CLI now opens the same store, it fails the same way there.
  • The index lock. It only serializes writers that share one store object, so separate processes can race on index.json. That was already possible: two squad_state servers race (for example squad watch with maxConcurrent > 1), and so do the CLI and a session on the local backend from the repo root. This PR makes the CLI share the store in the setups that used to be split, so the race becomes reachable there too. A lock key on the squad-state branch roughly doubled the time per write in my tests on Windows, so I'd rather agree on the locking approach separately.

⚠️ Quick Check

  • If SDK/CLI source files changed: completed the applicable Changeset step below (.changeset/memory-cli-same-store.md)

PR Readiness Checklist

Branch & Commit

  • Branch created from dev (not main)
  • Branch is up to date with dev (rebased on 9d7dff8)
  • Verified diff contains only intended changes
  • PR is not in draft mode
  • Commit history is clean

Build & Test

  • npm run build passes
  • npm test passes (all tests green). On my Windows machine the full suite shows the same pre-existing failures on this branch as on plain dev (gh-aw compiler, terminal and path-related suites). The few tests that differ between runs are timing-sensitive, including two memory-provider concurrency tests, and they pass when rerun alone. The memory, tools and state-mcp suites are green, and the new tests fail without the fix (3 of 3). CI is the real check here.
  • npm run lint passes (type check clean)
  • npm run lint:eslint passes on the changed files (no new warnings in memory.ts)

Changeset

  • Changeset added (@bradygaster/squad-cli patch)

Docs

  • Docs feature page updated (features/memory.md)

Exports

  • No new subpath. openGovernedMemoryStore is a new named export of the existing @bradygaster/squad-cli/commands/memory entry point.

Breaking Changes

  • squad memory run outside a squad now fails instead of silently creating <cwd>/.squad/. That includes squad memory classify, which does no storage I/O but now needs a squad to open.
  • On orphan and two-layer, the CLI now reads and writes the squad-state branch. Entries that older CLIs wrote into working-tree .squad/memory/ files on those backends won't show up until they're moved over.

Waivers

None.

@github-actions

Copy link
Copy Markdown
Contributor

🟡 Impact Analysis — PR #2317

Risk tier: 🟡 MEDIUM

📊 Summary

Metric Count
Files changed 4
Files added 2
Files modified 2
Files deleted 0
Modules touched 4

🎯 Risk Factors

  • 4 files changed (≤5 → LOW)
  • 4 modules touched (2-4 → MEDIUM)

📦 Modules Affected

docs (1 file)
  • docs/src/content/docs/features/memory.md
root (1 file)
  • .changeset/memory-cli-same-store.md
squad-cli (1 file)
  • packages/squad-cli/src/cli/commands/memory.ts
tests (1 file)
  • test/memory-store-resolution.test.ts

This report is generated automatically for every PR. See #733 for details.

@github-actions

github-actions Bot commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

🛫 PR Readiness Check

ℹ️ This comment updates on each push. Last checked: commit 5bcca2c

PR Scope: 📦🔧 Mixed (product + infrastructure)

⚠️ 3 item(s) to address before review

Status Check Details
❌ Single commit 2 commits — consider squashing before review
✅ Not in draft Ready for review
✅ Branch up to date Up to date with dev
❌ Copilot review No Copilot review yet — it may still be processing
✅ Changeset present Changeset file found
✅ Scope clean No .squad/ or docs/proposals/ files
✅ No merge conflicts No merge conflicts
✅ Copilot threads resolved No Copilot review threads
❌ CI passing 15 check(s) still running

Files Changed (4 files, +145 −20)

File +/−
.changeset/memory-cli-same-store.md +5 −0
docs/src/content/docs/features/memory.md +5 −1
packages/squad-cli/src/cli/commands/memory.ts +44 −19
test/memory-store-resolution.test.ts +91 −0

Total: +145 −20


This check runs automatically on every push. Fix any ❌ items and push again.
See CONTRIBUTING.md and PR Requirements for details.

`squad memory` built its LocalMemoryStore over plain files at
<cwd>/.squad, while the memory.* tools in squad_state resolve the team
with resolveSquadState and go through the configured state backend. On
orphan and two-layer backends, in linked teams, in worktrees without
their own .squad and from subfolders the two read and wrote different
stores, and running the CLI from a subfolder created a stray .squad.

The CLI now resolves the squad the same way and opens the same store.
Outside a squad it fails with a clear message; `squad memory help` still
works anywhere.

Closes github#2316
@tamirdresher

Copy link
Copy Markdown
Collaborator

Thanks Jose! I confirmed the split store bug in packages/squad-cli/src/cli/commands/memory.ts:164 (
ew FSStorageProvider() on projectRoot vs
esolveSquadState(startDir) and context.paths.teamSquadDir in packages/squad-cli/src/cli/commands/state-mcp.ts:77). Aligning the CLI onto openGovernedMemoryStore with lazy initialization keeps squad memory help working outside a repo while bringing CLI reads and writes under the same fail-closed resolver and state backend boundary as squad_state. The merge-tree is clean against dev and I approved the CI runs. We are in a release freeze for 2.0.0-preview.2 and will merge this right after #2315 once the release is out.

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.

squad memory and the agents' memory.* tools use different stores on git backends, linked teams and subfolders

2 participants