Composite Bifrost endpoint + PAD read-endpoint — memory + live PAD in one session (#17 follow-on) #18
Closed
opened 2026-06-18 01:16:01 -07:00 by vh
·
0 comments
No Branch/Tag Specified
main
diag/r30-gap-injection-harness
diag/r30-phi0-step-response
diag/r29-pad-series
graphify-tooling
v0.22.3
v0.22.2
v0.22.1
v0.22.0
v0.21.20
v0.21.19
v0.21.18
v0.21.17
v0.21.16
v0.21.15
v0.21.14
v0.21.13
v0.21.12
v0.21.11
v0.21.10
v0.21.9
v0.21.8
v0.21.7
v0.21.6
v0.21.5
v0.21.4
v0.21.3
v0.21.2
v0.21.1
v0.21.0
v0.20.17
v0.20.16
v0.20.15
v0.20.14
v0.20.13
v0.20.12
v0.20.11
v0.20.10
v0.20.9
v0.20.8
v0.20.7
v0.20.6
v0.20.5
v0.20.4
v0.20.3
v0.20.2
v0.20.1
v0.20.0
v0.19.9
v0.19.8
v0.19.7
v0.19.6
v0.19.5
v0.19.4
v0.19.3
v0.19.2
v0.19.1
v0.19.0
v0.18.11
v0.18.10
v0.18.9
v0.18.8
v0.18.7
v0.18.6
v0.18.5
v0.18.4
v0.18.3
v0.18.2
v0.18.1
v0.18.0
v0.17.17
v0.17.16
v0.17.15
v0.17.14
v0.17.13
v0.17.12
v0.17.11
v0.17.10
v0.17.9
v0.17.8
v0.17.7
v0.17.6
v0.17.5
v0.17.4
v0.17.3
v0.17.2
v0.17.1
v0.17.0
v0.16.1
v0.16.0
v0.15.1
v0.15.0
v0.14.2
v0.14.1
v0.14.0
v0.13.0
v0.12.0
v0.11.0
v0.10.0
v0.9.0
v0.8.2
v0.8.1
v0.8.0
v0.7.1
v0.7.0
v0.6.5
v0.6.4
v0.6.3
v0.6.2
v0.6.1
v0.6.0
v0.5.1
v0.5.0
v0.4.1
v0.4.0
v0.3.0
v0.2.1
v0.2.0
v0.1.0
Labels
Clear labels
blocked-needs-contract
blocked-needs-dependency
bug
cli
documentation
duplicate
enhancement
invalid
needs-architect-decision
needs-info
needs-triage
observability
ready-for-agent
sse-client
task
tui
wontfix
Sleipnir refuses dispatch — issue-scoped contract missing
Sleipnir holds dispatch — INV-029 dependency-aware gate
Something is not working
Command-line surface (--send, --new, --session, etc.)
Docs / contract / spec work
Duplicate of another issue
New feature or improvement
Not a real issue
Escalated for a design call
More info required from reporter
Newly filed, not yet sorted
Log-pane / debug-surface work (persona, admin events, Bifrost, tools)
Gates AFK dispatch via Sleipnir (applied by /sleipnir-preflight)
SSE consumer module (src/ratatoskr/sse_client.py)
Implementation task
Textual app shell + presenters
Accepted as not-fixing
No labels
enhancement
Milestone
No items
No Milestone
Projects
Clear projects
No projects
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: vh/ratatoskr#18
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Context
Follow-on to #17 (Bifrost-binding the chat client — shipped this session, v0.17.8–v0.17.13, live-smoke proven). #17 delivered single-plane bind + the dispatch-layer op-feed, with two limits deliberately parked at v1:
POST /sessionsbinds exactly onebifrost.endpoint_url. Our memory (:8391) and affect (:8390) providers are separate processes, so a session binds memory or affect — not both. A Sindra session that should both remember and show live PAD can't do both at once.affect.emitto our:8390store and it persists (live-proven this session: op-feedop:"emit", session_id:"7f65a975…", status:"ok", stored:true). But the web persona pane still reads Worldtree'spersona_state(loadPersona, index.html:707), which 404s for every Tier-3 colon-id agent (ADR-0009 — persona_state is Tier-1-only). So the pane prints "persona telemetry isn't exposed for Tier-3 … yet" even though our store HAS the PAD. The pane was never wired to read from our own store — the "persona-pane payoff" the #17 affect-binding was meant to unlock.Goal
Make a single bound Sindra session both remember (memory plane) and show live PAD/valence in the persona pane (affect plane), in one seat. Two deliverables:
1. Composite Bifrost endpoint (un-parks #17 open-question)
A single ASGI facade (new port, e.g.
:8392) fronting BOTH our memory + affect stores, advertising BOTHmemory+affectcaps at the handshake. One session binds it → Worldtree dispatches both memory-calls AND affect-calls to it. Bifrost's own reference server already mounts both planes in one app (reference_server/server.py: handshake + memory-call + affect-call routes taking both stores), so this is a thin combined builder mirroring the two existing ones (build_memory_provider_app/build_affect_provider_app).Per the #17 contract's parking note, this is NOT just "handshake lists both caps":
instrument_provider_appcurrently takes a FIXEDplaneparam — for the combined app it must derive plane per-request from the path (/bifrost/memory-callvs/bifrost/affect-call), which it already half-does in_op_from.2. PAD read-endpoint → persona pane renders our store
A small non-bifrost read route on the affect provider (recommended over the web server opening
affect.dbdirectly — keeps the provider the owner of its store, no web↔SQLite coupling). The store already hasget(agent_id, end_user_id)→ the PAD/valence snapshot. Then:GET /api/affect/{agent_id}) proxies it server-side;loadPersona(or a sibling) renders PAD/valence from OUR store instead of (or as fallback to) the Tier-3-gatedpersona_state.affect.fetchover bifrost is reserved/blocked (Worldtree can't fetch) — irrelevant here: we own the store and read it directly, no Worldtree dependency. (WT #289affect.fetch/affect:readis an OPTIONAL mediated-read — their intelligence over our raw store — NOT a prerequisite.)Operator decisions (this session)
Acceptance
memory+affect.searchAND an affectemit, each correlated to the bound session_id.ratatoskr:sindra) from OUR:8390store — no "telemetry isn't exposed" for affect-bound sessions.Dependencies / scope
endpoint_url)..contract.mdcovering both pieces before code.