# OSS-ADR-0049 — The `because` clause pre-registers a Plan or Wake against a thesis by content hash

Status: accepted (2026-07-16, owner-ratified canon reconcile — reverse-direction
boundary-split of PLAT-ADR-0026; kestrel-wlw9). Implemented on `main` as kestrel-rtf.

Related: PLAT-ADR-0026 (platform seam — the Thesis artifact and its pre-registration
ledger live platform-side; the cross-repo consumer is `kestrel-markets-rku.7`).
OSS-ADR-0001 (four statement kinds), OSS-ADR-0004 (the typed object model IS the
language; byte-stable round-trip), OSS-ADR-0033 (byte-stable trivia that travels WITH
the action).

## Context

PLAT-ADR-0026 introduced a `because` citation clause on Plan and Wake statements so an
agent can **pre-register** a document against a platform-side Thesis: the clause carries
the Thesis's content hash, and because a Kestrel document's armed identity is
`sha256(print(module))`, the citation binds into the armed-document hash — pre-registration
becomes tamper-evident the moment the plan is armed.

But `because` is a change to the **Kestrel language grammar** — a new optional field on two
of the four statement nodes, a new keyword, new fail-closed refusals, and a temporal
predicate envelope. PLAT-ADR-0026 recorded it in a **platform** file only. The decision has
no OSS home, even though the AST (`src/lang/ast.ts` `Citation`), parser, printer, and golden
contract (`tests/golden/{accept,rejects}/because-*`) all live in this repo and shipped under
kestrel-rtf. This ADR is that OSS home: it records the grammar decision on the OSS side and
companions PLAT-ADR-0026, which retains the platform-side Thesis/ledger concerns.

## Decision

1. **`because` is an optional AST field, NOT a fifth statement kind.** The statement
   algebra stays exactly {View, Wake, Plan, Grade} (OSS-ADR-0001). `because?: Citation` is
   added to `PlanStatement` and `WakeStatement` only. A `Citation` is
   `{ kind: "citation"; algo: "sha256"; hash: <64 lowercase hex> }` — never a `StatementKind`,
   never a `PlanClause`.

2. **Content-hash ONLY — `sha256:<64 hex>`, no inline body.** The token reuses the repo's
   ubiquitous sha256 digest shape (the same 64-lowercase-hex form as `bus_sha256` /
   `plans_sha256` / `ConfigId`) — no second citation scheme. The Thesis *prose* lives
   platform-side; the clause carries only the digest that references it.

3. **The citation binds into the armed-document hash automatically.** It prints byte-stably
   like any other canonical line, so `sha256(print(module))` covers it with no special
   casing — pre-registration is tamper-evident once armed. This is why the clause is
   content-hash-only: the hash is the whole point, and an inline body would be
   un-hashable-into-identity noise.

4. **The thesis temporal envelope `{within, until, at}` reuses the Wake predicate surface —
   no second predicate language.** `within` already existed; `until <HH:MM>` and `at <HH:MM>`
   are added as **postfix combinator siblings** of `within` over the SAME `Trigger` algebra,
   each carrying a `TimeOfDay`. An expectation like `expects` / `invalidated_when` is
   therefore an ordinary Trigger wrapped in a temporal window, not a bespoke thesis grammar.
   Runtime *firing* of `until` / `at` is deferred: a session that cannot evaluate them reads
   UNKNOWN and de-arms with a logged reason (fail-closed), pending a runtime ADR.

5. **Three fail-closed refusals, enforced symmetrically on every surface** (parser rejects
   the text with a positional `KestrelParseError`; the builder refuses to construct it; the
   printer throws on it — the OSS-ADR-0004 round-trip discipline, so a hand-built citation
   throws exactly where the parser does):
   - **(a) bad/absent digest** — anything not of the fixed shape `sha256:<64 lowercase hex>`
     is refused (`because sha256:deadbeef` → refused).
   - **(b) inline body** — any token trailing the digest (a quoted thesis body, more prose)
     is refused; the body lives platform-side.
   - **(c) `because` on a View or Grade** — a citation may pre-register only a Plan or Wake
     (never a fifth statement kind, OSS-ADR-0001); pre-registration binds an *executable
     expectation* to a thesis, which a View and a Grade do not author.

## Consequences

- **Pre-registration is tamper-evident by construction**, riding the existing armed-document
  hash — no new integrity mechanism, no runtime semantics for the citation itself (like a
  comment under OSS-ADR-0033, it is authored reasoning that travels with the action; unlike a
  comment, its digest is load-bearing for identity).
- **The golden corpus is the grammar contract** (OSS-ADR-0004): `plan-because.kestrel` and
  `wake-because-envelope.kestrel` (accept) and `because-{bad-hash,inline-body,on-grade,on-view}.kestrel`
  (rejects) lock the round-trip and the three refusals. `print(parse(text))` stays byte-stable.
- **This is the single cross-repo grammar edge.** The platform (`kestrel-markets-rku.7`) consumes
  the clause to look the Thesis up by hash and check `expects` / `invalidated_when` against
  the realized tape; the split keeps the *grammar* decision in OSS and the *Thesis artifact +
  ledger* decision in PLAT-ADR-0026, each in its own repo's ADR line.
- **The statement algebra is unchanged.** Every existing builder, deep-equality test, and the
  four-kind invariant hold; the field is simply absent on documents that do not pre-register.

## Concrete syntax

See `docs/spec/SURFACES.md` (Citation section + the fail-closed doctrine checks) for the
printed form, fixed clause placement (Plan: after `WHEN`; Wake: after `WHEN`, before
`DELIVER`), and the `until` / `at` temporal postfixes.
