Fix: registered algorithms silently produced no graph via the CLI - #38
Merged
Conversation
discover's if/elif chain covers only the built-ins and had no else, so --algorithm <plugin-name> passed validation, printed "Results saved to...", exited 0, and wrote a summary.json with no graph at all. Reproduced with a real pip-installed third-party package before fixing, and again after. - cli.py: added the else branch. Runs run_algorithm(df=df, ci_test=ci, max_lag=max_lag), saves estimated_graph.npy like every other branch. The edge-list/diagnostics code after the chain already reloads the graph from disk, so it picks this up for free. - algorithms/__init__.py: added entry-point discovery, so an installed distribution reaches the causal-ts command without the caller importing anything. list_algorithms() builds --algorithm's choices at cli.py import time, and entry points are scanned inside it, so no cli.py change was needed for this half. Scans once, lazily. A plugin that fails to import warns and is skipped; a plugin can never shadow a built-in name. - cli.py: --validate is rejected for plugins. Its bootstrap re-discovery closure only special-cases cdnots/cdnots+ and otherwise re-runs CEDAR -- dead code for grace/grace-ss (rejected earlier, same file), but the new else-branch makes it reachable for plugins, where it would silently annotate the plugin's edges with CEDAR's persistence values. - custom_algorithm.ipynb: Step 6 claimed "once your module is imported, the CLI picks up your algorithm automatically" -- false, since the CLI runs in a separate process that never imports the caller's code. Replaced with the entry-point workflow that actually works, plus two smaller instances of the same overclaim in cells 0 and 13. Only df/ci_test/max_lag reach a plugin from the CLI; forwarding CDNOTS/CEDAR-specific flags like --alpha or --include-c has no defined meaning for an arbitrary plugin, so that limit is documented rather than guessed at. Tested end to end in a fresh venv with a real pip-installed plugin package (not just python -m / PYTHONPATH tricks): before install, --algorithm rejects the name; after, it appears in --algorithm's choices and produces a real graph via the plain installed causal-ts command; --validate is rejected with nothing written. Built-ins, GRACE's existing --validate guard, and unknown-algorithm rejection all unaffected. 13 new tests, 328/328 full suite, notebook runs clean, lint clean.
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
causal-ts discover --algorithm <plugin>silently produced nothing.discover'sif/elifchain covers only the built-ins and had noelse, so a registered third-partyalgorithm passed validation, printed "Results saved to…", exited 0, and wrote a
summary.jsonwith no graph at all.cli.py— added theelsebranch: runsrun_algorithm(...)and savesestimated_graph.npylike every other branch. The edge-list/diagnostics code after thechain already reloads the graph from disk, so it picks this up for free.
algorithms/__init__.py— addedcausalts.algorithmsentry-point discovery, so aninstalled distribution reaches the
causal-tscommand without the caller importinganything. Scans once, lazily; a broken plugin warns and is skipped; a plugin can never
shadow a built-in name.
cli.py—--validateis now rejected for plugins. Its bootstrap re-discoveryclosure only special-cases
cdnots/cdnots+and otherwise re-runs CEDAR — dead codefor
grace/grace-ss(rejected earlier in the same file), but the newelsebranchmakes it reachable for plugins, where it would have silently annotated the plugin's
edges with CEDAR's persistence values.
custom_algorithm.ipynb— Step 6 claimed "once your module is imported, the CLIpicks up your algorithm automatically." That can't work: the CLI is a separate process
that never imports the caller's code. Replaced with the entry-point workflow that
actually works, plus two smaller instances of the same overclaim in cells 0 and 13.
Only
df/ci_test/max_lagreach a plugin from the CLI. Forwarding CDNOTS/CEDAR-specificflags like
--alphaor--include-chas no defined meaning for an arbitrary plugin, sothat limit is documented rather than guessed at.
Test plan
causal-tsconsole script(not
python -m/PYTHONPATH): before install--algorithm grangeris rejected;after install it appears in
--algorithm's choices and produces a real 7-edge graph--validate+ plugin → cleanBadParameter, exit 2, nothing written--validatestill works (persistence.npywritten); GRACE's existing--validateguard still fires; unknown algorithm still rejectedcustom_algorithm.ipynbexecutes 0 errors