Skip to content

feat(memory): project identity and global namespace - #533

Open
initializ-mk wants to merge 1 commit into
mainfrom
worktree-memory-p0-namespaces
Open

initializ-mk wants to merge 1 commit into
mainfrom
worktree-memory-p0-namespaces

Conversation

@initializ-mk

Copy link
Copy Markdown
Contributor

Phase 0 of the semantic-memory + procedural-rework track

Establishes the foundation for a unified global memory store at ~/.forge/memory with two ownership namespaces that never cross-contaminate:

Namespace Keyed by Written by Contents
projects/<project-id>/ git remote optimizer proxy (coding sessions) 3-tier card system (later phases)
agents/<agent-id>/ forge.yaml agent_id agent runtime operational memory

This PR lands only the identity + namespace + migration primitives and the forge memory CLI. Later phases build the card, exports, procedure rework, promotion ladder, context_load, and the optimizer rewire on top.

What's here

  • ProjectID(worktree) = sha256(normalized remote)[:12], with a local-<hash> fallback. NormalizeRemote collapses scp/https/ssh forms + credentials + ports + .git so equivalent URLs map to one id; distinct local checkouts never collapse.
  • AgentID(raw) normalizes a forge.yaml agent_id into a filesystem-safe segment.
  • Registry — JSON map (projects.json / agents.json) of id → entry, unioning local paths across checkouts. Atomic writes.
  • NewGlobalFileStore(root, namespace, id) with a single-segment path guard (traversal barrier). NewFileStore retained for repo-local use.
  • MigrateRepoLocal — copies a repo-local .forge/memory into agents/<agent-id>/, mapping daily logs (YYYY-MM-DD.md) into sessions/. Copy, not move: the source is left intact with a .migrated sentinel, so it's idempotent and nothing is stranded for a still-repo-local runtime.
  • forge memory {migrate,projects,agents} CLI (migrate --dry-run, --dir).

Incidental fixes (from grounding the spec against real code)

  • Added a real atomic-write helper (temp → fsync → rename) for all new writes — the spec assumed one existed; only FileVectorStore had a partial temp→rename (no fsync).
  • Fixed FileVectorStore.Search silently clamping k<=0 to 10, which capped keyword-only full scans. It now returns the whole corpus for k<=0.

Gate (all green)

  • go test ./forge-core/memory/... -run 'TestProjectID|TestAgentID|TestRegistry|TestMigrate' -v ✅
  • go vet ./forge-core/memory/... ✅
  • forge memory migrate --dry-run / forge memory projects / forge memory agents exercised end-to-end in a sandbox HOME ✅
  • gofmt clean.

Note: golangci-lint is not installed on the dev machine (Makefile notes it must be installed separately), so lint was not run locally — CI should cover it.

Introduce the foundation for a unified global memory store under
~/.forge/memory with two ownership namespaces:

  projects/<project-id>   coding-session memory keyed by git remote
  agents/<agent-id>       deployed-agent operational memory keyed by agent_id

- ProjectID: sha256(normalized git remote)[:12] with a local-<hash>
  fallback so equivalent remote URLs collapse and distinct local
  checkouts never do. AgentID normalizes forge.yaml agent_id to a
  filesystem-safe segment.
- Registry: JSON map (projects.json / agents.json) id -> entry,
  unioning local paths across checkouts; atomic writes.
- NewGlobalFileStore(root, namespace, id) with a single-segment path
  guard; NewFileStore retained for repo-local use.
- MigrateRepoLocal: copies repo-local .forge/memory into
  agents/<agent-id>/, mapping daily logs to sessions/, leaving the
  source intact with a .migrated sentinel (idempotent).
- forge memory {migrate,projects,agents} CLI.
- Add atomic-write helper (temp -> fsync -> rename) for all new writes.
- Fix FileVectorStore.Search silently clamping k<=0 to 10, which
  capped keyword-only full scans.

Tests: TestProjectID, TestAgentID, TestRegistry, TestMigrate,
TestNormalizeRemote.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant