diff --git a/Taskfile.yaml b/Taskfile.yaml index 649a5b9d..da868ec5 100644 --- a/Taskfile.yaml +++ b/Taskfile.yaml @@ -31,7 +31,7 @@ tasks: || { echo "lint-core - the Residue section of core/README.md was rewritten; commit it"; exit 1; } test-gate: - desc: Run the fixture matrices of the generated scripts — the repo-brain gate, the review's scope bundle and its detection pass — for every plugin + desc: Run the fixture matrices of the generated scripts — the repo-brain gate, the review's scope bundle, its detection pass and the gap linter — for every plugin cmds: - bash go-linter-driven-development/scripts/check-repo-brain_test.sh - bash linter-driven-development/scripts/check-repo-brain_test.sh @@ -45,6 +45,10 @@ tasks: - bash linter-driven-development/scripts/ldd-detect_test.sh - bash python-linter-driven-development/scripts/ldd-detect_test.sh - bash ts-react-linter-driven-development/scripts/ldd-detect_test.sh + - bash go-linter-driven-development/scripts/ldd-lint_test.sh + - bash linter-driven-development/scripts/ldd-lint_test.sh + - bash python-linter-driven-development/scripts/ldd-lint_test.sh + - bash ts-react-linter-driven-development/scripts/ldd-lint_test.sh test-gen: desc: Unit tests and lint for the generator diff --git a/core/README.md b/core/README.md index 290e3633..07f0e7a4 100644 --- a/core/README.md +++ b/core/README.md @@ -31,12 +31,16 @@ Go `text/template` with the default delimiters. Core files use only two construc - `{{.Plugin}}`, `{{.Lang}}`, `{{.CmdPrefix}}`, `{{.SrcGlob}}`, `{{.TestGlob}}`, `{{.ProjectMarker}}`, `{{.Nolint}}`, `{{.CommentPrefix}}`, `{{.DefaultTest}}`, `{{.DefaultLint}}`, `{{.DefaultLintFix}}`, `{{.Nil}}`, `{{.Task}}`, `{{.DocForm}}`, - `{{.DocComment}}`, `{{.SrcExt}}`, `{{.Unexported}}` — scalars from `profile.yaml`. - The last six are single words core prose uses as common nouns (the missing value, a - unit of concurrent work, the documentation comment form, the source-file suffix, - the visibility of a non-public symbol); which sentences use them, and which Go - idioms are includes instead, is recorded in `docs/language-residue.md`. A template that names a scalar the profile does not - define fails to render. + `{{.DocComment}}`, `{{.SrcExt}}`, `{{.Unexported}}`, `{{.FileMaxLines}}`, + `{{.PackageWarnFiles}}`, `{{.PackageMaxFiles}}` — scalars from `profile.yaml`. + Six are single words core prose uses as common nouns (the missing value, a unit of + concurrent work, the documentation comment form, the source-file suffix, the + visibility of a non-public symbol); which sentences use them, and which Go idioms + are includes instead, is recorded in `docs/language-residue.md`. The last three + are the gap linter's thresholds, positive integers with the warning below the + limit, so the prose that names a limit and the script that applies it cannot + disagree. A template that names a scalar the profile does not define fails to + render. - `{{include "rules/R1/canonical-example.md"}}` — the body of that file under `lang//`, with exactly one trailing newline removed. When the binding has no file of that name, the body comes from `core/includes/` under the same path: the @@ -128,8 +132,8 @@ unchanged. Promotion into `core/` happens when a second language needs the text: own that says so and points at the repository's test utilities; the Python binding ships a short pytest catalogue in the same shape, and the ts-react binding a Vitest, React Testing Library and MSW catalogue. -- `README.md`, `CHANGELOG.md`, `.claude-plugin/plugin.json`, `hooks/`: describe or - configure the Go plugin itself. +- `README.md`, `CHANGELOG.md`, `.claude-plugin/plugin.json`: describe or configure + the Go plugin itself. Three promoted pieces carry a note here because the Go plugin renders them differently from the other bindings: @@ -173,6 +177,19 @@ differently from the other bindings: by the language of each file, a group goes to the plugin installed for its language, else to this plugin's block, else to the generic plugin, else it is excluded and every file of it named. +- `scripts/ldd-lint.sh` and `scripts/ldd-lint_test.sh`, the gap linter and its + fixture matrix, are core templates. The linter measures lines per source file and + source files per directory, where the repository's linter does not hold them. It + reads the language table and the language block, and a third include with a core + default, `scripts/ldd-lint-langs.sh`, the linter table: per language id, the + comment syntax, the files a directory count leaves out, and whether the + repository's own linter config names a file-length rule. A named rule belongs to + the linter, so the script reads no limit out of a config and copies no linter's way + of counting. The table is the one place core names linters, and its + `residue-exempt:` marker says so. The + matrix reads the binding's `scripts/ldd-fixture.sh` for the source suffix, the + comment forms, a test file's name and two linter configs per row: one that names the + file-length rule and one that names a rule of a similar name. - `scripts/check-repo-brain_test.sh` is a core template whose cases read one include, `scripts/repo-brain-fixture.sh`: the fixture rows (marker, code file, second package, sub-project) for every language the rendered gate's adapter serves. The diff --git a/core/includes/rules/R5/falsifying-questions.md b/core/includes/rules/R5/falsifying-questions.md index afb08de9..7ef697c0 100644 --- a/core/includes/rules/R5/falsifying-questions.md +++ b/core/includes/rules/R5/falsifying-questions.md @@ -13,7 +13,7 @@ The inverse shape is the god file, and it needs no feature noun: `xargs wc -l < files.txt | sort -n | tail -6` over the scope's file list names the longest files; check each against the repository's file-length limit, when its - linter sets one. + linter sets one, else {{.FileMaxLines}} code lines. Violation: the same feature living in `handlers/` and `services/` (etc.) — it is horizontally scattered; or one file over the length limit, or with a `{{.Nolint}}` directive silencing the limit, standing in for the whole slice — diff --git a/core/includes/scripts/ldd-lint-langs.sh b/core/includes/scripts/ldd-lint-langs.sh new file mode 100644 index 00000000..4a7509b8 --- /dev/null +++ b/core/includes/scripts/ldd-lint-langs.sh @@ -0,0 +1,137 @@ +# ==================== linter table ==================== +# What the gap linter needs to know per language id: how a comment is written, +# which source files a directory count leaves out, and whether the +# repository's own linter holds the file-length limit. The same table is +# rendered into every plugin, so two plugins measure one file the same way. +# residue-exempt: the table names every language's linter and config file on +# purpose, the same in every rendering. +# +# lint_comment_style c (// and /* */), d (also /+ +/) or hash (#) +# lint_strip_comments