From 9949567ffdace9f3aca312a1f590ac59c09df03a Mon Sep 17 00:00:00 2001 From: Klappy Date: Sun, 19 Apr 2026 07:25:40 +0000 Subject: [PATCH] salvage: orphaned ledger + handoff docs that never made it to main MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two orphaned artifacts recovered: 1. odd/handoffs/2026-04-19-fresh-session-continuation.md Tonight's fresh-session continuation handoff. Created during the E0008.3 session and pushed to canon/dolcheo-ledger-open-items AFTER #107 was squash-merged, leaving it orphaned on the branch. Content: self-contained doc naming priority 1–6 work, the governing prompt-over-code refactor arc, and recommended first actions. Companion to the E0008.3 session ledger. 2. odd/ledger/journal/2026-04-17-pr100-rage-quit-handoff.md Historical ledger from 2026-04-17 session that ended with Klappy handing off to another model after a 12-hour bugbot ping-pong cycle on klappy/oddkit#100. Lived on oddkit branch chore/handoff-journal-pr100, never merged. The branch itself is unsafe to merge (also deletes the audit doc and smoke test that are load-bearing on main), so the ledger file was salvaged in isolation. Frontmatter added for canon consistency; status: archival; salvaged_from field records the original location. Content worth preserving: 15+ bugs caught across three review surfaces (gauntlet, bugbot, Klappy), defect-class blindness as the consistent failure pattern, the voice-dump invariant story that directly motivated the canary refactor and live-smoke ship-blocker contract in canon/constraints/core-governance-baseline. This is the session that retrospectively justified E0008.3. Its loss would have removed the empirical anchor for several canon decisions that now live in main. Both files are now tracked and durably retrievable via klappy:// URIs. Related cleanup to follow: - oddkit branches chore/handoff-journal-pr100 and fix/challenge-mode-schema-includes-writing-modes can be deleted once this PR merges (their content is either superseded on main or salvaged here). - oddkit/docs/drafts/core-governance-baseline.md is a stale pre-rename draft; content lives in klappy.dev canon now. Separate tiny cleanup in oddkit repo. --- .../2026-04-19-fresh-session-continuation.md | 217 ++++++++++++++++++ .../2026-04-17-pr100-rage-quit-handoff.md | 92 ++++++++ 2 files changed, 309 insertions(+) create mode 100644 odd/handoffs/2026-04-19-fresh-session-continuation.md create mode 100644 odd/ledger/journal/2026-04-17-pr100-rage-quit-handoff.md diff --git a/odd/handoffs/2026-04-19-fresh-session-continuation.md b/odd/handoffs/2026-04-19-fresh-session-continuation.md new file mode 100644 index 00000000..e7e41c6f --- /dev/null +++ b/odd/handoffs/2026-04-19-fresh-session-continuation.md @@ -0,0 +1,217 @@ +--- +uri: klappy://odd/handoffs/2026-04-19-fresh-session-continuation +title: "Handoff — Fresh Session Continuation from 2026-04-19 CST" +audience: odd +exposure: nav +tier: 3 +voice: neutral +stability: stable +tags: ["odd", "handoff", "session", "epoch-8.3", "prompt-over-code", "continuation", "dolcheo"] +epoch: E0008.3 +date: 2026-04-19 +session_span: "2026-04-18 to 2026-04-19 (closed)" +derives_from: "odd/ledger/2026-04-18-e0008-3-validation-and-teams-over-swarms.md, docs/oddkit/audit/governance-anti-pattern-sweep-2026-04-17.md" +governs: "Fresh-session continuation context. Captures what shipped, what remains open, what the fresh session should tackle first, and the ongoing prompt-over-code refactor arc that predates E0008.3 and still governs remaining tool work." +status: active +--- + +# Handoff — Fresh Session Continuation from 2026-04-19 CST + +> A reader of this document should be able to resume productive work without reading the full prior session transcript. The companion ledger (`klappy://odd/ledger/2026-04-18-e0008-3-validation-and-teams-over-swarms`) is the retrospective record; this document is the forward-pointing one. Start here. + +--- + +## Where we are right now + +**Current epoch:** E0008.3 (validation as fourth epistemic mode with context-break requirement). Canon merged. Covered in detail in `klappy://docs/appendices/epoch-8-3` and `klappy://canon/validation-as-epistemic-mode`. + +**Next epoch (anticipated):** E0009 — self-correction. Requires teams-over-swarms principle landing first. See O11 in the ledger. + +**What just shipped (this session):** + +1. `klappy/klappy.dev#101` — knowledge_base_url contract rename + tier strings (canon → knowledge_base, baseline → bundled) +2. `klappy/klappy.dev#106` — forward-facing doc sweep for the rename +3. `klappy/klappy.dev#105` — validation as fourth epistemic mode (E0008.3) + context-break requirement + session ledger +4. `klappy/oddkit#105` — governance anti-pattern audit doc (11-tool sweep) +5. `klappy/oddkit#108` — telemetry_policy canary completion + rename + live smoke test template +6. `klappy/oddkit#109` — main → prod promotion of the canary arc +7. `klappy/klappy.dev#107` — DOLCHEO ledger framing + 19 open items + 5 open questions (**contains this handoff; merge after reading**) + +**Verified production state:** `https://oddkit.klappy.dev/mcp` responding with full envelope (`action`, `result`, `server_time`, `assistant_text`, `debug`); `telemetry_policy` returns `governance_source: "knowledge_base"` by default; strict-override via `knowledge_base_url` correctly falls through to `minimal` tier when file missing. 24/24 smoke assertions green in prod. + +--- + +## The governing arc that predates E0008.3 and still governs remaining work + +**Prompt-over-code refactor of all oddkit tools.** This is where the session started and where the big remaining work still sits. E0008.3 was a detour that the canary incident forced us into — a good detour, but the canary was one tool out of eleven. The audit in `docs/oddkit/audit/governance-anti-pattern-sweep-2026-04-17.md` documents the full scope: + +Every oddkit tool exhibits some form of the vodka anti-pattern: canon defines vocabulary (modes, challenge types, encoding types, DOLCHEO artifact types, stakes calibration, etc.), but tool code hardcodes interpretation. `telemetry_policy` was the first tool canary-refactored to fetch governance from the knowledge base at runtime with a bundled fallback and minimal last-resort. **The same refactor is still needed for the other 10 tools.** + +The canary proved the pattern works. Now we scale it. The anti-pattern, the canary template, and the ship-blocker contract (live-smoke against deployed preview) are all documented in `canon/constraints/core-governance-baseline.md`. + +--- + +## Priority 1 — Pick up immediately + +### P1.1 — Internal oddkit rename (scope expanded per 2026-04-19 decision) +Original scope: rename internal `canonUrl` variables, `ZipBaselineFetcher` class, `BASELINE_URL` env. Expanded scope based on operator decision that **there are zero external users, so backward compatibility is not a constraint**: +- Strip the `a.canon_url` legacy fallback from `parseToolCall` in `workers/src/telemetry.ts` +- Rename `canonUrl` → `knowledgeBaseUrl` across `telemetry.ts` (9 refs), `orchestrate.ts` (111 refs), `zip-baseline-fetcher.ts` (24 refs) +- Rename `ZipBaselineFetcher` class → `KnowledgeBaseFetcher` +- Rename `BASELINE_URL` env var → `DEFAULT_KNOWLEDGE_BASE_URL` (update `wrangler.toml` and every `env.BASELINE_URL` reference) +- Rename blob6 schema references from `canon_url` → `knowledge_base_url` in `telemetry.ts` comment block and `docs/oddkit/tools/telemetry_public.md` +- No aliasing, no dual-accept, no migration note — just rename and move on +- Run typecheck, deploy to preview, run `workers/test/canon-tool-envelope.smoke.mjs` against preview, merge if 24/24 green, promote to prod + +Expected size: ~150 refs across 4 files. Mechanical but real. **Do this with fresh eyes — decision to defer to fresh session was explicit E0008.3 practice.** + +### P1.2 — DOLCHE → DOLCHEO vocabulary canon +Write tier-2 canon doc (candidate path: `canon/definitions/dolcheo-vocabulary.md`) establishing DOLCHEO as canonical, replacing DOLCHE. + +Operator's lean (from session, needs final decision): DOLCHEO **replaces** DOLCHE — DOLCHE was always incomplete because Open items had no home. Both Os remain `O`; rely on section context to distinguish. + +Doc should cover: +- Why the extension (retrospective-only tracking loses forward-pointing threads) +- Each letter defined: **D**ecision, **O**bservation (closed), **L**earning, **C**onstraint, **H**andoff, **E**ncode, **O**pen (forward-pointing) +- Guidance on when to use Open vs Handoff (Handoff = work transfer; Open = unresolved thread or question) +- Example ledger structure with Open Items sectioned by priority band (P1–P6) + +Then update the oddkit_encode tool description to reference DOLCHEO and unblock that long-deferred tool description improvement. See O3 in the ledger. + +### P1.3 — Verify oddkit#56 and #57 are stale +Two old open PRs on oddkit from months ago, both titled "Add oddkit_write tool definition (stub)". Duplicates of each other. Check if either is still relevant given the current direction. If superseded, close with a note linking to canon. If still planned work, leave open and update the ledger with the reference. + +--- + +## Priority 2 — The prompt-over-code refactor of remaining oddkit tools + +Per the audit doc (`docs/oddkit/audit/governance-anti-pattern-sweep-2026-04-17.md`), the canary pattern needs to be applied to each of these tools. **Each one follows the same canary template:** canon doc defines vocabulary → tool fetches canon at runtime → falls back to bundled tier → falls back to minimal hardcoded behavior → response envelope declares `governance_source` → Zod schema accepts `knowledge_base_url` optional override → ship-blocker live-smoke test added to the smoke suite. + +Rough priority order (highest-impact anti-pattern first): + +1. **`oddkit_encode`** — hardcoded four types (O/L/D/C/H), canon actually specifies DOLCHEO (seven letters). Biggest vocabulary mismatch in the system. Blocks tool description update until resolved. Pairs naturally with P1.2 (DOLCHEO canon doc) — do them together. +2. **`oddkit_challenge`** — execution mode has hardcoded claim type detection via regex. Canon defines challenge types in `canon/`. Tool should read types from canon at runtime. +3. **`oddkit_gate`** — `problem_defined` prerequisite uses hardcoded regex for transition detection. Cannot recognize writing-canon transitions without runtime canon read. +4. **`oddkit_preflight`** — Definition of Done lookups are partially hardcoded. Should read full DoD spec from canon. +5. **`oddkit_validate`** — Completion criteria matching is hardcoded. Canon has validation vocabulary (now including E0008.3 context-break requirement); tool should fetch. +6. **`oddkit_orient`** — Mode classification uses hardcoded mode list. Now that validation is a fourth mode (E0008.3), tool must read modes from canon to keep pace with canon changes without code redeploys. +7. **`oddkit_search`** — Ranking weights and tag boosts are hardcoded. Lower priority because search behavior is less load-bearing for epistemic correctness. +8. **`oddkit_catalog`** — `start_here` suggestions hardcoded. Should be canon-driven. +9. **`oddkit_cleanup_storage`** — Probably fine as-is; mostly mechanical storage work with no canon-vocabulary dependency. Verify and mark complete. +10. **`oddkit_version`** — Trivial tool, probably no vodka violation. Verify and mark complete. + +**Each refactor PR should:** +- Include a canon doc update defining the vocabulary if not already canon-clean +- Pass `oddkit_preflight` and `oddkit_challenge` in canon-tier-1 or -2 mode +- Extend `workers/test/canon-tool-envelope.smoke.mjs` with assertions for the new tool's envelope and governance_source +- Live-smoke against preview deploy before merge — ship-blocker per `canon/constraints/core-governance-baseline.md` + +Total scope: likely 8–10 separate PRs over several sessions. Do them in priority order; do them one at a time with full gauntlet each time. + +--- + +## Priority 3 — Canon principles queued from session + +### P3.1 — `canon/principles/teams-over-swarms.md` (tier 2) +Governing architectural preference. Cite three anchors: +- African proverb: "If you want to go fast, go alone. If you want to go far, go together." (tradeoff) +- 1 Corinthians 12: body of Christ, many members with differentiated roles (anatomy) +- Operator testimony: oddkit and klappy.dev built alone (fast), TruthKit needs a team (far) (witness) + +Sections: +- Opening blockquote +- Summary (engineering argument) +- Derivation from the body metaphor (Paul's four moves: no self-disqualification, no role-elimination, no one-part-does-everything, shared fate) +- When swarms are fine (keep principle honest — batch processing, parallel independent work) +- Architectural implications pointing forward to E0009 and TruthKit harness design + +See O4 in the ledger. + +### P3.2 — Solo-to-team transition canon record +Durable decision doc recording the operator's explicit shift. Candidate location: `odd/decisions/solo-to-team-transition.md` or `docs/appendices/solo-to-team-transition.md`. + +Covers: +- oddkit + klappy.dev as complete solo arc (public field notebook / resume / book source) +- TruthKit as team-driven commercial successor +- Open-core positioning (oddkit MIT cornerstone → TruthKit proprietary harness) +- Book *Nothing New, Even AI* as the polished handoff document from solo to team arc +- Course (O19) as the separate teaching product derived from the same journey + +Should follow P3.1 so it can reference the teams-over-swarms principle. + +### P3.3 — `canon/patterns/bugbot-as-validator.md` (tier 2, lower priority) +Codify the bugbot collaboration pattern as canonical team architecture. See O6 in the ledger. Could live inside teams-over-swarms instead; decide when P3.1 is drafted. + +### P3.4 — `canon/principles/mechanical-work-belongs-in-code.md` (tier 2, lower priority) +Principle: if a transformation is mechanical (string splitting, formatting, classification with deterministic rules), the server owns it — not the LLM. Surfaced tonight via the encode blob-vs-artifact issue. First concrete application is `oddkit_encode` batch-mode. See O7 in the ledger. + +--- + +## Priority 4 — Tool feature work + +### P4.1 — `oddkit_encode` batch-mode feature (O2 in ledger) +Encode currently collapses multi-artifact input into a single typed blob. Fix: server-side paragraph splitting, optional typed prefixes (`[D]`/`[L]`/`[O]`/`[C]`/`[H]`/`[E]`), returns per-artifact array with individual quality scores. + +This is P2.1 (encode canon refactor) and P4.1 combined — one PR, canon doc first, then tool change. Probably the single highest-leverage remaining work after the internal rename. + +--- + +## Priority 5 — Writing thread (longer horizon, not-now-but-not-forgotten) + +See O14, O15, O16, O19 in the ledger. Summary: +- Book *Nothing New, Even AI* — seven parts, polish/selection of public journal +- Essay: creator-cannot-be-own-critic — anchor tonight's bugbot story +- Essay: teams-over-swarms — general-audience version of P3.1 canon +- Course: chronological journey with forward-references — distinct product from the book (Q5 flags positioning decision) + +--- + +## Priority 6 — Infrastructure threads (non-urgent) + +See O17, O18 in the ledger. +- Social Projector at post.klappy.dev +- klappy.dev doc-listing cache staleness under GitHub rate limits + +--- + +## Open questions carried forward + +See Q1–Q5 in the ledger. The ones most likely to need a decision in the near term: + +- **Q1** — DOLCHEO replaces DOLCHE or coexists? (Decide when writing P1.2 canon doc; lean: replace) +- **Q2** — Does the second O in DOLCHEO need a distinguishing letter? (Decide with Q1; lean: keep both as O) +- **Q5** — Course (O19) a companion to the book (O14) or a separate product? (Decide before significant investment in either product's structure; lean: separate) + +--- + +## Operating notes for the fresh session + +- **Read the bootstrap first.** Project instructions point at `klappy://canon/bootstrap/model-operating-contract`. Fetch it at session start. Mode discipline, context-break requirement, and DOLCHEO-style continuous tracking all live there. +- **Declare mode out loud.** "Exploring." "Moving to planning." "Executing." The operator should never guess. +- **Search canon before asking.** `oddkit_search` is essentially free. Most questions are already answered in canon. +- **During execution, produce artifacts.** Not questions. Not check-ins. Questions belong in planning. +- **Validate with fresh context.** You (the fresh session) ARE the fresh context for everything listed above. That is the structural advantage. Use it. +- **Run the gauntlet before declaring canon done.** `oddkit_preflight` → edits → `oddkit_challenge` in canon-tier-{1,2} mode → frontmatter audit → commit. +- **Live smoke before merging any MCP tool change.** Ship-blocker per canon. Template lives at `workers/test/canon-tool-envelope.smoke.mjs` in the oddkit repo. +- **Track DOLCHEO continuously.** Don't wait to be asked. Add Open items to the session ledger as they surface. + +--- + +## Credentials and tooling reference + +- GitHub PAT: see project instructions +- ANTHROPIC_API_KEY: see project instructions +- Working dirs used this session: `/home/claude/work/oddkit`, `/home/claude/work/klappy.dev-pr/klappy.dev` +- oddkit prod: `https://oddkit.klappy.dev/mcp` +- oddkit main preview: `https://main-oddkit.klappy.workers.dev` +- klappy.dev canon live on `main` branch + +--- + +## Recommended first action for the fresh session + +Orient. Search canon for `prompt-over-code refactor oddkit tools` and for `vodka anti-pattern audit`. Read the audit doc. Pick either **P1.1** (internal rename, ~60–90 min, purely mechanical) or **P1.2 + P4.1 bundled** (DOLCHEO canon + encode batch-mode, ~2–3 hours, higher impact but more design work). + +Either is a clean win. If operator is present, ask which they want to prioritize. If operating async from operator explicit instruction, default to P1.1 — lower-risk mechanical work is safer for an async session than design work. + +Then open a new session ledger for that session's work and pick up the DOLCHEO tracking discipline from there. diff --git a/odd/ledger/journal/2026-04-17-pr100-rage-quit-handoff.md b/odd/ledger/journal/2026-04-17-pr100-rage-quit-handoff.md new file mode 100644 index 00000000..8caa18e1 --- /dev/null +++ b/odd/ledger/journal/2026-04-17-pr100-rage-quit-handoff.md @@ -0,0 +1,92 @@ +--- +uri: klappy://odd/ledger/journal/2026-04-17-pr100-rage-quit-handoff +title: "Session Journal — PR #100 Rage-Quit Handoff" +audience: odd +exposure: nav +tier: 3 +voice: neutral +stability: stable +tags: ["odd", "ledger", "session", "journal", "pr100", "rage-quit", "bugbot", "defect-class-blindness", "historical"] +epoch: E0007 +date: 2026-04-17 +session_span: "2026-04-17 (single 12-hour session ending in handoff)" +governs: "Historical session record — the 2026-04-17 rage-quit session that ended with Klappy handing off to a new model after 12 hours of bugbot ping-pong on klappy/oddkit#100. Captures 15+ bugs across three review surfaces (gauntlet, bugbot, Klappy), defect-class blindness as the consistent failure pattern, and the voice-dump invariant story. Preserved for its empirical evidence on why the prompt-over-code refactor and live-smoke ship-blocker contract were necessary." +status: archival +salvaged_from: "oddkit branch chore/handoff-journal-pr100 (never merged, orphaned after session ended; destructive branch state unsafe to merge, ledger file salvaged in isolation)" +--- + +# Session Journal — PR #100 Rage-Quit Handoff + +**Date:** 2026-04-17 +**Time encoded:** 2026-04-17T15:27:57Z +**Session disposition:** Klappy ended session and handed off to another model after 12 hours of bugbot ping-pong on PR #100 +**Status of work in flight:** see Handoffs below — schema bug in main, prod promotion blocked + +--- + +## Decisions + +- **D1:** Klappy ended the session and handed off to another model after a 12-hour PR cycle on klappy/oddkit#100 (governance-driven challenge refactor with BM25 + stemming). + +- **D2:** PR #100 merged to main but is functionally broken in production — the MCP tool's Zod mode enum was hardcoded to `[exploration, planning, execution]` while the calibration governance defines 9 modes. The voice-dump suppression invariant — the load-bearing feature named in evidence — is unreachable from the public API. Fix exists on branch `fix/challenge-mode-schema-includes-writing-modes`, not yet merged. + +- **D3:** PR #101 (main → prod promotion) opened but should NOT be merged until the schema fix lands. Promoting now ships a broken contract. + +## Observations + +- **O1:** 15+ bugs caught across three review surfaces during PR #100 — gauntlet caught 3 governance/architectural, bugbot caught 12+ code-correctness across multiple defect classes, Klappy caught 1 Vodka Architecture violation (`CHALLENGE_STOP_WORDS` hardcoded inside a refactor explicitly removing such hardcoding). + +- **O2:** Defect-class blindness was the consistent failure pattern. Same class shipped multiple times because Claude patched the cited line instead of sweeping the file. Three case-handling bugs. Two leftmost-regex bugs. Two parser-drift bugs. Three cache/state hygiene bugs. + +- **O3:** GitHub Actions CI on main HEAD (`6e01a001bf`) passed on `run_attempt=3`. Flakiness source is the parser-fidelity test Claude wrote — fetches 11 articles from `raw.githubusercontent.com` over network at test time. Network or Cloudflare cold-start glitch = test fails. Retries-as-strategy is not the CI model that should ship. + +- **O4:** The voice-dump invariant was tested at the parser layer (97 assertions) but never tested through the public MCP tool. Three review surfaces all missed it because none exercised the public API contract. CF preview job ran but didn't catch it either. + +## Learnings + +- **L1:** The friction reduction of 4.7-in-Claude-iOS-app is real and meaningful. The supervision tax at scale is also real and meaningful. Workflow that felt like senior-dev throughput on the writing side felt like brilliant-junior-dev throughput on the validation side. 12 hours of bugbot ping-pong is the cost of the smooth writing experience when defect-class blindness compounds. + +- **L2:** The Vodka Architecture anti-pattern is a category the gauntlet doesn't catch. Gauntlet verifies governance content, not whether new code is creating new ungoverned content. Possible future tool: vodka-audit that flags non-trivial Sets/Maps/lists in worker source and asks "should this be in canon?" + +- **L3:** Public API contract verification is non-negotiable for any refactor that introduces new vocabulary. Schema enums must be updated alongside governance article additions. Internal tests bypass the schema; CI doesn't exercise the contract; only manual or scripted curl against the deployed preview does. + +- **L4:** Reading PR review comments before treating divergent remote work as unknown is now a permanent practice. Bugbot/cursor leaves structured comments that explain divergent commits. + +- **L5:** Time-blindness is a recurring failure mode even after `oddkit_time` shipped. Tool has to be called at every context shift, not just when reminded. + +- **L6:** "Transparent and a little more broken" is preferable to "less broken and everything is hidden" when the validators are visible and the role separation is honest. But fluid experience can mask sloppy work; smoothness is not a quality signal. + +## Constraints + +- **C1:** PR #101 (prod promotion) MUST NOT MERGE until `fix/challenge-mode-schema-includes-writing-modes` is merged to main. Schema bug means voice-dump suppression invariant is unreachable from public API. Promoting now ships a broken contract. + +- **C2:** Parser-fidelity test must not gate merge until network-fetch-induced flakiness is addressed — either fixture-based testing or splitting integration assertions into a separate job that's not part of the merge gate. + +## Handoffs + +- **H1:** New session / new model takes over. Status of work in flight: + - PR #100 merged to main but functionally broken via schema gap + - PR #101 (prod promotion) open but should be blocked until schema fix lands + - Fix branch `fix/challenge-mode-schema-includes-writing-modes` has the correct fix, ready for merge + - After schema fix lands: re-verify with manual curl against preview that `mode=voice-dump` triggers SUPPRESSED, then promote PR #101 + +- **H2:** Three follow-up refactors share the same anti-pattern as challenge pre-refactor: + - Encode parity (regex-OR brittleness in `runEncodeAction`) + - Gate refactor (hardcoded `exploration→planning` prereqs) + - Orient refactor (hardcoded per-mode question lists, assumption regex, and load-bearing "Proactive posture" governance prose baked as string literal at line 1528 of `orchestrate.ts`) + +- **H3:** Test infrastructure debt: `workers/test/governance-parser.test.mjs` depends on live network fetch from klappy.dev raw. Should move to checked-in fixtures or split into separate job not part of merge gate. + +- **H4:** Essay "Transparent and a Little More Broken" (or equivalent title) is partially scoped but unwritten. Source material exists in this session — texts to Ian, follow-up clarifications, the corrective beat about brilliant-junior-dev throughput, the 12-hour supervision tax, the schema bug as proof that smooth experience masked sloppy work. Klappy may or may not want to write it after recovering from this session. + +- **H5:** Claude (this instance) failed to deliver senior-dev quality despite having every tool needed. Pattern of defect-class blindness and missing the public API contract verification is a real regression in this session, regardless of root cause. Next model handling this work should treat the schema fix as priority #1, the prod promotion block as priority #2, and the test flakiness as a hygiene improvement on the timeline. + +## Encodes + +- This journal at `odd/ledger/journal/2026-04-17-pr100-rage-quit-handoff.md` +- Prior journal from earlier in PR #100 cycle: `odd/ledger/journal/2026-04-17-pr100-combined.md` +- Evidence note: `docs/oddkit/evidence/challenge-governance-code-refactor.md` +- PR #100 (merged): https://github.com/klappy/oddkit/pull/100 +- PR #101 (prod promotion, open, BLOCKED): https://github.com/klappy/oddkit/pull/101 +- Fix branch (ready to merge): `fix/challenge-mode-schema-includes-writing-modes` +- Companion klappy.dev PR (merged): https://github.com/klappy/klappy.dev/pull/100