fix(lint): burn down the kanon-lint debt baseline and delete it - #86
Merged
Conversation
Resolves every entry in .kanon-lint-baseline.toml plus the 7 unbaselined
violations kanon lint carried outside it, so the baseline (due to
hard-fail on 2026-08-13) can be deleted rather than extended.
Crate rename (NAMING/no-owner-prefix): hamma-core -> mitos. The old name
prefixed the parent fleet repo; mitos (Greek mitos, "loom-thread") keeps
the family's weaving vocabulary (hamma "knot", dictyon "net", histos
"loom") and reads as the raw material those crates knot and weave from.
Every use hamma_core:: / hamma-core path across dictyon, docs, and CI
comments moves with it; CHANGELOG.md is untouched (historical record).
File-too-long (RUST/file-too-long): wire.rs (1288 lines) splits into
wire/{mod,support,tests}.rs; config.rs and types.rs each split into
<name>/{mod,tests}.rs, moving their test modules into sibling files --
the same pattern control.rs and noise.rs already use in this crate.
Cross-module helpers land as pub(super) fns called via `support::`.
RUST/indexing-slicing: parse_server_key_response now uses
response.get(body_start..) instead of &response[body_start..].
RUST/no-silent-result-swallow: hex_encode no longer routes through
fmt::Write (whose Result on a String can never actually be Err, which is
what made `let _ =` a swallow); it writes nibbles through a checked
lookup table instead.
RUST/no-debug-derive-on-public-types (RegisterRequest, MapRequest, Node,
PeerChange): each flagged struct's only "secret-shaped" fields are public
key hex (already carrying field-level plain-string-secret ignores) or,
for RegisterRequest, the already-redacting AuthInfo::Debug the derive
calls into -- kanon:ignore with a NOTE recording why, mirroring the
existing plain-string-secret convention in this same file.
COMMENTS/deflection-without-tracking: RegisterRequest::followup's doc
reworded off the trigger phrase "Follow-up" (the field names a real
protocol continuation URL, not deferred work).
RUST/primitive-for-domain-id: Hostinfo::backend_log_id is now a
BackendLogId newtype (#[serde(transparent)]) instead of a bare String,
with every construction site (mitos, dictyon, both test suites) updated.
RUST/non-exhaustive-enum: PeerRemoval gains #[non_exhaustive]; dictyon's
one exhaustive match over it (PeerRemovalIndex::build) gets the required
wildcard arm.
RUST/config-deny-unknown-fields: DnsConfig mirrors Tailscale's wire
DNSConfig response type, not a local operator config -- denying unknown
fields would make dictyon reject a MapResponse the day a conforming
server adds a DNS field. kanon:ignore with a NOTE recording the
forward-compatibility rationale.
YAML/missing-concurrency: gate-attestation.yml deliberately carries no
concurrency block (the reusable it calls already declares one; a second
one under the same key self-cancels, per that file's own WHY comment).
Suppressed via .kanon-lint-ignore rather than "fixed" into a regression.
OIKOS/private-content: the internal kanon.lan forge hostname is redacted
to a <kanon-forge-host> placeholder across CONTRIBUTING.md (3 sites);
the one occurrence that was purely restating "the forge is unreachable"
drops the hostname entirely instead of adding a fourth placeholder.
WRITING/identity-fluff: drops "sovereign"/"sovereignty" from README.md
(thumos's description, the histos hardware-attestation phase heading and
its Phase C entry) in favor of concrete descriptions of what those
extensions do.
Refs #57Uh oh!
There was an error while loading. Please reload this page.
forkwright added a commit
that referenced
this pull request
Aug 15, 2026
… lint-debt gap (#91) ## What was wrong `kanon lint` carried one live violation on `main`: `SHELL/unpinned-action` on `.github/workflows/gate-attestation.yml:88` — the reusable-workflow call to `forkwright/.github/.github/workflows/hybrid-gate.yml` used a mutable `@main` ref instead of a pinned commit SHA. The gate fails on any warning by default, so this alone blocked `kanon gate --stamp` for every PR. ## Re-verified premise, corrected The literal 12-entry `.kanon-lint-baseline.toml` this issue was filed against (`remove_after = "2026-08-13"`) no longer exists on `main` — PR #86 (merged 2026-08-09) already resolved every one of those entries plus 7 unbaselined findings and deleted the baseline file. `kanon lint .` against a fresh `origin/main` checkout confirms this: none of the original rule families (`RUST/file-too-long`, `RUST/indexing-slicing`, `NAMING/no-owner-prefix`, `RUST/no-silent-result-swallow`, `RUST/no-debug-derive-on-public-types`, `COMMENTS/deflection-without-tracking`, `RUST/primitive-for-domain-id`, `RUST/non-exhaustive-enum`, `RUST/config-deny-unknown-fields`) fire anymore. `crates/hamma-core` is `crates/mitos` now, so the specific `NAMING/no-owner-prefix` entry this issue's follow-up note asked about is already gone with it — nothing left to carry forward in a new baseline. What #86 did *not* catch was `SHELL/unpinned-action` on the reusable-workflow call itself, which is the one violation still blocking the gate today. This PR closes that gap so #57's actual acceptance criterion — `kanon lint .` clean on main — is met, with no baseline file needed at all. ## What changed - **`SHELL/unpinned-action`:** pin `forkwright/.github/.github/workflows/hybrid-gate.yml` to its current `main` SHA (`df92942bcc41cc7ffd0339b75b2f01e52269d0ef`), matching the convention already used by `typikon` and `thumos` (SHA + a trailing `# main` comment, plus a WHY comment documenting the refresh command). - **Adjacent drift, same class:** `.kanon-lint-ignore` still carried `RUST/pub-visibility:crates/dictyon/src/control.rs` and `.../noise.rs` from before both modules split into `control/mod.rs` / `noise/mod.rs` (the same split `wire.rs` already went through, whose ignore entry is already a glob). The stale entries matched no file and silently suppressed nothing; `kanon lint` warned about both on every run. Re-globbed to match the current layout. ## Verification ``` $ kanon lint . 0 error(s), 0 warning(s), 0 info (9 suppressed) $ kanon gate --tier nobuild PASS config check PASS advisory ignore parity PASS derive check (deterministic) PASS fleet-names freshness PASS cargo fmt PASS kanon lint ok light gate passed — push to the forge for authoritative clippy + nextest + verifier ``` `--tier nobuild` is the local-verifiable slice (zero rustc invocations, per this box's compile-on-CI-only posture); `cargo build`/clippy/nextest run on this PR's GitHub Actions checks, which is what actually gates merge. No Rust source changed — YAML and `.kanon-lint-ignore` only. Closes#57 --------- Co-authored-by: forkwright <cody@forkwright.com>
forkwright added a commit
that referenced
this pull request
Aug 26, 2026
#120) ## Finding Two live docs-drift defects. `_llm/current_state.toml` hadn't been touched since 2026-05-25 (3 commits total, `git log --follow`) and still carried an unfilled `<canonical-state-doc>/STATE.md` template placeholder in `source_docs`. The same broken placeholder was copy-pasted into `_llm/architecture.toml`, `_llm/decisions.toml`, and `_llm/glossary.toml` (4 sites total, `grep -rn canonical-state-doc`). `README.md`'s Status paragraph named issue #20 ("Phase 3 audit: missing PeersChangedPatch...") as the "current audit backlog" topic set. #20 closed 2026-05-25T19:46:08Z. Of the issues open when the underlying finding was written, neither #65 nor #67 was named, and a third (#61, open since 2026-07-21) wasn't caught either — issue numbers embedded in prose go stale the moment the tracker moves, independent of whether anyone remembers to update the doc. ## Evidence - `git log -1 --format='%ci %h' -- _llm/current_state.toml` → `2026-05-25 ... 3b5b82b` while the file said `updated = "2026-05-01"`. - Since that commit: `crates/hamma-core` renamed to `crates/mitos` (#86, landed 2026-08-08 per `git log --diff-filter=A -- crates/mitos/Cargo.toml`), `crates/dictyon/src/wire.rs` split into `wire/mod.rs`, PR #58 cut the v0.2.0 changelog (2026-07-28), and 100+ PRs merged after that (`git log --oneline 3b5b82b..origin/main | wc -l`). - `grep -rn "canonical-state-doc" .` → 4 hits, all `_llm/*.toml`. - The placeholder was never a mystery token: hamma's own README auto-metadata block already resolves it — `Planning state: projects/hamma/STATE.md` — and `gh api repos/forkwright/kanon/contents/projects/hamma/STATE.md` confirms the file exists. `_llm/*.toml` now point at the same target via the full URL hamma's own `CLAUDE.md` already uses for this cross-repo link (`https://github.com/forkwright/kanon/blob/main/projects/hamma/STATE.md`). - `gh issue list --repo forkwright/hamma --state closed` → #20 closed 2026-05-25T19:46:08Z. `gh issue list --repo forkwright/hamma --state open` → #61 (2026-07-21), #65 (2026-07-21), #67 (2026-07-21), #118 (2026-08-26, opened today) — none is #20's topic set. ## Why this matters `_llm/*.toml` is the corpus other agents and tools read instead of re-deriving repo state from scratch; a doc that's been silently wrong for three months defeats that purpose worse than no doc at all, since it reads as authoritative. A broken placeholder that's been copy-pasted across four files is the same defect four times, not four defects. README's Status section is the first thing a human or agent reads; naming a closed issue as "the current backlog" points readers at the wrong problem set entirely. ## Desired correction Refresh `_llm/current_state.toml`'s `summary`, `current_phase`, `updated`, and `recent[]`/`open_threads[]` against present-day repo state; point every `<canonical-state-doc>` placeholder at the real STATE.md; stop naming specific issue numbers in README's Status prose and point at the tracker instead. **Done when:** `grep -rn "canonical-state-doc\|map deltas, zstd framing"` returns nothing, and `_llm/current_state.toml`'s `updated` field and `open_threads[]` reflect the tree at merge time. Both hold in this PR — see the diff. ## Note (out of scope, flagged for the right owner) `forkwright/kanon`'s `projects/hamma/STATE.md` — the doc `_llm/*.toml` now points at — is itself stale in a worse way than what this PR fixes: its frontmatter claims `last_updated: 2026-08-15` but its body still says `Version: v0.1.0 (unreleased)`, references `crates/hamma-core` (renamed 2026-08-08, before the claimed update date), and says "No dictyon code touched since 2026-04-13" against 100+ merged PRs. That's a `forkwright/kanon` planning-doc defect, not a `forkwright/hamma` one — this PR doesn't touch it, since kanon is a shared planning tree outside this lane's scope. Co-authored-by: forkwright <cody@forkwright.com>
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 freeto 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.
What was wrong
kanon lintcarried 18 pre-existing violations against hamma main (11 in.kanon-lint-baseline.toml, 7 unbaselined), blockingkanon gate --stamp— no PR could earn theGate-Passedtrailer required by gate-attestation. The baseline entries carryremove_after = "2026-08-13"; an expired non-empty baseline makeskanon lintreturn an error and stop linting entirely, which also blocks the gate.What changed
Resolves every entry in
.kanon-lint-baseline.tomlplus the 7 unbaselined violations, so the baseline can be deleted rather than extended:NAMING/no-owner-prefix):hamma-core→mitos. The old name prefixed the parent fleet repo;mitos(Greek mitos, "loom-thread") keeps the family's weaving vocabulary (hamma"knot",dictyon"net",histos"loom"). Everyhamma_core::/hamma-corepath acrossdictyon, docs, and CI comments moves with it;CHANGELOG.mdis untouched (historical record).RUST/file-too-long):wire.rs(1288 lines) splits intowire/{mod,support,tests}.rs;config.rsandtypes.rseach split into<name>/{mod,tests}.rs, moving their test modules into sibling files — the same patterncontrol.rsandnoise.rsalready use in this crate. Cross-module helpers land aspub(super)fns called viasupport::.RUST/indexing-slicing:parse_server_key_responsenow usesresponse.get(body_start..)instead of&response[body_start..].RUST/no-silent-result-swallow:hex_encodeno longer routes throughfmt::Write(whoseResulton aStringcan never actually beErr, which is what madelet _ =a swallow); it writes nibbles through a checked lookup table instead.RUST/no-debug-derive-on-public-types(RegisterRequest,MapRequest,Node,PeerChange): each flagged struct's only "secret-shaped" fields are public-key hex (already carrying field-levelplain-string-secretignores) or, forRegisterRequest, the already-redactingAuthInfo::Debugthe derive calls into —kanon:ignorewith a NOTE recording why, mirroring the existingplain-string-secretconvention in this same file.COMMENTS/deflection-without-tracking:RegisterRequest::followup's doc reworded off the trigger phrase "Follow-up" (the field names a real protocol continuation URL, not deferred work).RUST/primitive-for-domain-id:Hostinfo::backend_log_idis now aBackendLogIdnewtype (#[serde(transparent)]) instead of a bareString, with every construction site (mitos, dictyon, both test suites) updated.RUST/non-exhaustive-enum:PeerRemovalgains#[non_exhaustive]; dictyon's one exhaustive match over it (PeerRemovalIndex::build) gets the required wildcard arm.RUST/config-deny-unknown-fields:DnsConfigmirrors Tailscale's wireDNSConfigresponse type, not a local operator config — denying unknown fields would make dictyon reject aMapResponsethe day a conforming server adds a DNS field.kanon:ignorewith a NOTE recording the forward-compatibility rationale.YAML/missing-concurrency:gate-attestation.ymldeliberately carries no concurrency block (the reusable it calls already declares one; a second one under the same key self-cancels, per that file's own WHY comment). Suppressed via.kanon-lint-ignorerather than "fixed" into a regression.OIKOS/private-content: the internalkanon.lanforge hostname is redacted to a<kanon-forge-host>placeholder acrossCONTRIBUTING.md(3 sites); the one occurrence that was purely restating "the forge is unreachable" drops the hostname entirely instead of adding a fourth placeholder.WRITING/identity-fluff: drops "sovereign"/"sovereignty" fromREADME.md(thumos's description, the histos hardware-attestation phase heading and its Phase C entry) in favor of concrete descriptions of what those extensions do.Verification
Not restated with a
Gate-Passedtrailer on this commit; CI on this PR (fmt, check, clippy, nextest,kanon lint) is the verifier per the current op-pause convention on this repo.Refs #57