Course / Lesson 24  ·  PT-BR
Lesson 24 · Advanced · the decisions

The ADR trail: the decisions that shaped the fusion

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.

What an ADR is. A dated, immutable record of one architectural decision: the context, the choice, the options rejected, and the consequences. The repo keeps them in 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.

The trail at a glance

ADRThe decisionHow it constrains the fusion
0001Alembic is an internal engine, not a customer SKUNo UI/billing/onboarding in the engine — @alembic/hermes ships libraries, not product surfaces
0005The human gate sits at ship / irreversible spendThe ClarifyGateway (Lesson 10) is the T4 surface; learning + distill run HITL-free
0006Frontier depth everywhere, via the cheapest model above a floor; the Validator is the emission gateThe learning loop must clear a quality floor before sediment — it can't auto-write
0009A model call never throws; returns a discriminated resultEvery hermes subsystem returns Result, injects its ports, and is store-agnostic
0018Internalize Hermes' loop as a Validator-gated propose→dispose passThe keystone: reviewer proposes, Validator disposes, never auto-applies
ADR-0001 — engine, not product (the outer boundary: no customer surfaces in the engine) ADR-0009 — run() never throws (the contract every subsystem speaks) ADR-0006 — Validator is the emission gate  ·  ADR-0005 — human gate at irreversible spend ADR-0018 — the gated learning loop propose → gate (disposes) → sediment — never auto-apply sits inside all four outer constraints at once

ADR-0001 — engine, not product

"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.

ADR-0009 — the contract that makes everything composable

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.

ADR-0006 — the Validator is the emission gate

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.

ADR-0005 — the human gate at irreversible spend

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.

ADR-0018 — the keystone, and why it's an ADAPT not a CLONE

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:

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.

The trail is a constraint graph, not a wish list

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.

1. ADR-0018 says the learning loop is an ADAPT, not a literal CLONE of Hermes. The more important reason given is:
Correct: c. The ADR lists two reasons (no Python 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.
2. Per ADR-0005, what decides whether an action needs a human gate?
Correct: b. The ADR is explicit: "the deciding criterion is reversibility/externality, not pipeline position." That's why distill and discover→build are HITL-free (reversible) but ship and real spend default to T4-park.
3. Why does the project record rejected options inside each ADR (e.g. "throwing clients — rejected")?
Correct: d. ADR-0011 makes this explicit elsewhere ("a future agent cannot 'simplify' by ingesting CL4R1T4S or copying tac source — the prohibition is explicit and versioned"). Recording the rejected path is what makes the decision enforceable, not just informative.

Common confusions

"ADRs get updated when the design changes." No — they're append-only. A new decision supersedes an old one with its own dated record; the old one stays as history. ADR-0001 even spells out the protocol for its own future reversal.
"0006 is just about money." Its headline is cost, but the clause the fusion leans on is the emission principle — nothing sediments without clearing a quality floor. That single idea is what makes learning gated rather than automatic (0018).