v0.1.0
Initial release. Baseline shipping everything from the Phase 0 spike through Phase 5 (UML class diagram).
Added
- Phase 0: Rigor plugin API spike against
rigortype 0.2.1rbs ~> 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.
[Unreleased]: v0.1.1...HEAD [0.1.1]: v0.1.0...v0.1.1 [0.1.0]: https://github.com/nozomemein/rigor-module-graph/releases/tag/v0.1.0