Assemble the existing total-recall faculties (perception · grounding · intuition · credit · recall-wrapper) into the closed learning loop via a hub/blackboard orchestrator plus the two missing pieces — the decision/action HEAD and fusion. Recall-agnostic; additive; fixture-tested. BUILD double-gated.
The orchestrator holds a mutable WorkingContext and routes a projection of it to each faculty — faculties take different inputs, they are not chained. The hub retains the original RecallContext because credit.computeOutcomeReward(RecallContext, outcome) needs it (disk-verified) — a linear pipe would lose it.
flowchart TD
IN["input: RawMemory[] + root"]:::io
subgraph HUB["orchestrator.ts — WorkingContext (blackboard)"]
direction TB
P["perception
perceiveToSessionGraph → SessionGraph"]:::f
R["recall-wrapper
→ Candidate[]"]:::f
G["grounding-gate
groundCheck(GroundingCandidate, {ledger,root})"]:::f
I["intuition
IntuitionEngine → hints (MemoryId[])"]:::f
H["decision-action.ts (HEAD)
grounded + hints → Action | Abstention"]:::new
FU["fusion.ts
deterministic dedup/merge"]:::new
C["credit
computeOutcomeReward(RecallContext, outcome)"]:::f
end
IN --> P --> R --> FU --> G --> I --> H
H -->|Action → outcome| C -->|OutcomeReward| SEAL["seal → MEMORY"]:::io
H -->|Abstention| ABS["reward = null · NO seal"]:::risk
classDef f fill:#161b22,stroke:#4c8dd6,color:#e6edf3;
classDef new fill:#12261a,stroke:#5bbf7b,color:#e6edf3,stroke-width:2px;
classDef io fill:#1c232d,stroke:#9aa7b4,color:#e6edf3;
classDef risk fill:#2a1820,stroke:#d1607a,color:#e6edf3;
| File | Role | Key contract | |
|---|---|---|---|
| faculty-contract.ts | authoritative typed interface map + adapter types | imports the 5 real faculty types; defines the genuine-new Candidate→GroundingCandidate adapter | new |
| orchestrator.ts | the hub: WorkingContext + projection routing + the loop | holds groundingContext={ledger,root}, recallContext; seals only on Action | new |
| decision-action.ts | the HEAD — grounded+hints → Action | Abstention | abstain on empty/low-confidence; Action carries a RecallOutcomeTrace outcome | new |
| fusion.ts | deterministic multi-source candidate fuse (dedup/merge) | order-independent, idempotent | new |
| Task | Builds | Test (layer) |
|---|---|---|
| T1 | faculty-contract.ts + adapters | L1 — each of 5 entrypoints callable in isolation on fixtures; type-checks |
| T2 | fusion.ts | L3 (A3-3) — dup/overlap sets → identical fused set, order-independent |
| T3 | decision-action.ts (HEAD) | L3 (A3-1/A3-2) — fabricated→abstain; low-conf→abstain; terminal-state: Action→seal, Abstention→reward null, NO seal |
| T4 | orchestrator.ts (hub) | L0 (A0-1) + L2 (A2-1) — full loop on fixtures; every seam type-checks or has a documented adapter |
| T5 | NC battery | L4 — NC1 faculty tests green · NC2 recall-agnostic · NC3 grounding fail-closed · NC4 fusion determinism + credit=utility · NC-abstain (no seal) · NC5 no live-recall/empty-store BUILD |
Traceability: L0→T4 · L1→T1 · L2→T4 · L3→T2,T3 · L4→T5. All five layers covered.
Genuine 2-round PLAN panel (signed seats: Grok mandatory + Codex + Gemini; recall endpoint = corroborating dogfood seat).
R1 → R2: Codex caught an abstention/credit contract gap (does Abstention seal credit?); Gemini caught a missing groundingContext in WorkingContext + a mislabeled adapter (sliceMemoriesToCandidates is memories→Candidate, not Candidate→GroundingCandidate). All verified on disk and closed in the revision → R2 unanimous approve.
Holds until (1) keystone-convergence (the serving-lane W1 harness) and (2) store-fill (WICK_CONTINUOUS_INGEST fills the real co-access store). PLAN/DESIGN proceed now; BUILD waits.
This faculty layer consumes the filled store; it does not rebuild revive-build's serving-lane W1–W5 (per WICK_WIRING_ROADMAP).
Fixture-to-real-store shape drift after store-fill — mitigated by NC2 (recall-agnostic) + thin adapter-typed seams + the L4 battery. New contract seams stay unexercised until the W1 harness lands (Grok's residual).