Repository navigation
setup: recommended linter configs for Go, Python and TypeScript - #105
Merged
Merged
Conversation
Add three core templates under setup/, rendered into every plugin:
golangci.yaml, ruff.toml and eslint.config.ldd.mjs. Each enables the
linter rules that the routing tables route to a design rule, at the
limits the rules name, and takes the file-length limit from
{{.FileMaxLines}}. Each says how to adopt it on an existing codebase:
golangci-lint's new-from-merge-base, ESLint's bulk suppressions, ruff on
changed files. The plugin never writes them into a repository.
- The gap linter's threshold line names the rule and the setup file that
would hold a file-length limit. For Python it says that ruff has no
file-length rule and the gap linter holds it; it no longer proposes
adding pylint, a tool the repository may not use.
- The ldd-lint matrix checks that the named setup file sets the rule at
the scalar's value. When golangci-lint, ruff or node is on PATH, it
also runs each tool's own check of its file.
- Fix: ldd-lint.sh did not parse under bash 3.2 (macOS /bin/bash). bash
3.2 misreads a case pattern inside a process substitution; the case
moves into a function, dir_of.
- The READMEs and docs/quick-start.md say "zero configuration to run" and
name the recommended setup.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- eslint.config.ldd.mjs: spread the fragment before the repository's own entries. Later entries win in flat config, so every limit the repository already sets stays the repository's. Before, the example put the fragment last, and it replaced those limits. - eslint.config.ldd.mjs: add the routed rules it lacked: no-magic-numbers, react/no-array-index-key, @typescript-eslint/no-unsafe-*, @typescript-eslint/no-unnecessary-condition, react-hooks/set-state-in-effect. State the type-information requirement, and why no-restricted-syntax is left out. - golangci.yaml: "default: standard" keeps golangci-lint's standard linters on; "none" turned off staticcheck, unused and ineffassign for anyone who copied the file. Note that the ratchet needs main in a CI clone. - ruff.toml: say what preview mode also turns on. - A matrix case reads each plugin's routing table and checks that the language's recommended config names every rule id routed to a design rule, except the ids the fixture row lists as left out on purpose. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
🟡 Changes recommended
Configuration thresholds and adoption behavior need correction to reliably enforce the documented design rules.
4 open issues
What changed in this PR
Adds recommended Go, Python, and TypeScript linter configurations to every generated plugin, connecting setup guidance to existing design-rule routing.
Changes:
- Adds shared configuration templates and generated copies with incremental adoption guidance.
- Updates gap-linter messages, restores Bash 3.2 compatibility, and extends configuration checks.
- Documents recommended setup across plugin READMEs and changelogs.
| File | Description |
|---|---|
| ts-react-linter-driven-development/setup/ruff.toml | Generated Ruff configuration. |
| ts-react-linter-driven-development/setup/golangci.yaml | Generated Go configuration. |
| ts-react-linter-driven-development/setup/eslint.config.ldd.mjs | Generated ESLint fragment. |
| ts-react-linter-driven-development/scripts/ldd-scope_test.sh | Adds setup fixture metadata. |
| ts-react-linter-driven-development/scripts/ldd-lint.sh | Updates guidance and Bash compatibility. |
| ts-react-linter-driven-development/scripts/ldd-lint_test.sh | Adds configuration checks. |
| ts-react-linter-driven-development/scripts/ldd-detect_test.sh | Adds setup fixture metadata. |
| ts-react-linter-driven-development/README.md | Documents ESLint adoption. |
| ts-react-linter-driven-development/CHANGELOG.md | Records setup and compatibility changes. |
| python-linter-driven-development/setup/ruff.toml | Generated Ruff configuration. |
| python-linter-driven-development/setup/golangci.yaml | Generated Go configuration. |
| python-linter-driven-development/setup/eslint.config.ldd.mjs | Generated ESLint fragment. |
| python-linter-driven-development/scripts/ldd-scope_test.sh | Adds setup fixture metadata. |
| python-linter-driven-development/scripts/ldd-lint.sh | Updates guidance and Bash compatibility. |
| python-linter-driven-development/scripts/ldd-lint_test.sh | Adds configuration checks. |
| python-linter-driven-development/scripts/ldd-detect_test.sh | Adds setup fixture metadata. |
| python-linter-driven-development/README.md | Documents Ruff setup and file-length checking. |
| python-linter-driven-development/CHANGELOG.md | Records setup and compatibility changes. |
| linter-driven-development/setup/ruff.toml | Generated Ruff configuration. |
| linter-driven-development/setup/golangci.yaml | Generated Go configuration. |
| linter-driven-development/setup/eslint.config.ldd.mjs | Generated ESLint fragment. |
| linter-driven-development/scripts/ldd-scope_test.sh | Adds setup fixture metadata. |
| linter-driven-development/scripts/ldd-lint.sh | Updates guidance and Bash compatibility. |
| linter-driven-development/scripts/ldd-lint_test.sh | Adds configuration checks. |
| linter-driven-development/scripts/ldd-detect_test.sh | Adds setup fixture metadata. |
| linter-driven-development/README.md | Introduces recommended configurations. |
| linter-driven-development/CHANGELOG.md | Records setup and compatibility changes. |
| lang/ts-react/scripts/ldd-fixture.sh | Defines TypeScript setup expectations. |
| lang/ts-react/passthrough/README.md | Source for ESLint adoption guidance. |
| lang/ts-react/passthrough/CHANGELOG.md | Source for release notes. |
| lang/python/scripts/ldd-fixture.sh | Defines Python setup expectations. |
| lang/python/passthrough/README.md | Source for Ruff setup guidance. |
| lang/python/passthrough/CHANGELOG.md | Source for release notes. |
| lang/go/scripts/ldd-fixture.sh | Defines Go setup expectations. |
| lang/go/passthrough/README.md | Source for Go setup guidance. |
| lang/go/passthrough/CHANGELOG.md | Source for release notes. |
| lang/generic/scripts/ldd-fixture.sh | Defines generic setup expectations. |
| lang/generic/passthrough/README.md | Source for configuration guidance. |
| lang/generic/passthrough/CHANGELOG.md | Source for release notes. |
| go-linter-driven-development/setup/ruff.toml | Generated Ruff configuration. |
| go-linter-driven-development/setup/golangci.yaml | Generated Go configuration. |
| go-linter-driven-development/setup/eslint.config.ldd.mjs | Generated ESLint fragment. |
| go-linter-driven-development/scripts/ldd-scope_test.sh | Adds setup fixture metadata. |
| go-linter-driven-development/scripts/ldd-lint.sh | Updates guidance and Bash compatibility. |
| go-linter-driven-development/scripts/ldd-lint_test.sh | Adds configuration checks. |
| go-linter-driven-development/scripts/ldd-detect_test.sh | Adds setup fixture metadata. |
| go-linter-driven-development/README.md | Documents optional Go setup. |
| go-linter-driven-development/CHANGELOG.md | Records setup and compatibility changes. |
| docs/quick-start.md | Introduces optional recommended configurations. |
| core/setup/ruff.toml | Shared Ruff configuration template. |
| core/setup/golangci.yaml | Shared Go configuration template. |
| core/setup/eslint.config.ldd.mjs | Shared ESLint configuration template. |
| core/scripts/ldd-lint.sh | Updates threshold messages and directory handling. |
| core/scripts/ldd-lint_test.sh | Adds routing, threshold, and tool checks. |
| core/README.md | Documents setup generation and validation. |
| core/includes/scripts/ldd-lint-langs.sh | Adds setup checks and threshold guidance. |
Review effort: Balanced
- eslint.config.ldd.mjs: sonarjs/max-lines-per-function 50 and sonarjs/nested-control-flow 2, the limits R3 names (more than 50 lines or more than 2 nesting levels). They were 200 and 4. - ruff.toml: max-nested-blocks 2, R3's nesting limit. It was 5. - ruff.toml: the changed-files command passes NUL-delimited paths and exits 0 without running ruff when no Python file changed. Before, GNU xargs ran ruff once with no paths, and ruff checked the whole repository. - The gap linter treats eslint.config.ldd.mjs at the repository root as a linter config. A repository that keeps the fragment as its own file and imports it hands file length to ESLint. Before, the gap linter still measured with its own default. A matrix case covers it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.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 free
to 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
Every plugin gets a
setup/directory with the recommended linter configuration for Go, Python and TypeScript:setup/golangci.yamlissues.new-from-merge-base: main, so only code changed since main fails; CI needs main in the clonesetup/ruff.tomlsetup/eslint.config.ldd.mjsnpx eslint --suppress-allrecords today's violations, so only new ones failEach file enables the linter rules that the plugin's routing tables route to a design rule (R1, R2, R3, R5, R8, R10, R11, R12), at the limits the rules name. For R3 those are more than 50 lines or more than 2 nesting levels. Each rule line names the design rule that its failures feed. The file-length limit comes from the
{{.FileMaxLines}}scalar, which the gap linter also uses. The plugin never writes these files into a repository. The owners copy them, or the parts they want, and limits that a repository already sets stay the repository's.Changes
core/setup/. They render into every plugin, so the generic plugin has all three for the languages it reviews. Each file has aresidue-exempt:marker because it names its linter on purpose.revive file-length-limit, as the plugin's setup/golangci.yaml sets it. For Python it says that ruff has no file-length rule and that the gap linter holds the limit. It no longer proposes adding pylint, because that would add a tool the repository may not use (house rule A1).cyclop, which is the alternative togocyclo, andno-restricted-syntax, which needs the repository's config module path. A second case checks that the named setup file sets the file-length rule at the scalar's value. Whengolangci-lint,ruffornodeis on PATH, a case also runs that tool's own check of its file. In CI none of the three is on PATH, so those cases skip.ldd-lint.shunder bash 3.2. macOS's/bin/bashstopped the merged script with a syntax error. bash 3.2 misreads acasepattern inside a process substitution, so thecasemoves into a function. The matrix now passes under bash 3.2 and bash 5.docs/quick-start.mdsay "zero configuration to run" and name the recommended setup. The Python, ts-react and generic READMEs name it too.Departures from the plan
lint-rules.yamlthrough three writers in the generator. Hand-written core templates are shorter than that, and they give the same guarantee, because the threshold is a substituted scalar and a test pins it.doctormoves to its own PR. It is the part that reads linter output, and it should be written against real output fromgolangci-lint lintersandruff check --show-settings.max-public-structsis left out. No routing-table row routes it, so the configs include only rules that already have a route.lint-corecheck. The plan put it in the generator. A shell case over the rendered routing table needed no Go code.Checks
golangci-lint config verifyacceptssetup/golangci.yaml. A run with it overtools/ldd-genworks and reports 20 errcheck and wrapcheck issues, because the repository's own exclusions are not in the recommended file.ruffrunssetup/ruff.toml. Over py-mini it reports 42 issues: 24 for PLR1702, because nesting is held at R3's limit of 2, and 18 for PLR2004.node --checkparsessetup/eslint.config.ldd.mjs. ESLint is not installed here, so ESLint itself has not loaded the fragment.task check,task lint-coreandtask docs:checkpass. Theldd-lint,ldd-detect,ldd-scopeandcheck-repo-brainmatrices pass for all four plugins.🤖 Generated with Claude Code