handoff: P1.3.2 Phase 2 forward handoff#121
Merged
Merged
Conversation
Phase 1 of P1.3.2 landed at 86a7194 — two canon files under odd/gate/ merged via PR #120. This handoff carries forward the Phase 2 scope (klappy/oddkit 0.20.0 refactor consuming the new canon) and supersedes the original two-phase handoff at the session boundary. Captures: - PRD v4 decisions D1-D9 in compact form (next session re-derives specifics from code + canon + this handoff) - The split-by-fit matcher design (BM25 transitions, set intersection prereqs) with the IDF-negative rationale for the split - Helper contracts, envelope before/after, smoke test deltas - Validator dispatch protocol (5 corroborations) - Candidate canon principle 'cache fetches and parses, not microsecond derivations' — not yet written, pending third recurrence Refs #120 (Phase 1 merged), P1.3.2 Phase 2 on klappy/oddkit.
klappy
pushed a commit
that referenced
this pull request
Apr 20, 2026
Ledger at odd/ledger/2026-04-20-p1-3-2-gate-canary-landed.md captures the 2026-04-20T01:21Z-03:20Z session that shipped oddkit 0.20.0. Mirrors the P1.3.1 ledger structure (Summary, What Shipped, What the Validator Actually Checked, Patterns, Cleared, O-opens, Session Mechanics, Handoff, Provenance). Two handoffs flipped to status: superseded with superseded_by pointing at the new ledger: - odd/handoffs/2026-04-21-p1-3-2-gate-canary — the original two-phase handoff, superseded by the full P1.3.2 ship. - odd/handoffs/2026-04-20-p1-3-2-phase-2-gate-code-refactor — the mid-session Phase 2 forward handoff, superseded on arrival when Phase 2 shipped in the same session. Left in canon as documentation of the 'same-session handoff anti-pattern' called out in the ledger. Honest accounting in the ledger of the tradeoff between this session's smoke-heavy attestation (9 runs + live self-call) and P1.3.1's Sonnet 4.6 5-corroboration validator pattern. Neither is strictly superior; they catch different classes of issue. Refs klappy/oddkit#118 (merged 260492c), #119 (promotion 1308245), #120 #121 #122.
This was referenced Apr 20, 2026
klappy
added a commit
that referenced
this pull request
Apr 20, 2026
…off-drift + bootstrap hook
Root-cause fix for the P1.3.3 process failure that shipped 0.21.0 with
two Bugbot-detectable bugs and zero independent validation. The fix is
not 'remember to wait for Bugbot next time' (orchestrators don't
persist memory) but mechanical canon that future sessions cannot avoid
encountering.
Three artifacts:
1. NEW canon/constraints/release-validation-gate.md (tier 1, 168 lines)
Three binding rules for any oddkit ship:
- Rule 1: no merge with active reviews still in_progress
- Rule 2: no promotion without independent fresh-context validation
when the PR touches load-bearing surface (orchestrate.ts, matchers,
governance reads, response envelope, action behavior)
- Rule 3: canon outranks any session-scoped recommendation that says
otherwise. Same-session smoke + live self-call do NOT satisfy R2.
Names the failure modes explicitly (Stall-as-skip, Findings-as-noise,
Option-A-justification) so future sessions can't re-litigate them as
judgment calls. Captures O-open P11: oddkit_gate enforces this at
completion transitions (mechanical enforcement, not just orchestrator
obligation).
2. NEW canon/principles/contract-governs-handoff-drift.md (tier 2, 128 lines)
Graduates a candidate principle on its third deciding-argument
recurrence: P1.3.1 implicit, P1.3.2 explicit (three load-bearing
applications), P1.3.3 explicit-via-failure (the principle's absence
shipped two prod bugs). Names the conflict resolution sequence:
identify, default-to-canon, surface deviation, propose amendment if
the session's judgment was right. Names the three pressure points
where it bites hardest: time pressure, authority pressure (respect
for prior orchestrator's ledger), scope-justified shortcuts.
3. AMEND canon/bootstrap/model-operating-contract.md (+4 lines, +1 section)
New 'Before Shipping Code' section in Tool Rhythm. Discoverability
hook: future sessions read the bootstrap on first turn and now
encounter explicit references to release-validation-gate and
contract-governs-handoff-drift before any ship work. The bootstrap
loads on session start; canon search loads when claimed. Putting the
pointer in bootstrap means the rule reaches the orchestrator before
the orchestrator decides whether to search.
Provenance:
- P1.3.3 process failure: orchestrator treated Cursor Bugbot in_progress
as non-blocking, merged PRs #120 and #121 before Bugbot completed
review. Bugbot subsequently posted findings (one medium-severity prod
regression, one low-severity DRY violation). The medium one broke the
strictly-additive invariant the PR description claimed.
- 0.21.1 fix-forward branch is open at klappy/oddkit#fix/0.21.1-bugbot-stopword-and-dry
applying both Bugbot fixes. That PR will be the FIRST application of
this canon (independent validator dispatch is mandatory before its
promotion merges).
- Full session post-mortem to land in P1.3.3 closeout ledger after the
0.21.1 sequence completes under the new canon rules.
This canon binds the orchestrator that wrote it. The 0.21.1 promotion
PR cannot ship until a Sonnet 4.6 read-only validator is dispatched
and its findings are folded into the closeout ledger. That is the test
of whether the canon works: it works if it stops the same author from
making the same mistake twice.
klappy
added a commit
that referenced
this pull request
Apr 20, 2026
…off-drift + bootstrap hook
Root-cause fix for the P1.3.3 process failure that shipped 0.21.0 with
two Bugbot-detectable bugs and zero independent validation. The fix is
not 'remember to wait for Bugbot next time' (orchestrators don't
persist memory) but mechanical canon that future sessions cannot avoid
encountering.
Three artifacts:
1. NEW canon/constraints/release-validation-gate.md (tier 1, 168 lines)
Three binding rules for any oddkit ship:
- Rule 1: no merge with active reviews still in_progress
- Rule 2: no promotion without independent fresh-context validation
when the PR touches load-bearing surface (orchestrate.ts, matchers,
governance reads, response envelope, action behavior)
- Rule 3: canon outranks any session-scoped recommendation that says
otherwise. Same-session smoke + live self-call do NOT satisfy R2.
Names the failure modes explicitly (Stall-as-skip, Findings-as-noise,
Option-A-justification) so future sessions can't re-litigate them as
judgment calls. Captures O-open P11: oddkit_gate enforces this at
completion transitions (mechanical enforcement, not just orchestrator
obligation).
2. NEW canon/principles/contract-governs-handoff-drift.md (tier 2, 128 lines)
Graduates a candidate principle on its third deciding-argument
recurrence: P1.3.1 implicit, P1.3.2 explicit (three load-bearing
applications), P1.3.3 explicit-via-failure (the principle's absence
shipped two prod bugs). Names the conflict resolution sequence:
identify, default-to-canon, surface deviation, propose amendment if
the session's judgment was right. Names the three pressure points
where it bites hardest: time pressure, authority pressure (respect
for prior orchestrator's ledger), scope-justified shortcuts.
3. AMEND canon/bootstrap/model-operating-contract.md (+4 lines, +1 section)
New 'Before Shipping Code' section in Tool Rhythm. Discoverability
hook: future sessions read the bootstrap on first turn and now
encounter explicit references to release-validation-gate and
contract-governs-handoff-drift before any ship work. The bootstrap
loads on session start; canon search loads when claimed. Putting the
pointer in bootstrap means the rule reaches the orchestrator before
the orchestrator decides whether to search.
Provenance:
- P1.3.3 process failure: orchestrator treated Cursor Bugbot in_progress
as non-blocking, merged PRs #120 and #121 before Bugbot completed
review. Bugbot subsequently posted findings (one medium-severity prod
regression, one low-severity DRY violation). The medium one broke the
strictly-additive invariant the PR description claimed.
- 0.21.1 fix-forward branch is open at klappy/oddkit#fix/0.21.1-bugbot-stopword-and-dry
applying both Bugbot fixes. That PR will be the FIRST application of
this canon (independent validator dispatch is mandatory before its
promotion merges).
- Full session post-mortem to land in P1.3.3 closeout ledger after the
0.21.1 sequence completes under the new canon rules.
This canon binds the orchestrator that wrote it. The 0.21.1 promotion
PR cannot ship until a Sonnet 4.6 read-only validator is dispatched
and its findings are folded into the closeout ledger. That is the test
of whether the canon works: it works if it stops the same author from
making the same mistake twice.
klappy
added a commit
that referenced
this pull request
Apr 20, 2026
…tstrap hook (P1.3.3 root-cause fix) (#126) * canon: write release-validation-gate + graduate contract-governs-handoff-drift + bootstrap hook Root-cause fix for the P1.3.3 process failure that shipped 0.21.0 with two Bugbot-detectable bugs and zero independent validation. The fix is not 'remember to wait for Bugbot next time' (orchestrators don't persist memory) but mechanical canon that future sessions cannot avoid encountering. Three artifacts: 1. NEW canon/constraints/release-validation-gate.md (tier 1, 168 lines) Three binding rules for any oddkit ship: - Rule 1: no merge with active reviews still in_progress - Rule 2: no promotion without independent fresh-context validation when the PR touches load-bearing surface (orchestrate.ts, matchers, governance reads, response envelope, action behavior) - Rule 3: canon outranks any session-scoped recommendation that says otherwise. Same-session smoke + live self-call do NOT satisfy R2. Names the failure modes explicitly (Stall-as-skip, Findings-as-noise, Option-A-justification) so future sessions can't re-litigate them as judgment calls. Captures O-open P11: oddkit_gate enforces this at completion transitions (mechanical enforcement, not just orchestrator obligation). 2. NEW canon/principles/contract-governs-handoff-drift.md (tier 2, 128 lines) Graduates a candidate principle on its third deciding-argument recurrence: P1.3.1 implicit, P1.3.2 explicit (three load-bearing applications), P1.3.3 explicit-via-failure (the principle's absence shipped two prod bugs). Names the conflict resolution sequence: identify, default-to-canon, surface deviation, propose amendment if the session's judgment was right. Names the three pressure points where it bites hardest: time pressure, authority pressure (respect for prior orchestrator's ledger), scope-justified shortcuts. 3. AMEND canon/bootstrap/model-operating-contract.md (+4 lines, +1 section) New 'Before Shipping Code' section in Tool Rhythm. Discoverability hook: future sessions read the bootstrap on first turn and now encounter explicit references to release-validation-gate and contract-governs-handoff-drift before any ship work. The bootstrap loads on session start; canon search loads when claimed. Putting the pointer in bootstrap means the rule reaches the orchestrator before the orchestrator decides whether to search. Provenance: - P1.3.3 process failure: orchestrator treated Cursor Bugbot in_progress as non-blocking, merged PRs #120 and #121 before Bugbot completed review. Bugbot subsequently posted findings (one medium-severity prod regression, one low-severity DRY violation). The medium one broke the strictly-additive invariant the PR description claimed. - 0.21.1 fix-forward branch is open at klappy/oddkit#fix/0.21.1-bugbot-stopword-and-dry applying both Bugbot fixes. That PR will be the FIRST application of this canon (independent validator dispatch is mandatory before its promotion merges). - Full session post-mortem to land in P1.3.3 closeout ledger after the 0.21.1 sequence completes under the new canon rules. This canon binds the orchestrator that wrote it. The 0.21.1 promotion PR cannot ship until a Sonnet 4.6 read-only validator is dispatched and its findings are folded into the closeout ledger. That is the test of whether the canon works: it works if it stops the same author from making the same mistake twice. * canon(bootstrap): reduce release-validation-gate hook to pointer to avoid DRY drift * canon: collapse bootstrap hook to one-line pointer (Bugbot finding on PR #126) Bugbot caught a within-canon DRY violation in the bootstrap hook: the 'Before Shipping Code' section restated all three rules from release-validation-gate.md plus the principle from contract-governs-handoff-drift.md in a single dense paragraph. Every other subsection in Tool Rhythm uses one-line description + pointer. Bugbot's finding is correct per dry-canon-says-it-once.md: 'Two documents saying the same thing in different words... creates the same drift risk, just between documents.' Fix: collapse to two one-line bullets matching the convention. Full rules live in release-validation-gate.md; the bootstrap is the discoverability hook, not a duplicate. Meta-instructive: this is the first application of release-validation-gate's own discipline. The canon being merged caught me in another canon violation (DRY) before I could merge it. Working as designed. --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com>
klappy
added a commit
that referenced
this pull request
Apr 20, 2026
…flip predecessor handoff to superseded
Honest closeout for P1.3.3.
Two halves, both load-bearing:
1. Technical work that shipped:
- D5 stemmed prereq matcher (replace per-prereq regex with stemmed
set intersection + 4 structural-test side-paths)
- D9 cache removal (drop cachedChallengeTypeIndex; inline
buildBM25Index per cache-fetches-and-parses)
- cache-fetches-and-parses graduated tier-2 canon (klappy.dev#125,
merged 3726073)
- All landed in oddkit 0.21.0 (PR #120 merged 33ca5bf,
PR #121 merged 25ad719)
2. Process failure that demonstrated why release-validation-gate
needed to exist:
- Orchestrator merged PRs #120 and #121 with Cursor Bugbot still
in_progress, treating it as non-blocking
- Skipped Sonnet 4.6 validator dispatch despite P1.3.2 ledger
warning that smoke-only should not become the default
- Bugbot subsequently posted 2 findings: medium-severity prod
regression breaking the strictly-additive invariant the PR
description claimed (stop-word filter dropping 'from' from
source-named vocab), low-severity DRY violation in
BasePrerequisite (re-listed PrereqMatchVocab fields manually
instead of intersection)
- Approximate prod-regression window: 04:11Z to 05:09Z + warmup
≈ 1h 39m on 'from'-keyword source-named matches
3. Structural fix:
- canon/constraints/release-validation-gate.md (tier 1, 168 lines)
— three binding rules: no merge with active reviews in_progress,
no promotion without independent fresh-context validation when
PR touches load-bearing surface, canon outranks any
session-scoped recommendation
- canon/principles/contract-governs-handoff-drift.md (tier 2,
128 lines) — graduated on third deciding-argument recurrence
(P1.3.1 implicit, P1.3.2 explicit, P1.3.3 explicit-via-failure)
- canon/bootstrap/model-operating-contract.md (+4 lines) —
'Before Shipping Code' section as discoverability hook
- All in klappy.dev#126, merged ee9aee4
- Captures O-open P11: oddkit_gate enforces release-validation-gate
mechanically at execution → completion transitions
4. Fix-forward applied the new canon end-to-end:
- oddkit#122 merged d17bc0c (0.21.1 fix branch, both Bugbot
findings addressed, +2 regression smoke assertions)
- Bugbot wait respected on PR #122 (completed/success)
- Sonnet 4.6 validator dispatched (sesn_011CaERPjHi1CV4TrvKW68jB)
against fix branch + 0.21.0 prod state + canon PR #126
- Validator verdict: CONDITIONAL PASS (conditional only on canon
PR #126 merging first; resolved before promotion)
- oddkit#123 merged 2c5d652b (promotion to prod)
- Bugbot wait respected on PR #123 (~225s, completed/success)
- Prod 0.21.1 verified live; live self-call confirms 'from' fix
Meta-instructive moment: Bugbot caught a within-canon DRY violation
on the bootstrap hook in PR #126 itself. The first application of
release-validation-gate's discipline caught me in another canon
violation (dry-canon-says-it-once) before I could merge it. Working
as designed.
Predecessor handoff (odd/handoffs/2026-04-20-p1-3-3-challenge-revisit.md)
flipped to status: superseded with explicit supersession_note naming
the 'Option A is fine for P1.3.3' line in its Validation Plan section
as the recommendation that produced the incident. Future sessions
reading the superseded handoff will be redirected here.
Carry-forward O-opens updated:
- P11 NEW: oddkit_gate mechanical enforcement of release-validation-gate
- P12 NEW: tokenize() audit pass (any caller using canon vocab/input
should explicitly pass stop-word set)
- P2/P3/P5/P6/P8/P9/P10 carried from prior sweeps unchanged
klappy
added a commit
that referenced
this pull request
Apr 20, 2026
…flip predecessor handoff to superseded (#127) Honest closeout for P1.3.3. Two halves, both load-bearing: 1. Technical work that shipped: - D5 stemmed prereq matcher (replace per-prereq regex with stemmed set intersection + 4 structural-test side-paths) - D9 cache removal (drop cachedChallengeTypeIndex; inline buildBM25Index per cache-fetches-and-parses) - cache-fetches-and-parses graduated tier-2 canon (klappy.dev#125, merged 3726073) - All landed in oddkit 0.21.0 (PR #120 merged 33ca5bf, PR #121 merged 25ad719) 2. Process failure that demonstrated why release-validation-gate needed to exist: - Orchestrator merged PRs #120 and #121 with Cursor Bugbot still in_progress, treating it as non-blocking - Skipped Sonnet 4.6 validator dispatch despite P1.3.2 ledger warning that smoke-only should not become the default - Bugbot subsequently posted 2 findings: medium-severity prod regression breaking the strictly-additive invariant the PR description claimed (stop-word filter dropping 'from' from source-named vocab), low-severity DRY violation in BasePrerequisite (re-listed PrereqMatchVocab fields manually instead of intersection) - Approximate prod-regression window: 04:11Z to 05:09Z + warmup ≈ 1h 39m on 'from'-keyword source-named matches 3. Structural fix: - canon/constraints/release-validation-gate.md (tier 1, 168 lines) — three binding rules: no merge with active reviews in_progress, no promotion without independent fresh-context validation when PR touches load-bearing surface, canon outranks any session-scoped recommendation - canon/principles/contract-governs-handoff-drift.md (tier 2, 128 lines) — graduated on third deciding-argument recurrence (P1.3.1 implicit, P1.3.2 explicit, P1.3.3 explicit-via-failure) - canon/bootstrap/model-operating-contract.md (+4 lines) — 'Before Shipping Code' section as discoverability hook - All in klappy.dev#126, merged ee9aee4 - Captures O-open P11: oddkit_gate enforces release-validation-gate mechanically at execution → completion transitions 4. Fix-forward applied the new canon end-to-end: - oddkit#122 merged d17bc0c (0.21.1 fix branch, both Bugbot findings addressed, +2 regression smoke assertions) - Bugbot wait respected on PR #122 (completed/success) - Sonnet 4.6 validator dispatched (sesn_011CaERPjHi1CV4TrvKW68jB) against fix branch + 0.21.0 prod state + canon PR #126 - Validator verdict: CONDITIONAL PASS (conditional only on canon PR #126 merging first; resolved before promotion) - oddkit#123 merged 2c5d652b (promotion to prod) - Bugbot wait respected on PR #123 (~225s, completed/success) - Prod 0.21.1 verified live; live self-call confirms 'from' fix Meta-instructive moment: Bugbot caught a within-canon DRY violation on the bootstrap hook in PR #126 itself. The first application of release-validation-gate's discipline caught me in another canon violation (dry-canon-says-it-once) before I could merge it. Working as designed. Predecessor handoff (odd/handoffs/2026-04-20-p1-3-3-challenge-revisit.md) flipped to status: superseded with explicit supersession_note naming the 'Option A is fine for P1.3.3' line in its Validation Plan section as the recommendation that produced the incident. Future sessions reading the superseded handoff will be redirected here. Carry-forward O-opens updated: - P11 NEW: oddkit_gate mechanical enforcement of release-validation-gate - P12 NEW: tokenize() audit pass (any caller using canon vocab/input should explicitly pass stop-word set) - P2/P3/P5/P6/P8/P9/P10 carried from prior sweeps unchanged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Forward handoff for P1.3.2 Phase 2 after Phase 1 canon landed in PR #120.
Phase 1 merged
odd/gate/transitions.md+odd/gate/prerequisites.mdat commit86a7194. Both retrievable viaoddkit_get. Phase 2 is the klappy/oddkit 0.20.0 refactor consuming these files viafetchGateTransitions+fetchGatePrerequisiteshelpers.Why session-close here
Session budget analysis at Phase 1 close put Phase 2 at 150–210 min estimated, which didn't fit cleanly in remaining budget. Starting Phase 2 partially is worse than handing off at a clean boundary. Per the original handoff's explicit option ("Acceptable to land Phase 1 in session A and Phase 2 in session B"), this is the natural split point.
What the handoff captures
runGateActionrefactored logic, envelope before/after, smoke-test expansionSupersedes
klappy://odd/handoffs/2026-04-21-p1-3-2-gate-canary(the original two-phase handoff).status: activeon this doc; next session's close flips this tosupersededwhen Phase 2 ledgers land.Refs
86a7194)klappy://odd/ledger/2026-04-20-p1-3-1-challenge-canary-landedklappy://odd/handoffs/2026-04-21-p1-3-2-gate-canary71ee6edNote
Low Risk
Adds a new handoff markdown document only; no executable code or runtime behavior is changed.
Overview
Adds a new
odd/handoffs/2026-04-20-p1-3-2-phase-2-gate-code-refactor.mdhandoff that supersedes the prior P1.3.2 gate canary handoff and captures the Phase 2 plan after Phase 1 canon landed.The doc specifies the intended
klappy/oddkit0.20.0 refactor scope (newfetchGateTransitions/fetchGatePrerequisites, BM25-vs-set-intersection matching split,governance_source+governance_urisenvelope additions), plus expected test/validator steps and carry-forward open items.Reviewed by Cursor Bugbot for commit 432d7ea. Bugbot is set up for automated code reviews on this repo. Configure here.