SummaryWhat Shipped
- Action:
oddkit_auditstandalone tool + unifiedoddkitaction: "audit"enum value - Version: oddkit
0.25.0 → 0.26.0(strictly additive +1 action; enum count12 → 13) - Default scope:
["writings/"]; opt-in wider viascope.paths - Surface:
https://oddkit.klappy.dev/mcp(and any oddkit-pattern MCP server using this Worker codebase) - Promote PR: klappy/oddkit#146 — merged 2026-04-27T02:51:55Z via regular merge (
merge_method: "merge", promote convention) - First real findings: 3 dead-reference findings surfaced in default-scope smoke; 17 in
["writings/", "canon/"]smoke. Real link-rot in canon — useful Phase 3 input.
Decisions Made This Session
D — Bugbot lineSeen finding waived rather than fix-forwarded
The Cursor Bugbot review on PR #146 head SHA 428b6769 posted one Low-severity finding: the lineSeen property on the pendingSuppress object in workers/src/orchestrate.ts:1947,1959 is assigned but never read. Independently verified via grep -n lineSeen — only two writes, no reads.
Disposition: waived in PR body with rationale + tracked at klappy/oddkit#148. Rationale: fix-forward would re-touch orchestrate.ts (load-bearing surface per klappy://canon/constraints/release-validation-gate Rule 2), which would force another full validator dispatch for what is a cosmetic-only cleanup with no behavioral surface. The release-validation-gate canon explicitly enumerates "waive in PR body with rationale" as one of three valid dispositions for completed/neutral Bugbot reviews with comments. The tracking issue keeps the dead code visible for the next PR that legitimately touches the audit code path.
D — Spec amended to v2.2 in this same canon PR
Validator findings F-3 (index_state field shipped omitted but spec mandated it) and F-5 (PARTIAL_INDEX status absent but spec listed it) are intentional drift documented in CHANGELOG. The spec is the authoritative future-target; rather than carry permanent drift, the spec graduates to v2.2 in this canon PR with both fields marked deferred. F-4 (suppressed_findings returns full objects vs spec's "count only") was dispositioned "no action" by the validator and remains unchanged in v2.2 — additive, not harmful, and any future amendment can be a separate small PR if alignment becomes useful.
D — Original handoff persisted only via reference, not reconstruction
Item 9 of the resume handoff said BOTH handoffs needed persisting:
odd/handoffs/2026-04-27-link-rot-phase-2-promote-and-phase-3.md— the "original," attached at start of the prior sessionodd/handoffs/2026-04-27-link-rot-phase-2-promote-resume.md— the resume
This session has the resume in full text but does not have the original. The original was attached to the prior session's chat context only; it was never persisted to canon and the prior session's container/transcript was no longer accessible. Per axiom 4 ("You Cannot Verify What You Did Not Observe"), this session refuses to reconstruct the original from inference. The resume is comprehensive enough to stand alone for forensic purposes — it summarizes the validator dispatch, the F-1 fix-forward, the open promote-PR state, and the full continuation test. The original's loss is recorded honestly in the resume's "Persistence Note" appendix.
Observations
O — Containers reset DNS resolution mid-session
POST /mcp from curl in the working container hit "DNS cache overflow" reproducibly after enough other network calls — the same environmental issue the validator's container hit (recorded as F-7 in the validator findings). Switching to Python urllib.request with an explicit User-Agent header bypassed it cleanly. This is a CF Workers Containers / Anthropic execution-environment quirk, not an oddkit defect. Worth carrying forward: post-deploy verification scripts should default to urllib over curl when running inside this environment.
O — Cursor Bugbot Autofix is correctly non-blocking per canon Rule 1
The promote PR's Cursor Bugbot Autofix check sat in in_progress while the parent Cursor Bugbot check completed neutral. The mergeable_state was unstable as a result. Canon (klappy://canon/constraints/release-validation-gate Rule 1) explicitly addresses this: "Cursor Bugbot Autofix may remain in_progress indefinitely without blocking, BUT only after the parent Cursor Bugbot check has reached completed." This session followed canon and merged anyway. Confirming the canon's specific carve-out is real and operational.
O — Real link-rot exists in writings/
Default-scope audit returned 3 dead-reference findings on first prod run:
writings/choosing-faith-not-fear.md:203→klappy://writings/four-questions-that-change-everything- (two more — visible in any subsequent default-scope audit call)
Phase 3 enforcement will surface these on the next PR that touches a writings file. The campaign was always "wire the gate, then fix what it surfaces" — this is the input data for the fix sweep.
Learnings
L — Validator findings split cleanly into "fix" vs "amend spec" vs "no action"
The 7-finding validator report disposed cleanly:
- F-1: real bug → fix-forward (PR #147)
- F-2, F-4, F-6: doc-debt or additive — no action
- F-3, F-5: intentional implementation drift from spec → amend spec (this PR)
- F-7: environmental — not a code defect
This is the pattern the release-validation-gate is meant to produce. Each finding gets a category, each category has a standard disposition. No finding gets ignored; no finding's disposition is left ambiguous. The review is genuinely a contract, not a ceremony.
L — Continuation Test as written-in-handoff is a strong checkpoint mechanism
The resume handoff's three-action Continuation Test (oddkit_version → GET /repos/.../pulls/146 → patch+merge or rerun) gave this session an unambiguous starting line. The handoff's failure clause ("If the next session starts re-dispatching the validator, re-deriving validator findings, or arguing about scope — the handoff failed") gave a clear failure signal. Sessions that lose state benefit enormously from explicit Continuation Tests in the prior handoff.
Constraints Held
C — Release-Validation-Gate Rules 1, 2, 3 all honored
- Rule 1: every check-run reached
completedwith acceptable conclusion (success / neutral) before merge. The one Bugbot review comment was dispositioned (waive + tracking issue) per the rule's three valid options. - Rule 2: the original PR #143 had been validated by an independent fresh-context Sonnet 4.6 agent. F-1 was fixed-forward in PR #147 before promote merged. The validator did its job — this session honored its findings rather than re-litigating them.
- Rule 3: the resume handoff explicitly noted the prior session's compaction; this session did not treat any session-scoped recommendation as overriding canon. The Bugbot finding got a canon-prescribed disposition.
HandoffWhat Remains
Item 6 from the resume handoff: Phase 3 PR-3.1
.github/workflows/canon-quality.yml on klappy/klappy.dev. Triggers on PR + push, calls oddkit_audit against prod via curl (or python -c "import urllib..." if curl fails — see the DNS observation above), sticky comment via marocchino/sticky-pull-request-comment@v2, respects vars.AUDIT_ENFORCEMENT_MODE (soft default).
Spec is at klappy://docs/oddkit/specs/oddkit-audit (v2.2 after this PR). The workflow is a separate execution beat — substantial enough to warrant its own gate transition.
Item 7: Observation cycle
3-5 PRs through the soft-block gate, observing finding rate and noise patterns. Cannot run inside a single session.
Item 8: PR-3.2 — flip enforcement to hard mode
Single-line change to vars.AUDIT_ENFORCEMENT_MODE. Trivial mechanically; gated on item 7.
Item 10 (resolved in this PR): spec amendment v2.2
This PR contains the spec amendment. After merge, F-3 and F-5 close cleanly.
Continuation Testfor the next session
If picking up Phase 3 PR-3.1:
oddkit_version— confirm prod is still0.26.0.oddkit_getonklappy://docs/oddkit/specs/oddkit-audit— confirm v2.2 amendment landed (Origin section shows v2.2 entry).GET /repos/klappy/klappy.dev/contents/.github/workflows/canon-quality.yml— confirm workflow does NOT yet exist (404 expected).- Begin PR-3.1: branch, write workflow per spec, open draft PR, smoke locally if possible, ungate.
See Also
klappy://odd/handoffs/2026-04-27-link-rot-phase-2-promote-resume— the handoff this session executedklappy://canon/constraints/release-validation-gate— Rules 1/2/3, all honoredklappy://docs/oddkit/specs/oddkit-audit— the spec, now at v2.2klappy://docs/planning/link-rot-elimination-campaign— the multi-phase campaign this PR completes Phase 2 of- klappy/oddkit#146 — the promote PR
- klappy/oddkit#147 — the F-1 fix-forward
- klappy/oddkit#148 — tracking issue for the dead
lineSeenfield