Development record
06-lint.md section 1 (the lint-code namespace) is a catalogue of a predecessor project's Python-era implementation — the `IL001`–`RC007` code families and the class names they cite (`IntentLinter`, `BundleLinter`, `PromptLinter`, `SpecLinter`) describe code this repo does not carry. Re-filed here from iss-37 (2026-08-03 maintainer disposition), which is re-scoped to its three doc-claim instances.
06-lint.md section 1 (the lint-code namespace) is a catalogue of a predecessor project's Python-era implementation — the IL001–RC007 code families and the class names they cite (IntentLinter, BundleLinter, PromptLinter, SpecLinter) describe code this repo does not carry. Re-filed here from iss-37 (2026-08-03 maintainer disposition), which is re-scoped to its three doc-claim instances.
The removal is the maintainer's decision, explicit and not open for reinterpretation by the round that implements it:
- The catalogue is removed, never archived. It documents another project's implementation, not this one, so it has no historical claim on the brief.
The replacement form is the orchestrating session's recommendation, and it stands unless the maintainer overrides it in a later trusted comment before this issue is picked up:
- The catalogue is not replaced with a Go-equivalent table. The Go lint engine has no numbered-code scheme, and minting one is taxonomy design rather than doc repair; a hand-typed catalogue would already be stale against this cycle's own rules (
record_schema,index_drift,delivery_state,context_citation_currency). - Section 1 is reworked in generic language: what the lint engine covers, stated in categories and in the present tense, pointing at the live sources of truth — the armed rules in
.abcd/record-lint.jsonand.abcd/docs-lint.json, and the engine ininternal/core/lint. Any literal enumeration of rules must be generated and gated (anindex_drift-style marked region), never hand-kept — the same discipline iss-38 and iss-42 established.
The gate cross-check detector moves here from iss-37: every named gate, lint code, Makefile target, or workflow step in the record resolves to a live definition, and a planned check is written as an intent rather than in the present tense. Its scoping is unsettled: both questions below MUST be settled in this body before any round implements the detector.
- Scan root — which trees the check reads (
.abcd/development/alone, or the repo root markdown anddocs/as well), and whether dated plans, ratified ADRs and superseded intents are in scope or exempt as chronological records. - What "a live definition" means for a prose-named gate — a Makefile target and a workflow step name resolve mechanically, but a gate named only in prose has no symbol to resolve against, so the check needs either a declared registry of gate names or a rule that confines it to citations carrying a resolvable handle.
From the 2026-08-05 maintainer disposition on iss-43, a candidate extension of the detector's scope, to be settled alongside those two questions rather than committed to here: README capability and status claims, where a claimed-shipped capability resolves to a wired verb and a phase claim resolves against the roadmap (dropped from iss-43, whose one surviving instance is doc repair).
Related fact recorded in the iss-40 decision dcn-2608020000000008: 06-lint.md's TM003–TM011 rows and the H1 schema-load row claim "Delivered" schema validation that no Go code implements. That is the same phantom-claim class and is in scope for this issue.
Frontmatter
| id | iss-181 |
|---|---|
| type | issue |
| lifecycle | resolved |
| severity | major |
.abcd/work/issues/resolved/iss-181-brief-lint-contract-python-era-catalogue.md
open on GitHub ↗ · commit history ↗
mentions10
- dcn-26080200000000082026-08-02 — iss-40: one canonical glossary, chosen as a ROUTING rule rather than a migration. `.abcd/development/brief/glossary/` keeps the name "glossary" and 04-naming.md stops claiming it; what stays behind in 04-naming.md is its ~60-row Reserved-vocabulary table, unchanged, because those rows are closed enums and spec-pinned reserved names (`dormant`, `task_classes` members, `index.json` field names) and the glossary schema's `aliases`/`forbidden_synonyms` fields mean nothing for an enum value. Folding them into term files would have invented scope and misused the schema; the defect was the false self-identification, and only that is retired. `VR001` keeps its reserved status and its two registration targets — the word "glossary" is removed from its descriptions across the brief and itd-37 so the term resolves to one place, but nothing about what the reserved lint would check is changed, since no Go code implements it. The index is made derived on the brief↔lifeboat-mapping pattern (`internal/core/glossary` renders, a test in the same package gates the committed README against it) rather than by a new schema-validation engine, which the README had been promising through a JSON-schema file and a `abcd lint terminology` verb that do not exist. Three limits are recorded rather than papered over: the drift gate checks the index against the term files, NOT each term file against the field tables, so the frontmatter shape stays a review responsibility; the banlist entry `names/record/glossary-self-identification` reaches only the docs-lint roots (`docs/`, root `README.md`), so it guards the published surface, not the brief where the retired phrase lived — adding `.abcd/development/brief` as a lint root surfaces 75 pre-existing blockers and is its own piece of work; and `05-internals/06-lint.md`'s `TM003`–`TM011`/H1 rows still claim `terminology.schema.json`-backed schema validation "Delivered" that no Go code implements — the same phantom-enforcement-claim class this change retires for the glossary README's validation section, but for TM003+ it sits outside iss-40's self-identification scope and inside iss-37 (phantom-enforcement-claims), stopped at round 13 pending maintainer disposition; left untouched here rather than pre-empting that disposition.
- dcn-26080500000000012026-08-05 — iss-37 (v0.5.0 item D): re-scoped in place per the 2026-08-03 maintainer disposition, from five instances to the three doc claims that describe the gate suite wrongly, and the fix direction is doc-side throughout because the issue's class is claims-must-match-reality and the disposition frames all three as doc claims — the Makefile and every gate's behaviour are untouched. `AGENTS.md` names the three lint gates `make preflight` runs (`lint-reviews`, `record-lint`, `docs-lint`) ahead of build/vet/test/race, and its definition of done keeps `gofmt -l .` as a requirement while attributing it to CI's own format step rather than to preflight, which does not run gofmt. The `ci.yml` record-lint comment claimed the step was "visible but non-blocking for now"; the step has no `continue-on-error` and `record-lint` exits non-zero on a blocker, so the comment described an intention the workflow had already outgrown — it now states the gate blocks and that warns surface in the log only (comment-only; no step structure touched). `README.md` and `CONTRIBUTING.md` describe the real suite, and CONTRIBUTING stops claiming preflight and CI run "the same checks" where they do not. Instance 1 of the original five (the `docs/reference/cli/README.md` freshness claim) was verified accurate in round 13 and carries no work. The brief's 06-lint.md section-1 catalogue — a predecessor project's Python-era `IL001`–`RC007` families and class names — plus the gate cross-check detector are re-filed as iss-181 rather than reworked here, because the disposition on them is substantive (remove the catalogue, never archive it; do NOT mint a Go-equivalent numbered scheme, which is taxonomy design and would ship already-stale against this cycle's own rules; rework section 1 generically over the live armed rules and `internal/core/lint`, with any literal enumeration generated and gated) and the detector's scoping — scan root, and what "a live definition" means for a prose-named gate — is unsettled and recorded as two open questions in that issue's body. iss-37 is resolved against the re-scoped body.
- dcn-26080500000000052026-08-05 — iss-43 (v0.5.0 item D): the three-claim corpus is closed as OVERTAKEN rather than fixed — the Status section and the surface list were removed by `73428b6` (2026-07-17, "manual: Revise README with new badges and project details"), a manual revision predating the v0.5.0 plan, so the Phase 0 claim and the native review oracle / spec-task engine / autonomous run claims no longer exist to correct, and re-deriving a corpus against a rewritten document would be inventing findings to justify a ticket. That attribution is itself a correction worth recording: the round first credited the iss-143 tagline commit `48a3524`, which touches ONE README line (the strapline), because it read a SHALLOW clone whose truncation window opened well after 2026-07-17 and therefore could not see the real commit — a truncated history answers a `git log` question confidently and wrongly, and the cheap guard is `git log -S` over the file for the exact removed string, unshallowed first. Two corollaries earned the same way: the corpus's third claim was never `73428b6`'s at all (`git log -S "never shipped"` puts that line in the scaffold commit and in this branch alone), so "all three overtaken" was a second wrong attribution riding on the first; and a whole-phrase probe can miss a claim that was line-wrapped in the original, which is why `"spec/task"` reproduces where `"spec/task engine"` returns nothing. One instance survives, and it is half true rather than false, which is why it needed splitting instead of deleting: the Layout line called `.abcd/` "never shipped", which holds for the released binaries alone (release.yml uploads the four of them and `checksums.txt`, nothing else) and fails everywhere else — `.claude-plugin/marketplace.json` declares `source: "./"`, so a marketplace install takes the whole repository, and GitHub attaches auto-generated source archives to each release, which carry the directory too because `.gitattributes` declares no `export-ignore`. The line now divides on the boundary that is real: every repository checkout against the released binaries, rather than a per-channel split that would have been wrong about the release page. Doc-side deliberately: the marketplace manifest schema has no per-path exclusion, so making "never shipped" true everywhere means building a curated publish path — feature work with its own design questions, not doc repair, and writing the doc to describe a packaging mechanism that does not exist is the phantom-claim failure this item belongs to. The proposed detector (README capability and status claims resolve to wired verbs and to the roadmap) is DROPPED here and re-pointed at iss-181 as a candidate extension of the gate cross-check detector's scope, recorded as a candidate rather than a commitment because it shares that detector's two unsettled scoping questions and a second half-specified scanner would answer neither. The same claim survives across the record — CONTEXT.md's sharp-edges list, AGENTS.md, both `.abcd/` READMEs, `02-constraints/01-platform.md`, `05-internals/03-configuration.md` and `phase-1-ahoy.md`, with adr-0028, the dated plans and the planned/shipped intent bodies exempt as decision and historical records — and it is recorded as iss-183 rather than fixed here, since the disposition scoped this item to one README line. That issue also corrects a claim this round made twice: the exclusion is NOT unimplemented. `internal/core/launch/bundle.go` denies the `.abcd` namespace structurally, with tests, reachable from the wired `abcd launch ship`; it is unwired, because `Ship` stops at `WouldPublish` with no network call and `release.yml` uploads the binaries without ever invoking the verb. "No mechanism exists" and "the mechanism never runs" ask for different fixes, and only the second is true.
- iss-37Phantom enforcement claims: developer docs describe gates that do not run as described. Re-scoped by the 2026-08-03 maintainer disposition to three doc-claim instances, each a claim about the local pre-push gate or CI:
- iss-38hand-maintained index drift: intents/README.md corpus listings have drifted from the filesystem; commands/README.md lists three of the seven plugin verb files; internal/README.md still describes core as two capabilities with adapter/scanner as a planned seam; the repo README Layout omits skills/ from the plugin surface. Detector (per adr-5 derive-dont-store): hand enumerations of sibling files are generated or deleted — a lint flags a README that enumerates directory contents by hand, or the enumeration is emitted by tooling with a drift test. Acceptance corpus: the four stale indexes above.
- iss-40one canonical glossary: 02-constraints/04-naming.md maintains a term registry that competes with the brief glossary/ directory; glossary/ is itself stale (contexts and terms missing from its own index, a validation command that does not exist) and is invisible to the brief — neither README.md nor 00-meta.md mention it. Detector: a single-registry rule enforced by a glossary lint — one canonical home, terms in the record resolve to it, the index derived rather than hand-kept, and a banlist entry for the retired registry location once merged. Acceptance corpus: the competing registry, the missing index entries, and the phantom validation command.
- iss-42record orientation currency: CONTEXT.md is stale on the record trust caveat — its single most important orientation fact; phase-shift updates are not a required handoff step so the staleness recurs structurally; record README routing claims point at moved locations; research/ contradicts its own naming convention. Detector: a handoff checklist rule (a phase shift or trust-caveat change requires a CONTEXT.md update in the same change) plus banlist coverage for the moved routing targets. Acceptance corpus: the four instances above.
- iss-43README capability currency. Re-scoped by the 2026-08-05 maintainer disposition to one surviving instance; the original three-claim corpus is closed as filed.
- iss-316README process section asserts two unshipped capabilities a brief-drafting skill and a Socratic interview the framework provides
- iss-2608260944055780Brief self-contradiction on abcd lint's exit grammar: 05-internals/06-lint.md:174 states "Exit code follows the standalone grammar (blocker -> 1, warn -> 2, clean -> 0)", which inverts the two non-zero codes. internal/core/repolint/repolint.go:147 exitCode() returns 2 on any blocker, 1 on warnings only, 0 clean, and its own comment names the Conftest tri-state; 04-surfaces/16-lint.md:41 agrees with the code. Observed: this tree at 19 errors and 3 warnings exits 2. The consequence is worse than count drift, because an exit code is a number a CI job branches on: a job written against 06-lint.md would treat 1 as its failure condition and pass green on a tree full of blockers, a gate that runs and never fires. Same class as iss-142 (the iss-37 phantom-enforcement class) and the same file, different line; iss-181 and iss-251 also sit on this file and cover neither. Brief-tier, so under adr-28 it ships in no release artefact and reaches no installed surface, which is the standing disposition for brief drift and the argument for a lower severity. Refines iss-2608261029074763, which records the wider defect this is one symptom of: 06-lint.md section 3 documents an architecture that was never built, verified as internal/core/lint having no package main so the documented invocation cannot run, --codes-filter, --promote-check, --touched-line and --display-path having zero hits across internal/ and cmd/, no .pre-commit-config.yaml, and IntentLinter, _classify_and_filter, _parse_hunk_lines and _detect_location present in no source file. That record cites this one for the exit grammar rather than restating it. Adjacent and distinct: iss-2608231000561060 covers the gates-CI claim and gate-readiness. Detector: enforcement-claims-are-facts sweep over the brief's exit-code and gating claims. Acceptance corpus: the three lines above.