SummaryWhat Shipped and What the Session Proved
P1.3.1 delivered the challenge canary completion described in the prior session's handoff: envelope contract compliance (governance_source), four peer canon URIs (governance_uris), and debug.knowledge_base_url echo. Two PRs on klappy/oddkit — #116 (squash-merged at 71ee6ed), #117 (main→prod merge at 1b4fce8). Prod at 0.19.0 (https://oddkit.klappy.dev/health confirmed). Smoke 126/126 × 5 consecutive on prod after 40s CF warmup; main-preview required two isolate-warmup flakes before settling (the pattern the P1.2 handoff named).
Three patterns deserve naming — each one a test of whether the P1.2 ledger's hard-won lessons actually propagate.
Code-first discipline caught two handoff errors on first pass. The P1.3 handoff described four discovery helpers all named discover* (recency-as-authority: pattern-matching encode's discoverEncodingTypes onto challenge). Direct grep of workers/src/orchestrate.ts@290dde5 showed only one was discover*; the other three are fetch*. The PRD called this out in §3.1 and committed to preserving the names (minimizing diff, zero behavioral impact). Second catch: the handoff framed the bundled tier as contract aspiration but didn't explicitly note that workers/baseline/ does not exist in the repo at all. ls workers/baseline/ returned "NO BASELINE DIR". The two-tier cascade (knowledge_base | minimal) isn't a classification-specific call for challenge — it's the current reality for every knowledge-base-driven tool. The PRD named this in §3.2 and the risk register called out that the validator would need to see this explicitly, which is exactly what it did when corroborating against core-governance-baseline.
Operator pivot on D4 was load-bearing. The PRD's first draft proposed governance_uri: "klappy://odd/challenge/stakes-calibration" — single string, parity with encode's shape. The operator flagged this: challenge reads four peer governance files (base-prerequisites, challenge-types/, normative-vocabulary, stakes-calibration) and stakes-calibration doesn't govern or represent the other three. A single anchor pointing at it would mislead callers about where the vocabulary and prerequisite contracts live. Alternative: governance_uris: [array of four], alphabetical. Shape divergence from encode is accepted because the underlying governance reality diverges. The PRD §7 envelope-after diagram was updated, D6 CHANGELOG language specifically named the divergence for consumers reading both tools, and the smoke test asserts governance_uri (singular) is NOT emitted on challenge. This decision was the most consequential of the session; every other decision fell in line.
Validator external-corroboration pattern worked end-to-end. Per canon/principles/agent-self-report-under-stress, terminal self-reports are not authoritative. The validator task explicitly required five external corroborations: main-branch bytes grep (pre-refactor state), live curl ×3 shapes (default, override, voice-dump SUPPRESSED), oddkit_get citation on core-governance-baseline, all 9 modes curl, and 3× independent smoke runs. Sonnet 4.6 pulled each piece independently — including cloning the repo itself to run the smoke test from its own session, not trusting the orchestrator's preview-smoke output. Disposition VERIFIED 5/5 with zero advisories. Zero advisories is unusual and worth marking — the PRD-first discipline (writing the plan as a file before touching code) appears to front-load the kind of review findings that would otherwise surface at validation time.
What Shipped
| PR | Repo | Merged SHA | Purpose |
|---|---|---|---|
| #116 | klappy/oddkit | 71ee6ed | feat(challenge): governance_source envelope + peer governance_uris (0.19.0). Squash-merged. |
| #117 | klappy/oddkit | 1b4fce8 | main → prod promotion for 0.19.0. Merge commit. |
Production state: https://oddkit.klappy.dev/health returns {"version":"0.19.0"}. Smoke 126/126 × 5 consecutive on prod.
Validator record: agent_011CaE62pg6jJ7yYpRj1o9Do / sesn_011CaE63LZhPUX1UAZPbiV7n. Disposition: VERIFIED, 5/5, zero blockers, zero non-blocking advisories.
Feature delta (files changed): 6 files, +222 / -19 lines in the feat commit.
workers/src/orchestrate.ts— four helpers retrofitted to{<domainNoun>, source}tuples (discoverChallengeTypes→{types, source},fetchBasePrerequisites→{prerequisites, source},fetchNormativeVocabulary→{vocabulary, source},fetchStakesCalibration→{calibration, source});runChallengeActionaggregates strictly and adds envelope fields on both SUPPRESSED and CHALLENGED paths;cleanup_storageextended to reset the three newcachedXSourcefieldsworkers/src/index.ts—oddkit_challengetool description updated to name the four governance surfaces and the two-tier envelope signalworkers/test/canon-tool-envelope.smoke.mjs— 47 new assertions: envelope shape on both paths,governance_urisarray of exactly 4 with expected alphabetical ordering,governance_urisingular asserted absent,knowledge_base_urloverride behavior, 9-mode parse integrity loop (voice-dumpasserts SUPPRESSED; others assert CHALLENGED)CHANGELOG.md—[0.19.0]entry with Added / Changed / Fixed / Known-limitations; divergence-from-encode called out explicitly in the governance_uris Added bulletpackage.json+workers/package.json— synced to0.19.0(pre-commit hook enforced)
What the Validator Actually Checked
The five corroborations are worth enumerating because the pattern should be the default for subsequent canaries in the sweep.
- Main-branch bytes grep. Validator cloned
klappy/oddkit, checked out main, greppedworkers/src/orchestrate.tsforgovernance_sourcereferences insiderunChallengeAction. Confirmed zero hits — pre-refactor state matches the PR's "before" claim. The one match at line 2262 of main is insiderunEncodeAction(P1.2), which the validator correctly disambiguated. - Live preview curl, three shapes. Default KB planning mode →
governance_source: "knowledge_base",governance_urislength 4,governance_uriundefined. Override totorvalds/linux→debug.knowledge_base_urlechoed,governance_sourcewithin enum. Voice-dump mode →status: "SUPPRESSED"with governance fields still present on the early-return envelope (the PRD §10 risk register flagged this branch specifically; validator confirmed it landed). - Canon citation on
core-governance-baseline. Validator usedoddkit_getto fetch§Runtime Invariantsand confirmed the three-tier enum is documented, plus fetched the§What-Ships-in-Baselinesection to confirmodd/challenge/stakes-calibration.mdis listed as required-in-baseline. Two-tier cascade today is coherent with the contract givenworkers/baseline/is not shipped. - Nine-mode curl. Validator iterated all nine modes from
odd/challenge/stakes-calibrationagainst the preview URL. Each returned a full envelope with validgovernance_sourceandgovernance_urislength 4.voice-dumpreturned SUPPRESSED; the other eight returned CHALLENGED. PR #100 regression guard is live. - Independent smoke runs. Validator cloned its own copy of the branch and ran the smoke test three consecutive times against the preview URL — not trusting the orchestrator's own smoke output. 126/126 each run.
The disposition block: VERIFIED / 5/5 / [] blockers / [] advisories.
Patterns Observed, Worth Carrying Forward
"PRD as a file before touching source" is a review-cost reducer. P1.2 landed with 3 non-blocking advisories. P1.3.1 landed with zero. The difference this session was the PRD: 296 lines including 8 explicit decisions (D1–D8) each with alternatives named, a risk register covering the SUPPRESSED early-return gotcha before the first line of code was written, and a §8 validator dispatch protocol naming five corroborations that the validator then faithfully executed. The hypothesis: review findings tend to come from (a) decisions the author didn't realize were decisions, and (b) edge cases the author didn't think about. Writing the PRD surfaces both before code, turning would-be review findings into planning-time clarifications.
Operator pivot on a design decision is more productive than operator approval of all decisions. D4 was the only pivot of eight decisions. The PRD's first-draft case for single-string was internally coherent — but the operator caught that it was optimizing for the wrong thing (envelope parity over accurate representation of governance reality). The change took one message, one PRD edit, and zero downstream rework. If the operator had approved D4 as drafted, the validator corroboration on the governance_uri field would have surfaced the same question at validation time, which is 10× more expensive to fix. The session confirms: review pivots during planning are the cheapest kind. "7 of 8 approved, D4 reconsider" is a high-value approval shape.
Isolate-warmup pattern is real across tiers. The P1.2 handoff established "3 consecutive clean as prod-ready gate" because CF isolates can serve mixed versions immediately after deploy. This session reproduced the pattern precisely on main-preview: two flakes, then three clean, then two more clean for confidence. Prod took 40s of warmup wait and then five clean in a row. The operational rule generalizes: trust the third-consecutive-clean, not the first.
Handoff errors are structural, not exceptional. The P1.2 ledger named recency-as-authority (three recurrences) and proposed a candidate canon principle on contract-governs-handoff-drift, pending one more recurrence before canonization. This session is that recurrence. The P1.3 handoff's claim of four discover* helpers was recency-as-authority in the forward-pointing doc itself — the author pattern-matched from the encode helper (discoverEncodingTypes) onto the challenge helpers without verifying against code. The fix worked: code-first discipline caught it in the PRD's §3.1 before any edits. Third instance confirmed; the canon principle now has standing.
What Is Cleared from the Prior Handoff
- [O-open P1] P1.3.1 challenge
governance_sourceretrofit — closed by #116/#117.
What Remains Open (Carry-Forward O-opens)
- [O-open P1] P1.3.2 — next tool in sweep. Candidates:
gate,preflight,validate,orient,search,catalog,cleanup,version. Priority to be decided in the next session's handoff. Audit doc atdocs/oddkit/audit/governance-anti-pattern-sweep-2026-04-17.mdhas the ranking. - [O-open P2]
getIndexstrict-mode (skipBaselineFallback). Inherited from encode 0.18.0; now affects challenge 0.19.0 as well. Same limitation, one fix — natural to pull into a later P1.3.x PR when a tool exercises the code path non-trivially, or as a standalone PR if the sweep doesn't naturally touch it. - [O-open P3] Handoff text corrections on klappy.dev. Two corrections deferred from this session: (a) P1.2 handoff
klappy://odd/handoffs/2026-04-20-p1-2-encode-canaryrename "bundled baseline" → "minimal fallback" to align with the contract's enum; (b) P1.3 handoffklappy://odd/handoffs/2026-04-20-p1-3-challenge-canaryrename the threediscover*→fetch*forfetchBasePrerequisites/fetchNormativeVocabulary/fetchStakesCalibration. Low priority, archival; bundle both into a single tiny canon PR. - [O-open P4] Canon principle on contract-governs-handoff-drift. P1.2 ledger called for one more recurrence before writing the principle. This session is recurrence #3 (P1.3 handoff's
discover*naming error). The principle has standing. Draft location:canon/principles/contract-governs-handoff-drift.md. Core claim: "when a handoff's word choice disagrees with a governing contract's enum or a live code reality, the contract/code wins — the handoff is a bridging artifact, not a source of truth." Draft in a small canon PR when the next session opens a klappy.dev PR for any reason. - [O-open P5]
workers/baseline/bundled-tier build pipeline. The contract§Build-Time-Invariantsdescribes the regeneration process (fetch canon at pinned SHA, extract required-baseline files, schema-check against canon, fail build on divergence). Nothing in the repo implements this today. Separate epoch's work — not a single-session unit. First step would be writing the MANIFEST.json and the regeneration script; second step would be the schema check; third step would be aoddkit_baseline_checkprobe. Deferred until the sweep surfaces concrete need or TruthKit's TruthKit-specific baseline needs force the question. - [O-open P6] CHANGELOG render route on klappy.dev +
version_notes_urlon MCPinitialize. Low priority, unchanged from prior handoffs. Slot into a tool-envelope PR window.
What This Session Added to the Carry List
None beyond the above — the session stayed in scope. No new scope-creep O-opens.
Canon Principle Now Standing: contract-governs-handoff-drift
Three recurrences justify the principle. Named explicitly:
When a handoff's word choice or described state disagrees with a governing contract's enum or the target code's live reality, the contract and code win. The handoff is a bridging artifact — useful for session continuity, but not authoritative over the governing documents or the repo state. The fix is always the same: before acting on a handoff's framing, grep the target code and re-fetch the governing contract. Recency is not authority.
Three recurrences this principle addresses:
- P1.2 session: handoff described three-tier cascade; contract's enum for encoding-types is two-tier (
knowledge_base|minimal). Word collision, not design conflict. - P1.2 session: handoff's scope framing treated "bundled DOLCHEO minimum" as a tier name; contract calls that case
"minimal". Same pattern at scope-framing level. - P1.3.1 session (this one): handoff described four
discover*helpers; code has onediscover*and threefetch*. Pattern-matched from encode without verifying.
The principle should be drafted in the next klappy.dev PR (natural to bundle with the handoff text corrections in O-open P3). The candidate doc already has three attestation cases in the ledger — a stronger grounding than most canon principles get at draft time.
Session MechanicsWhat Worked and What Didn't
What worked:
- PRD as a file before code. 296 lines of planning produced an execution path the validator could corroborate exactly, zero advisories.
- Time discipline via
oddkit_timefirst each turn withserver_timereference. The session's elapsed-time claims in final reporting (3h 25m total wall clock) are observed, not inferred. - Two explicit gates (exploration→planning, planning→execution) named the mode transitions out loud, even though the session started mid-plan. Cheap tool call; binds the scope lock that follows.
- Strict aggregation rule (any helper minimal → aggregate minimal) matched encode's single-helper precedent trivially and has no edge cases.
- Per-helper domain-noun tuples (
{types, source},{prerequisites, source}, etc.) read more cleanly at the call site than a generic{data, source}would have. Operator's style nit on D3 was right.
What didn't work as well:
- Initial PRD draft on D4 optimized for parity over accuracy. Single-string
governance_uriwould have been merged if the operator hadn't pushed back. The review caught it cheaply; the PRD-first discipline is not a substitute for operator design review on non-obvious tradeoffs. - Smoke output pipeline filtering hid the pass/fail tallies on the first prod-smoke attempt. The fix was trivial (
tail -1instead of a grep filter), but the lesson is that observability tooling around verification steps should itself be verified before trusting its output. - Two main-preview isolate flakes before three clean. Not a defect — the P1.2 handoff predicted this — but a reminder that the 3-consecutive-clean gate is doing real work, not ritual.
Handoff
Next session's atomic unit: P1.3.2 — apply the canary pattern to the next tool in the sweep. Forward handoff at klappy://odd/handoffs/2026-04-21-p1-3-2-next-tool-canary. This ledger is status: active; a future closeout session will flip it to status: superseded with a pointer to that successor.
Provenance
- Source handoff:
odd/handoffs/2026-04-20-p1-3-challenge-canary.md— the instructions this session executed against. - Predecessor ledger:
odd/ledger/2026-04-19-p1-2-encode-dolcheo-landed.md— the P1.2 retrospective whose code-first and recency-as-authority observations this session tested. - Merged PRs:
klappy/oddkit#116(feat),klappy/oddkit#117(promotion). - Validator session:
sesn_011CaE63LZhPUX1UAZPbiV7nunder agentagent_011CaE62pg6jJ7yYpRj1o9Do. Model:claude-sonnet-4-5. Event log ephemeral to the validator's container; the VERIFIED 5/5 disposition is summarized above and in the final disposition block retrieved from the session's terminalagent.messageevent. - PRD:
/home/claude/work/prd-p1-3-1-challenge-canary.md— local planning artifact in the orchestrator's working directory, not committed to any repo. Referenced in PR #116 commit message and inline orchestrate.ts comments.