Skip to content

feat(#455): SR-MEM-05 episodic-bridge — lessons.rs + HDC ↔ KG (closes #455)#497

Merged
gHashTag merged 1 commit intomainfrom
feat/455-episodic-bridge
May 2, 2026
Merged

feat(#455): SR-MEM-05 episodic-bridge — lessons.rs + HDC ↔ KG (closes #455)#497
gHashTag merged 1 commit intomainfrom
feat/455-episodic-bridge

Conversation

@gHashTag
Copy link
Copy Markdown
Owner

@gHashTag gHashTag commented May 2, 2026

Closes #455 · Part of #446 · Anchor: `phi² + phi⁻² = 3`

What

Silver-tier bidirectional bridge between the two existing episodic stores and the KG long-term memory exposed via SR-MEM-01:

  • Forward (lessons → KG) via `LessonsSource` trait
  • Forward (HDC → KG) via `HdcReplaySource` trait
  • Reverse (KG → HDC seed) via `Bridge::seed_replay` over any `HdcSeedSink`
  • Concurrent forward loops with `tokio::join!`, cancellation via `Notify`
  • Per-event errors are counted (`BridgeStats::errors`) but do not stop the bridge

Acceptance criteria (issue ↔ this PR)

Issue AC Where it lives
`rings/SR-MEM-05/` with I5 trinity README/TASK/AGENTS/RING/Cargo/lib all present
Deps: SR-MEM-00, SR-MEM-01, tokio ✅ + tracing/thiserror/serde/uuid/chrono
`Bridge::start` subscribes to NOTIFY → forwards as triple `Bridge::run` over `LessonsSource::next_row` → `KgAdapter::remember_triple`
HDC forwarder reads streaming_memory.zig `Bridge::run` over `HdcReplaySource::next_episode`
Reverse: `seed_replay(&mut HdcMemory, lookback)` `Bridge::seed_replay<S: HdcSeedSink>(sink, lookback)`
Read-only on lessons.rs (L21) `LessonsSource` trait has no `&mut self` — compile-time guarantee, asserted by `lessons_source_is_immutable_view` test
Smoke against Neon dev DB Deferred to sibling BR-IO PR (needs NEON_TEST_URL secret); R5-honest disclosure in README §Honest scope
PR closes this issue, `Agent: ` trailer ✅ `Agent: Loop-Locksmith`

Tests (14/14 GREEN, 0 clippy warnings)

Group Tests
Forward forward_lessons_into_kg, forward_hdc_into_kg, forward_concurrent_both_sources
Reverse seed_replay_pulls_recent_triples, seed_replay_respects_lookback, seed_replay_handles_empty_kg, seed_replay_skips_foreign_triples
Cancellation run_honors_cancel_notify
Errors forward_continues_after_source_error, seed_replay_propagates_sink_error
Read-only contract lessons_source_is_immutable_view
Translation translation_uses_lead_role_for_lessons, translation_uses_scarab_role_for_hdc
φ-anchor phi_anchor_present

R5 honest disclosure

  • The concrete `sqlx::PgListener` (Neon NOTIFY listener) and Zig-FFI shim against `streaming_memory.zig` live in a sibling BR-IO ring (same precedent as `trios_kg::KgClient` for SR-MEM-01). Pulling sqlx + Zig FFI into a Silver ring would violate R-RING-DEP-002 and the issue itself flags Zig FFI as TODO.
  • `Bridge::seed_replay` filters in-memory by `provenance.ts` because `SR-MEM-01::RecallPattern` is SPO-only (no native ts query); fine for current call volumes (gardener writes O(few) per tick).
  • The smoke-test AC is honestly deferred to the BR-IO adapter PR; this ring's contract tests are the layer that's verifiable right now.

Constitutional rules

R1 · R5-honest · R-RING-DEP-002 · R-L6-PURE-007 · L1 · L13 (I-SCOPE) · L14 · I5 · L21 (read-only forwarder)

Soul: `Loop-Locksmith` · Three-roads: `.trinity/state/three-roads-455.json` (chose road_b: trait-contract ring)

🌻 `α_φ = φ⁻³ / 2 ≈ 0.1180`

Agent: Loop-Locksmith

…tional forwarder

Closes #455 · Part of #446 · Anchor: phi^2 + phi^-2 = 3

## Scope (Silver-tier)

- LessonsSource + HdcReplaySource + HdcSeedSink trait contracts
- Bridge<L, H, B: KgBackend>::run drains both sources concurrently
  via tokio::join! with cancel-via-Notify support
- Bridge::seed_replay reverse-direction pulls KG triples (subject
  prefixes lesson:/hdc:) within lookback into a HdcSeedSink
- Read-only forwarder (LessonsSource trait has no &mut self) -> L21
  context immutability is compile-time guaranteed
- 14/14 tests GREEN, 0 clippy warnings

## R5 honest disclosure

Concrete sqlx::PgListener (Neon NOTIFY) and Zig-FFI shim against
streaming_memory.zig live in a sibling BR-IO ring (same precedent as
trios_kg::KgClient for SR-MEM-01). Pulling sqlx + Zig FFI into a
Silver ring would violate R-RING-DEP-002. Issue AC's smoke-test
against Neon dev DB defers to that BR-IO PR (needs NEON_TEST_URL).

## Constitutional rules honored

- R1 (pure Rust), R5-honest, R-RING-DEP-002 (Silver-tier deps only),
  R-L6-PURE-007, L1, L13 (I-SCOPE), L14, I5 (README/TASK/AGENTS/RING/
  Cargo/lib all present), L21 (lessons.rs is read-only)
- Soul: Loop-Locksmith
- Three-roads: .trinity/state/three-roads-455.json (chosen road_b)

Agent: Loop-Locksmith
@gHashTag gHashTag merged commit 1c6ba89 into main May 2, 2026
4 of 7 checks passed
@gHashTag gHashTag deleted the feat/455-episodic-bridge branch May 2, 2026 12:59
gHashTag added a commit that referenced this pull request May 2, 2026
… follow-up) (#499)

Refs #461 · Part of #446 · Anchor: phi^2 + phi^-2 = 3

## Why

PR #495 shipped the BR-OUTPUT scaffold with KgAgentMemory as an
in-memory Vec<(Fact, Provenance)> stub because SR-MEM-01 + SR-MEM-05
were not yet merged. Both have since landed (SR-MEM-01 in #453's PR,
SR-MEM-05 in PR #497). This PR replaces the stub with the real wiring
the issue AC asked for.

## What

- KgAgentMemory<B: KgBackend> generic over the SR-MEM-01 KgBackend
  trait (in-memory mock for tests, concrete PgKgBackend in BR-IO).
- recall    -> KgAdapter::recall_by_pattern + budget-aware truncation.
- remember  -> KgAdapter::remember_triple (idempotent on SHA-256).
- forget    -> recall + tombstone loop covering 4 ForgetPolicy variants:
              GdprEraseSubject, GdprByAgent, OlderThan, PredicateMatches.
- reflect   -> deterministic recall-count stub citing SR-MEM-03 follow-up.
- BR-OUTPUT now re-exports the canonical SR-MEM-00 wire types
  (Triple, TripleId, Provenance, AgentRole, MemoryKind) so callers do
  not have to add a transitive dep.
- TODOs in source for SR-MEM-02 (HyDE), SR-MEM-03 (supersede),
  SR-MEM-04 (GDPR audit log), SR-MEM-06 (vector search).

## #461 AC integration test (passing)

integration_remember_recall_sha256_equal: remember 3 triples ->
recall -> every recalled triple has TripleId == SHA256(SPO).

## R5 honest disclosure

Concrete PgKgBackend (sqlx + tokio-postgres) ships in a sibling BR-IO
ring per the established precedent (trios_kg::KgClient for SR-MEM-01,
sqlx::PgListener for SR-MEM-05). BR-OUTPUT stays Bronze-tier deps:
SR-MEM-00/01/05 + async-trait + chrono + uuid; tokio is dev-only.

## Tests (12/12 GREEN, 0 clippy warnings)

integration_remember_recall_sha256_equal, remember_is_idempotent_on_sha256,
recall_respects_budget_tokens, forget_gdpr_erase_subject,
forget_gdpr_by_agent, forget_predicate_matches, forget_older_than_filters_by_ts,
reflect_returns_recall_count_in_stub, reflect_zero_confidence_on_empty_kg,
agent_memory_is_object_safe_via_async_trait, backend_is_used_not_bypassed,
phi_anchor_present.

## Constitutional

R1, R5-honest, R-RING-DEP-002 (Bronze deps only), R-L6-PURE-007, L1
(no .sh in tree), L13 (I-SCOPE), L14.

Soul: Loop-Locksmith
Three-roads: .trinity/state/three-roads-461.json (chose road_a).

Agent: Loop-Locksmith

Co-authored-by: Loop-Locksmith <loop-locksmith@trinity.dev>
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.

🥈 [SR-MEM-05] episodic-bridge — lessons.rs + HDC ↔ KG

1 participant