14 · Architecture¶
Internals, invariants, and the mapping from this definition to build phases.
Crate & package layout¶
horismos/ (workspace)
├── crates/
│ ├── horismos-core/ # THE product: ontology, world, reasoner, agent, traces, verify
│ │ ├── ontology/ # turtle parse, profile, imports, interning
│ │ ├── world/ # store, gate, snapshots, transactions, queries
│ │ ├── reason/ # subsumption, forward (rete-lite), backward, proofs
│ │ ├── workflow/ # step interpreter, edges, outcomes
│ │ ├── verify/ # BDD checks + witnesses (port of sigil-lang verifier)
│ │ ├── trace/ # horismos.trace/1 emit + replay
│ │ └── wasm.rs # [wasm] HorismosRuntime
│ ├── horismos-bridges/ # provider clients ([bridges-*] features), mock
│ ├── horismos-py/ # PyO3 bindings only — no logic
│ ├── horismos-host/ # format-neutral snapshot/effect SPI + artifact policy
│ ├── horismos-fhir/ # R4 hydration/mapping/conditional commit + CDS surface
│ └── horismos-harness/ # recorded repository projection + artifact handoff
├── python/horismos/ # pure-Python surface: proxies, testing utils, export
├── docs/framework/ # ← you are here (becomes the docs site)
├── PRPs/ # phase plans
├── examples/
│ ├── triage/ # flagship (ttl + runs + tests)
│ ├── no-llm-monitoring/ # the anti-wrapper demo
│ ├── mcp-tools/
│ └── taubench-harness/
└── planning/ # living plan artifact
The dependency invariant (anti-wrapper, enforced)¶
horismos-core → (nothing model-related) # compiles & tests with zero LLM deps
horismos-host → horismos-core # pure format-neutral host values
horismos-bridges → provider SDKs
horismos-fhir → horismos-host + horismos-core # transport remains adapter-local
horismos-harness → horismos-host # no filesystem/process execution
horismos-py → horismos-core (+ optional bridges)
Mechanical enforcement, not convention:
horismos-corehas no dependency onhorismos-bridges— theBridgetrait lives inhorismos-core::bridgeas a pure interface; implementations live outside.- CI job
no-model-gate: buildshorismos-core --no-default-features --features verify, runs the full symbolic test suite with no network and no keys. Red = the anti-wrapper claim broke. - CI job
wasm-gate:wasm32-unknown-unknownbuild of the same.
Data flow (one perception transaction)¶
text ──Bridge──▶ JSON (schema-forced) ──gate──▶ base facts
│ forward chain (rete-lite, in-core)
▼
derived facts + proofs
│ constraint re-check
▼
commit ── snapshot ── trace append ── subscribers
Everything inside the box after the Bridge call is allocation-light Rust over interned IRIs. There is no cross-language chatter inside a transaction — the sigil-lang benchmark lesson (PyO3 marshaling dominated small workloads) is designed out: Python/WASM hand a whole input over, get a whole outcome back.
Two-boundary data flow for a standards-hydrated deployment¶
The diagram above is the inner box, unchanged. A standards-hydrated deployment wraps it
with two more boundaries, both outside horismos-core, both entirely before/after the
transaction above — never interleaved with it:
FHIR/CIS or repo/harness ──Adapter (hydrate)──▶ ExternalSnapshot ──▶ [ inner box above ]
│
[ inner box above ] ──▶ ProposedEffectSet ──Adapter (commit,
conditional on source version)──▶
FHIR/CIS or repo/harness
This is the reference data flow from the adopted design
(horismos-thin-pivot-s1/report.md §"Reference data flow"). It changes nothing about the
dependency invariant above: the format-neutral contract lives in horismos-host; adapters
live in their own crates (horismos-fhir and horismos-harness) and depend inward, never
the reverse. A future HTTP transport may exist only in the FHIR adapter behind a feature;
the shipped recorded transport and harness prototype have no network, filesystem-mutation,
or process-execution dependency.
Performance posture¶
| Path | Target (triage-scale: ~50 rules, ~10² facts) | Rationale |
|---|---|---|
| Gate + chain transaction | < 1 ms | In-core, interned, rete-lite indexed |
prove / explain |
< 1 ms | Depth-capped, indexed rule heads |
| Load + verify | < 1 s | Authoring-loop interactivity (doc 13) |
| Perception step | Bridge latency + < 5 ms overhead | The model call dominates by orders of magnitude |
| Adapter hydration/commit | External I/O latency, not core-budgeted | A live FHIR read/write is bounded by the external system, not the kernel — measured and reported separately, never blended into the deterministic-kernel numbers above |
Benchmarks (criterion) are CI-tracked from PRP-002 onward; regressions fail builds. Scaling beyond (10³+ rules, 10⁵+ facts) is measured, not promised — the Rete-lite → full-Rete decision point is data-driven (PRP-002). Split, going forward: the table's existing rows measure deterministic kernel time only; any future adapter benchmark is a separate, clearly-labeled external I/O latency number — conflating the two would hide a network-bound adapter behind an in-core performance claim.
Concurrency model¶
One World = one serial transaction stream (single-writer). Horizontal pattern:
one world per case/session/conversation, sharing an immutable Ontology. This
matches the domain shape (a triage case, a claim, an incident) and eliminates
lock discipline from the mental model. Cross-world aggregation is a query/reporting
concern, outside the runtime.
Amended (2026-08-24, bounded-projection pivot): for a standards-hydrated deployment, read "one world per case" as one projection per decision epoch — a World's lifetime is bound to one hydration/decision, not to the case's own lifetime, which the external system of record continues to own. A long-running case may span many projections (one per decision point, each re-hydrated), rather than one World living as long as the case does. This is a refinement of the existing pattern, not a different one: a standalone deployment where the case genuinely is the World's lifetime (the shipped triage example) is unaffected.
Security & trust boundaries¶
- Untrusted: NL input, LLM output, tool return values → all pass gates.
- Trusted after sign-off: the ontology (it is the program — its supply chain is git + SME sign-off + verification, doc 13).
- Sandboxing tool-execution processes (including MCP servers and the authoring
agent) is the deployer's concern;
horis:redactInputbounds sensitive NL retention (doc 09). This is the deployer-process-isolation boundary specifically — for the v1 threat model in full (assets, all four trust boundaries, per-boundary mitigations vs. what stays deployer-owned), see doc 15.
Definition → build mapping¶
| Docs | PRP |
|---|---|
| 02 Ontology, 03 World | PRP-001 |
| 04 Reasoning, 09 Traces (schema) | PRP-002 |
| 11 Python API | PRP-003 |
| 05 Workflows, 06 Boundaries, 07 Tools, 08 Bridge | PRP-004 |
| 10 Verification | PRP-005 |
| 12 Rust API surface polish, packaging, docs site | PRP-006 |
| 13 Authoring | PRP-007 |
| 15 Security & Trust | PRP-004, PRP-006, PRP-007, PRP-008 (per boundary — see doc 15) |
| Standards/host-integration additions across 00–03, 06, 07, 09, 10, 13, 14 | PRP-008 |
Every [DECIDE] marker in these docs is owned by exactly one PRP; activating a PRP begins by resolving its markers.