Skip to content

feat(phase5): explainable memory operations (v3.10)#160

Open
salishforge wants to merge 1 commit into
mainfrom
feat/phase5-explainable-memory
Open

feat(phase5): explainable memory operations (v3.10)#160
salishforge wants to merge 1 commit into
mainfrom
feat/phase5-explainable-memory

Conversation

@salishforge

Copy link
Copy Markdown
Owner

Summary

Feature 2 of the Phase 5 split from umbrella #129 (F1 landed in #137, F5+F6 in #136/#138). No schema migration — pure code feature.

  • explain=true on GET /memory/:id/query — each result carries an ExplanationFactor[] (rank_score, epistemic_status weight 1.0/0.5/0.2, search_mode, temporal_decay when decay is active).
  • GET /memory/:id/explain?warm_id= + MemoryManager.explainMemory() — state report for a single warm memory: scores, epistemic status, access patterns, and standing against the sleep-cycle score thresholds. The outlook flags are deliberately scoped (would_evict_by_threshold, would_flag_low_confidence); capacity eviction and outcome/contradiction-driven revision depend on live cross-table state and are not predicted.
  • Full checklist parity the umbrella branch lacked: memforge_explain MCP tool wired to a real client method (the umbrella version was a stub returning memoryHealth), TS + Python SDK methods including both resilient wrappers, tool-definitions, OpenAPI entries.
  • Hardening from adversarial review (17-agent workflow, 13 raw → 8 confirmed findings, all addressed): warm_id bounded to int8 at REST + MCP boundaries (was: Postgres 22003 → 500), invalid agent id on /explain returns 400 like sibling routes, query cache key extracted to queryKey() in cache.ts so the explain flag's key participation is pinned by unit tests without Redis.

Test evidence

Suite Result
npm run type-check 0 errors
npm run lint clean
tests/explainable-memory.test.ts (new) 27/27
npm run test:http 36/36
npm run test:integration 24/24
npm run test:epistemic-confidence 30/30

Pre-existing issues surfaced by review (out of scope, filing separately)

  • Python SDK QueryResult dataclass rejects unknown response keys — already incompatible with v3.8/v3.9 response fields at HEAD.
  • /entities and /graph return 500 (not 400) for invalid agent ids — same pattern this PR fixes for /explain.
  • epistemic query param missing from the OpenAPI query-path spec (F1 gap).

🤖 Generated with Claude Code

https://claude.ai/code/session_011xCqQo49d3CEbn6oEvb3Ru

Feature 2 of the Phase 5 split (umbrella #129): every retrieval can say
why, and any warm memory can be asked where it stands.

- query(): opt-in explain=true attaches ExplanationFactor[] per result
  (rank_score, epistemic_status weight, search_mode, temporal_decay)
- explainMemory() + GET /memory/:id/explain?warm_id= reports scores,
  access patterns, and standing against the sleep-cycle score
  thresholds. Flags are scoped honestly (would_evict_by_threshold,
  would_flag_low_confidence): capacity eviction and the outcome /
  contradiction revision channels depend on live cross-table state and
  are deliberately not predicted here.
- memforge_explain MCP tool wired to the real client method; TS +
  Python SDKs including both resilient wrappers; OpenAPI entries
- query cache key extracted to queryKey() in cache.ts so the explain
  flag's participation in the key is unit-testable without Redis
- warm_id validated to int8 range at REST and MCP boundaries; invalid
  agent ids on /explain return 400 like sibling routes

No schema migration — pure code feature.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011xCqQo49d3CEbn6oEvb3Ru
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.

1 participant