Code tells you what the engine does; the Architecture Decision Records tell you why — and why the alternatives were rejected. Five ADRs form the spine of everything you've learned: that Alembic is an engine and not a product (0001), that the human gate sits at irreversible spend (0005), that the Validator is the emission gate (0006), that a model call never throws (0009), and that the self-improvement loop is Validator-gated (0018). Each one is a constraint the fusion had to honor — read together they explain why @alembic/hermes looks the way it does and not some easier way.
docs/adr/; eighteen are accepted. They are append-only — a later decision supersedes an earlier one (it never edits it), so the trail is a true history, not a tidied-up snapshot.| ADR | The decision | How it constrains the fusion |
|---|---|---|
| 0001 | Alembic is an internal engine, not a customer SKU | No UI/billing/onboarding in the engine — @alembic/hermes ships libraries, not product surfaces |
| 0005 | The human gate sits at ship / irreversible spend | The ClarifyGateway (Lesson 10) is the T4 surface; learning + distill run HITL-free |
| 0006 | Frontier depth everywhere, via the cheapest model above a floor; the Validator is the emission gate | The learning loop must clear a quality floor before sediment — it can't auto-write |
| 0009 | A model call never throws; returns a discriminated result | Every hermes subsystem returns Result, injects its ports, and is store-agnostic |
| 0018 | Internalize Hermes' loop as a Validator-gated propose→dispose pass | The keystone: reviewer proposes, Validator disposes, never auto-applies |
"Alembic is the internal Appfy engine/platform, not a customer-facing SKU today." The consequence is sharp: customer-facing concerns — a public API for sale, billing, tenant onboarding/marketing — "live in products … not in the engine." This is why the fusion ported tools as libraries (a MemoryStore, a webSearch function) and never a runnable agent app with a UI. It also leaves a door open: "If there is real market pull, productizing Alembic as harness-as-a-service … may become a new decision" — recorded as a future ADR superseding this one's scope, never an edit.
You met this as Lesson 14's narrow waist. As a decision it reads: every model call goes through run(input): Promise<ModelRunResult>, a discriminated union, and "run() never throws: failures are values, not exceptions." The rejected option is named — "conventional throwing clients" — because they "scatter try/catch through orchestration … and couple callers to provider-specific error shapes." The consequence list is the load-bearing part: retry, circuit-breaking, budget metering, and council quorum "all operate on uniform typed results." That uniformity is exactly why every hermes subsystem could adopt the same Result shape with no special cases.
This ADR's headline is about cost (frontier depth on the whole corpus via the cheapest model above a depth floor), but its load-bearing clause for the fusion is the emission principle: nothing sediments without clearing a quality floor. That is the rule the learning loop had to obey — a reviewer's proposal is not truth, it is a candidate, and a gate decides. The default scoreThresholdGate(0.7) is the conservative encoding of that floor until the real @alembic/coda Validator wires in.
Where does a human have to be in the loop? Not at design time — "code in a branch is reversible." The deciding criterion is "reversibility/externality, not pipeline position — the gate lives where an autonomous mistake stops being 'delete a branch' and becomes money or reputation." So ship and real spend default to T4-park (fail-closed), while "Distillation (T0–T3 → Signal/Learning) and discover→build are HITL-free." This is the principle the ClarifyGateway implements: a structured, blocking question is the T4 human surface, used only where reversibility runs out.
The newest of the five (accepted 2026-06-23) is the one that authorizes the whole learning subsystem. Hermes had the missing piece — a post-turn reviewer that writes straight to durable memory — but Alembic could not copy it literally for two reasons it states plainly:
AIAgent to fork as a daemon thread" — so the mechanism becomes a pass over injected ports, not a background thread.Read those two bullets and you see the ADR trail working as a system: 0018 cannot just clone Hermes because 0006 forbids un-gated emission and 0009 forbids throwing — so the only shape left is exactly the propose→gate→apply over injected ports that you built in Lab 2. The decision even names the four guarantees: injected ports only, Validator-gated not auto-applied, conservative default with a richer gate opt-in, and the pass is fail-closed with Zod at the boundary.
Each ADR removes options. 0001 removes "build a product." 0009 removes "throw on error." 0006 removes "auto-apply." 0005 removes "gate everything" and "gate nothing." By the time 0018 is written, the design space has narrowed so far that the implementation is almost forced. That is the value of writing decisions down: a future agent can't "simplify" by reintroducing a rejected option, because the rejection is versioned and dated.
AIAgent to fork; and the emission-gate principle) and flags the second as "more importantly." 0006 forbids un-gated sediment, which forces the propose→dispose shape rather than Hermes' direct write.ship and real spend default to T4-park.