You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Replace the pyreverse-generated PNG UML diagrams with a curated, auto-generated mermaid class diagram embedded in ARCHITECTURE.md. Mermaid is plain text (useful for AI agents reading the repo) and renders as a clean diagram on GitHub and in Sphinx (useful for humans). This supersedes #814 and removes the graphviz/pylint dependency and the weekly auto-PR workflow.
Motivation
The current pyreverse -o png diagrams (docs/source/_static/classes.png, packages.png) are near-useless: every class is dumped with full attribute lists and long method signatures.
PNG images cannot be read by AI agents at all, so they do nothing for the goal ARCHITECTURE.md serves (orienting agents to repo structure).
The PNGs are only referenced in CONTRIBUTING.md; they are not part of the rendered Sphinx docs.
Feasibility findings (already verified locally)
The installed pylint 4.0.4pyreverse can already emit mermaid via -o mmd, so mermaid output needs no new tooling and no unreleased pylint.
Raw pyreverse -o mmd is 714 lines of attribute/signature bloat — the exact problem we want to avoid.
pyreverse -o mmd -k (class names only) is 136 lines, no signatures (sidesteps Use pyreverse --no-signatures for UML diagrams once pylint 4.1 is released #814), but it is a flat, alphabetical, ungrouped dump and it drops every BaseExperiment -> subclass inheritance arrow (the most important hierarchy in the repo). So zero-code pyreverse-mermaid removes the bloat but is still incomplete and ungrouped.
pyreverse offers no "member names without signatures" mode: it is all-or-nothing (-k strips members entirely; default dumps full signatures; --no-signatures is the unreleased pylint 4.1 feature from Use pyreverse --no-signatures for UML diagrams once pylint 4.1 is released #814). The desired output — attribute and method names but no parameter/return signatures — therefore requires a small custom generator regardless.
The pyreverse packages mermaid diagram is broken: every node renders as class py (dotted-name bug). Useless.
The repo already has AST introspection that does not import causalpy (scripts/_ast_introspection.py), and a drift-check pattern that keeps ARCHITECTURE.md honest (scripts/check_architecture_inventory.py, wired into prek via make check-architecture). A curated mermaid generator should reuse this infrastructure.
Proposed approach
Add a small AST-based generator (reusing scripts/_ast_introspection.py) that emits a curated, subsystem-grouped mermaid class diagram, and embed it directly in ARCHITECTURE.md inside a fenced ```mermaid block.
Each class shows its attribute names and method names, but never full function signatures — methods render as bare name() with no parameters or return types. This is the key difference from raw pyreverse -o png: we keep the member inventory (which orients both humans and agents) while dropping the signature bloat that made the PNGs unreadable. AST gives us member names directly (function defs, annotated/plain assignments) without resolving parameters or types.
Target diagram shape (grouped by subsystem; attribute + method names, no signatures):
BaseExperiment and its 12 subclasses (experiment inventory)
ModelAdapter -> PyMCModelAdapter / SklearnModelAdapter, plus the BaseExperiment *-- ModelAdapter (_model_backend) composition
PyMCModel and its subclasses (the Bayesian model backend)
(Members shown as bare names — e.g. effect_summary(), not effect_summary() EffectSummary — so the diagram stays readable. Subclasses carry their own members the same way; omitted here for brevity.)
Keeping it current
Follow the existing inventory pattern: the generator supports --check (fail if the embedded diagram drifts from the code) and --write/--print (regenerate). Wire --check into prek alongside check-architecture, and add a make target to regenerate. This replaces the weekly cron auto-PR with a deterministic check that runs on every PR.
Decisions confirmed by maintainer
Embed the diagram in ARCHITECTURE.md (agent-readable text + GitHub/Sphinx render for humans).
Replace the PNGs in CONTRIBUTING.md with the mermaid (or a link to the ARCHITECTURE.md diagram).
Delete .github/workflows/uml.yml, the two PNGs, and the pylint docs dependency.
Add scripts/generate_uml_mermaid.py (or extend check_architecture_inventory.py) that builds the curated mermaid from AST via scripts/_ast_introspection.py, with --check / --write / --print modes. It must emit attribute and method names only (strip parameters and return annotations — render methods as name()).
Decide on a marker convention in ARCHITECTURE.md (e.g. <!-- BEGIN AUTO-UML --> / <!-- END AUTO-UML -->) to delimit the auto-generated mermaid block.
Embed the generated mermaid block in ARCHITECTURE.md.
Update CONTRIBUTING.md "Overview of code structure": remove the classes.png / packages.png embeds and make uml, point to the ARCHITECTURE.md mermaid.
Replace the make uml Makefile target with a mermaid regenerate target (e.g. make uml -> runs the generator --write).
Wire --check into .pre-commit-config.yaml (prek) next to the architecture inventory check.
Delete .github/workflows/uml.yml.
Delete docs/source/_static/classes.png and docs/source/_static/packages.png.
Remove pylint (and confirm graphviz is no longer needed) from the relevant dependency group in pyproject.toml; regenerate environment.yml via the prek hook.
Confirm GitHub renders the mermaid in ARCHITECTURE.md; optionally add sphinxcontrib-mermaid if the diagram should also appear in the Sphinx site.
Should the diagram also render in the Sphinx docs site (requires adding sphinxcontrib-mermaid to docs deps), or is GitHub rendering of ARCHITECTURE.md enough?
Include the Check hierarchy in the main diagram, or keep the main diagram to experiments/models/pipeline and add checks as a second smaller diagram?
One combined diagram vs. a few small per-subsystem diagrams (smaller diagrams render and diff more cleanly).
Replace pyreverse PNG UML with auto-generated mermaid overview (humans + agents)
Summary
Replace the pyreverse-generated PNG UML diagrams with a curated, auto-generated mermaid class diagram embedded in
ARCHITECTURE.md. Mermaid is plain text (useful for AI agents reading the repo) and renders as a clean diagram on GitHub and in Sphinx (useful for humans). This supersedes #814 and removes the graphviz/pylint dependency and the weekly auto-PR workflow.Motivation
pyreverse -o pngdiagrams (docs/source/_static/classes.png,packages.png) are near-useless: every class is dumped with full attribute lists and long method signatures.pylint(>=4.1) just to get--no-signatures. That has been pending for months with no release in sight.ARCHITECTURE.mdserves (orienting agents to repo structure).CONTRIBUTING.md; they are not part of the rendered Sphinx docs.Feasibility findings (already verified locally)
pylint 4.0.4pyreversecan already emit mermaid via-o mmd, so mermaid output needs no new tooling and no unreleased pylint.pyreverse -o mmdis 714 lines of attribute/signature bloat — the exact problem we want to avoid.pyreverse -o mmd -k(class names only) is 136 lines, no signatures (sidesteps Use pyreverse --no-signatures for UML diagrams once pylint 4.1 is released #814), but it is a flat, alphabetical, ungrouped dump and it drops everyBaseExperiment-> subclass inheritance arrow (the most important hierarchy in the repo). So zero-code pyreverse-mermaid removes the bloat but is still incomplete and ungrouped.-kstrips members entirely; default dumps full signatures;--no-signaturesis the unreleased pylint 4.1 feature from Use pyreverse --no-signatures for UML diagrams once pylint 4.1 is released #814). The desired output — attribute and method names but no parameter/return signatures — therefore requires a small custom generator regardless.packagesmermaid diagram is broken: every node renders asclass py(dotted-name bug). Useless.causalpy(scripts/_ast_introspection.py), and a drift-check pattern that keepsARCHITECTURE.mdhonest (scripts/check_architecture_inventory.py, wired into prek viamake check-architecture). A curated mermaid generator should reuse this infrastructure.Proposed approach
Add a small AST-based generator (reusing
scripts/_ast_introspection.py) that emits a curated, subsystem-grouped mermaid class diagram, and embed it directly inARCHITECTURE.mdinside a fenced ```mermaid block.Each class shows its attribute names and method names, but never full function signatures — methods render as bare
name()with no parameters or return types. This is the key difference from rawpyreverse -o png: we keep the member inventory (which orients both humans and agents) while dropping the signature bloat that made the PNGs unreadable. AST gives us member names directly (function defs, annotated/plain assignments) without resolving parameters or types.Target diagram shape (grouped by subsystem; attribute + method names, no signatures):
BaseExperimentand its 12 subclasses (experiment inventory)ModelAdapter->PyMCModelAdapter/SklearnModelAdapter, plus theBaseExperiment *-- ModelAdapter(_model_backend) compositionPyMCModeland its subclasses (the Bayesian model backend)Stepprotocol ->EstimateEffect/SensitivityAnalysis/GenerateReportCheckand its subclassesExample output (prototype):
classDiagram class BaseExperiment { +data +idata +labels +model +supports_bayes +supports_ols +effect_summary() +fit() +generate_report() +get_plot_data() +plot() +print_coefficients() } class ModelAdapter { +fit() +predict() +score() } class PyMCModel { +idata +fit() +predict() +score() +calculate_impact() } class Step { +run() } BaseExperiment <|-- InterruptedTimeSeries BaseExperiment <|-- PiecewiseITS BaseExperiment <|-- DifferenceInDifferences BaseExperiment <|-- StaggeredDifferenceInDifferences BaseExperiment <|-- SyntheticControl BaseExperiment <|-- SyntheticDifferenceInDifferences BaseExperiment <|-- RegressionDiscontinuity BaseExperiment <|-- RegressionKink BaseExperiment <|-- PrePostNEGD BaseExperiment <|-- InversePropensityWeighting BaseExperiment <|-- InstrumentalVariable BaseExperiment <|-- PanelRegression ModelAdapter <|-- PyMCModelAdapter ModelAdapter <|-- SklearnModelAdapter BaseExperiment "1" *-- "1" ModelAdapter : _model_backend PyMCModel <|-- LinearRegression PyMCModel <|-- WeightedSumFitter PyMCModel <|-- SoftmaxWeightedSumFitter PyMCModel <|-- SyntheticDifferenceInDifferencesWeightFitter PyMCModel <|-- InstrumentalVariableRegression PyMCModel <|-- PropensityScore PyMCModelAdapter ..> PyMCModel : wraps Step <|.. EstimateEffect Step <|.. SensitivityAnalysis Step <|.. GenerateReport(Members shown as bare names — e.g.
effect_summary(), noteffect_summary() EffectSummary— so the diagram stays readable. Subclasses carry their own members the same way; omitted here for brevity.)Keeping it current
Follow the existing inventory pattern: the generator supports
--check(fail if the embedded diagram drifts from the code) and--write/--print(regenerate). Wire--checkinto prek alongsidecheck-architecture, and add amaketarget to regenerate. This replaces the weekly cron auto-PR with a deterministic check that runs on every PR.Decisions confirmed by maintainer
ARCHITECTURE.md(agent-readable text + GitHub/Sphinx render for humans).CONTRIBUTING.mdwith the mermaid (or a link to theARCHITECTURE.mddiagram)..github/workflows/uml.yml, the two PNGs, and thepylintdocs dependency.Tasks
scripts/generate_uml_mermaid.py(or extendcheck_architecture_inventory.py) that builds the curated mermaid from AST viascripts/_ast_introspection.py, with--check/--write/--printmodes. It must emit attribute and method names only (strip parameters and return annotations — render methods asname()).ARCHITECTURE.md(e.g.<!-- BEGIN AUTO-UML -->/<!-- END AUTO-UML -->) to delimit the auto-generated mermaid block.ARCHITECTURE.md.CONTRIBUTING.md"Overview of code structure": remove theclasses.png/packages.pngembeds andmake uml, point to theARCHITECTURE.mdmermaid.make umlMakefile target with a mermaid regenerate target (e.g.make uml-> runs the generator--write).--checkinto.pre-commit-config.yaml(prek) next to the architecture inventory check..github/workflows/uml.yml.docs/source/_static/classes.pnganddocs/source/_static/packages.png.pylint(and confirmgraphvizis no longer needed) from the relevant dependency group inpyproject.toml; regenerateenvironment.ymlvia the prek hook.ARCHITECTURE.md; optionally addsphinxcontrib-mermaidif the diagram should also appear in the Sphinx site.Open questions
sphinxcontrib-mermaidto docs deps), or is GitHub rendering ofARCHITECTURE.mdenough?Checkhierarchy in the main diagram, or keep the main diagram to experiments/models/pipeline and add checks as a second smaller diagram?Reference
--no-signaturesonce pylint 4.1 releases).scripts/_ast_introspection.py,scripts/check_architecture_inventory.py,make check-architecture.