feat: memory scope+visibility contract v1 + embedder default alignment, drift-tested (#28)#29
Conversation
…ed to public, drift-tested (#28) Adds docs/contract.md: one convention every eidetic memory-store consumer pins to — a personal scope per repo named by culture.yaml's `suffix` (record families ride the existing `type` field + metadata, no new scope primitives), and a `public` default visibility for in-repo team-shared records (private stays one explicit `--visibility private` away). Includes the store-resolution table copied verbatim from eidetic/memory/backend.py's _resolve_write_dir/_candidate_read_dirs. Fixes the live bug this convention exists to close: the vendored recall/remember skill wrappers here (.claude/skills/{recall,remember}/ scripts/*.sh) silently overrode the plain `eidetic remember`/`recall` CLI's own `--visibility` default (verified: argparse default is already "public" in eidetic/cli/_commands/{remember,recall}.py — no CLI code changed) to "private" for a no-flag invocation, while colleague's separate colleague/memory.py runtime hardcodes "public" for its own shell-outs. Two consumers of the same store disagreeing on the default by accident. Both wrappers now default to public, matching the CLI and colleague; the no-suffix-resolved warning (which only made sense when a silent private->public downgrade was the risk) is removed since there's no longer a privacy-downgrade risk either way. SKILL.md descriptions for both skills updated to match. This is a deliberate reversal of the private-by-default decision recorded in docs/specs/2026-06-23-eidetic-cli-s-remember-recall-skill-wrappers-are-h.md (FIX-4) — recorded honestly in docs/contract.md's History section rather than silently overwritten, since that spec affirmed private was intentional at the time and only fixed a doc/behavior mismatch around it. Provenance note: recall/remember are FIRST-PARTY to eidetic-cli (origin, not vendored from guildmaster — see docs/skill-sources.md), and are fanned out to ~57 downstream repos including colleague's own vendored copy. This fix needs to be propagated DOWNSTREAM via the next re-sync/ rollout to those consumers — it is not itself a change to push upstream. Tests: tests/test_wrapper_convention.py shells both the vendored wrapper and the raw CLI (via python -m eidetic, no uv/network dependency) with EIDETIC_DATA_DIR pointed at a tmp dir and no --visibility flag, asserting both land the same visibility (fails before this fix, passes after) plus a mutual-visibility recall proof. tests/test_contract_drift.py parses contract.md's machine-readable block and cross-checks it against both wrapper scripts' literal default and the CLI's actual argparse default (exercised via a real parse_args() call, not introspection) — a future divergence on any of the three surfaces fails here. Verified: eidetic's own --visibility argparse default was already "public" for both remember and recall (no CLI code touched, per task scope). Full suite: 355 passed, 2 pre-existing skips (unrelated). black/isort/flake8/ bandit/markdownlint-cli2/teken doctor --strict all clean on changed files. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…02 / Qwen3-Embedding-0.6B), drift-tested (#28) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… default alignment) (#28) Record the CHANGELOG entry for docs/contract.md (memory scope+visibility convention v1), the recall/remember wrapper default reversal to public visibility, and the embedder default alignment to 8002/Qwen3-Embedding-0.6B.
PR Summary by QodoPin memory scope/visibility convention v1; default wrappers to public; drift-test embedder
AI Description
Diagram
High-Level Assessment
Files changed (12)
|
Code Review by Qodo
Context used✅ Tickets:
🎫 spec: one memory scope + visibility convention, drift-tested on both sides [colleague#291/S9]✅ Compliance rules (platform):
32 rules✅ Skills:
version-bump 1.
|
Resolve the version-bump collision: - pyproject.toml / uv.lock: keep 0.11.0 (> main's 0.10.2). - CHANGELOG.md: union — [0.11.0] on top, splice main's [0.10.2] entry in before [0.10.1]. No content contradicts; purely ordering. Brings in #26's repo-contained-store spec doc + .devague state. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Harden tests/test_wrapper_convention.py — test-only, no wrapper change:
- Finding 1 (store resolution): new hermetic test
test_wrapper_and_raw_cli_resolve_the_same_default_store_location proves
both surfaces resolve the SAME store dir under the real _resolve_write_dir
algorithm (throwaway `git init` repo + redirected HOME, no EIDETIC_DATA_DIR
override). Safe because store-dir resolution is CWD-driven, independent of
the wrapper's script-location scope resolution. (Qodo comment 3531674260)
- Finding 2 (version skew): _pin_eidetic_on_path prepends the venv bin to
PATH so the wrapper's `command -v eidetic` resolves to this checkout's
0.11.0 console script, not a globally-installed eidetic (verified: a stale
global 0.10.1 shadowed it before). No edit to the 57-repo-fanned-out
wrappers. (Qodo comment 3531674266)
- Finding 3 (file scraping): _all_records now reads via the in-process API
get_backend("files").all() / record.scope.visibility instead of parsing
*.jsonl, decoupling from data-refinery's on-disk layout. (Qodo comment 3531674270)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|



Summary
Lands the eidetic-cli slices for colleague#291's integration arc (issue #28, slices S9+S2):
docs/contract.md, a memory scope+visibility convention (v1) that every consumer of the eidetic memory store — the vendoredrecall/rememberskill wrappers here, colleague's owncolleague/memory.pyruntime, or a future direct CLI consumer — now pins to (a personal scope per repo named byculture.yaml'ssuffix, and apublicdefault visibility for in-repo team-shared records). It fixes a live disagreement: the vendored wrapper scripts silently defaulted a no-flag invocation toprivatewhile the plain CLI's own argparse default was alreadypublicand colleague's runtime hardcodespublic— two consumers of the same store disagreeing on the default by accident. Both wrappers now default topublic, matching the CLI and colleague.This is a deliberate reversal of the private-by-default decision recorded in
docs/specs/2026-06-23-eidetic-cli-s-remember-recall-skill-wrappers-are-h.md(FIX-4) — recorded honestly indocs/contract.md's History section, not silently overwritten; that spec affirmed private was intentional at the time and only fixed a doc/behavior mismatch around it. Downstream note:recall/rememberare first-party to eidetic-cli and fan out to roughly 57 downstream repos (including colleague's own vendored copy) — this fix needs a downstream re-sync/rollout to actually take effect there, which is not part of this PR. Also aligns the embedder code default to the documented reference deployment (port 8002 /Qwen3-Embedding-0.6B, was 8101 /text-embedding-3-small), with a three-way drift test pinning code, docs, and wrapper scripts in agreement.Test plan
uv run pytest -n auto -q— 359 passed, 2 skipped (live Neo4j not reachable; cross-backend ranking now data-refinery's concern)tests/test_contract_drift.pyandtests/test_wrapper_convention.pycross-checkdocs/contract.md's machine-readable block against both wrapper scripts' literal defaults and the CLI's actual argparse defaulttests/test_embed_default_drift.pypins the embedder default three ways (code, docs, wrapper scripts)Honest limit: this PR ships the convention and the local wrapper fix only; the ~57-repo downstream propagation of the wrapper default flip is separate follow-up work, not included here.
🤖 Generated with Claude Code