Skip to content

campaign(link-rot): Phase 1 — specs, canon principle, deferred ledger, sequencing#142

Merged
klappy merged 5 commits intomainfrom
campaign/link-rot-elimination-phase-1
Apr 26, 2026
Merged

campaign(link-rot): Phase 1 — specs, canon principle, deferred ledger, sequencing#142
klappy merged 5 commits intomainfrom
campaign/link-rot-elimination-phase-1

Conversation

@klappy
Copy link
Copy Markdown
Owner

@klappy klappy commented Apr 26, 2026

Summary

Phase 1 of the link-rot-elimination campaign. Lands the four planning/canon artifacts that scope and govern the work:

  1. docs/oddkit/specs/oddkit-resolve.mdoddkit_resolve action spec (DRAFT v4 — KISS)
  2. docs/oddkit/specs/oddkit-audit.mdoddkit_audit action spec (DRAFT v2 — KISS)
  3. canon/principles/identity-resolved-by-protocol.md — tier-1 canon principle (sibling to anti-cache-lying)
  4. docs/planning/link-rot-deferred-concerns.md — ledger of cuts and revisit conditions
  5. docs/planning/link-rot-elimination-campaign.md — campaign sequencing doc

All five docs are one coherent design. Splitting into separate PRs would create review windows where each doc references siblings that don't yet exist. Landing as a unit keeps the canon graph consistent.

Why this campaign exists

Recurring broken-link reports on klappy.dev. The April 9, 2026 reference integrity audit found 85 broken references; a 2026-04-24 scan found 11 more in writings authored just weeks earlier. Discipline alone has empirically failed.

The architectural answer

Identity references are resolved by the protocol, never authored as locations.

Authors write klappy:// URIs (identity). The protocol layer (oddkit) resolves to current location at request time, walking supersession transparently. Consumers (Lovable, claude.ai, agents, future renderers) call the resolver and render whatever it returns — never hardcode URLs in source.

This is anti-cache-lying applied to references. A hardcoded /page/some-slug is a cached projection of "this article currently lives at this URL"; supersession metadata exists but cannot help if references don't go through resolution.

Vodka discipline

The campaign was redrafted from a 6-phase / ~15-PR / four-action-with-bundled-checks shape down to a 3-phase / 8-PR / two-thin-actions shape. Cuts:

  • oddkit_resolve_batch action
  • resolve_links flag on get/search
  • aliases and supersession_response frontmatter fields
  • Identity-by-meaning queries
  • Three audit checks (terminological-drift, projection-staleness, epoch-gaps)
  • Deprecated-terms registry, epoch-completeness rules
  • audit_allow: frontmatter field
  • CI pre-commit hook

Each is captured in docs/planning/link-rot-deferred-concerns.md with an explicit revisit trigger. Use Only What Hurts.

What's NOT in this PR

  • Implementation of either action (Phase 2: separate PRs in klappy/oddkit, gated on E0008.3 release-validation-gate)
  • Writings cleanup converting /page/... and relative-path patterns to klappy:// URIs (Phase 2)
  • canon-quality.yml workflow (Phase 3)
  • Hard-block CI enforcement flip (Phase 3)

Lineage

  • Resolver spec: v1 → v2 (canon scan) → v3 (canon-tier-2 challenge) → v4 (Vodka cut)
  • Audit spec: v1 (four-check) → v2 (single-check KISS)
  • Campaign sequencing: v1 (six-phase) → v2 (three-phase KISS)

Cross-references this PR establishes

The five docs reference each other. The principle cites the resolver spec for implementation; the resolver spec cites the principle for axiom; the audit spec cites the resolver as its dependency; the campaign references all three; the deferred ledger references the campaign for context. Landing together, every cross-reference resolves on day one.


Note

Low Risk
Low risk because this PR only adds documentation/spec artifacts (no runtime code or workflow enforcement changes), though it sets contracts that later implementation PRs will need to follow.

Overview
Defines the Phase-1 foundation for eliminating link rot by standardizing on klappy:// identity references that are resolved by the protocol rather than hardcoded URLs/paths.

Adds draft specs for oddkit_resolve (supersession-aware URI→current location resolution with partial-data reporting) and oddkit_audit (CI-oriented scan that flags unresolved klappy:// URIs and legacy /page/.../relative markdown link patterns, with a line-level allowlist).

Adds planning docs that capture the campaign sequencing and a deferred-concerns ledger enumerating cut scope and explicit triggers for reintroducing it.

Reviewed by Cursor Bugbot for commit cbd06d6. Bugbot is set up for automated code reviews on this repo. Configure here.

@klappy klappy merged commit 140bd5d into main Apr 26, 2026
1 check passed
@klappy klappy deleted the campaign/link-rot-elimination-phase-1 branch April 26, 2026 03:43
klappy added a commit to klappy/oddkit that referenced this pull request Apr 26, 2026
…ssion (#140)

Phase 2 of the link-rot-elimination campaign. Implements oddkit_resolve
per klappy://docs/oddkit/specs/oddkit-resolve (DRAFT v4 — KISS) and
klappy://canon/principles/identity-resolved-by-protocol.

URI in, current canonical answer out. Walks superseded_by chains in
existing frontmatter to terminus, normalizing across three shapes used
in canon authoring (full klappy:// URI, path with .md, path without).
Backward-compatible — purely additive net-new action; existing callers
unchanged. Reads only the existing index.

Status enum: FOUND | NOT_FOUND | INVALID_INPUT | CIRCULAR_SUPERSESSION

Vodka discipline applied. v3 of the spec proposed a richer surface
(batch action, resolve_links flag, aliases field, supersession_response
field, identity-by-meaning queries). v4 cut to the minimum: one input,
one job. Cuts captured with explicit revisit triggers in
klappy://docs/planning/link-rot-deferred-concerns.

Co-authored-by: Cursor Agent <bugbot@cursor.com>

Caught in review:
- VALID_ACTIONS array missing 'resolve' (Cursor Agent fix)
- supersession_chain field-name inconsistency in error branches (Cursor Agent fix)
- state-threading parity with peer actions (Cursor Agent fix)
- mixed-shape superseded_by lookup failure (independent Sonnet 4.6
  validator fix per E0008.3 release-validation-gate)

Version bump: 0.24.0 → 0.25.0
Canon basis: klappy://canon/constraints/release-validation-gate,
klappy://canon/principles/vodka-architecture,
klappy://canon/methods/supersession
Canon PR: klappy/klappy.dev#142
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant