Skip to content

feat: author read filter takes a list of agents - #381

Merged
yw0nam merged 2 commits into
mainfrom
feat/author-list-filter
Oct 20, 2026
Merged

yw0nam merged 2 commits into
mainfrom
feat/author-list-filter

Conversation

@yw0nam

@yw0nam yw0nam commented Oct 20, 2026 •

Copy link
Copy Markdown
Owner

Summary

A note read defaults to the caller's own notes and the shared notes. Another agent's notes come back only when the caller names that agent. author used to take one slug or "all", so a caller could not name two agents at once.

  • author on search_memory, list_notes, list_memory_duplicates, and read_entity takes a list of slugs or "all". The MCP schema is array of string | "all" | null.
  • POST /search takes author as a list (a single slug string still resolves to one author). GET /notes, /admin/notes, /admin/duplicates, and POST /admin/archive take repeated author params.
  • The SQL filter is metadata->>'author' = ANY($n::text[]). The internal keyword is authors from note_scope down to history_predicates.
  • The author description and the server instructions state the default scope and the explicit form, author=["natsume", "claude-code"].
  • Consolidation groups keep one author per request. The route takes the single slug from the resolved list.

Related issues

Closes #380

Runtime evidence

search_memory input schema from an in-process MCP client:

"author": {
 "anyOf": [{"items": {"type": "string"}, "type": "array"}, {"const": "all", "type": "string"}, {"type": "null"}],
 "description": "Omitted: your own notes and shared notes. Another agent's notes come back only when you name it: a list of slugs returns exactly those agents' notes, e.g. [\"natsume\", \"claude-code\"]; include your own slug to keep yours. \"all\": every agent's notes."
}

test_a_list_of_authors_reads_exactly_those_authors against the throwaway Postgres and the live embedder: author C reads author=[A, B] through GET /notes and POST /search and gets exactly A's and B's notes, not its own.

$ uv run pytest -q tests/serve/test_author_scope_integration.py -k list_of_authors
1 passed, 4 deselected in 11.53s
$ uv run pytest -q -m integration
149 passed, 2 failed
$ uv run pytest -q tests/serve/test_supersede.py tests/serve/test_turns_integration.py
32 passed
$ uv run pytest -q -m "not integration"
1745 passed, 151 deselected

The two full-run failures pass in isolation. test_concurrent_appends_to_one_session_get_distinct_seqs fails the same way in a full run on main (an asyncio lock bound to another event loop, order dependent); the other was a 503 from the live search endpoint and changes between runs.

Verification

  • uv run pytest passes (integration tests run locally against a throwaway Postgres container and the live embedder)
  • uv run ruff format --check . and uv run ruff check . pass
  • docker compose build mcp passes (Dockerfile / dependency changes) — N/A, no dependency change
  • Runtime evidence attached above, or N/A justified

Checklist (core principles)

  • Selective storage — notes stay distilled; verbatim text lives only in doc_rows and the turns lane
  • Source-specific logic stays out of the source-agnostic core (ingest pipeline, retrieval, serving)
  • No hardcoded endpoints/models — configuration lives in .env
  • New/changed behavior ships a test in this PR (or skip-tests label justified)

@yw0nam
yw0nam merged commit f72381e into main Oct 20, 2026
4 checks passed
@yw0nam
yw0nam deleted the feat/author-list-filter branch October 20, 2026 02:25
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.

feat: author read filter takes a list of agents

1 participant