dartrics 1.2.0
dartrics: ^1.2.0 copied to clipboard
Citation-anchored Dart code-quality metrics (CK, Halstead, McCabe, Martin, Cognitive) plus Periphery-style unused public-API detection, shaped for AI refactor loops.
Changelog #
1.2.0 #
Toolchain alignment release: tracks analyzer 13.1.0. No metric, threshold, exit-code, or schema change.
- Dependency floors raised:
analyzer ^13.1.0,analysis_server_plugin ^0.3.16,analyzer_testing ^0.3.0(dev). The deprecatedExtensionTypeDeclaration.primaryConstructorAST getter is replaced with its successornamePart; behaviour is unchanged.
1.1.0 #
An AI-loop fidelity release: the ai report announces per-section totals, --since narrows to the scopes the diff touched, and cognitive complexity stops taxing declarative test registration. Report schema 1.1 → 1.2, additive. No threshold, exit-code, or wire-format-breaking change.
--reporter aiemits acounts:block (violations / unused / staleDismissals / signals) ahead of the sections. All four sections share the- file:entry shape, so agents that grepped to count findings over-counted; totals now read fromcounts:plustruncated:for dropped tails.--limitis documented as what it always was — a per-section cap, not a global one.--since <ref>filters violations to the scopes the diff touched. The filter was file-granular: an untouched function re-surfaced whenever a sibling in the same file changed. Violations now intersectgit diff -U0hunk ranges with the scope span;unused/signalsstay file-granular because they are call-graph-relational — a change elsewhere in the file can legitimately flip them on an untouched declaration. Pure renames (100% similarity, no hunks) no longer surface.- Cognitive complexity applies a test-DSL discount. On
*_test.dartfiles undertest//integration_test/, closures passed as invocation arguments (group()/test()registration callbacks) no longer accrue to the enclosing function — declarative test mains were firing purely on the closure-nesting tax. The function's own control flow and named helpers stay scored. Gate withdartrics: { test: false }; applies to both the CLI engine and the analyzer-plugin rule. Stale-dismissal note:// dartrics:dismiss cognitive-complexitycomments that suppressed the closure-nesting tax on test mains may now be reported as stale — remove them. - Report schema
1.1→1.2:ScopeRefgains an optionalendLine(last line of the declaration, inclusive) — the span--sinceintersects. Additive; pre-1.2 reports re-emit throughdartrics reportunchanged.
1.0.0 #
First stable release. The metric battery, the --reporter ai wire format (# dartrics ai-report v1), the JSON and SARIF schemas, and the embeddable Dart API (FunctionMetric family + dartricsVersion) commit to semver — non-breaking until 2.0.0. No metric, threshold, exit-code, or wire-format change from 0.8.0. The metric catalogue is dartrics rules; the operator reference is doc/manual.md and dartrics manual; the wire formats are in schemas/.
- One-time editorial pass over the 0.x CHANGELOG entries. Verbose originals remain at
pub.dev/packages/dartrics/versions/<version>and ingit log.
0.8.0 #
Correctness release. Several lenses, the coverage reader, the regression diff, and the report writers had edge-case defects; dartrics unused --apply is also narrowed to the deletions it can make safely. No metric default or schema change.
dartrics unused --applynow performs only whole-node deletions. A variable that shares anint x, y, z;declaration with siblings, and enum constants, are reported asunsupportedand left in place for you to remove —--applyno longer rebalances the surrounding commas (which could leave invalid Dart). dartrics surfaces those decisions rather than guessing at them; the unused detector still lists the declaration.- Cyclomatic complexity no longer folds a nested closure into the enclosing function. A lambda's
if/&&/casedecision points were leaking into the value of the function that contained it; nested closures are measured separately, as documented. - lcov branch coverage keys on
(line, block, branch). Two distinct branches that share a line and branch number across different blocks (e.g. an&&that lowers to two blocks) no longer collapse last-write-wins, so the branch-coverage fraction behindcomplexityJustifiedis correct. dartrics regression --root <sub-dir>compares the matching sub-tree on both sides.git worktree addchecks out the whole repository, so the historical side previously analysed the entire repo and normalised paths against the repo root — every scope reported as added + removed. It is now scoped to the sub-directory.- Report output escapes special characters. A free-text field such as a dismiss reason starting with
-or[no longer breaks the re-parsedai/rulesYAML, and a|in a scope name (e.g.operator |) no longer splits the Markdown signals table. - A non-numeric metric threshold raises a config error. A quoted or otherwise non-numeric value (
error: "15", which YAML reads as a string) was silently dropped, so a gate without a built-in default never fired; it is now reported instead of dropped or coerced.
0.7.3 #
Detection-fidelity and discoverability release driven by external agent feedback. No metric, threshold, or schema change.
- Unused detector now follows operator-method calls through
IndexExpression,BinaryExpression, and the operator element onPrefixExpression/PostfixExpression. User-definedoperator [], binary operators (including custom+/==), unary-, and the+reached viac++/c--were previously flagged as unused when their only caller was the textual operator form.==overrides were already kept alive by theObjectdunder auto-root, but theirsignals:fan-in / fan-out (anddartrics inspect ==upstream walk) now reflect the actual call sites. Stale-dismissal note: projects with// dartrics:dismiss unusedcomments suppressing the prior false-positives on those operators may now see those dismissals reported as stale — remove them. dartrics ai-looprepositioned as the operational entry point. Its--helpone-liner now reads "Operational playbook: commands, prompts, dismiss syntax (start here for AI agents).";dartrics --helpgains a footer pointing at it;doc/manual.mdopens with a cross-ref banner; and the README "AI agents — start here" admonition, Quick start block, Subcommands table, and Documentation list all lead withai-loopand reframemanualas the conceptual reference (lens design, decision tree, flag catalogue). Driven by an agent who skippedai-loopbecause the prior blurb read as a recap of the manual.
0.7.2 #
AI-consumer ergonomics release driven by a real dartrics session report from another agent. No metric, threshold, or schema change.
looksCosmetic→cosmeticSplitDetectedindartrics regression. The old name read as a verdict; the detector is a narrow opt-in signal (the cosmetic-split signature) parallel toanalyze'ssignals:block, not a refactor-quality verdict. All reporters now emit# narrow heuristic, not a global verdictalongside the boolean, and the manual reframes the block as a signal rather than a pass/fail.- Stray
// dartrics:dismisscomments no longer silently no-op. WhencommentSourceis off (the default — thedismissals:block is not yet authored) and the run is not--strict-dismiss,analyzescans for dismiss-shaped comments and emits a stderr WARN naming the affected files and the opt-in needed. - Operational protocol step 5 documents
--snapshot none. The snapshot cache rewrites itself every run, so two consecutiveanalyzeruns always reportchangedFiles: 0. The manual now flags this on the verify step. - README directs AI agents to
dartrics manualfirst. The subcommand was hidden behind--help; the README banner makes it the explicit entrypoint for AI consumers. - ACCEPT becomes a first-class decision in the loop diagram and manual. Borderline values on healthy code are now explicitly "no edit, no
// dartrics:dismiss, no punt — move to the next violation," distinct from dismiss (which is a tracked, recurring-reason commitment).
0.7.1 #
Documentation-only release. The 0.7.0 surface — dartrics inspect, the signals: reference block — shipped without matching updates to dartrics manual and dartrics ai-loop. 0.7.1 catches the in-binary walkthroughs up to the released CLI surface. No code, schema, or threshold change.
dartrics ai-loopsample report now carriessignals:andsnapshot:; documents what the agent reads out of it and clarifies thatviolations:/explain:go absent on a clean run whilesignals:keeps emitting. New "The unused-detector loop" section covers theread → inspect → --applyflow.dartrics manualgains a "Signals — reference information, not verdicts" section, an inlinedartrics inspectsubsection, and aninspectentry in the operational protocol flag map.
0.7.0 #
A call-graph release. The element-resolved reachability pass already powering dartrics unused now also surfaces per-declaration fan-in / fan-out reference signals and backs a new dartrics inspect <symbol> subcommand. Signals carry no threshold and no severity — they are reference information, not violations.
- Report schema bumps from
1.0to1.1. Three new top-level fields land in the JSON output:signals,explanations(previously AI / MD only), andstaleDismissals(previously AI only). All additive;additionalProperties: falseis now consistent withtoJsonagain. Seeschemas/dartrics-report.schema.json. - New
dartrics inspect <symbol> [--depth N] [--direction up|down|both]subcommand. Walks upstream callers and / or downstream callees within--depthhops; emits JSON or the YAML-ish AI shape. Homonym methods on different classes stay disambiguated as separate matches. - MD reporter gains
## Signals (reference)and## Stale Dismissalssections. The AI reporter'sunused:block is reframed in-output: entries may be leftover code OR unwired implementations — the framing comments instruct the loop to confirm against intent before acting.
0.6.6 #
A dartrics unused correctness fix. Detection now sees references that live inside machine-generated files. Output changes for any project whose source declarations are reached only from generated code (.g.dart, .freezed.dart, etc.). No CLI flag, exit code, schema, or threshold change.
dartrics unusedreachability now includes references from machine-generated files; previously edges like ariverpod_generatorprovider's reference back to its source function were missing and the source was reported unused. Snapshots and the analyzed-file count still track the handwritten subset only.dartrics analyze's unused output retains the same defect. Surfaced by dogfooding on a multi-moduleriverpod_generatorproject.
0.6.5 #
A README narrative simplification. No metric, threshold, exit-code, or wire-format change.
- Drops the wager and lens paragraphs from
## What it does(duplicateddoc/manual.md's## The premise); the## Documentationentry fordartrics manualnow signposts the design premise.
0.6.4 #
A dead-code cleanup surfaced by dogfooding dartrics on its own source. No metric, threshold, exit-code, or wire-format change.
SourceLocation.toJsonremoved — every serializer that holds aSourceLocationbuilds its own field set inline, so the method had no caller inlib/. Detected by runningdartrics analyzeon dartrics itself.
0.6.3 #
A dartrics unused --apply correctness fix plus two documentation additions. No metric, threshold, exit-code, or wire-format change.
unused --apply --filter fieldnow refuses fields whose name appears as athis.<field>initializing formal on the enclosing class's constructor; previous behaviour broke compilation. NewApplyOutcome.coupledConstructorFormalmarks each refused entry.unused --applyno longer leaks the leading whitespace of a deleted declaration into the next line.doc/manual.md— "Punt" section now names the output channel (natural-language between AI and operator; no comment directive or YAML key); new## Reporters — pick by audiencesection.
0.6.2 #
A documentation-only patch on top of 0.6.1. No metric, threshold, exit-code, or wire-format change.
- Per-file Martin lenses (
efferent-coupling/afferent-coupling/instability) reframed frompolarity: downtopolarity: neutralin docs to match theLibraryMetricdefault; rationale indoc/calibration.md's new "Per-file Martin granularity" section. - README metric tables gain a
Default warningcolumn in place ofNotes; the library-level table tagsinstabilityas informational;## Limitationssurfaces "Per-file Martin granularity".
0.6.1 #
A small documentation-correctness patch on top of 0.6.0. No metric, threshold, exit-code, or wire-format change.
unused --applysummary message rewritten — the previous text claimed methods, fields, and enum values were "not yet auto-deletable" (stale since 0.5.x). Only "removing the last constant of an enum" remains an unsupportedApplyOutcome.unsupportedKindoutcome.
0.6.0 #
A calibration release. Four metrics drop after a citation re-audit, four citations corrected, and the Dart-specific deviations from cited sources consolidate into doc/calibration.md.
Breaking changes #
maximum-nesting-levelremoved — the cited NIST SP 500-235 §4 attribution was incorrect and no peer-reviewed alternative establishes a defect-correlated threshold. The calculator, plugin rule, lint id, config key, and public-API export are gone. Schema'spropertyNames.enumno longer accepts the id.boolean-trapremoved — the McConnell / Bloch attributions were wrong;dart-lang/linter'savoid_positional_boolean_parametersalready covers the ground with a stricter binary threshold.abstractnessanddistance-from-main-sequenceremoved — Martin's "package = release unit" framing has no equivalent in Dart's language model. Rationale indoc/calibration.md.
Citation corrections #
cognitive-complexity— SonarSource 2017 (not 2018); rationale now flags the source as an industry white paper.halstead-volume— Alfadel et al. 2017, 9th IEEE-GCC Conference, not the previously-cited 2018 venue.lcom4— Hitz & Montazeri (1995) introduced the connected-components variant; the "LCOM4" label is a later community convention.martin 1994— full bibliographic citation; the C++ Report attribution that some sources use is incorrect.
Other #
doc/calibration.md— new audit page for selection principles, counting-rule deviations, and off-by-default rationales.- README trimmed by ~58 % (437 → 184 lines); content redistributed to
dartrics manual/dartrics ai-loop/schemas/.
0.5.1 #
A maintenance release. No metric, threshold, exit-code, or wire-format change. Internals modernised against Dart 3.10 idiom, plus a self-application CI gate and a coverage-data docs fix.
- New CI job runs
dartrics analyzeon dartrics itself on every push/PR and fails on warning-level violations. - Coverage-data docs in README /
dartrics manual/dartrics ai-loopnow spell out how to generatecoverage/lcov.info(previously assumed users already had it).
0.5.0 #
A pruning release. Five pieces of dead-or-deferred CLI / model surface come off, plus one payload addition on the regression side.
Breaking changes #
dartrics explain <id>subcommand removed — auto-explain has been default-on since 0.1.0; lookup against a saved JSON report is a directMap<id, violation>build.--no-auto-explainflag removed — auto-explain unconditional. Token-budget control is--limit <n>.--fatal-styleflag removed from every subcommand —Severity.infowas never emitted by any built-in lens.- Per-subcommand option scoping —
--rootand analysis-time flags no longer accepted bydartrics report(drop them from CI scripts). Severity.inforemoved from the public enum — embedder metrics that synthesised it will fail to compile; treat aswarning.
Other #
MetricChange.idfield added — samesha256("<file>|<scope>|<metric>")[..16]asMetricViolation.id, emitted unconditionally so AI loops can correlate sub-threshold drift across runs.
0.4.0 #
Breaking changes #
- Three Dart-shape metrics removed:
widget-tree-depth,null-aware-chain-depth,async-chain-depth. All three were tool-originated lenses without academic anchor; schema'spropertyNames.enumno longer accepts the ids. FunctionMetric.referencesandClassMetric.referencesare now abstract — embedders implementing custom metrics must declareList<String> get references => const [];explicitly when there is no primary citation.
Other #
number-of-methodscites Lorenz & Kidd (1994) and CK (1994);class-lengthcites Beck (1996), Fowler (1999), and Lippert & Roock (2006).
0.3.0 #
Breaking changes #
--explain <metric-id>removed fromdartrics analyzeanddartrics unused— auto-explain is default; for post-hoc lookup usedartrics explain <id> --input report.json.MetricPolarity.upremoved from the enum — no built-in metric used it. Custom embedder metrics that registeredMetricPolarity.upwill fail to compile; treat asneutral.dartrics: { unused: { presets: [...] } }removed — was a no-op since 0.1.0. Schema rejects the key.
Other #
dartrics ai-loopsubcommand added — prints the AI-loop walkthrough; byte-mirrored fromdoc/ai-loop.md.referencesfield added to every built-in metric, surfacing throughdartrics rules, AI / md / SARIF reporters, and the explain blocks.- README rewritten and trimmed (545 → 429 lines).
0.2.2 #
Bugfixes #
maximum-nesting-levelno longer counts named-argument closures (Widget builders, event handlers) as a nesting level.- Summary tables surface snapshot mode and the diff filter so the cache-mode default doesn't render as a regression.
snapshotModeandchangedFileCountadded at the JSON report root (field additions only; AI/JSON header version unchanged).
0.2.1 #
Bugfix #
.pubignore'scoverage/pattern (no leading slash) matched at any depth, so the0.1.0and0.2.0archives shipped withoutlib/src/coverage/coverage_loader.dartandlib/src/coverage/lcov_reader.dart. Anyone who installed from pub.dev hit unresolved-import errors. Pattern is now/coverage/; reinstall to recover.
0.2.0 #
- Public-API unused-code detection switched from a simple-name reference graph to the analyzer's resolved element graph — keyed on canonical
Element.ids. Member granularity added (instance methods, fields, getters / setters, enum values). - New
--filter <kinds>CLI flag and matchingunused: { filter: [...] }YAML key. Seedartrics analyze --help. - Auto-rooting for
@overridemembers, Object dunder names, and members of classes carrying a keep-alive annotation. LibraryElement.exportNamespacenow drives theexcludeExportedroot set.
0.1.0 #
First public release. Ships the function / class / library metric battery (see dartrics rules), the public-API unused detector, the analyzer plugin (function-level rules), the --reporter ai AI-integration surface, and the embeddable Dart API (FunctionMetric family + dartricsVersion). Operator reference in doc/manual.md and dartrics manual; AI-loop walkthrough in doc/ai-loop.md and dartrics ai-loop; wire formats in schemas/. Exit codes sysexits-aligned.