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.
130 lines (111 loc) • 9.44 kB
Markdown
# Reconciliation NOTE — agent-architecture ADRs 0029 / 0031 / 0032 (kestrel-2sy)
**Status: owner-decision input, 2026-07-15. Not an ADR — enumerates the contradictions so the
owner can decide fast. Does NOT pick a resolution.** Prepared during the cross-repo canon
reconciliation sweep. Read-only pass over `docs/adr/{0012,0029,0031,0032,0035}`.
---
## ✅ RESOLVED — owner, 2026-07-15 (grill). *The enumeration below is kept for history.*
The three unblocking decisions were made and are now applied to the ADRs (append-only amendments;
tracker **kestrel-2sy**):
1. **WIRE (#1/#2) — the pure-Kestrel turn is CANONICAL.** The whole reply IS Kestrel; `SHOW VIEW` /
`STAND-DOWN` directives per **ADR-0031**. JSON `{requestView}` is demoted to **forgiving-ingest
compatibility only** (normalized to the same typed request; the logged/canonical/corpus form is
always the Kestrel projection). Rationale: JSON adds heavy token + cognitive overhead vs pure text
(percept thesis on the authoring side); one grammar = one corpus = one CFG constraint; the
free-is-licensed corpus (platform L2) must not bifurcate. **Amends ADR-0029 Option C** (loop,
caps, budgets, fail-closed `standDown`, emergence log all survive verbatim).
2. **a57.14 envelope projection (#2) — KEPT as the A/B control arm** (ADR-0031 §8), measured via the
platform's experimentation overlay on parse-failure rate / stand-down
honesty / grade; retired on evidence. Season SEAM deps on a57.14 unaffected.
3. **ADR-0031 RATIFIED (#8) — Proposed → Accepted (2026-07-15).** Its two open grammar questions
become blocking beads **kestrel-qim.1** (STAND-DOWN keyword) and **kestrel-qim.2** (SHOW VIEW
marker). Fixes the Accepted-0032-§7/§8.4-depends-on-Proposed-0031 authority inversion.
Consequential (per the NOTE's own "everything else follows"):
- **Naming (#3/#5) — do NOT mass-rename.** `STAND-DOWN` (grammar directive) / `standDown` (typed
Action) / `STAND_DOWN` (fail-closed sentinel) are three *layers*; explicit mapping table added to
**ADR-0031**'s ratification note. `watcher-GATE` vs `watcher-MANAGER` per ADR-0032's amendment;
**bare "watcher" deprecated in new docs.**
- **Scope-sequencing (#6) — NOT decided today.** Filed as **kestrel-8di.2** (blocker): ADR-0032 §5's
in-loop SHOW VIEW for the watcher-manager needs explicit scoping before implementation reaches it
(ADR-0029 §Scope / ADR-0031 Open q5 are OPEN-only for v1).
- **"The View" three referents (#7) — NOT decided today, owner decision needed.** Filed as
**kestrel-8di.3**.
- **`cancelOrder`-by-ref (#4)** remains ADR-0031 Open q3 (a `CANCEL <ref>` directive recommended);
tracked in epic **kestrel-qim**.
**Amended ADRs:** ADR-0031 (status → Accepted + ratification note + naming table), ADR-0029 (Option C
amendment), ADR-0032 (§7/§8.4 dependency-resolved note + watcher-deprecation pointer).
---
## The three designs (thesis + status)
- **ADR-0029 — agent-requested emergent View authoring loop.** *Accepted (owner 2026-07-13); v1
slice under impl (epic kestrel-d72).* At OPEN the agent may reply with a **JSON top-level
`requestView`** to re-materialize a different lens on the same frozen cutoff and be re-asked — a
bounded loop (`viewRequestCap` + `authoringTokenBudget`, fail-closed `standDown`) whose logged
requests are the emergence log a default View is later frozen from.
- **ADR-0031 — envelope-free pure-Kestrel AgentTurn.** *Proposed (2026-07-13); no code until two
grammar questions confirmed.* Drop the JSON envelope: the whole reply IS Kestrel; the driver
routes on statement-kind plus two new directives **`STAND-DOWN`** and **`SHOW VIEW`**, with
forgiving extraction + `parse()` + repair-retry; CFG grammar-constrained decoding is optional.
- **ADR-0032 — two-tier (→ five-layer) Strategist + Watcher.** *Accepted (2026-07-14), 7 Qs
owner-approved, NO code landed (epic kestrel-8di).* The trading agent is a cascade —
Scan → watcher-GATE → Strategist → watcher-MANAGER → Human — over the deterministic floor; the
safety keystone is the runtime admission Gate enforcing the Mandate (admit-never-trust); a
five-level `*_alpha` attribution ladder.
**Authority inversion to resolve first:** 0029 and 0032 are **Accepted**, but 0032 structurally
depends on **Proposed** 0031 (see #8). Decide 0031's status before 0032 implementation leans on it.
## Contradictions the owner must resolve (term by term)
1. **View-request wire surface (0029 vs 0031) — the sharpest.** 0029 §1 (Option C, recommended)
ships the view request as a **JSON object** `{requestView:{view,reason}}` and *explicitly
rejects* authoring a bare `VIEW`. 0031 §2b re-supplies the same disambiguator as a Kestrel
keyword **`SHOW VIEW`**. Identical outcome, two mutually exclusive byte-level wires.
**As accepted today the contract is 0029's JSON.** Decision: keep `requestView` JSON, or accept
`SHOW VIEW`.
2. **Envelope vs envelope-free (the a57.14 tension in the bead).** 0029 assumes the JSON envelope
and its `parseTurn`/`parseAuthoringReply` parsers throughout; 0031 removes the envelope entirely
and declares the just-landed structured-output-envelope work (a57.14) **superseded, kept only as
a hypothetical fallback**. This is *proposal-vs-landed-code*. Decision: retire the envelope
projection, keep it as an A/B control (0031 §8), or reject 0031.
3. **Turn/outcome model + naming collisions.** Same concept, three structural identities:
`standDown` (0012/0029 typed **Action**) vs `STAND-DOWN` (0031 grammar **directive**) vs
`STAND_DOWN` (0012 fail-closed **sentinel**); and `requestView` means a JSON key in 0029 but only
an internal variant name in 0031. Any resolution must fix the vocabulary, not just the wire.
4. **Action union + "every Action is one Bus event" (0012 vs 0031).** 0029 preserves 0012's Action
union (`supersede|scheduleWake|placeOrder|cancelOrder|standDown`) and keeps `requestView` out of
it to protect the invariant. 0031 dissolves the union into document-reads: `placeOrder` folds
into a fire-now `PLAN`, and **`cancelOrder`-by-ref has no home — genuine open item (0031 q3)**.
5. **Layer/tier count + "watcher" collision (internal to 0032).** Count churned 3→5 layers (§1→§10)
and the attribution ladder 3→4→5. "watcher" now names two roles — the amendment declares the
old "watcher" = **watcher-MANAGER**, the new role = **watcher-GATE**; `watcher_alpha` renamed
`manager_alpha`. Bare "watcher" (incl. cross-repo memory) is now under-specified.
6. **Scope: OPEN-only vs in-loop (0029/0031 vs 0032).** 0029 §Scope and 0031 q5 both defer
mid-session view-requests out of v1 (OPEN-only). 0032 §5 gives the **in-loop watcher-manager**
`SHOW VIEW` at wake cadence — presuming exactly the mid-session affordance the other two
postponed. Sequencing conflict: 0032's watcher can't have in-loop `SHOW VIEW` until that
extension is scoped.
7. **"The View" may silently name three objects (0029 vs 0032).** (i) 0029's emergence-discovered,
then-frozen default View; (ii) 0032's Strategist-authored token-lean standing View the watcher
watches; (iii) the watcher's SFT/RL curriculum. 0032 claims they are one object — owner should
confirm, else "the View" is three things.
8. **Accepted-depends-on-Proposed (0032 → 0031).** 0032 §7/§8.4 rest the family×size×regime map and
the watcher loop-speed on CFG + "envelope-free (0031) is what makes the single grammar
constrainable" — but 0031 marks CFG "explicitly not a dependency" and is only Proposed. If 0031
changes/rejects, 0032 §7 loses its stated enforcement layer.
## Complementary — do NOT over-reconcile
- 0029 and 0032 are building-block ↔ consumer: 0032 explicitly *folds in* 0029 (Brief/Mandate
split, emergence log, `SHOW VIEW` for the watcher). Not rivals.
- 0031 and 0032 sit on different axes (turn-wire vs tier-topology); 0032 *wants* what 0031 enables.
- 0031 is a self-declared reconciler of 0029 §1 (preserves 0029's outcome model, loop, budgets,
emergence log) — the only open item between them is accept/reject `SHOW VIEW`.
- **The determinism-line invariant is shared and consistent across all three** (0029 §5, 0031 §7,
0032 §6): only the parsed terminal `AgentTurn` crosses into the graded Bus; requestView/SHOW
VIEW/gate-verdict sit above the line, emit zero Bus events; `SimRunId = sha256(gradedBus)`
unchanged. This is the anchor any reconciliation can stand on.
- Brief/Mandate two-channel split + hard admission Gate (the platform's language-as-interface canon / 0032 §3, extends 0012 §4)
is cited consistently. `*_alpha` ladder + "measured-not-designed / discover-then-freeze" is shared
lineage, not competing claims.
## Bottom line for the owner
Three decisions unblock kestrel-2sy: **(1)** JSON `requestView` vs `SHOW VIEW` (#1); **(2)** the
fate of the landed envelope projection under envelope-free (#2); **(3)** ratify or downgrade 0031's
status so Accepted-0032 stops depending on a Proposed ADR (#8). Everything else (naming #3/#5,
scope-sequencing #6, one-View-or-three #7, cancel-by-ref #4) follows once those three are set.
Cross-ref: ADR-0012's single-agent seam now carries an amendment marker pointing at 0032/0035 (also
landed 2026-07-15). Related epic kestrel-8di open (children 8di.1 attribution ladder P1; tracer
kestrel-aus done).