Changelog
All notable changes to this project will be documented here.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Categories:
-
Added — new functionality
-
Changed — behaviour of existing functionality
-
Deprecated — scheduled for removal
-
Removed — gone
-
Fixed — bug fixes
-
Security — security fixes
-
Performance — user-visible performance improvements
Unreleased
0.1.3 — 2026-06-20
The first release that pairs the published gem with the interactive viewer the README has been showcasing, plus the supply-chain hardening that justifies shipping a vendored third-party JS file inside the gem.
Added
-
Interactive
view --output htmlviewer. Replaces the static Mermaid embed with a Cytoscape.js-based page that renders 5k+ nodes, filters live bykind/confidence, supports a name-substring search, and copiespath:lineto the clipboard on node click. The Cytoscape library is vendored into the gem at a sha256-pinned version (lib/rigor/module_graph/templates/vendor/cytoscape.min.js); no CDN, no npm, no Dependabot auto-bump. Seedocs/plan.md“2D interactive viewer” for the supply-chain rationale. -
--path-mode {relative,absolute,none}flag onview— controls how node paths reach the viewer’s click-through metadata.nonestrips paths from the HTML artefact, which is the right setting when sharing the file outside the project (PR comment, gist, …). -
--open-with vscodeflag onview— flips the node-click action from clipboard copy tovscode://file/<path>:<line>so the editor jumps straight to the source location. -
bundle exec rake vendor:verifytask — recomputes sha256 for every file invendor/CHECKSUMSand fails on mismatch. Wired into pre-commit on any staged file underlib/**/templates/vendor/**. -
.github/dependabot.yml— weekly Bundler + GitHub Actions bumps;vendor/**is explicitly excluded so vendored third-party JS never auto-updates. -
bundle exec rake vendor:audit— 4-source cross-check (local sha256 / npm tarballdist.integrity/ tarball-internal copy / GitHub raw / every CDN). Readslib/rigor/module_graph/templates/vendor/MANIFEST.ymlfor the provenance metadata. Use on bump PRs; not part of the regular CI pipeline (network-using). -
CI now runs
rake vendor:verifyindependently of pre-commit so an unaudited bump can’t land onmaineven if local hooks were skipped. -
CI now regenerates
examples/billing/viascript/ check_billing_drift.rband fails on drift between the freshly-built artefacts and the committed copies. Normalises the graphviz version banner so the runner’s apt-shipped version doesn’t trigger a false positive. -
New docs/security.md consolidates the supply-chain story (Bundler / Dependabot cooldown, vendored-JS sha256 + 4-source audit, action SHA pinning, OIDC trusted publishing).
Changed
-
view --output htmlsemantics. The flag now produces the interactive viewer. The previous static Mermaid HTML moves behind--output mermaid-html(still loads Mermaid from a CDN, kept for back-compat). -
CI workflows read Ruby from
.ruby-versioninstead of pinning"4.0.0"inline, so future.ruby-versionbumps no longer need a.github/workflows/chase. -
RDoc dependency bumped from
~> 6.0to~> 7.0(resolves to 7.2.0).gemspec.rdoc_optionscorrected to--markup markdownto match.rdoc_optionsand the Rakefile, fixing the silent inconsistency left when the README rendering fix landed in 0.1.2. No code change;rake rdocemits no warnings under 7.x. -
README hero leads with the Cytoscape viewer screenshot (the default output) and the Graphviz SVG follows.
examples/billing/preview.pngresized from 1280x860 to 720x483 so it fits the RDoc darkfish content pane on the GitHub Pages site without overflow. -
README Documentation index re-ordered along the natural reading flow: how-it-works → security → limitation → development → plan.
0.1.2 — 2026-06-20
First release that exercises the full automated pipeline end to end — Trusted Publishing + GitHub Release + asset upload all drive off a single gh workflow run release.yml after the tag is pushed.
Added
-
viewandcollectnow emit step-level progress on stderr:==> Running rigor check ..., post-step counts (18 edge(s), 16 node(s)), and inline elapsed time (done (428ms)). TTY-aware — the start / done halves render inline on a terminal, on separate lines for redirected output, so logs stay grep-friendly.-q/--quietsuppresses the progress output for scripted use; the finalwrote N edge(s) to ...summary line stays. Driven by a newStatusReporterclass pinned bytest/rigor/module_graph/status_reporter_test.rb.
Changed
-
README restructured along the install → getting started → usage → configuration flow. The “How it works” walkthrough (pipeline diagram + the “not a call graph” framing) moves to docs/how-it-works.md so the README stays focused on “what do I type”. Configuration section now notes that
.rigor.ymlis required (rigor reads it to discover the plugin), with a two-line minimum example up top and the fully-elaborated default form below.
Fixed
-
RDoc generation now parses Markdown instead of RDoc syntax, so
images in README.md / CHANGELOG.md /docs/*.mdactually render.Rake::Task[:rdoc]is enhanced to copyexamples/billing/graph.svg(and any futureRDOC_ASSET_PATHSentries) intodoc/so the generated site resolves the relative image references the README uses.
0.1.1 — 2026-06-20
First Action-driven publish. The 0.1.0 release happened via the CLI fallback before the rubygems.org Trusted Publisher registration was in place; 0.1.1 is the first version to land through release.yml.
The user-visible code surface is intentionally tiny: the major correctness fix (namespaced association resolution), the Stats / Reachability / Edge perf rewrites, the SHA-pinned workflows, the docs split, and the MIT LICENSE.txt all already shipped in 0.1.0.
Changed
-
--version/-v/versionnow printsrigor-module-graph X.Y.Zinstead of a bareX.Y.Z. Matches the conventionbundler --versionandgh --versionuse; bug reports pasted into chat are self-identifying.
0.1.0 — 2026-06-20
Initial release. Baseline shipping everything from the Phase 0 spike through Phase 5 (UML class diagram).
Added
-
Phase 0:
Rigorplugin API spike againstrigortype 0.2.1 -
rbs ~> 4.0, validating thatnode_rule(Prism::ClassNode)and friends work and locking in the:infodiagnostic output channel. -
Phase 1 (MVP): extraction of
inherits/include/prepend/extendedges.Rigor::ModuleGraph::Edge(aDatasubclass) with a JSONL writer, Graphviz DOT and Mermaid flowchart renderers, and cycle detection via an iterative Tarjan SCC. -
Phase 2: Zeitwerk-style path → constant inference (
ZeitwerkResolver), namespace collapse in both renderers (DOTsubgraph cluster_*and Mermaidsubgraph), andconst_refedges from constant references inside method bodies (gated oninclude_constant_refs). Confidence promotes fromsyntax→zeitwerkwhen the path-inferred name agrees with the lexical owner. -
Phase 3: indirect mixin resolution via
scope.type_of. ARigor::Type::Singletoncarrier lifts the edge toconfidence: "rigor_type"; everything else degrades to"unresolved"with the source slice preserved inraw. CLI gains--kindand--confidencefilters. -
Phase 4:
statssubcommand reporting per-namespace fan-in / fan-out / internal / nodes (text and JSON, with--grouping-depth Nand--limit N). Packwerk overlay (--package/--package-root PATH) discoverspackage.ymlfiles recursively and uses them as the cluster boundary. The Dot / Mermaid renderers accept an explicitgroups:mapping for arbitrary node → cluster assignments. -
Phase 5: UML-style class diagram.
collectwrites a siblingnodes.jsonlcovering class / module declarations, method definitions, andattr_*attributes — with visibility tracked via theVisibilityMap‘s bareprivate/protected/publickeyword walk. Rails associations land as edges (has_many/belongs_to/has_one/has_and_belongs_to_many, with cardinality and a tiny Rails-style inflector that maps:invoices → Invoice). A newUml::ClassDiagramrenderer andclass-diagramsubcommand emit MermaidclassDiagramsyntax; filters--no-methods,--no-attributes,--public-only,--no-private. -
viewone-shot subcommand:rigor-module-graphwith no args (orviewexplicitly) analyses the current directory, writes a self-contained HTML report under.rigor/module_graph/, and opens it in a browser. The--output html|mermaid|dot|svg|class-diagramflag switches format; non-html streams to stdout unless-o PATHis given. -
Reachability filter (
--from NAMES,--depth N,--direction in/out/both) shared by every reader subcommand. Subsequent--edge-scope cluster|walkflag distinguishes “show the neighbourhood as a cluster” (default) from “show only the edges the BFS actually traversed” (Codex review confirmed naming and direction-both semantics). -
Billing example (
examples/billing/): Customer / Invoice / Payment / LineItem + concerns.build.rbruns the sameview --outputpipeline that ships in the CLI, and commitsindex.html,class-diagram.html,graph.svg, and apreview.pngso the GitHub view of the repo shows the rendered output directly. -
RDoc support via
rake rdoc/rake rdoc:preview/rake rdoc:server. -
minitest + minitest-snapshot test harness. Snapshots refresh with
UPDATE_SNAPSHOTS=1 rake test. -
SimpleCov C2 (branch) coverage measurement via
COVERAGE=1 rake testorrake coverage. Baseline is 91.19% branch coverage (445 / 488 branches). -
lefthook wiring rubocop / betterleaks / rigor / zizmor on pre-commit and minitest on pre-push.
-
GitHub Actions:
ci.yml(test, lint, workflow-lint) andrelease.yml(workflow_dispatch-only, uses RubyGems trusted publishing — no long-lived API token).
Performance
-
Stats.computerewritten as a single pass with a mutable per-namespace counter array instead of aData#withcascade per edge. On 2016 edges this took the call from 139 ms to 47 ms (3.0×). -
Reachability.walkswapsSetforHash<name, true>+Arrayfrontier, builds only the adjacency direction it actually needs, and the:both-directionwalked_edge_indexesshares one pair of indexed adjacencies between its out-walk and in-walk. Cluster depth-3 outbound: 27 ms → 14 ms (1.9×); both direction: 35 ms → 19 ms (1.8×). -
Edge#dedup_keyis now a generated Data member set once inEdge.buildas a--frozen joined string. Renderer dedup Hashes go fromHash<Array,_>toHash<String,_>, which drove the 1.2× Dot / Mermaid render gain. -
YJIT (
--yjit) adds another ~1.5×. ZJIT measured between baseline and YJIT, and trailed baseline on Stats and CycleDetector — recommendation stays YJIT.