Roadmap
This roadmap is scope-based; dates are deliberately omitted. Each version is a closed cut — work that doesn’t fit moves to a later version. See ARCHITECTURE.md for the design these phases build out.
Latest release: v0.9.20 (2026-05-10). Cross-command
output-polish capstone for the v0.9 cut: width-aware human
output across every alint command (check / fix / list /
explain / facts / suggest), --no-docs and --width N
honored uniformly, bundled-rule message audit, em-dash scrub on
first-impression marketing surfaces, install-snippet pin sweep
(curl + bash now leads everywhere), polyglot demo rebuilt with
5 auto-fixable seeds. See CHANGELOG.md for
v0.9.12 - v0.9.20 details and
docs/development/launch-evidence.md
for the case-study corpus + rule-kind demand aggregation.
Launch readiness: clean. Pre-flight gates wired:
cargo fmt --check + clippy + test + docs + version-pin
consistency + dogfood, all bundled into
ci/scripts/preflight.sh and gated by an opt-in pre-push hook
(ci/githooks/pre-push). The install-snippets-match-workspace -version rule in the dogfood .alint.yml flags drift between
Cargo.toml’s workspace version and any user-facing install
snippet, so a release with stale v0.9.X README/Docker/GHA pins
fails CI before it ships. v0.9.20 is the version we expect to
launch on.
v0.9 cut closed (2026-05-02). A scaling-profile
investigation surfaced a +28-37% 1M S3 regression vs
v0.5.6 — for_each_dir cross-file dispatch was running
nested rules in O(D × N) shape (5 B glob-match operations
at 1M with 5,000 packages). The fix landed on main as
v0.9.5 (lazy path-index on FileIndex + literal-path fast
paths in file_exists, structured_path,
iter.has_file); 1M S3 wall: 731.9 s → 11.19 s (65×) full,
6.73 s (108×) changed. v0.9.5 also folded in the
test/coverage/dogfood floor that prevents the same class of
regression from slipping by again:
- v0.9.5.5 — cross-file dispatch fast paths (the headline)
- v0.9.5.6 — coverage audits (pass/fail symmetry, bundled- ruleset coverage, git-mode symmetry)
- v0.9.5.7 — 16 coverage scenarios filling the audit punch list
- v0.9.5.8 — bench-scale S6 (per-file content fan-out) / S7 (cross-file relational) / S8 (git-tracked overlay)
- v0.9.5.9 —
docs/development/rule-authoring.mdworkflow doc - v0.9.5.reorg —
docs/benchmarks/{micro,macro,investigations,archive}/layout + per-version results +xtask publish-benches
Full v0.9.5 design: docs/design/v0.9/coverage-and-dogfood.md.
v0.9.6 (2026-05-02) — scope_filter: primitive. Closest-
ancestor manifest scoping for per-file rules, plus the
bundled-ecosystem-ruleset migration that motivated it. The
is_* ecosystem facts (is_rust, is_node, …) renamed to
has_* and broadened from root-only [Cargo.toml] to
[Cargo.toml, "**/Cargo.toml"] so polyglot monorepos with
no root manifest correctly fire the ruleset; per-file content
rules add scope_filter: { has_ancestor: <manifest> } so
they only fire on files inside their ecosystem’s package
subtree. New bench-scale S9 scenario (nested polyglot:
rust + node + python over crates/ + packages/ + apps/)
captures the dispatch shape this primitive was designed for.
Full design: docs/design/v0.9/scope-filter.md.
Forward plan, ordered by user-facing payoff. The next two
versions split what was originally one v0.10 release into two
focused cuts. Rule-kind coverage ships first because the
case-study aggregation (30 repos under
docs/development/launch-evidence.md)
identified 8 primitives with 5-13 demand sources each. LSP +
editor integration is the second cut because no user is blocked
on it for adoption — they can lint without it.
-
v0.10 — Case-study coverage push. 8 case-study-validated rule kinds + 2 bundled rulesets. Closes the gap that today requires
command:shell-out for what should be declarative rules. Sized 2-4 weeks. Headline primitives:cross_file_value_equals(12 sources),registry_paths_resolve(13 sources),ordered_block(8),generated_file_fresh(8),import_gate(5),command_idempotent(5),pair_hash(3),xml_path_matches+xml_path_equals(2 — completes the structured-query family). Bundled rulesets:apache/governance@v1(3 Apache TLPs converge),dotnet@v1(Microsoft / Azure SDK adopter surface). Design candidates land opportunistically as a second demand source materialises. -
v0.11 — LSP + developer experience. LSP server, VS Code extension, ScopeFilter generalisation (
has_sibling,has_descendant), single-file re-eval hot path, and the v0.11+ ship-targets that didn’t make v0.10:cross_language_implementation_complete(5 sources: arrow, tensorflow, protobuf, angular, flutter), Bazel-licensing-declaration-aware rule kind (tensorflow’slicenses(["notice"])discipline),walk_error_policy:engine knob (pnpm broken-symlink fixtures). LSP design +tower-lspworkspace dep already landed in v0.9.7 so the crate scaffold is the only structural lift. -
v0.12 — WASM plugins. Per the existing v0.11 scope, bumped one slot.
wasmtimehost, signed plugin registry, blessed examples (mock-ratio checker, near-dup detector, debug-statement stripper). -
v1.0 — Stability. DSL committed, plugin ABI committed,
alint-corepublic API frozen, docs site committed.
Single-source design candidates that surfaced in the
case-study aggregation but haven’t hit a second demand source:
*_path_contains, pair_inverse, command_per_repo,
json_schema_passes config-shape mode, *_path_array_iter,
json_key_sort_order, column_alignment, line_spacing,
not_executable, directory_hash. Most won’t survive
demand-validation; they’re tracked under “Emerging gaps” in
examples/README.md
so post-launch users can vote with their adoption.
Positioning
Section titled “Positioning”alint’s scope is the filesystem shape and contents of a
repository, not the semantics of the code inside it. Sweet
spot: workspace-tier monorepos (Cargo, pnpm, yarn, Lerna) and
OSS-style polyglot monorepos. Honest limits: dependency-graph
problems (cargo deny, bazel mod, buildifier) and
code-content problems (linters, SAST) are explicit non-goals;
hyperscale Bazel monorepos are not the design center —
some primitives (notably for_each_dir) need a per-iteration
when: filter to apply there cleanly, addressed in the v0.5
Monorepo & scale subsection below.
The adoption ladder this design points toward:
one-line bundled start → ecosystem overlay (rust@v1 /
node@v1 / python@v1 / go@v1 / java@v1) → CI hardening
(ci/github-actions@v1) → field-level overrides → custom
structured-query rules → pre-commit + GHA wiring →
git_tracked_only for absence rules → nested_configs: true.
v0.5 prioritizes the next rung: tighter monorepo ergonomics
for workspace-tier and OSS-polyglot adopters.
v0.1 — MVP (shipped)
Section titled “v0.1 — MVP (shipped)”The smallest scope that is usefully adoptable.
- ✅ Walker (honors
.gitignore), config loader (YAML + JSON Schema validation), globset-based scopes. - ✅ Rule primitives:
file_exists,file_absent,dir_exists,dir_absent,file_content_matches,file_content_forbidden,file_header,filename_case,filename_regex,file_max_size,file_is_text. - ✅ Output formats:
human,json. - ✅ CLI subcommands:
check,list,explain. - ✅ JSON Schema published for editor autocomplete (
schemas/v1/config.json). - ✅ Benchmarks published with the release — criterion micro-benches under
crates/alint-bench/and hyperfine macro-benches viaxtask bench-release. Methodology atdocs/benchmarks/METHODOLOGY.md; per-platform results underdocs/benchmarks/archive/v0.1/. - ✅ Static binaries on GitHub Releases, install script,
cargo install alint— release workflow at.github/workflows/release.yml, installer atinstall.sh. - ✅ Pre-publish hygiene: binary package renamed
alint-cli→alint; internal crates flaggedpublish = false(onlyalint+alint-corepublish); crates.io metadata populated on the public crates;LICENSE-APACHE+LICENSE-MIT+ rootREADME.mdadded. - ✅ Dogfood
.alint.ymlexercising the tool against its own repo.
v0.2 — Cross-file and composition (shipped)
Section titled “v0.2 — Cross-file and composition (shipped)”- Cross-file primitives: ✅
pair, ✅for_each_dir, ✅for_each_file, ✅every_matching_has, ✅dir_contains, ✅dir_only_contains, ✅unique_by. (complete) - Facts system: ✅
any_file_exists, ✅all_files_exist, ✅count_files, ✅file_content_matches, ✅git_branch, ✅custom(security-gated; only allowed in the top-level config, never inextends:); ⏳detect: linguist, ⏳detect: askalono— both likely v0.5 alongside bundled rulesets. - ✅
whenexpression language — bounded grammar withand/or/not, comparison ops (==!=<<=>>=),in(list/substring),matches(regex), literal types (bool/int/string/list/null), andfacts.X/vars.Xidentifiers. Parsed at rule-build time; gates rules in Engine + nested rules infor_each_*. - ✅
extends: local files (recursive resolution, cycle detection, child-overrides-parent merge) + HTTPS URLs with SHA-256 SRI and caching under the platform user cache dir (~/.cache/alint/rulesets/on Linux). Nested remote extends deferred to v0.3 — a relative path inside a fetched config has no principled base. - ✅
fixsubcommand withfile_create,file_remove,file_prepend,file_append,file_rename(the latter wired tofilename_case— target name derived from the rule’scase:setting; extension preserved).- Deferred for later (likely v0.5 when bundled rulesets land):
content_from: <path>forfile_create/file_prepend/file_append, so long bodies (LICENSE texts, standard boilerplate) can live alongside the rule rather than inline in YAML. - Deferred (likely v0.3): a
rename_to:template forfilename_regex, so the pattern’s capture groups can drive a substitution target. Not yet designed.
- Deferred for later (likely v0.5 when bundled rulesets land):
- ✅ Output formats:
sarif,github. - ✅ Official GitHub Action (
action.ymlat repo root; composite action wrappinginstall.sh).
v0.3 — Hygiene, portable metadata, byte fingerprints (shipped)
Section titled “v0.3 — Hygiene, portable metadata, byte fingerprints (shipped)”The v0.3 cut shifted scope mid-cycle. The originally-planned “structured content” family (JSON/YAML/TOML path queries) was rolled over to v0.4; the freed capacity was spent on content and metadata rules that surfaced during dogfooding as common pain points in real repos.
- ✅ Text hygiene:
no_trailing_whitespace,final_newline,line_endings,line_max_width,indent_style,max_consecutive_blank_lines(+file_collapse_blank_linesfix op). - ✅ Security / Unicode sanity:
no_merge_conflict_markers,no_bidi_controls,no_zero_width_chars(+file_strip_bidi/file_strip_zero_widthfix ops). - ✅ Encoding + content fingerprint:
no_bom(+file_strip_bom),file_is_ascii,file_hash. - ✅ Structure:
max_directory_depth,max_files_per_directory,no_empty_files. - ✅ Portable metadata:
no_case_conflicts,no_illegal_windows_names. - ✅ Unix metadata:
no_symlinks,executable_bit,executable_has_shebang,shebang_has_executable. - ✅ Git hygiene:
no_submodules. - ✅ Byte-level fingerprint:
file_starts_with,file_ends_with. - ✅ Auto-fix ops added:
file_trim_trailing_whitespace,file_append_final_newline,file_normalize_line_endings,file_strip_bidi,file_strip_zero_width,file_strip_bom,file_collapse_blank_lines. - ✅
fix_size_limittop-level config knob (default 1 MiB;nulldisables) — content-editing fixers skip oversize files with a stderr warning rather than rewrite them. - ✅ Short-name rule aliases (
content_matches,content_forbidden,header,max_size,is_text) for rules without adir_*sibling.
Deferred to v0.4: structured-query primitives (json_path_*, yaml_path_*, toml_path_*, json_schema_passes), file_footer, file_max_lines, file_shebang, opt-in nested .alint.yml discovery for monorepos, markdown / junit / gitlab output formats, alint facts subcommand for debugging when clauses.
v0.4 — Bundled rulesets + pre-commit (shipped)
Section titled “v0.4 — Bundled rulesets + pre-commit (shipped)”Pulled forward from what was v0.5: bundled rulesets are the
single biggest adoption lever, turning “write 20 rules” into
“add one extends: line.” Also lands pre-commit framework
integration so any pre-commit user adopts alint with 4 lines of
YAML.
- ✅
.pre-commit-hooks.yaml— exposesalint(check) andalint-fix(manual-stage) hooks.language: rustmeans zero setup for pre-commit users. - ✅ Bundled rulesets infra:
alint://bundled/<name>@<rev>URI scheme resolved offline viainclude_str!. Cycle-safe, leaf-only (bundled rulesets cannot themselvesextends:). Inherits the samecustom:-fact guard as HTTPS extends. - ✅
alint://bundled/oss-baseline@v1— 9 rules. Community docs + content hygiene most OSS repos want. - ✅
alint://bundled/rust@v1— 10 rules. Gatedwhen: facts.has_rustso it’s a safe no-op in polyglot trees. - ✅
alint://bundled/node@v1— 8 rules. Gatedwhen: facts.has_node. - ✅
alint://bundled/monorepo@v1— 4 rules. Language-agnosticfor_each_dirover{packages,crates,apps,services}/*.
v0.4.x point releases (shipped)
Section titled “v0.4.x point releases (shipped)”Ten point releases shipped after v0.4.0, expanding scope well past the original cut. Most of what was originally planned for v0.5 landed here.
- v0.4.1 — packaging fix.
- v0.4.2 — pretty
humanformatter overhaul. - v0.4.3 — composition: field-level rule override; nested
.alint.ymldiscovery for monorepos (nested_configs: true). Four bundled rulesets:hygiene/no-tracked-artifacts@v1,hygiene/lockfiles@v1,tooling/editorconfig@v1,docs/adr@v1. - v0.4.4 —
file_min_size+file_min_linescontent rules; six structured-query rule kinds ({json,yaml,toml}_path_{equals,matches}). README rewritten as a 12-pattern cookbook. - v0.4.5 —
alint://bundled/ci/github-actions@v1;if_present: trueon structured-query rules; selective bundled adoption (only:/except:onextends:entries). - v0.4.6 —
alint://bundled/python@v1+alint://bundled/go@v1;alint factssubcommand for debuggingwhen:clauses. - v0.4.7 — distroless Docker image (
ghcr.io/asamarts/alint)- Homebrew tap (
asamarts/alint).
- Homebrew tap (
- v0.4.8 —
git_tracked_only: bool— first git-aware rule primitive. Closes the absence-rule false-positive on locally built artifacts. - v0.4.9 —
alint://bundled/java@v1. First bundled use ofgit_tracked_only. - v0.4.10 —
file_max_lines+file_footer+file_shebanground out the content family. Catalogue at ~55 rule kinds.
v0.5 — Monorepo scale + plugins v1 + remaining distribution
Section titled “v0.5 — Monorepo scale + plugins v1 + remaining distribution”The v0.4.x cuts cleared most of the original v0.5 scope (structured-query, ecosystem rulesets, alint facts, Docker, Homebrew, first git-aware primitive). What remains, plus new monorepo-scale work surfaced by the 2026-04 monorepo positioning analysis.
Composition & reuse
Section titled “Composition & reuse”A coherent sub-theme on making .alint.yml shareable,
overridable, and monorepo-friendly. Ranked by leverage ÷ effort.
- ✅ Field-level rule override. Children in the
extends:chain can specify only the fields they change (rules: - {id: X, level: off}); kind/paths/etc inherit from the earliest ancestor that declares them. Shipped 2026-04-22 (commit261dda5). - ✅ Refreshed
extends:schema docs. Mention SRI syntax,alint://bundled/URLs, merge semantics, and thelevel: offdisable idiom. Shipped 2026-04-22 (commit261dda5). - ✅ Nested
.alint.ymldiscovery for monorepos. Opt-in vianested_configs: trueon the root config. Each nested rule’s path-like scope fields (paths,select,primary) auto-prefix with the config’s relative directory. Cross- subtree id collisions are rejected for MVP. Shipped 2026-04-22. - ✅ Rule templates / parameterized rules — shipped in
v0.5.10 (2026-04-27). New top-level
templates:block defines reusable rule bodies; rules instantiate them viaextends_template: <id>and avars:map for the{{vars.<name>}}substitution. Templates merge through theextends:chain by id. Leaf-only — a template can’t itself reference another, mirroring the bundled-rulesets restriction. - ✅ Selective bundled adoption. Mapping form on
extends:entries withonly: [...](keep listed rules) orexcept: [...](drop listed rules); mutually exclusive; unknown ids error at load. Closes the all-or-nothing limitation. Shipped 2026-04-23 in v0.4.5. - ✅
.alint.d/*.ymldrop-ins — shipped in v0.5.10 (2026-04-27). Auto-discovered next to the top-level.alint.ymland merged alphabetically; the last drop-in wins on field-level conflict (/etc/*.d/shape). Trust-equivalent to the main config — drop-ins live in the same workspace and CAN declarecustom:facts andkind: commandrules. Non-yaml files in the dir are skipped silently. Sub-extended configs don’t get their own.alint.d/; only the top-level config does.
Monorepo & scale
Section titled “Monorepo & scale”Identified by the 2026-04 monorepo positioning analysis as the largest delta between alint’s current shape and what workspace-tier + OSS-polyglot monorepos typically reach for. Ranked by leverage.
- ✅
alint check --changed [--base=<ref>]. Incremental mode: diffgit diff --name-only <base>...HEAD(orgit ls-files --modified --others --exclude-standardwhen no base) and only evaluate rules whose path scopes intersect the changed-file set. Cross-file rules (pair,for_each_dir,every_matching_has,unique_by,dir_contains,dir_only_contains) and existence rules (file_exists,file_absent,dir_exists,dir_absent) opt out of the changed-set filter for iteration — their verdicts span the whole tree by definition — but existence rules still skip when theirpaths:scope doesn’t intersect the diff, so an unchanged-but-missing LICENSE doesn’t fire on every PR. Empty diffs short-circuit to an empty report. Pairs naturally withgit_tracked_only. Shipped in v0.5.0. - ✅ Per-iteration
when_iter:filter onfor_each_dir/for_each_file/every_matching_has— shipped in v0.5.2 (2026-04-26). Newiter.*namespace in the existingwhen:grammar exposes the iterated entry’spath,basename,parent_name,stem,ext,is_dir, andhas_file(pattern); iterations whose verdict is false are skipped before any nested rule is built.iter.has_file("Cargo.toml")/iter.has_file("**/*.bzl")/iter.has_file("BUILD") or iter.has_file("BUILD.bazel")cover the Cargo / Bazel-style workspace gates without a language-specific parser. - ✅
alint init [--monorepo]discovery preset — shipped in v0.5.4 (2026-04-26). Newalint initsubcommand detects ecosystem (Rust / Node / Python / Go / Java) from root manifests and writes a.alint.ymlextending the matching bundled rulesets. With--monorepo, also detects Cargo[workspace], pnpm-workspace.yaml, andpackage.jsonworkspacesfield, and emitsmonorepo@v1+monorepo/<flavor>-workspace@v1plusnested_configs: true. Bazel / Lerna / Nx / Turbo detection deferred (the three covered flavours match the bundled-overlay set). The runtime-side--monorepoflag onalint checkis deferred too —alint initis the primary adoption shape. - ✅ Workspace-aware bundled rulesets — shipped in
v0.5.3 (2026-04-26). Three thin overlays on
monorepo@v1:monorepo/cargo-workspace@v1,monorepo/pnpm-workspace@v1,monorepo/yarn-workspace@v1. Each gated by anis_*_workspacefact (declared inline in the ruleset) and useswhen_iter: 'iter.has_file(...)'to scope per-member checks to actual package directories — no false positives on straycrates/notes/orpackages/drafts/. - ✅ Documented scale ceiling — shipped in v0.5.6
(2026-04-26) as
xtask bench-scale. Publishes hyperfine timings across (size × scenario × mode) matrix with hardware fingerprint; numbers underdocs/benchmarks/macro/results/linux-x86_64/v0.5.7/. 1M-file size opt-in via--include-1m. - ✅ Competitive comparisons — shipped in v0.5.7
(2026-04-26). Same harness now drives ls-lint,
Repolinter, and
find+ripgreppipelines alongside alint, gated to the scenarios each tool can sanely express. Reproducibility via theghcr.io/asamarts/alint-benchDocker image (pinned versions of every competitor) plus a--dockerflag that re-execs the bench inside the image.
Other scope
Section titled “Other scope”- ✅ Structured-query primitives (v0.4.4, 2026-04-23):
json_path_equals,json_path_matches,yaml_path_equals,yaml_path_matches,toml_path_equals,toml_path_matches. JSONPath per RFC 9535; YAML and TOML coerce through serde into the same tree shape.json_schema_passesstill ⏳. - ✅
if_present: trueon structured-query rules (v0.4.5). - ✅ Additional content primitives (v0.4.10):
file_footer,file_max_lines,file_shebang. - ✅
alint factssubcommand (v0.4.6). - ✅ Homebrew formula via
asamarts/alinttap (v0.4.7). - ✅ Distroless Docker image at
ghcr.io/asamarts/alint(v0.4.7). - ✅ Git-aware primitive:
git_tracked_only(v0.4.8). - ✅ Additional bundled rulesets:
python(v0.4.6),go(v0.4.6),ci/github-actions(v0.4.5),java(v0.4.9). - ✅ Output formats:
markdown,junit,gitlab— shipped in v0.5.8 (2026-04-26). Brings the format count to seven; SARIF / GitHub /JUnit/ GitLab fall through to the human formatter onalint fixsince they describe findings, not remediations. - ✅
commandplugin kind (v0.5.1, 2026-04-26). Per-file rule wrapping any CLI onPATH(actionlint/shellcheck/taplo/kubeconform/ etc.); exit0= pass, non-zero = violation carrying stdout+stderr. Trust-gated: only the user’s own top-level config can declare these (mirror of thecustom:fact gate). Pairs naturally with--changedso external checks become incremental in CI. - ✅ npm shim (
@alint/alint) — shipped in v0.5.11 (2026-04-27). Closes the install-path gap for JS adopters who don’t already have Cargo, Homebrew, or Docker. Wraps a download of the matching pre-built binary at install time; package itself ships zero JS runtime behaviour. Auto-published fromrelease.ymlalongside crates.io / Docker / Homebrew. - ✅ Git-aware primitives:
git_no_denied_paths,git_commit_message— both shipped in v0.5.9 (2026-04-27). The first fires on tracked paths matching a glob denylist (secrets / artefacts / “do not commit”); the second validates HEAD’s commit message shape via regex / max-subject-length / requires-body. Both no-op silently outside a git repo. - ✅
json_schema_passesprimitive — shipped in v0.5.9 (2026-04-27). Validates JSON / YAML / TOML targets against a JSON Schema; reuses the same serde-tree normalisation asjson_path_*. Schema is loaded + compiled lazily and cached on the rule viaOnceLock. - ✅ Remaining bundled rulesets:
compliance/reuse@v1+compliance/apache-2@v1shipped in v0.5.5 (2026-04-26). Both usefile_headerfor SPDX / Apache header checks; reuse adds adir_existsonLICENSES/; apache-2 addsfile_content_matchesfor the LICENSE text +file_existsfor NOTICE. Both extend without a fact gate — adopting the ruleset signals intent. - ✅ Additional Scorecard-overlap rules in
oss-baseline@v1— shipped in v0.5.9 (2026-04-27). Four new rules: SECURITY.md non-empty, Dependency-Update-Tool (Dependabot OR Renovate), CODEOWNERS exists, CODEOWNERS non-empty. Branch-protection state is GitHub-API-only and out of scope; the on-disk piece (CODEOWNERS) is what alint can see.ci/github-actions@v1is unchanged — its scope is workflow content, not on-disk artefacts; CODEOWNERS belongs in oss-baseline.
Generic hygiene rulesets (shipped in v0.4.3)
Section titled “Generic hygiene rulesets (shipped in v0.4.3)”Identified in a research pass across Turborepo/Nx/Bazel/Cargo/ pnpm docs, OpenSSF Scorecard, Repolinter’s archived corpus, and large orgs’ community-health-file conventions. Four rulesets built on the existing primitive set — no new rule kinds needed.
- ✅
hygiene/no-tracked-artifacts@v1— node_modules, target, dist, .next, .DS_Store, editor backups, .env variants, 10 MiB size gate. Several auto-fixable. - ✅
hygiene/lockfiles@v1— one rule per package manager (npm/pnpm/yarn/bun/Cargo/Poetry/uv) forbidding nested lockfiles. - ✅
tooling/editorconfig@v1—.editorconfig+.gitattributesexistence with atext=normalization directive. - ✅
docs/adr@v1— MADR naming pattern + required## Status,## Context,## Decisionsections. Gap-free numbering deferred (needsnumeric_sequenceprimitive).
v0.6 — Agent-era bundled rulesets and output
Section titled “v0.6 — Agent-era bundled rulesets and output”Two bundled rulesets aimed at the most common AI-coding
leftovers, plus a new output format for agents consuming alint
inside their own self-correction loops. All work composes from
existing rule kinds — no engine changes, no new primitives —
matching the same shape as the language-ecosystem rulesets
(python@v1, go@v1, ci/github-actions@v1, …) shipped in
earlier cuts. The agent-driven-development moment makes
alint’s existing niche especially valuable; v0.6 ships
ecosystem-specific bundled rulesets to capitalise on that
without changing the underlying tool.
- ✅
alint://bundled/agent-hygiene@v1— backup-suffix bans (*.bak,*.orig,*~,*.swp), versioned-duplicate filename guards (*_v2.ts,*_old.py), scratch-doc bans at root (PLAN.md,NOTES.md,ANALYSIS.md, …),.env-file bans, AI-affirmation regex ("You're absolutely right", emoji watermarks), debug-residue bans (console.log,debugger,breakpoint()), and model-attributed TODO bans (TODO(claude:),TODO(cursor:), …). All composable fromfile_absent/filename_regex/file_content_forbidden. - ✅
alint://bundled/agent-context@v1— hygiene rules forAGENTS.md/CLAUDE.md/.cursorrules: existence recommended, stub guard viafile_min_lines, bloat guard viafile_max_lines(per Augment Code research, context files >300 lines correlate with worse agent performance), stale-path heuristic via regex. Subsumes ctxlint’s niche with no new rule kinds. - ✅
--format=agentJSON output — sibling of--format=jsonshaped for LLM consumption. Each violation carries anagent_instructionfield templated from the rule’smessage+fixblock: a remediation phrasing optimised for an agent to act on, not for a human to read. Closes the “agents already consume our JSON, but the SARIF shape is awkward in their context” feedback gap.
Out-of-scope for v0.6 (deliberately): new rule kinds, semantic analysis, secret-entropy scanning, AGENTS.md export. All of those land in v0.7 or later.
v0.7 — New rule kinds for agentic problems (shipped)
Section titled “v0.7 — New rule kinds for agentic problems (shipped)”Targeted rule-kind additions that close the gaps Tier-1 exposed. Each got a short design doc before implementation because heuristic detection has a real false-positive surface that bundled rulesets don’t.
Per-feature design drafts live under
docs/design/v0.7/ — each settled schema,
semantics, false-positive surface, implementation notes, and
open questions before code started, then was flipped to
Status: Implemented on the matching feature commit.
- ✅
markdown_paths_resolverule kind (v0.7.1) — validates that backticked paths in markdown files resolve to real files. Targets the AGENTS.md staleness problem more precisely than the v0.6 regex heuristic. Requiredprefixes:field eliminates the “is this a path or a word” question by construction. - ✅
commented_out_coderule kind (v0.7.2) — heuristic detector for blocks of commented-out source code, scored on punctuation density rather than identifier-token density (English prose has identifier-shaped words too). Severity floorwarning— heuristics have non-zero FP rate. - ✅
git_blame_agerule kind (v0.7.3) — fire on lines matching a regex whosegit blameauthor-time exceedsmax_age_days. Closes the gap betweenlevel: warningon every TODO (too noisy) andlevel: off(accepts unbounded debt accumulation). Engine plumbing introduces a sharedBlameCacheand the{{ctx.match}}message placeholder. - ✅
alint suggestsubcommand (v0.7.4) — scans the current repo for known antipatterns and proposes rules that would catch them. Three suggester families ship: bundled-ruleset (high confidence), antipattern (medium — agent-hygiene leftovers), stale-TODO (medium — eats the v0.7.3 dogfood). Three output formats (human / yaml / json) and a strict stdout-vs-stderr split for slow operations:--progress=auto|always|nevercontrols animated bars on stderr,-q/--quietsilences both. - ✅
alint export-agents-mdsubcommand (v0.7.5) — renders the active rule set as anAGENTS.mddirective block. Inline mode splices between<!-- alint:start -->/<!-- alint:end -->markers; re-runs are byte-identical (no mtime bump on round-trip). Closes the “67% of teams maintain duplicate configs between AGENTS.md and CI lint” gap by making alint the single source of truth.
v0.8 — Comprehensive test + bench foundation (shipped)
Section titled “v0.8 — Comprehensive test + bench foundation (shipped)”Five sub-phases (v0.8.2 → v0.8.5) building the
test/bench/rot-prevention foundation that engine
optimization (now v0.9) needs to land safely. Scope agreed
2026-04-28 after a four-agent coverage audit; phases
merged to main 2026-04-28 / 2026-04-29 with full CI
(Linux self-hosted + Coverage 90.57% + Cross-Platform
macOS/Windows + Mutants nightly) green throughout.
v0.8.2 — Rule-kind coverage uplift
Section titled “v0.8.2 — Rule-kind coverage uplift”Goal: every rule kind has ≥5 unit tests + ≥2 e2e (pass +
fail). Pre-v0.8.2: 34 of 54 rule kinds had 0 unit tests; 4
had 0 e2e (json_schema_passes, git_no_denied_paths,
git_commit_message, command); 3 had only pass-variant
e2e (no_symlinks, executable_bit,
executable_has_shebang).
- ✅ ~155 new unit tests across the 34 under-covered rule kinds (build / options / evaluate fires / evaluate silent / edge cases — the standard quintet).
- ✅ Fail-variant e2e for the 3 pass-only unix-metadata rules.
- ✅ E2E for the 4 zero-e2e rules.
- ✅ Integration tests (under
crates/alint-rules/tests/) for the shell-out rules —git_no_denied_paths,git_commit_message,command(mirrors the v0.7.3git_blame_ageintegration-test pattern).
v0.8.2 — Infrastructure-crate coverage
Section titled “v0.8.2 — Infrastructure-crate coverage”alint-core’s engine.rs, walker.rs, registry.rs,
report.rs, error.rs, level.rs, scope.rs,
config.rs, rule.rs all had 0 unit tests pre-v0.8.2.
The most important crate had the worst coverage of its own
internals.
- ✅ Unit tests for
walker::walk,Registry::build,Reportaggregation,Scope::matchesedge cases,Engine::run(changed-mode path-scope intersection, fact-eval failure paths),BlameCachethread-safety under contention.config.rsandrule.rscovered during v0.8 housekeeping (2026-04-29). - ✅ alint-dsl edges: extends-chain cycle detection,
diamond inheritance,
extends:filter validation (only:/except:), nested-config path-prefix rewriting,.alint.d/merge order determinism, HTTPS timeout / size-cap enforcement, SRI algorithm-mismatch errors, template-instantiation edge cases. - ✅ Cross-formatter snapshot test —
crates/alint-output/tests/cross_formatter.rs. Same fixed Report rendered through all 8 output formatters with 13 invariant tests. Catches silent formatter divergence; SARIF + agent + JSON-schema validation bundled in.
v0.8.3 — CLI surface coverage
Section titled “v0.8.3 — CLI surface coverage”trycmd 33 → 56 cases (pre-v0.8.3 had 27 happy-path; only 2 stderr snapshots).
- ✅ Stderr snapshots for every error path:
--changedon non-git,--base invalid-ref, malformed YAML, unknown rule kind,--fail-on-warningexit-code verification,export-agents-md --inlinemalformed markers. - ✅ Per-subcommand
--helpsnapshot tests for all 9 subcommands. - ✅
--color auto×NO_COLOR×CLICOLOR_FORCEmatrix (5 cases). Surfaced + fixed a real bug: CLICOLOR_FORCE wasn’t honored under--color=auto. - ✅
--progress=auto|always|never× TTY/non-TTY matrix via trycmd env vars +portable-ptyintegration test for the actual TTY branch.
v0.8.4 — Benchmark uplift
Section titled “v0.8.4 — Benchmark uplift”Pre-v0.8.4: 6 of ~50 rule kinds had isolated criterion benches. 0 output formatters benched. 0 fix-throughput benches.
- ✅
single_file_rules.rs— every per-file rule kind, parameterised over file size and tree size. - ✅
cross_file_rules.rs—pair,for_each_dir,every_matching_has,unique_by,dir_contains,dir_only_containsat varying tree shapes. - ✅
structured_query.rs— JSON / YAML / TOML parse + path-query throughput;json_schema_passesvalidation. - ✅
output_formats.rs— 1k / 10k / 100k violation Reports rendered through all 8 formatters. - ✅
fix_throughput.rs— every fix-op type on synthetic violation lists. - ✅
blame_cache.rs— cold/warm/miss-rate characterisation. - ✅
dsl_extends.rs— extends-chain depth + drop-in merge cost. - ✅ Two new hyperfine scenarios: S4
agent-hygiene, S5fix-pass. Walker parallelism baseline captured for v0.9’sbuild_parallelswitch.
v0.8.5 — Regression-guard + rot-prevention
Section titled “v0.8.5 — Regression-guard + rot-prevention”Closes the v0.8 cut. Makes test/bench rot mechanically impossible to ship.
- ✅
xtask bench-compare— diffs twotarget/criterion/trees; fails when any scenario regresses past--threshold(default ±10%). PR-time gate-ready. - ✅ Baseline against v0.7.0 captured at
docs/benchmarks/micro/results/linux-x86_64/v0.7.0/so v0.9 engine work has a documented floor. - ✅ Fixture-completeness test —
alint-dsl/tests/schema.rs::fixture_covers_every_registered_rule_kindasserts every registered kind appears inall_kinds.yaml(now 70 kinds, up from 18). - ✅ Scenario-coverage audit test —
crates/alint-e2e/tests/coverage_audit.rs. - ✅ Default-option snapshot test —
crates/alint-dsl/tests/default_options_snapshot.rswith elide rules for crate-internal Debug churn. - ✅ CLI flag inventory snapshot per subcommand —
crates/alint/tests/cli_flag_inventory.rs(separate from —help text snapshots). - ✅ JSON report schemas at
schemas/v1/{check-report,fix-report}.json+ cross- formatter validation tests. - ✅
cargo llvm-covinstrumentation —.github/workflows/coverage.ymlenforces 85% line coverage floor (90.57% achieved).xtaskexcluded (dev tooling, structurally low coverage). Codecov upload opt-in viaCODECOV_TOKEN. - ✅
cargo mutantsnightly —.github/workflows/mutants.ymlrotates one crate per night. - ✅ Cross-platform CI —
.github/workflows/cross-platform.ymlrunscargo test --workspace --lockedon macOS-arm64 + Windows-x86_64. Caught two real production bugs not surfaced by the Linux lane: a glob mixed-separator bug in the DSL nested-config prefix handling and a bench-compare key separator bug, both fixed before merge.
Out of scope (deferred to v0.9 engine cut)
Section titled “Out of scope (deferred to v0.9 engine cut)”- Per-file-rule dispatch flip (engine restructure).
- Parallel walker (
WalkBuilder::build_parallel). - Memory-footprint pass (Cow / lazy file content / dhat profile).
All three were originally v0.8 sub-themes; they shift to v0.9 because the v0.8 test/bench foundation is the gate that lets engine work land without regressing user-visible behaviour.
v0.9 — Engine optimization
Section titled “v0.9 — Engine optimization”(Was v0.8 sub-themes 2–4 in the pre-2026-04-28 plan;
displaced by the v0.8 test/bench foundation. Per-feature
design drafts live under
docs/design/v0.9/ — same shape as the v0.7
design pass.)
- ✅ Parallel walker (v0.9.1, 2026-04-30) — replaces
WalkBuilder::build()withbuild_parallel()driving a per-threadParallelVisitorthat accumulatesFileEntrys in a thread-localVecand merges viaDrop. A deterministicsort_unstable_bypost-sort restores the byte-identical output snapshot tests + formatters depend on. Walker bench: -64% at 10k files, -41% at 1k files, +61% at 100 files (1ms thread-spawn overhead — accepted trade per design doc). - ✅ Memory-footprint pass — type-level only (v0.9.2,
2026-04-30).
Arc<Path>onFileEntry::path/Violation::path,Arc<str>onRuleResult::rule_id/policy_url,Cow<'static, str>onViolation::message. Per-violation path / id clones become atomic refcount bumps. Byte-slice scanning + bounded prefix/suffix reads bundled into v0.9.3 alongside the dispatch flip (rule bodies get touched once instead of twice). - ✅ Per-file-rule dispatch flip + 8-rule reference
migration (v0.9.3, 2026-04-30). New
PerFileRuletrait; engine partition; file-major loop reads each matched file once and dispatches to every applicable rule. 6 line-oriented rules (no_trailing_whitespace,final_newline,line_endings,max_consecutive_blank_lines,indent_style,line_max_width) and 2 bounded-read rules (file_starts_with,file_ends_with) migrated; bounded-read helpers (read_prefix_n/read_suffix_n) incrates/alint-rules/src/io.rs. - ✅ Content-rule mechanical migration (v0.9.4,
2026-04-30). 16 more per-file content rules opt into
the dispatch flip:
file_content_matches,file_content_forbidden,file_header,file_footer,file_shebang,file_max_lines,file_min_lines,file_hash,file_is_ascii,file_is_text,no_bom,no_bidi_controls,no_zero_width_chars,no_merge_conflict_markers,markdown_paths_resolve,structured_path(json/yaml/toml_path_*).file_max_size/file_min_sizestay rule-major (metadata-only);json_schema_passesstays rule-major (repo-level error path doesn’t fit per-file dispatch). - v0.8.5’s
bench-comparegate catches any regression from the engine restructure for free.
Reopened sub-phases (2026-05-01)
Section titled “Reopened sub-phases (2026-05-01)”A scaling-profile investigation surfaced that the v0.9.4 1M
S3 hyperfine number had drifted +28-37% vs v0.5.6 — every
for_each_dir rule with a crates/* select instantiated a
fresh nested rule per matched directory and each ran a
linear scan of ctx.index.files(), giving O(D × N) shape
that hit ~5 B glob-match ops at 1M with 5,000 packages.
- ✅ Cross-file dispatch fast paths (v0.9.5, released
2026-05-01). Lazy
OnceLock<HashSet<Arc<Path>>>path-index onFileIndex(contains_file(&Path) -> boolis the canonical O(1) “does this path exist?” query); literal- path fast paths infile_exists::evaluate,structured_path::evaluate, and theiter.has_filewhen_iter:builtin;pairswitchesfind_file().is_some()tocontains_file. Engine addstracing::info!per-phase- per-cross-file-rule wall-time emission via
ALINT_LOG=alint_core=info. Numbers (1M S3 hyperfine, —warmup 1 —runs 3): full 731.9 s → 11.19 s ± 0.15 (65×); changed 724.4 s → 6.73 s ± 0.06 (108×). Also ~80× faster than the v0.5.6 baseline.
- per-cross-file-rule wall-time emission via
- ✅ Coverage audits (v0.9.5.6). Three new tests under
crates/alint-e2e/tests/: pass/fail symmetry per kind; bundled-ruleset coverage; git-mode symmetry. Plus a soft- warning bench-coverage listing. - ✅ Coverage scenarios (v0.9.5.7). 16 new YAMLs under
crates/alint-e2e/scenarios/check/<family>/filling the audit punch list. E2e count 205 → 221. - ✅ Bench-scale extension (v0.9.5.8). S1-S5 unchanged;
three new perf-shape scenarios — S6 (per-file content
fan-out), S7 (cross-file relational), S8 (git-tracked
overlay). New
alint_bench::tree::generate_git_monorepohelper. - ✅ Rule-authoring workflow doc (v0.9.5.9).
docs/development/rule-authoring.mdcodifies the four-step workflow new rules / bundled rulesets / aliases follow. Self-dogfooding viaaction-selftest.ymlcovers the in-repo lint enforcement. - ✅
scope_filter:primitive (v0.9.6, released 2026-05-02). Closest-ancestor manifest scoping for per- file rules —Rule::scope_filter() -> Option<&ScopeFilter>trait method, engine integration inEngine::run_per_file’s applicable-filter, walksPath::parent()upward and consults the v0.9.5 path-index at each step. The five bundled ecosystem rulesets (rust@v1,node@v1,python@v1,go@v1,java@v1) renamedis_*→has_*, broadened heuristics to catch nested manifests, and addedscope_filter:to per-file content rules so they only fire on files inside their ecosystem’s package subtree. New bench-scale S9 scenario (nested polyglot: rust + node + python overcrates/+packages/+apps/) at K100 = 688 ms ± 13 ms. Full design:docs/design/v0.9/scope-filter.md. - ✅
scope_filter:runtime no-op fix + audit cleanup + v0.10 LSP design pass (v0.9.7, released 2026-05-02). v0.9.6 shipped the field, the runtime types, and the engine gate but no per-file rule builder threaded the parsed filter onto the built rule —Rule::scope_filter()always returned the trait defaultNone, so the gate was a silent no-op. v0.9.7 wired each of 25 per-file content rules throughparse_scope_filter(). Same release added 10 cross-filereject_scope_filter_on_cross_fileunit tests, the release.yml preflight gate (fmt + clippy + testcargo doc -D warnings), and the v0.10 LSP design pass (docs/design/v0.10/{lsp_server,single_file_reevaluation,vscode_extension}.md) withtower-lsp = "0.20"added as a dormant workspace dependency.
- ✅ Cross-file dispatch fast paths round 2
(v0.9.8, released 2026-05-02).
FileIndex::children_of,file_basenames_of,descendants_oflazyOnceLockindexes;dir_only_contains+dir_containsrewrite to usechildren_ofinstead of full-index scan;evaluate_for_each(shared byfor_each_dir,for_each_file,every_matching_has) gains a literal- path bypass for nested per-file rules. 1M S7 full: 614 s → 15.3 s (40×); 1M S7 changed: 618 s → 17.9 s (34×). Newcoverage_audit_cross_file_dispatch.rssoft audit. Full design:docs/design/v0.9.8/cross-file-fast-paths-v2.md. - ✅
scope_filter:coverage sweep (v0.9.9, released 2026-05-03). 17 rules whoseRule::evaluateiteratesctx.index.files()directly (rather than opting into the engine’s per-file dispatch) had noscope_filterplumbing at all — same shape as the v0.9.6 → v0.9.7 bug for per-file content rules but on a different rule set. 16 rules now honour the filter (file_max_size,file_min_size,no_empty_files,executable_bit,executable_has_shebang,shebang_has_executable,no_symlinks,filename_case,filename_regex,no_illegal_windows_names,max_files_per_directory,max_directory_depth,json_schema_passes,command,git_blame_age,no_case_conflicts);no_submodulesrejectsscope_filter:at build time via the newreject_scope_filter_with_reasonhelper since it’s hardcoded to.gitmodulesat the repo root. Same release added afor_each_dirliteral-path bypass guard (the v0.9.8 fast path was skippingnested_rule.scope_filter()) and a new S10 macro bench scenario (scope_filter outside the per-file dispatch path). - ✅
ScopeownsOption<ScopeFilter>(structural fix) (v0.9.10, released 2026-05-03). The v0.9.6 / v0.9.7 / v0.9.9 silent-no-op bug class is closed structurally.Scopebundles itsOption<ScopeFilter>andScope::matches(&Path, &FileIndex)covers both predicates in one call; 41 rules cleaned up to drop the standalonescope_filterfield and runtime check;Rule::scope_filter()trait method removed; newcoverage_audit_scope_owns_filter.rsaudit fails CI if the field re-appears. Breaking —alint-core::Scope::matchessignature changed; CLI users + bundled rulesets unaffected, out-of-tree library consumers see a compile error at every call site. Workspace-wide -319 LOC. Same release bundled v0.9.11-prep cleanups: alint-bench clippy debt,git_tracked_onlyaudit test, HISTORY.md regenerated with v0.9.7-v0.9.10 columns. Full design:docs/design/v0.9/scope-owns-scope-filter.md.
Full v0.9.5 design: docs/design/v0.9/coverage-and-dogfood.md.
v0.9.11 — git_tracked_only structural fix + held v0.9 follow-ups
Section titled “v0.9.11 — git_tracked_only structural fix + held v0.9 follow-ups”The same recurrence-risk shape that produced the v0.9.6 /
v0.9.7 / v0.9.9 silent-no-op scope_filter: bug class
applies to git_tracked_only (declared on 4 existence
rules; an audit test landed in v0.9.10 as a pragmatic
backstop, but the structural fix was held). v0.9.11
chooses the engine-side filtered-FileIndex approach
(Option C in the design comparison) over Scope ownership
(Option A) — there’s no per-rule check to forget at all,
and the dir-mode vs file-mode discriminator never
pollutes Scope’s path-predicate model.
- Engine-side filtered FileIndex for git-tracked rules.
Engine::build_filtered_indexmirrors the existing--changedfiltered-index pattern: builds a file-tracked subset (set.contains(path)filter) and a dir-tracked subset (dir_has_tracked_filesfilter) once per run when any rule opts in. Existence rules (file_exists,file_absent,dir_exists,dir_absent) receive the pre-filtered index viapick_ctx; theif self.git_tracked_only && !ctx.is_git_tracked(...)runtime check disappears from each rule’sevaluate. Rule::wants_git_tracked()engine consultation consolidation. Once the filtered index handles the narrowing,wants_git_tracked()can derive from inspecting rules’ specs at engine-construction time rather than per-rule trait override.- No breaking API change (in contrast to v0.9.10) — the change is internal to engine + 4 rules.
- Acceptance: S8 macro bench at 100k/full and 1m/full
within ±5 % of v0.9.10 (slight win expected from
amortising the HashSet lookup across multiple rules
opting in);
coverage_audit_git_tracked_only.rsaudit retained as backstop.
Held v0.9 follow-ups also captured in v0.9.11 (smaller items, may slip if engine refactor takes longer than expected):
bench-record.ymlworkflow end-to-end run. Defined but never successfully executed — debug the path that opens a PR with bench results so post-release backfill is mechanical instead of manual.coverage_audit_cross_file_dispatch.rscleanup. Soft warning currently flags rules that still scanentries.iter()directly; convert tochildren_ofwhere the dispatch shape benefits.when:ownership — explicitly NOT included. Different semantics (eval-env, not a path predicate); no shared silent-no-op shape.
v0.9.12 - v0.9.20 (shipped)
Section titled “v0.9.12 - v0.9.20 (shipped)”Nine patch releases between the v0.9.11 structural fix and the launch-ready cut. Headline contents (full per-version detail in CHANGELOG.md):
- v0.9.12 (2026-05-03) — backlog cleanup of the explicitly- held v0.9 follow-up items.
- v0.9.13 (2026-05-04) — dependency refresh (Dependabot PR drainage).
- v0.9.14 (2026-05-05) — CI automation:
bench-record.ymlworkflow now opens PRs with bench results so post-release backfill is mechanical. - v0.9.15 / v0.9.16 (2026-05-06) — Config DX hardening:
21-pitfall catalogue with #18 (
respect_gitignore: false) and #19 (literal_is_nestedruntime guard) fixed in the engine; 30 OSS case studies completed; P2b Wave 2 aggregation; operator-polish (alint --versionSHA+date,alint validate-configsubcommand, JSON Schema generation, did-you-mean parse errors, domain-specific error messages, pre-filled crash-report URL on panic). v0.9.16 is the tag-only release that never published due to a clippy gate failure; v0.9.17 is the corrective re-publish. - v0.9.18 (2026-05-08) — pre-launch fix wave: 6 bundled-
ruleset refinements (A1-A6: hygiene-no-js-build-outputs
sibling-package.json gate; long-form Apache-2 preamble;
python@v1 test-fixture excludes; cargo-workspace member
parsing; LICENSE.TXT/.md recognition; rust-sources-snake-
case
allow_compiler_namingknob), 3 case-study config fixes (B1-B3: TypeScript pitfall #22, deno defensive|-, tensorflow header rule scope), B4 cross-cutting revalidation pass,dir_absentengine extension (now supportsscope_filter). - v0.9.19 (2026-05-09) — width-aware human output wrapping
--no-docsflag; verbose-message tightening; demo refresh.
- v0.9.20 (2026-05-10) — width-aware output extended to
every command;
cmd_list/cmd_explain/cmd_facts/cmd_suggestcolor parity withcheck/fix; newstyling_uniformintegration test enforces the contract uniformly going forward; bundled-rule message length audit; em-dash scrub on first-impression marketing surfaces; install-snippet pin sweep (curl + bash now leads everywhere); polyglot CLI demo with 5 auto-fixable seeds;install-snippets-match-workspace-versiondogfood rule; preflight + pre-push hook bundle.
v0.10 — Case-study coverage push
Section titled “v0.10 — Case-study coverage push”The 8 rule kinds + 2 bundled rulesets the case-study aggregation demand-validated. Splits out from the original v0.10 “LSP” framing because rule-kind coverage is what unblocks early adopters; LSP is developer-experience polish that can ship separately (now v0.11). Order within the cut by demand × adopter surface:
| # | Primitive / ruleset | Demand | Notes |
|---|---|---|---|
| 1 | registry_paths_resolve | 13 | Largest demand surface. Spans rust, clap, cpython, next.js, arrow, pytorch, nodejs/node, NixOS, dotnet, flutter, kubernetes, protobuf, tensorflow. |
| 2 | cross_file_value_equals (incl. value_extractor:) | 12 | Past saturation. istio surfaces the per-file extractor refinement (pitfall #20); dotnet/runtime SDK band coherence raises the count. |
| 3 | ordered_block | 8 | Lines between marker pairs sorted unique under configurable comparator. |
| 4 | generated_file_fresh | 8 | Run a generator, diff against on-disk file. Opt-in framing: alint’s deliberate non-goal is running codegen. |
| 5 | import_gate | 5 | Forbid imports of pattern X in scope Y. k8s prometheus-imports + airflow + go + helm + pytorch. |
| 6 | command_idempotent mode | 5 | --check mode that fails if working tree would change. ruff-format / prettier —check / dprint check / deno fmt —check / eslint —no-fix shape. Promoted from design candidate in the deep-analysis aggregation. |
| 7 | xml_path_matches + xml_path_equals | 2 | Completes the structured-query family (JSON / YAML / TOML / XML). spark + dotnet/runtime ~7,100 manifests. |
| 8 | pair_hash | 3 | Hash of file A appears at offset Y of file B. golang/go FIPS = highest stakes (CMVP submission references the file format). |
| 9 | apache/governance@v1 (bundled ruleset) | 3 | LICENSE + NOTICE + KEYS + RAT discipline. Apache TLPs converge: arrow + spark + airflow on 9 of 12 governance artefacts. v0.9.18 A2 is a prerequisite. |
| 10 | dotnet@v1 (bundled ruleset) | 1 | Single demand source but huge adopter surface (every dotnet/* + every Azure SDK + every microsoft/* .NET project). Depends on xml_path_*. |
Plus design candidates landing opportunistically when a 2nd
demand source materialises: *_path_contains (3 sources today;
resolves pitfall #17), pair_inverse (2 sources), command_per_repo
(1), json_schema_passes config-shape mode (2), *_path_array_iter
(1), multi_doc_mode: knob on yaml_path_* (1; resolves
pitfall #21).
Per-repo coverage tables + per-primitive demand citations live
in examples/README.md
and docs/development/launch-evidence.md.
v0.11 — LSP + developer experience
Section titled “v0.11 — LSP + developer experience”What was originally the v0.10 cut, deferred one slot. Inline
diagnostics, hover-on-rule docs, code actions, VS Code
extension. The per-file dispatch shape from v0.9.3 powers the
per-file-edit re-eval hot path; v0.9.5’s
FileIndex::contains_file makes single-file path-scope
re-tests O(1). Plus the v0.11+ ship-targets the case-study
aggregation surfaced for the smaller-demand long tail.
- LSP server (
alint lsp). Design pass landed in v0.9.7 (docs/design/v0.10/lsp_server.md);tower-lsp = "0.20"is already in[workspace.dependencies]as a dormant dep. Crate scaffold (crates/alint-lsp/) is the only structural lift remaining. - VS Code extension that bundles the LSP. Design in v0.9.7
(
docs/design/v0.10/vscode_extension.md). ScopeFiltergeneralisation beyondhas_ancestor— candidates includehas_sibling,has_descendant, custom predicates. v0.9.10’sScope::from_specmakes additions purely additive (no API churn).cross_language_implementation_complete(5 sources: arrow, tensorflow, protobuf, angular, flutter). Densest demand: protobuf’s 10 in-tree language bindings + 1 spun-out (~45 cross-language assertions one rule would express). Three distinct topologies (data-format-driven, within- language source ↔ golden, platform-driven).- Bazel-licensing-declaration-aware rule kind (1 source:
tensorflow’s
licenses(["notice"])BUILD-file discipline). Single-source but the source is a 100k+ file tree with high alignment cost. walk_error_policy:engine knob (1 source: pnpm’stests/fixtures/has-broken-symlinks/).strict/skip-broken-symlinks/permissivemodes.
v0.12 — WASM plugins
Section titled “v0.12 — WASM plugins”Per the previous v0.11 scope, bumped one slot.
wasmplugin kind with awasmtimehost, stable WIT interface.- Plugin registry scaffolding with signature verification.
- Bless a few canonical agent-aware semantic plugins (mock-ratio checker, file-similarity / near-dup detector, debug-statement auto-stripper) as documented examples — not bundled, to keep the binary lean.
v1.0 — Stability
Section titled “v1.0 — Stability”- DSL schema committed; semver on
version: 1. - Plugin ABI committed.
alint-corepublic API frozen; breaking changes follow semver-major.- Documentation site.