Commit Graph
5 Commits
Author SHA1 Message Date
vh 7f4ceaab2b feat(#18): composite Bifrost endpoint — build_combined_app (Deliverable 1)
One ASGI app fronting BOTH the memory.* and affect.* planes (:8392), so a single
bound Worldtree session both remembers AND shows live PAD. Closes #18 end-to-end
(D2 PAD read-endpoint shipped v0.17.14; D1 was bifrost-blocked, now unparked by
bifrost 0.10.0's public build_combined_app + FR-1 resolved — zero Worldtree change).

- provider/combined.py: build_combined_provider_app wraps bifrost.consumer.build_combined_app
  over both stores + mounts the shared affect read route. Advertises both caps by store
  presence; per-route call-time isolation is bifrost's (INV-013).
- affect_store.py: extract add_affect_read_route shared helper (the D2 INV-007 promise —
  composite + standalone mount the SAME read route over the same affect.db, INV-011).
- opfeed.py: plane='combined' derives the OpEvent plane per request path
  (memory-call->memory, affect-call->affect, handshake->combined; INV-012).
- serve_combined.py + ratatoskr-combined-provider console script on :8392 (additive —
  standalone :8390/:8391 untouched, INV-014).
- contract: 18.contract.md § Deliverable 1 (INV-009..INV-014); D1 un-deferred.

Latent bug fixed (exposed by the contract-mandated memory `search` dispatch test running
through TestClient = a worker thread): open_memory_store lacked check_same_thread=False —
the SAME sqlite thread-safety bug already fixed in the affect store (D2). The composite
serves the memory plane over HTTP, so a memory-call on uvicorn's threadpool would trip it.
Fix: check_same_thread=False + PRAGMA busy_timeout=5000 (memory contract Concurrency note).

heid-code-review panel (Groa/Hulda/Regin): ZERO drift findings; the implementation matches
INV-009..INV-014 at function-block level. Folded the genuine test-fidelity fix (memory leg
describe_store -> search per the contract TEST) + added the PRE-001/PRE-002 guard tests.
Suite 486 -> 502 green.
2026-06-19 23:32:47 -07:00
vh 96d61a4bb1 feat(provider): split memory search scope_filter → scope_all + scope_any (bifrost 0.8.0/wire v0.6)
Repin bifrost 0.7.0→0.8.0 and reimplement the memory store's search scope
filter to the v0.6 split (#11): scope_all (AND/intersection) + scope_any
(OR/union over a list of conjunctive scopes), at parity with the v0.6
reference _matches_scope / _validate_scope. No-compat: scope_filter removed.

scope_any is the union-visibility primitive that resolves the #295/#297
silent-zero AND foot-gun — a subset-scoped chunk now recalls via an OR
member. End-to-end cold recall now gated only on Worldtree emitting
scope_any on its recall path (#297, upstream).

- store: search(scope_all, scope_any); _scope_subset + _matches_scope + _validate_scope
- contract v1.2: search FN sig, INV-005 recomposed, PRE-003 both fields, scope_any_union test
- tests: scope_any union, scope_all∧scope_any compose, both-empty match-all; parity vs real 0.8.0 dispatch (433 green)
- #17 contract: sync stale scope_filter/_scope_matches-AND refs to scope_all/scope_any
- runbook + persistent-memory updated; provider bounced onto 0.8.0 (fresh empty db)

v0.17.6
2026-06-16 23:09:31 -07:00
vh aac4353933 feat(provider): validate scope_filter against the v0.5 4-axis lattice
bifrost 0.7.0 (wire v0.5) makes agent_self canonical: the scope lattice is
now {end_user, group, tenant, agent_self}. Our store was MORE permissive than
bifrost's reference (no _validate_scope_filter), which silently 0-zeroed the
#295 cold recall instead of a loud 400. Now matched: search rejects an
out-of-lattice axis with InvalidFilter (-> memory.invalid_filter 400), agent_self
admitted. Purely additive — everything that validated before still validates.

Closes the parity gap our own foot-gun flag opened (bifrost-dev shipped the
lattice add #10 off it). Pin bumped bifrost>=0.6.1 -> >=0.7.0. Contract
search PRE-003 + lattice_axes test; 2 new store tests; full suite 429 green.
2026-06-16 01:24:01 -07:00
vh 1f94e5f251 docs(provider): memory contract v1.1 — heid-contract-review fixup
Panel review (Gróa/Hulda/Regin) → 11 spec-tightening fixes, no design change:
- INV-001 byte-equal → semantic round-trip (the slip that rode the affect copy-paste)
- search returns top_k IN-SCOPE results (filter-then-limit) — Regin's correctness catch
- idempotency_id reconciled to the reference's ("default", verb, actor, key)
- inline the reference's field keys (id/embedding/scope/distillate) + recalled_view + scope_filter shape
- drop scan from INV-005; clarify metadata_filter-v1 reject, transaction-term, delete atomicity, get_many, revision-on-replay
- revisions: marker records the v1.1 delta
2026-06-15 01:21:24 -07:00
vh eebab46812 docs(provider): memory-plane v1 contract (basic plane) + ignore provider runtime DBs
- docs/contracts/bifrost_memory_provider.contract.md: v1 memory consumer spec —
  SQLite+sqlite-vec basic plane (describe_store / search / get / upsert / delete),
  honest capability advertisement (edges/atomic/transaction off, optimistic-lock on),
  affect-reused replay-or-conflict idempotency, #195 parity gate. Memory is a
  STRUCTURAL INDEX (reads vector/scope/id/origin), not a blind conduit (INV-001).
- .gitignore: *.db (+ wal/shm) — provider stores hold persisted agent affect/memory
  state; never track them.
2026-06-15 00:49:52 -07:00