Extension Architecture (Arc History)
Narrative history of the extensibility architecture's evolution.
Date: May 2026 Status: Frozen record. Do not update — append a new section if the architecture evolves. Companion docs:
What this document is
The architecture doc (README.md) records what was decided. This doc records how we got there — the reasoning chain, the fabrications that were caught, the audit corrections, and the discipline that emerged. The architecture doc is append-only for findings; this doc is frozen at the end of the arc.
A future agent reading the README will see clean decisions. That cleanliness obscures how many confident-sounding claims turned out to be wrong, and how the audit-before-action loop caught them. This doc preserves that signal.
The arc in three phases
Phase 1 — Confident design from unverified premises
The initial conversation designed an addon system for extending OrderRequestItem with per-hospital typed fields. The design was confident and internally coherent:
- “Same registry pattern as your AdmissionRow extensions” — implying an existing pattern to match
- “SLH wants infection-screening attestation on blood orders” — implying a real customer wish
- “BATMC wants narcotic countersign” — implying a second customer wish
- “Mirrors the pattern from migration 067’s zod consumers” — implying validation precedent
- “Tier 2/3 sync” — implying cross-hospital data movement infrastructure
Every one of these premises was false. AdmissionRowExtension didn’t exist. SLH and BATMC are not real tenant codes. Migration 067 has zero consumer code. Tier 2/3 sync doesn’t exist. The design was internally consistent but externally fabricated — it matched a codebase that doesn’t exist.
Phase 2 — Audit caught the fabrications
The audit phase checked every claim against the actual codebase:
-
grep for existing patterns:
AdmissionRowExtension,NEWS2Extension,OrderItemExtension,useApplicableExtensions— all zero hits. There was no existing pattern to match. -
grep for tenant codes:
SLH,BATMC— no such constants inHospitalModuleConfigor anywhere in the config layer. Real gating is flat booleans, not hospital-code switches. -
Read migration 067: Real table (
order_dispatch_policieswith JSONB columns), but zero consumer code outside the e2e SQL spec. The “zod consumers we should match” claim was false — there’s nothing to match. -
Read
clinicalservice: The claim “audit logging is universally manual” was overgeneralized.clinicalwiresHookAuditLogMixinfor automatic capture. The blanket claim was wrong. -
Read
MedicalModelExtension: The claim this was a “FHIR extension system” was partially true — the UI exists but is a mock (// Mock data,console.loghandlers, zero imports outside its folder). The actual structured-data bridge turned out to beworkflow_form_models(migration 006), a completely different system that wasn’t mentioned in the initial design. -
Read
workflow_form_models: This was the most important discovery. The initial conversation treated EForm as one system. The audit found two: legacy Toolpad EForm (89 usage points,DialogEForm.tsx) andworkflow_form_models(FHIR 3-tier, JSON Schema, scope-aware resolution). The newer system was already partially doing what the addon system was designed to do — but for different use cases (open-ended admin-authored fields vs typed developer-coded fields).
Phase 3 — Redesign from verified ground
With fabrications removed, the design was rebuilt on verified premises only:
- Naming: “addons” not “extensions” — because
MedicalModelExtensionalready claims the extension vocabulary (even though it’s a mock). Precedent:addonCaptureOptimizer.service.tsin kaigo code. - Gating:
HospitalModuleConfigflat booleans — because that’s what actually exists, not hospital-code switches. - Storage: Mongo
Objectfield — mirrors 067’s pattern (structured blob on entity), not its mechanism (Postgres JSONB). Acknowledged tradeoffs. - Validation: Hand-rolled type guards — because zod has zero usage in the relevant packages. Convention-setting, not convention-matching.
- Activation: Code-defined — because the admin UI for runtime toggling (
worklist-editortabs,workflow_templatescolumns) doesn’t have the right shape for addon control.
The key architectural insight: addons and workflow_form_models answer different questions and don’t compete. Addons = “developer adds typed, validated, behavior-bearing field.” workflow_form_models = “admin adds open-ended fields without a release.” Same entity can carry both.
Fabrication patterns observed
These patterns are worth naming because they recur across agent conversations, not just this one:
-
Confident reference to nonexistent code. “Same pattern as X” where X doesn’t exist. Sounds like the agent read the code; actually it synthesized a plausible name. The fix is grep — if
Xreturns zero hits, the claim is fabricated regardless of how plausible it sounds. -
Imagined customer requirements. “SLH wants X” creates urgency and specificity. The specificity makes the requirement feel real. But without a ticket, a conversation log, or a config constant, it’s fiction. The fix is: never ship code gated on imagined requirements. Reference implementations should be explicitly marked as unregistered references, not auto-activated features.
-
Overgeneralization from partial observation. “Audit logging is manual everywhere” from observing it’s manual in one place. The fix is: qualify claims with scope (“in this service” not “everywhere”) and check at least two data points before generalizing.
-
Conflation of mock and real systems.
MedicalModelExtensionhas UI that looks real. But// Mock data+console.loghandlers + zero external imports = mock. The fix is: trace imports outside the folder. If nothing imports it, it’s not load-bearing regardless of how complete it looks. -
Missing system discovery.
workflow_form_modelswasn’t mentioned in the initial design because it wasn’t looked for. The initial conversation asked “how does EForm work?” and got the Toolpad answer. The question “is there another form system?” was never asked. The fix is: after finding one system, ask “is there another one?” — search for the concept, not just the known implementation.
The DialogOrder.tsx question
Late in the arc, the modification to DialogOrder.tsx was challenged: “is this coupling addon infrastructure to the imaging-specific legacy code that the Layer 4 pilot was supposed to extract?”
Investigation showed: No. The modification is a single line in the cross-cutting submit handler (_FormData.listitems.push({...})) that runs for every typeForm, not imaging-specific code. The submit handler is shared infrastructure — adding addons: item.addons there is the correct layer. The Layer 4 imaging extraction (deferred) won’t need to touch this line.
The challenge itself was useful: it applied the same audit-before-action discipline to pushback, not just to agent claims. “This feels like it’s coupling to legacy code” was a confident claim from an unverified premise — the same shape of mistake the audit loop catches. Checking the actual diff (Possibility A vs B) resolved it in 5 seconds.
What shipped
| Layer | What | Files |
|---|---|---|
| Backend entity | OrderRequestItem.addons field |
OrderRequestItem.ts |
| Framework | Types, registry, hook, barrel, wrapper components | addons/ (7 files) |
| Reference addon | Blood infection screening (NOT registered) | addons/builtin/blood-infection-screening.tsx |
| Submit handler | Generic addon pass-through | DialogOrder.tsx (1 line) |
| Config | bloodBankInfectionScreening flag |
hospital-config.ts |
| Admin UI | Extension Guide page | pages/admin/extension-guide/ |
| Admin UI | Addon Manager page (config toggles + preview) | pages/admin/addon-manager/ |
| Documentation | Architecture doc (Part A + Part B + Audit Log) | addons/README.md |
| Documentation | EForm UX design doc | EFORM_UX_DESIGN.md |
| Documentation | This arc-history | docs/architecture/extension-architecture-arc-history.md |
What was explicitly NOT shipped
- No auto-registered addons. The reference implementation exists as a file but is not in the registry. Registration happens when a real hospital wish lands.
- No imaging extraction (Layer 4 pilot). Deferred — the framework doesn’t depend on it.
- No zod. Hand-rolled type guards until usage justifies the dependency.
- No admin-driven registration. Addons are code-defined. The Addon Manager page controls activation (config flags), not registration (which addons exist).
- No lifecycle-stage attachment. “Must complete before status → X” requires workflow-action-handler changes that aren’t built.
The discipline that emerged
Audit before design. Every claim about existing code gets grepped before it influences a decision. “Sounds right” is not evidence.
Ship verified, defer imagined. Reference implementations are files, not features. Auto-registration creates the expectation of a feature. A file with a comment creates the expectation of a pattern.
Qualify scope. “X is true in service Y” not “X is true everywhere.” One observation is an observation, not a law.
Challenge your own pushback. “This feels wrong” is subject to the same verification standard as “this exists.” Check the diff before calling it debt.
Freeze the reasoning. Architecture docs record decisions. Arc-history docs record how the decisions were reached and which wrong paths were tried. Both are institutional memory; they serve different readers at different times.