feat(cli): mm agent register/list/share + hidden debug-resolve#461
feat(cli): mm agent register/list/share + hidden debug-resolve#461
Conversation
Addresses three nits from the PR #457 review: 1. Drop the unused CLAUDE_/GEMINI_/CODEX_MEMORY_NAMESPACE_PREFIX exports from `constants.py`. Promoting them while `cli/ingest_cmd.py` still hardcodes the literals would have created a *new* parallel-literal seam — exactly what `feedback_drift_close_must_derive` warns against. Wiring the ingest CLI is a separate change, not this PR's scope. 2. Drop the `_AGENT_NAMESPACE_PREFIX = AGENT_NAMESPACE_PREFIX` re-export alias in `multi_agent.py`. The "Re-export for callers that previously imported the local-private symbol" comment was misleading — underscore-private symbols have no external callers by definition, and grep confirms zero in-repo references on this branch. Stacked PRs (#459 / #461) that import the underscore-private symbol get updated when they rebase onto this PR; the public `AGENT_NAMESPACE_PREFIX` is the right import target. 3. Update the comment above `config.search.system_namespace_prefixes = ["archive:"]` in `test_trust_ux.py:68`. After this PR's default flip the override is *narrowing* (default has both `archive:` and `agent-runtime:`), not "spelling out" — the new comment says so and notes that multi-agent isolation has its own coverage in `test_multi_agent`. No behavior change. 2335 tests still pass. Co-Authored-By: Claude <[email protected]>
|
Merge-order coordination note (raised in #457 review): once #457 I'll handle the rebase + literal replacement before requesting merge here. |
* fix(multi-agent): hide agent-runtime: from default mem_search `search.system_namespace_prefixes` default was `["archive:"]` only, so agent A's private chunks (created by `mem_agent_register` / `mem_agent_search`) leaked into agent B's `mem_search(namespace=None)` results — directly contradicting the namespace-based isolation guarantee documented on the multi-agent guide. Extends the default to `["archive:", "agent-runtime:"]` and consolidates the literal in a new `memtomem.constants` module so config, MCP tools, and CLI all derive the prefix from one source. `mem_agent_search` is unaffected because it builds an explicit namespace filter; the hidden count surfaces through the existing `hidden_system_ns` hint. Behavior change: callers relying on plain `mem_search` to read `agent-runtime:*` chunks must now either pin `namespace=` or override `search.system_namespace_prefixes: []` in `config.json`. Documented under [Unreleased] / Changed. Threat model: `agent-runtime:<id>` is a *convenience* isolation boundary, not a security boundary. Direct storage access (raw `namespace=`, ingest `--namespace`, list_namespaces) still reaches private chunks; this PR closes the default-search UX leak only. Test surface (test_multi_agent.py): - `TestDefaultIsolation` pins constants, default factory freshness, and `Mem2MemConfig` default — derives from the constant per `feedback_pin_test_constant_over_source_scan`. - `TestAgentRuntimeIsolationPipeline` end-to-end: `agent-runtime:planner` chunks excluded from `namespace=None` search but reachable via pinned `namespace=`; `shared` namespace stays surfaceable. Co-Authored-By: Claude <[email protected]> * review fixup: drop dead alias/symbols + correct trust_ux comment Addresses three nits from the PR #457 review: 1. Drop the unused CLAUDE_/GEMINI_/CODEX_MEMORY_NAMESPACE_PREFIX exports from `constants.py`. Promoting them while `cli/ingest_cmd.py` still hardcodes the literals would have created a *new* parallel-literal seam — exactly what `feedback_drift_close_must_derive` warns against. Wiring the ingest CLI is a separate change, not this PR's scope. 2. Drop the `_AGENT_NAMESPACE_PREFIX = AGENT_NAMESPACE_PREFIX` re-export alias in `multi_agent.py`. The "Re-export for callers that previously imported the local-private symbol" comment was misleading — underscore-private symbols have no external callers by definition, and grep confirms zero in-repo references on this branch. Stacked PRs (#459 / #461) that import the underscore-private symbol get updated when they rebase onto this PR; the public `AGENT_NAMESPACE_PREFIX` is the right import target. 3. Update the comment above `config.search.system_namespace_prefixes = ["archive:"]` in `test_trust_ux.py:68`. After this PR's default flip the override is *narrowing* (default has both `archive:` and `agent-runtime:`), not "spelling out" — the new comment says so and notes that multi-agent isolation has its own coverage in `test_multi_agent`. No behavior change. 2335 tests still pass. Co-Authored-By: Claude <[email protected]> --------- Co-authored-by: pandas-studio <[email protected]> Co-authored-by: Claude <[email protected]>
dc59cc0 to
a1f47e4
Compare
651e4f6 to
4e57536
Compare
|
Done — rebased onto the post-#457 main (via the rebased #459 base) and
|
Adds operator-facing CLI mirrors of the multi-agent MCP tools so running multi-agent workflows no longer requires an MCP client. The hidden `debug-resolve` subcommand dumps the namespace filter `mem_agent_search` would resolve as JSON, given simulated AppContext state — so multi-agent integration scripts can verify namespace resolution end-to-end without standing up an MCP server. Stacked on top of PR-2 (session→agent_id inheritance) because `debug-resolve` reuses the `_resolve_agent_namespace` helper added there. Commands: * `mm agent register <id> [--description ...] [--color ...]` — mirrors `mem_agent_register`. Sanitizes the agent_id, creates the `agent-runtime:<id>` namespace, and ensures the cross-agent `shared` namespace exists. * `mm agent list [--json]` — table by default with two sections (agents and shared); `--json` for scripts. Non-agent namespaces (`default`, `claude-memory:*`, etc.) are intentionally not surfaced — the command is scoped to the multi-agent surface. * `mm agent share <chunk-id> [--target ...]` — mirrors `mem_agent_share`. Reuses `_build_shared_tags` from PR-3 (with a fallback for branches that pre-date it) so the audit-tag dedup contract stays in lock-step. * `mm agent debug-resolve [--agent-id ...] [--current-agent-id ...] [--current-namespace ...] [--include-shared/--no-include-shared]` — hidden, JSON-only. Re-uses `_resolve_agent_namespace` so the CLI reports exactly what the MCP tool would compute given the same inputs. Test surface (test_agent_cmd.py): 14 cases total — - TestAgentRegister: creates NS + ensures shared, skips shared when it already exists, rejects empty agent_id. - TestAgentList: table grouping, JSON shape, empty state. - TestAgentDebugResolve: explicit-id+shared, current_agent_id fallback, legacy current_namespace fallback, all-None → null filter. CliRunner mocks `cli_components` per `feedback_clirunner_isatty_seam` guidance. The share command is exercised via integration once PR-6 lands (it needs real index_engine wiring). Co-Authored-By: Claude <[email protected]>
4e57536 to
811714e
Compare
Summary
Adds operator-facing CLI mirrors of the multi-agent MCP tools so
running multi-agent workflows no longer requires an MCP client. The
hidden
debug-resolvesubcommand dumps the namespace filtermem_agent_searchwould resolve as JSON, given simulatedAppContextstate — so multi-agent integration scripts can verifynamespace resolution end-to-end without standing up an MCP server.
Stacked on top of #459 (PR-2: session→agent_id inheritance) because
debug-resolvereuses the_resolve_agent_namespacehelper addedthere. Merge order: #459 first, then this PR.
Commands
mm agent register <id> [--description ...] [--color ...]— mirrorsmem_agent_register. Sanitizes the agent_id, creates theagent-runtime:<id>namespace, ensures the cross-agentsharednamespace exists.
mm agent list [--json]— table by default (agents section + sharedsection);
--jsonfor scripts. Non-agent namespaces (default,claude-memory:*, etc.) are intentionally not surfaced — thecommand is scoped to the multi-agent surface.
mm agent share <chunk-id> [--target ...]— mirrorsmem_agent_share.Reuses
_build_shared_tagsfrom fix(multi-agent): admit mem_agent_share is a copy + add shared-from audit tag #458 (with a fallback for branchesthat pre-date it) so the audit-tag dedup contract stays in lock-step.
mm agent debug-resolve [--agent-id ...] [--current-agent-id ...] [--current-namespace ...] [--include-shared/--no-include-shared]— hidden, JSON-only. Re-uses
_resolve_agent_namespaceso the CLIreports exactly what the MCP tool would compute given the same
inputs. Designed for use in PR-6's integration scripts and the
manual e2e in the multi-agent guide.
Test plan
test_agent_cmd.py:TestAgentRegister— creates NS + ensures shared, skips sharedwhen it already exists, rejects empty agent_id.
TestAgentList— table grouping, JSON shape, empty state.TestAgentDebugResolve— explicit-id + shared,current_agent_idfallback, legacy
current_namespacefallback, all-None → nullfilter.
cli_componentsperfeedback_clirunner_isatty_seamguidance.uv run pytest -m "not ollama"— 2349 passed, 46 deselected.uv run ruff check+ruff format --check— clean.The
sharecommand itself is exercised end-to-end once PR-6 lands(needs real
index_enginewiring); the unit-style coverage aboveguards the command-construction surface.
🤖 Generated with Claude Code