kestrel.markets
Version:
A typed, token-efficient language + runtime for agentic trading: agents author bounded plans, the runtime fires them at the tick. CLI + typed library + MCP server.
411 lines (362 loc) • 30.8 kB
Markdown
# Percept inflection and template-as-hypothesis — pane args are a typed addressing morphology, and every founder View is a graded seed, never a blessed default
**Status:** **Accepted** (2026-07-15, owner-accepted same day). Committed output of the
4-lens divergent brainstorm on the percept space (record: session scratchpad
`brainstorm-percept-space.json`; the deepening pass that hardened this draft is recorded at
`docs/brainstorms/2026-07-15-adr-0041-deepening/` — including a post-synthesis fifth lens
(domain extension) from that same record, which folded in the `instrumentClass` cell-key
axis, the carry-cell doctrine, and scheme-relative addressing below; tracker
`kestrel-wa0j.23`). This ADR is a
**precondition** of Train 1 code (`kestrel-wa0j.24`) and the template ledger train
(`kestrel-wa0j.26`) — it must land before either. It extends ADR-0009 (**the screen is
measured, not designed** — no rendering is blessed by taste), ADR-0029 (**the
agent-requested emergent View authoring loop** — the tournament and owner-gated freeze
that promotes a discovered View), and ADR-0030 (**the grammar is measured, not
designed**). It reinterprets ADR-0004's `print(parse(text))` round-trip for a parameterized
pane vocabulary and inherits ADR-0038's Attribution discipline for cross-instrument
builders. Companion beads: the Train 1 inflection substrate (`kestrel-wa0j.24`), the
founder library + TemplateRecord ledger (`kestrel-wa0j.26`), the first live cohort
(`kestrel-wa0j.18`).
## Context
Two facts about the perception layer are now settled and pull in the same direction.
**The View language is wider than the catalog, and the golden corpus already spells the
destination.** `tests/golden/accept/views.kestrel` teaches a morphology the catalog does
not yet materialize — `macro week quarter rv20`, `vol straddle expected-move`, `tape
skyline 5m vwap detector-strip`, `levels registry`, `chain fair realness`. Every one of
those argument forms **parses and round-trips byte-stable**, and every one is **refused at
materialization today** (post-`wa0j.19`, only a single `window` arg on `tape` resolves).
That gap is not a defect in the corpus: goldens are the **grammar** contract (does it parse
and print byte-stable), never the **catalog** contract (does it materialize). The two
contracts are deliberately different, and the space between them *is* the inflection
backlog. Meanwhile the shipped catalog carries 16 panes whose only parameterized member is
`tape`, each having grown its own ad-hoc argument parsing (`renderTapeWithArgs` throws a
bespoke `KernelHonestyError` from inside the builder). Six more panes want arguments and
there is no shared substrate for giving them one.
**Structure is saturated; only economics can still discriminate.** The benchmark/launch
session's merged strategist hill-climb (owner relay, 2026-07-15) produced a hard empirical
result: on the matched-set harness, **every restraint pane tested lost to baseline**. The
mechanism is specific and instructive — forcing a `range-velocity` read made the strategist
stand down 5/6 on the ORB fakeout while baseline chased 6/6, which *looks* like the pane
teaching discipline. Graded on the matched set it was the opposite: baseline's fakeout plan
**floors at a profitable +75** because the model's authored defined-risk exit already prices
the fakeout, so the pane's stand-down **forfeited money it should have made**. A pane that
cuts the loss on the restraint pole while killing the gain on the action pole nets to
zero-or-worse — and grading only on the pole it obviously helps will tell you it is a win
when it isn't. Fable's *structural* rubric is saturated (26/26 at 5/5): structure cannot
separate a good pane from a passivity trap. Only **economics on matched setups** can.
Two cautions bound how strongly that result may be written. First, the pooled null (every
pane hurts) is **TRAIN-only, small-N, with an accumulating-transcript confound** — it is
*unproven, not settled*, and this ADR must record the admission rules that would make either
outcome credible rather than assume the null. Second, a pane's sign is **role-dependent**:
`range-velocity` was passivity for the **strategist** (whose exit already handles the
fakeout) but may be *correct* for the **watcher** on a stop-less trap. Sign is not universal.
## Decision
Three doctrines, each with its guarding invariants.
### 1. Inflection: pane parameters become a typed addressing morphology, never expression evaluation
Pane arguments are promoted from ad-hoc per-pane parsing to **typed `ParamSlot`
signatures** on the catalog entry — an *inflection substrate*. A `PaneCatalogEntry` gains a
first-order signature: an ordered list of `ParamSlot`s, each a `{ name, sort, arity,
default? }`. Materialization binds positional arguments to slots in signature order; a
sort or arity mismatch raises the **repair-guiding** `KernelHonestyError` uniformly (one
error surface, not sixteen), fail-closed, naming the pane, the slot, and the served sort —
never a silent drop, never a silent default.
**The one non-negotiable: arguments are ADDRESSES over closed index sorts, never
expressions.** A View argument is a **ground constant of a closed index sort** —
`Instrument`, `LevelName`, `Window`, `SessionOrdinal`, `ExpiryOrdinal`, `Count`, `Band` —
denoting an address into the frozen Frame. The composition grammar contains **zero function
symbols**: there is no application node, ever, and there never will be. Computation lives
*only* inside catalogued, attributed, receipted builders (ADR-0009's "the renderer invents
no value"; the pane is a pure function of its `PaneBuildContext`). Inflection changes the
**morphology of addressing** — richer, sort-checked ways to *name* a slice of the frozen
Frame — and adds **no** evaluation of authored expressions. Each sort has **one canonical
printed form** so `print(parse(text))` stays byte-stable (ADR-0004); `PaneArg` gains the
missing ground-literal forms (`arg-count`, `arg-ordinal`, `arg-expiry`) alongside today's
`arg-window` and `arg-ident`, and **not one** application form.
**Cross-instrument is morphology, not application.** A pair-basis read (`ES` vs `NQ`) is
spelled as a **CALC lexeme taking two `Instrument`-sorted ground args**, with the arithmetic
inside an audited builder that carries its definition as a receipt — *not* as
`spread(ES, NQ)` application syntax. The distinction is load-bearing: the former is an
address into an attributed builder; the latter would be the function symbol this doctrine
forbids.
**Scheme-relative ordinals.** `SessionOrdinal` denotes an ordinal into the instrument's
declared **SessionScheme** — a series-registry attribute (ADR-0036), the same registry slot
ADR-0038 uses one axis over for attribution — never a new sort. Equity RTH, a futures
RTH/overnight split, a perp's UTC-day convention, and an FX trading week are each a scheme
supplying the monotone boundary stream that `d-N` indexes, so 24/7 and multi-session markets
extend the *value* inventory of an existing sort without touching the closed roster.
Absent-not-hidden reaches the address space itself: "this instrument's scheme has no such
boundary" is a first-class rendering, never an invented one.
**Morphological identity discipline — one hypothesis, one hash.** The spelling→meaning map
is biunique at admission, because identity follows the printed bytes and two spellings of
one semantics are two sha256s that split one hypothesis's ledger evidence. Four invariants
guard it. *Canonical agglutination:* one printed morpheme realizes exactly one sort value —
no portmanteaux, no zero-exponence ambiguity. *One cross-pane position-class ordering:* the
order in which sorts print is fixed once, across every pane, and — because printed argument
order is part of the canonical bytes — it must be pinned **before Train 1 prints its first
canonical form**; this is the one piece of the doctrine that is hash-breaking to retrofit.
*Blocking:* no new lexeme or slot is admissible whose output duplicates an existing
inflected form. *Allomorphy only when value-conditioned,* published as a principal-parts
table so a reader can derive every surface form of a sort from its listed parts. These are
evidence integrity, not aesthetics: the ledger keys on the hash, so a non-canonical or
colliding spelling silently forks a template's evidence.
**Concord.** A View is a clause with a feature bundle. Band is marked **once** on the View
head and percolates to every pane — which is what makes Train 1's colonization of the
swing/position/multiday band space literal rather than aspirational. Every pane's Instrument
agrees with the head by default; the CALC lexeme's two explicit `Instrument` args are the
**marked** exception, so a covert cross-instrument read (a pane silently sourcing an
instrument the head did not license) refuses at resolve rather than rendering a mixed frame.
**Channel invariants.** Rendering is a coding channel, and two facts about it are doctrine.
*Safety-critical facts render exactly twice.* The never-naked floor, the bounded-risk cap,
the arm state, and `STAND_DOWN` are repetition-coded at exactly two positions — the kernel
(primacy) and the pane nearest the decision they govern (recency) — and a fail-closed guard
asserts the two occurrences byte-identical; every other fact renders exactly once. This is
the written answer to "why does the floor appear twice," and it survives every future
token-diet pass. *The honesty markers form a closed codebook.* `UNKNOWN`, `none`,
`CANONICAL`, `DEGRADED`, `STAND_DOWN`, and the refusal sentinels are a closed set; a new
marker is admitted only if it is few-token and **non-confusable** — sharing no prefix tokens
with any existing codeword — under every supported tokenizer, so a token-diet can never
collapse two honesty signals into an ambiguous surface form.
**Proven first on the tape, then it colonizes.** Train 1 (`kestrel-wa0j.24`) inflects
`tape` / `levels` / `chain` — `tape` gains bucket + `SessionOrdinal` + anchor with
gap-respecting aggregation in the builder (this closes `kestrel-wa0j.20` as *morphology*,
not a new pane); `levels` gains a band-keyed level-set slot; `chain` gains
`Instrument` + `Count` + `ExpiryOrdinal`. `failed-breaks` / `level-interaction` /
`prior-context` inherit band-awareness for free. One train colonizes the whole
swing/position/multiday band space from the *existing* catalog — the mechanism and its proof
ship in one PR sequence. The `ParamSlot` sorts are **derived by reconciling with what
`views.kestrel` already teaches**, not by coining a fresh vocabulary.
**The single measured-not-designed exemption to fail-closed.** Kernel additions that make
staleness *band-normalized* and expose a `CANONICAL`/`DEGRADED` data-health contract are the
one place where a measured signal, not a designed default, governs behavior. Fail-closed
semantics remains doctrine everywhere else; every such kernel addition carries an **explicit
safety-invariant justification** in its own change (why the measured signal cannot fail
open). This is not a licence to soften the parser or the builders — they stay exact.
**Legacy `configure_screen` is retired explicitly** — subsumed by named Views + `DELIVER`
(a Wake names the View it delivers; the wake decides *when*, the View decides *what*) + the
TemplateRecord ledger below.
### 2. Template-as-hypothesis: every founder View is a graded seed, and the null is that it HURTS
Every founder `.kestrel` template is a **hypothesis carrying a ledger entry**, never a
blessed default. ADR-0009 forbids *blessing a winner* by taste; it does not forbid *seeding
a candidate*. Founder Views therefore enter the ADR-0029 tournament against the required
baseline pair exactly as any agent-authored lens does.
**The ledger is `PerceptProfile` reduced to nothing more than a `TemplateRecord` set** —
`{ templateHash, cell, receipts, lineage, tier }`. The **cell key is instrumentClass × band
× archetype-family × phase × role** (a 5-tuple): `role` (strategist | watcher) is a
first-class axis because **a pane's sign is role-dependent**.
**`instrumentClass` is pinned NOW, while the ledger is empty.** It is a closed sort
(`equity-option | future | perp | fx-pair | spot-equity`, opened only by the
sort-introduction ceremony of §3), and every record carries `equity-option` until a
non-equity cohort exists. The axis is not deferrable: a cell key's axes are the **schema of
evidence**, and the phantom-index/no-coercion doctrine below makes an axis added after the
first TemplateRecord an evidence-splitting migration — either crypto evidence is pooled into
equity-shaped cells (ill-typed) or every existing record is re-keyed (splitting one
hypothesis's evidence, the crime the whole phantom-index rule exists to prevent). Adding the
axis to an empty ledger is one field; adding it later is the ledger-level analogue of
retrofitting slot order into canonical bytes. The capacity atlas inherits domain as a
first-class dimension for free.
`phase` (OPEN / WAKE / SHOCK / CLOSE) is orthogonal to band; a phase template is a named
View delivered by a Wake, and SHOCK switching is a *measured* trigger-algebra predicate with
a dwell/hysteresis convention, not a designed toggle. **Template identity is the sha256 of
the canonical printed bytes** — byte-stable print (ADR-0004) makes the hash the SKU and the
grading key, so no version machinery is needed.
**The dual hash.** Identity and evidence are keyed by two different hashes, and one rule
binds them. `templateHash` is the sha256 of the canonical printed bytes and carries
**identity** — it is the SKU. `elabHash` is the sha256 of the *elaborated* form: every
defaulted slot explicitly saturated and printed canonically (elaboration never leaves the
language — the saturated form is itself a byte-stable View), and it carries **evidence**. A
catalog default change can therefore move a template's meaning while its `templateHash` SKU
holds constant, but it will change the `elabHash`, so old grades can never silently re-attach
to a template whose denotation has drifted underneath them. Two hashes and one rule —
identity follows `templateHash`, evidence follows `elabHash` — are the *entire* versioning
story; this completes the hash-SKU doctrine rather than compromising it.
**The null hypothesis is that a pane or template HURTS until a both-poles matched set says
otherwise**, and promotion is bound by two *orthogonal* admission rules — both binding, never
conflated:
- **(a) Matched-set, both-poles grading.** A pane must be graded on **both poles** of a
matched set (fakeout *and* real breakout; gap-fill *and* gap-and-go), on **economics**
(`frozenPlanEv`), because structure is saturated. The trap is that a pane which looks
disciplined can be **passivity**: it cuts the loss on the restraint pole while forfeiting
the gain on the action pole, and grading only on the pole it obviously helps reports a
false win. The FOMC-options theta cell is the natural first both-poles cell — theta makes
standing down *natively costly*, so it catches a passivity-inducing pane by construction —
and it is the **equity-option instance of a general rule, not the rule itself**. Every
`instrumentClass` names its **carry cell**: the matched-set cell whose carry clock (theta
for equity options, perp funding, futures roll yield, FX swap points) makes standing down
natively costly, and that carry cell is the canonical *first* both-poles cell for the
class. A carry clock exists in every class the program will ever admit, so the passivity
assay is constructible cross-domain the day a class's tape exists.
- **(b) Pareto non-inferiority on every grade axis.** Promotion requires non-inferiority on
**every** axis; **never a scalar composite** (Goodhart bait). (b) does not imply (a): a
pane can be Pareto-non-inferior on every axis and still be a passivity trap, because the
axes were measured on the wrong corpus.
**The distortion measure and evidence typing.** The program's distortion measure is the
drop in `frozenPlanEv` on both-poles matched sets, per (cell, role); a pane earns tokens
exactly where its marginal EV-per-token exceeds the cell's measured rate. Grades are stored
as **pole-vectors per (cell, role), never sums** — the passivity trap is a *sign structure*,
and the record shape must be unable to hide it (a positive restraint-pole entry and a
negative action-pole entry must never be allowed to net to an innocent scalar). The cell key
is a **phantom index** on evidence: there is no coercion between cells, ever; pooling grades
across roles is ill-typed; reuse of a template in a new cell means an explicit,
lineage-recorded re-seed against a fresh null. This makes role-dependent sign a schema-level
fact, and it is why the passivity trap is a **theorem, not an anecdote**: a restraint pane
redundant with the reader's own authored exit carries zero conditional mutual information
with the decision, so its EV contribution on the matched set is bounded at or below zero by
construction.
**PredictionRecord — the pre-committed claim.** Beside `TemplateRecord`, the ledger carries
a second record kind: `{ predictionHash, templateHash?, cell, claim, falsifier, committedAt,
adjudication }`, with a closed adjudication state machine — COMMITTED → RUNNABLE | UNRUNNABLE,
RUNNABLE → GRADED → CONFIRMED | REFUTED. The `falsifier` must be a **predicate the merged
harness can compute**; an experiment whose falsifier is prose is refused admission,
fail-closed — the same doctrine as the parser, applied to claims. Tier promotion requires
citing a prediction whose hash **predates the grading sample's draw**, and the confirm-stage
draw seed is committed before any screen result is read — the two-stage firewall against
forking-paths. `UNRUNNABLE` is an honorable terminal state, not a failure: the in-repo
precedent is the theta pre-registration adjudicated un-runnable *before a dollar of grading
spend*. Refutations are recorded at identical schema fidelity to confirmations — there is no
file drawer.
Promotion to a frozen default stays **owner-gated on realized-blotter evidence** (ADR-0029
§q4) under both rules. The pooled "every pane lost" null is recorded here as **unproven,
not settled** — TRAIN-only, small-N, with an accumulating-transcript confound; these
admission rules are written so that *either* outcome (the null holds, or a pane earns its
cell) is credible when the re-measure lands. The theory ships its own refutation:
`kestrel-wa0j.26` seeds an **aliased-control arm** (a position-band cohort graded on the 1m
scalp View, predicted to lose on decision-quality-per-token).
Everything bazaar-shaped beyond the ledger — challenger lanes, royalties, bandit grading
allocators, a marketplace — is **deferred until the first owner-frozen default exists**.
Build the exchange after the first fixation, not before.
### 3. Golden-corpus doctrine: the judgment ladder
The corpus/catalog split is one rung of a **ladder of typing judgments**, each strictly
containing the next, each with its own named test surface, and no rung ever decided by
machinery belonging to a lower rung's surface:
- `⊢ V wf` — **WELL-FORMED.** `V` parses and `print(parse(V))` is byte-stable. Decided by
parser and printer alone, with zero catalog knowledge. Surface: `tests/golden/`.
- `C ⊢ V mat` — **MATERIALIZABLE** under catalog `C`. Every pane name resolves to a
signature; every argument elaborates at its slot's sort and arity. Surface: the
materialization fence (the `wa0j.19` prompt-taught forms).
- `C; F ⊢ V ⇓ P` — **RENDERABLE.** Against a frozen Frame `F`, `V` denotes a percept `P` —
a *total* judgment: absence and refusal are values, never stuckness. Surface: the
determinism property test (same `C`, same `F` ⇒ byte-identical `P`).
- `L ⊢ V graded @ cell` — **GRADED.** The template's hash carries ledger evidence in a
cell. Surface: the TemplateRecord ledger itself.
The **authority arrow** is doctrine: the parser never consults the catalog, the catalog
never consults the Frame, materialization never consults the ledger. "The corpus leads, the
catalog follows" is therefore not folklore but an inequality between rungs — `wf` strictly
outpaces `mat`, permanently, by design — and the inflection backlog is *literally* the set
`{ V : ⊢ V wf ∧ C ⊬ V mat }`, a set CI can enumerate and report as a burn-down, train by
train. Every `KernelHonestyError` names the rung it failed on, so "refused" is never one
undifferentiated condition.
**The four-state paradigm cell.** Every (pane × sort-value-bundle) cell is in exactly one of
four states: **ATTESTED** (materializes byte-identically), **LATENT** (not yet, but a named
train will land it), **DEFECTIVE** (never, for a written reason, with a sanctioned
periphrasis), or **UNATTESTED** (outside the closed roster). ATTESTED is **monotone forever**
— the conformance ratchet: once a cell is taught, its byte-identical materialization is never
regressed, and the accumulating ratchet suite is the CI expression of that law. Refusals cite
cell state: a LATENT refusal names its train, a DEFECTIVE refusal names its written reason and
its sanctioned periphrasis. A recurring graded periphrasis — a workaround the corpus keeps
reaching for — is the *measured* signal that a DEFECTIVE or UNATTESTED cell wants promotion
toward LATENT; demand is observed, not asserted.
**Paradigm state may be conditioned on registry attributes.** A cell that is DEFECTIVE for
one `instrumentClass` or SessionScheme and ATTESTED for another is **one paradigm, not two**,
and the refusal names the conditioning attribute. The `prior-context` pane against a scheme
with no close boundary is DEFECTIVE with reason *no close under this SessionScheme* and
sanctioned periphrasis *anchor to the declared rolling extreme* — it renders that declared
anchor, never an invented midnight "close." This is absent-not-hidden at the level of the
address: "this instrument's scheme has no such address" is a first-class rendering, exactly
parallel to value-conditioned allomorphy of forms.
**The sort-introduction ceremony.** A new ground sort is not coined; it is admitted by one
commit carrying five artifacts together: a teaching attestation in the corpus, a canonical
print + round-trip pair, a denotation (what address into the Frame it names), a consuming
signature (the slot that reads it), and a reject fixture (a near-miss that must refuse). The
roster is therefore **closed at any instant and opened only by ceremony** — which is what
lets the paradigm cell be a total function over a known grid rather than an open-world guess.
`tests/golden/accept/views.kestrel` is the **grammar spec of the destination morphology**.
It **must never be "fixed" to match today's catalog.** Stripping the arguments the catalog
cannot yet materialize (`week quarter rv20`, `straddle expected-move`, `skyline vwap
detector-strip`, `registry`, `fair realness`) would destroy the written specification of
where inflection is going. The golden corpus is a **grammar** contract (parse + byte-stable
print) and is *deliberately out of scope* of the `wa0j.19` CI fence, which covers the
**prompt-taught** examples that must materialize. The corpus leads; the catalog follows it,
train by train. Anyone tempted to reconcile the two contracts by editing the corpus is
breaking the specification to satisfy the implementation — the arrow points the other way.
## Consequences
- **One inflection substrate replaces sixteen ad-hoc arg parsers.** Adding a parameterized
pane becomes one catalog entry with a signature; the repair-guiding error surface is
uniform; the sort checker is the single place mismatches fail closed.
- **`print(parse(text))` is preserved by construction** — every new ground-literal sort has
one canonical printed form, and no application node is ever added, so the round-trip and
the golden corpus stay byte-stable.
- **Perception decisions become falsifiable on economics.** Because the TemplateRecord
ledger keys on cell and grades on `frozenPlanEv` over matched sets, "which pane belongs in
which cell for which role" is answered by the merged harness, not by taste — and the
passivity trap is visible in the aggregate rather than only in a transcript.
- **The grammar-vs-catalog split is now doctrine, not folklore.** The next agent who opens
`views.kestrel` and sees refused args knows the corpus is the spec, not the bug.
- **Date-blindness is structural, not merely intended.** `PaneBuildContext` carries no
clock field, so any builder that typechecks is date-blind by construction; the enforcement
lint (no ambient clock imports in builders) is the only thing that upgrades this from
morally true to checked, and it is beaded below.
- **Fail-closed, determinism, date-blindness, absent-not-hidden, kernel-leads, and
invents-no-value are untouched.** Inflection adds addressing morphology, not evaluation;
the builders stay pure functions of the frozen Frame; the one measured-not-designed
exemption (band-normalized staleness / CANONICAL-DEGRADED) carries its own safety-invariant
justification. Illustrative fixtures stay on generic tickers (SPX/SPY/QQQ).
## Open questions
1. **The closed sort roster — resolved by ceremony, not enumeration.** The question is no
longer "is `{ Instrument, LevelName, Window, SessionOrdinal, ExpiryOrdinal, Count, Band }`
complete?" (unanswerable ahead of the corpus) but "what admits a sort?" (answered): the
roster is closed at any instant and grows only through the sort-introduction ceremony of
§3 — five artifacts in one commit, reconciled against `views.kestrel`, never invented
ahead of a teaching example. A later train (vol / event / pairs) that needs a ground sort
adds it by ceremony; until then the paradigm cell treats any value outside the roster as
UNATTESTED and refuses it by name. Completeness is a property the ledger reports as a
burn-down, not a guess the ADR must make.
2. **The archetype-family taxonomy.** The cell key names `archetype-family` but the sparse
grid (scalp-open, day-open, day-close, swing-open, position-open, plus vol/event/pairs as
Train 3 lands) is a working set, not a closed enumeration; where its boundaries sit is a
measurement question for the first cohorts. The `instrumentClass` axis now bounds the
question: archetype-family ranges *within* a class, and whether a family name (say
ORB-fakeout) denotes the same archetype across classes is itself a transfer measurement,
not a taxonomy assumption.
3. **SHOCK dwell/hysteresis.** The exact dwell and hysteresis convention for the measured
SHOCK-switch predicate is left to Train 2/backlog to pin against real tape.
4. **When the null is re-measured.** The 2×2 re-measure (a re-drawn sample beating the noise
floor — $0.39 EARN / $12.74 ORB — plus SE) is what upgrades the pooled null from *unproven*
to *settled or refuted*; this ADR commits the admission rules, not the verdict.
## Amendment A1 — the role axis roster (owner-ratified 2026-07-16)
Ratified by the owner (2026-07-16, `kestrel-wa0j.52`) while the ledger is still empty — the same
pin-it-before-the-first-record discipline §2 applies to `instrumentClass`, applied now to the role
axis's value roster. First consumer: the founder seat library (`docs/views/founder-seat-views.md`),
which already screens three seats. Append-only: the accepted text above is unchanged; A1 pins the
roster and records the riders the owner articulated on ratification.
- **A1.1 — the role axis is the CLOSED roster `{ pm, strategist, watcher }`.** §2 wrote `role`
as `(strategist | watcher)`; it is amended to the full seat set. The seats are **fixed by the
pod doctrine** (ADR-0002/ADR-0032; the `Seat` glossary entry), not coined here — three roles
distinguished by the deliberation budget they can afford. The axis is not deferrable for the
same reason `instrumentClass` was not: a cell-key axis's *values* are the schema of evidence,
and pm-cell grading has its own natural carry story **by construction** — a PM's passivity trap
is mis-allocation, so both poles exist without contrivance: *the scan it should have authored a
leaf on* (restraint pole forfeited) vs *the head-fake scan it should have ignored* (action pole
chased). The FOMC-theta both-poles logic of §2 therefore instantiates in a pm cell as readily as
in a watcher cell.
- **A1.2 — new roster VALUES arrive by ceremony, and admitting a value never re-keys existing
evidence.** The §3 sort-introduction ceremony, applied to the ledger's role axis: **allocator**
and **scanner** enter as **pm sub-values** with `kestrel-wa0j.51`; a **historian** value enters
with its loop; a **risk** value enters *only if* a reading/auditing seat is ever earned. Today
there is no such seat — **Risk is the L0 LAYER** and **"risk manager" is a PERSONA** (a Brief
channel), **never a seat**, and so opens no role-axis value. The asymmetry §2 draws between axes
and their values is the whole point: adding a VALUE later opens **new cells** and leaves old
records on their old keys (no coercion, no evidence split), whereas adding an AXIS after the
first record is the evidence-splitting migration §2 forbids — which is exactly why
`instrumentClass` had to be pinned at birth while values may safely arrive by ceremony.
- **A1.3 — the trigger tier is an architecture TIER, not a role-axis value.** The trigger tier
(ADR-0048, pending) is a tier of the architecture, not a seat: it has **no judgment cells to
grade**, so it never enters the role roster. Keeping it out of the axis is the same
don't-pool-the-ungradable discipline the phantom-index rule enforces on cells.
- **A1.4 — seat-relative economics (rider, made explicit).** §2's "a pane earns tokens exactly
where its marginal EV-per-token exceeds the cell's measured rate" is evaluated **PER SEAT**.
Deliberation budgets differ across the roster by **orders of magnitude** (a pane too expensive
for a frontier strategist can be trivially affordable for a small fast RL'd watcher), so the
admission threshold in a watcher cell is **not** the strategist's. Pooling admission thresholds
across seats is **as ill-typed as pooling grades across roles** — the role axis already indexes
the cell, so this rider only names a consequence the phantom-index doctrine already carries. This
is the seat-relative alpha-per-token doctrine; its first hard numbers are on the wire (PM-1c: a
50–60× cost gap independent of the artifact question, `kestrel-wa0j.52`).