Membrane Buildout (Master)
Orchestrating plan for the buildable, additive slice of the Membrane sovereign multimodal-bio-AI vision.
The orchestrating plan for building the buildable, additive, useful-now slice of the Membrane vision into medOS-ultra: Layer 0 (the Human Event Stream schema) → the Intelligence Query layer on top of it → a demo surface. This is the institution-node scope. Everything that needs a fleet, a trained foundation model, or on-device compute is explicitly out of scope and gated — per Membrane’s own sequencing discipline (“the platform is the last organ to grow, not the first”).
Companion docs:
docs/architecture/human-event-stream-layer0.md(the Layer-0 spec, shipped), the Membrane platform analysis (in-conversation), and the execution frameworkdocs/module-loop/00-MASTER.md+docs/module-loop/AUTONOMOUS-MODE.md. This plan is a module-loop run: 10-stage discipline, 28 hard principles, additive-only, sandbox+static verification per iteration.
0. Why this scope, and not the whole platform
Membrane is five layers (schema → runtime → SDK → modules → coordination plane) plus the Osmosis federated protocol. The analysis established that medOS-ultra already realizes ~4 of the 5 in partial form except the live federated network, which is the actual business and which the doc says comes last. The honest, disciplined build target is therefore the part that is (a) additive, (b) reversible, © useful immediately, and (d) verifiable without a fleet or a trained model:
- Layer 0 — the typed, time-stamped, modality-tagged, encoder-versioned, consent-scoped event shape, as an additive extension of the live
observationsread model. (Substrate already shipped:20260603d.) - The Intelligence Query layer — structured cohort query + semantic (vector) retrieval over that stream, driven by an LLM that function-calls allowlisted, parameterized RPCs (never raw SQL). This is what “give me diabetic patients age 40–60” actually needs, and it reuses the shipped
runAgentLoop+ASSISTANT_REGISTRYsubstrate. - A demo surface — a read-only Cohort/Intelligence Query console in the super-admin Intelligence section.
Explicitly OUT OF SCOPE (gated — do NOT build in this loop)
| Excluded | Why gated |
|---|---|
| Federation / Osmosis (secure aggregation, DP, LoRA delta sync) | Gated on single-modality FL working at all; bleeding-edge; no scaffolding exists |
| On-device model training / tiered placement runtime | The secure-custody half (wallet/did:bio) exists; federated-compute half does not |
| Coordination plane (Layer 4 — the business) | Needs a fleet + a trained model to coordinate |
survival module (time-to-event) / predict_next_events() trajectory SDK |
Gated on a foundation model proving the moat (Horizon 1) |
| Pseudonymizing the operational store | Wrong by design — de-id is a Silver-layer concern (ai-training-corpus.md) |
Applying migrations to prod / pushing to release |
Manual + requires explicit user sign-off |
1. Invariants (every iteration must hold these)
- Additive-only. New columns/tables/functions/files only. Never alter/drop an existing column, constraint, index, RLS policy, or file. (web/CLAUDE.md ABSOLUTE GUARDRAILS.)
- LLM never writes raw SQL. It function-calls allowlisted, parameterized RPCs; it fills params; a vetted RPC executes. No hallucinated entities (reuse the
seenMatchesguard). - RLS +
consent_scopebound every read. Query RPCs run with caller privileges (RLS-enforced), notSECURITY DEFINER, unless a reviewed reason exists. PHI (patient lists) is gated behind an explicit param + role; default returns counts/aggregates. - Recommender-only. No autonomous writes, no gating of clinical actions, every AI call audited (
llm_audit_log). Feature-flagged OFF by default, per-tenant. - No migration is applied by the loop. Migrations are written + statically reviewed; apply is a manual, user-gated step (per Deployment Status table).
- Reuse, don’t rebuild.
runAgentLoop,ASSISTANT_REGISTRY,@medical-kit/code-systems,llm_search_embeddingspattern, design-kit wrappers, the cron_jobs registry — extend them. - Bilingual seed/UI (TH/EN) where user-facing, per repo i18n rule.
- Stay on
main, never branch/switch/stash. Commit additive work incrementally with loop trailers; do not push.
2. STOP conditions (halt the loop, ask the user)
- Any change that would be destructive / non-additive (drop, stub, bulk-edit, config edit).
- Any need to apply a migration to a live DB, push to
release, or deploy. - Any ambiguity in auth/RLS/consent semantics for a query that returns PHI.
- Any place where returning a patient list could leak beyond consent and the gate isn’t obvious.
- Discovery that an assumed read-model column/JSONB path doesn’t exist (verify, then proceed or ask).
3. Phases
Each phase is a loop iteration: build → static-verify → commit (feat(membrane): … / Loop: membrane-buildout / Phase: Pn). Order is dependency-driven; later phases consume earlier RPCs/types.
P0 — Layer 0 substrate completion
- ✅
20260603d_human_event_stream_layer0.sql—observations+modality/embedding(768)/encoder_id/encoder_version/consent_scope. - ✅
docs/architecture/human-event-stream-layer0.md. - ☐
20260603e_observation_modality_backfill.sql— idempotentcategory/source_kind→modalitybackfill (WHERE modality IS NULL). - ☐
HumanEventTS contract + read-only accessor overobservations(Layer-2 seed; no writes). Home:web/src/services/human-event-stream/. - Verify: SQL static review vs
20260512_observation_unification.sql;tscon the new TS.
P1 — Embedding producer + semantic search
- ☐
infrastructure/medbase/functions/observation-embedder/index.ts— Deno edge fn: selectobservations WHERE embedding IS NULL(batch), build a compact text doc per row (code_display+ value + unit + modality), call Ollama/api/embeddings(nomic-embed-text, 768),UPDATE embedding, encoder_id, encoder_version. Idempotent, batched, fail-soft, env-drivenOLLAMA_URL. - ☐
20260603f_observation_semantic_search.sql—search_observations_by_embedding(vector(768), patient_id?, modality?, limit, min_score)RPC (cosine<=>, RLS-enforced, capped limit). - ☐
cron_jobsregistry row for the embedder (off by default; percron-jobs-registry.md). - Verify: Deno typecheck if available; SQL static review vs
llm_search_embeddings/search_conference_decisions_by_embedding.
P2 — find_patient_cohort RPC
- ☐ Verify exact shapes first:
patient_clinical_cache(age/gender columns),encounter_journey_cachediagnosis JSONB path (handleDiagnosisRecorded),observationslab filter. - ☐
20260603g_find_patient_cohort.sql— parameterized RPC:{age_min, age_max, gender, diagnosis_codes text[], lab_code, lab_min, lab_max, date_from, date_to, include_subjects bool, limit}. Returns count + aggregates by default; subject rows only wheninclude_subjects(role-gated). RLS-aware. - Verify: SQL static review; a
*.sql-shaped self-test (EXPLAIN-able) documented in the phase notes.
P3 — Population READ tool (cohort-query domain)
- ☐
web/src/services/ai/cohort-query/{tools,runner,dispatcher,prompts,index}.ts— toolsfindPatientCohort,searchSimilarObservations; dispatcher callssupabase.rpc(...); registercohortQueryDomaininASSISTANT_REGISTRY(toolClassread,featureFlag: 'assistant.cohortQuery.enabled'). - ☐ Reuse
runAgentLoop; enforce no-raw-SQL + param allowlist + audit. - Verify:
tsc; unit test of the dispatcher mapping (NL params → rpc args) with a mocked supabase client.
P4 — Cohort Query Console (frontend demo)
- ☐
CohortQueryConsole.tsxin the super-admin Intelligence section + a route under/admin/intelligence/…. NL input → parsed cohort chips → result count + aggregate bar + gated subject table. design-kit wrappers; confidence + consent badges; read-only. - ☐ Sandbox target +
registry.tsentry +*.sandbox.spec.tssmoke. - Verify:
pnpm dev:sandbox+ Playwright sandbox smoke (no auth).
P5 — Docs + verification + UAT
- ☐ “Query & retrieval” section in
human-event-stream-layer0.md(3 modes: structured cohort RPC / per-patient time-series / semantic vector; the no-raw-SQL contract). - ☐ Demo script (
docs/demo-scripts/intelligence-query.md) + UAT checklist. - ☐ End-to-end static + sandbox verification pass; update this progress log.
4. Verification reality (what “verify” means without a fleet)
- SQL: static review against the exact patterns in already-applied migrations (read, don’t guess); idempotent + additive; never applied by the loop. Apply is the user’s manual step.
- TS:
tsc(workspace or scratch perdocs/architecture/fhir-ipd-handoff-2026-05-09.md/tmp/jest-runtrick if deps aren’t installed). - Frontend: lightweight sandbox (
:5179?target=…) +playwright.sandbox.config.ts(no auth). Local full-app Supabase is stale (memory) — do not rely on live data locally. - Edge fn: Deno typecheck; logic review; deploy is manual (
supabase functions deploy).
5. Progress log
| Date | Phase | What landed | Commit |
|---|---|---|---|
| 2026-06-03 | Plan + P0 | master plan + Layer-0 substrate (20260603d/e, HumanEvent TS contract, layer0 doc) |
3dd80d29e |
| 2026-06-03 | P1 + P2 | semantic-search RPC (20260603f) + observation-embedder edge fn + writer RPC (20260603h) + find_patient_cohort RPC (20260603g) |
bff52c8c0 |
| 2026-06-03 | P3 | cohort-query READ tool (6 files + registry); 11/11 dispatcher unit tests | 5a87a7394 |
| 2026-06-03 | P4 | CohortQueryConsole + /admin/intelligence/cohort-query route; 4/4 e2e agent-loop test |
4a69d8bee |
| 2026-06-03 | P5 | query-layer doc section + this log | (this commit) |
Buildout status (2026-06-03): P0–P5 SHIPPED as code — additive, verified, committed to main, NOT applied/pushed. To go live (each a manual, user-gated step): (1) apply migrations 20260603d–h to the target Supabase; (2) supabase functions deploy observation-embedder + set LLM_EMBED_URL; (3) optionally run the embedder + register its cron_jobs row; (4) set assistant.cohortQuery.enabled for the tenant; (5) deploy frontend via release. OUT-OF-SCOPE items (federation/Osmosis/on-device training/coordination plane) remain gated — promoting any is a separate decision. One flagged review item: the cohort-query cross-patient PHI posture (aggregates-first, RLS-safe-fail, subjects opt-in) — confirm before exposing the subject-list path to non-service roles.
Update this table every iteration. When all P0–P5 boxes are ticked and verified, the buildout is complete; promotion of any OUT-OF-SCOPE item is a separate, user-gated decision.
Design intent + build plan. Additive only. No federation, no on-device training, no prod apply, no push — all gated. “Membrane”/“Osmosis” are placeholder names.