Skip to content

Add LUCID to the CLI, inspect, skill, notebook and llms.txt - #37

Merged
fesanghary merged 1 commit into
mainfrom
lucid-integration
Aug 28, 2026
Merged

Add LUCID to the CLI, inspect, skill, notebook and llms.txt#37
fesanghary merged 1 commit into
mainfrom
lucid-integration

Conversation

@fesanghary

Copy link
Copy Markdown
Contributor

Summary

LUCID was reachable only from Python. Adds the four surfaces every other algorithm
already has.

  • CLIcausal-ts deconfound GRAPH --data CSV [--strategy adaptive|tetrad|pds],
    post-processing a graph saved by discover. Not registered in discover --algorithm:
    LUCID corrects a graph, it doesn't discover one.
  • inspectfacts["latent_factor"] {detected, spectral_ratio, tau}, taken from
    LUCID's own router so the two can't drift. recommend_config suggests .deconfound()
    only when detected is True, and never changes the algorithm/CI-test choice.
  • skillSKILL.md surfaces latent_factor, plus a "many contemporaneous edges →
    deconfound" step in the interpretation playbook.
  • notebook — new section 5 (5–9 renumbered). CDNOTS reports 23 spurious lag-0 edges;
    .deconfound() removes all 23 and keeps every true edge (F1 0.20 → 0.86). One lag-1
    false positive survives, which the notebook points out rather than hides.
  • llms.txt — adds LUCID.

detected is tri-state on purpose: False means no factor structure this test can see
not "no confounding", since a 2–3 variable confounder leaves no dominant
eigenvalue and stays invisible. None means the check couldn't run (NaN, d<2,
T<d+3), kept distinct from False so "didn't check" is never read as "checked and
found nothing".

Drive-by fixes

Both were blocking or actively wrong, and are in files this PR already touches:

  • api_reference.ipynb wouldn't execute: run_cdnots_gated unpacked as a 3-tuple, the
    p-value demo needed return_pvals=True, and a wrap_graph table predated
    GraceResult inheriting the DoWhy methods.
  • llms.txt's GRACE snippets unpacked run_cdnots_gated / run_stability_selection
    as 3-tuples — both return a single GraceResult, so the documented code raised
    TypeError for anyone following it.
  • Two LucidResult docstrings conflated the router's "pervasive" label with any
    detected factor: R > tau selects sf or pervasive (only regime says which),
    and n_factors counts eigenvalues above the MP bulk regardless of regime
    (verified: sf → 1, pervasive → 2, sparse → 0).

Test plan

  • 315/315 tests — 7 new, covering detection on pervasive vs full-rank data, all
    three guard paths (returning None, not False), nudge-only-on-positive, and
    that algorithm choice is unaffected
  • api_reference.ipynb executes end to end: 0 error cells
  • CLI exercised end to end (generatediscoverdeconfound) for all three
    strategies plus --json and the ignored-flag warning
  • python-lint job: black(24 pin) / isort / flake8, exact CI invocation
  • super-linter: markdownlint clean on SKILL.md, codespell clean on all
    changed files; no YAML/shell/workflow files touched
  • sphinx-build warning set identical to baseline

LUCID was reachable only from Python. Adds the four surfaces every other
algorithm already has.

- CLI: `causal-ts deconfound GRAPH --data CSV [--strategy adaptive|tetrad|pds]`
  post-processes a graph saved by `discover`. Not registered in
  `discover --algorithm`: LUCID corrects a graph, it doesn't discover one.
- inspect: facts["latent_factor"] {detected, spectral_ratio, tau}, taken from
  LUCID's own router. recommend_config suggests .deconfound() only when detected
  is True, and never changes the algorithm/CI-test choice. detected is tri-state:
  False means no factor structure this test can see, not "no confounding" (a 2-3
  variable confounder is invisible to it); None means the check couldn't run
  (NaN, d<2, T<d+3).
- skill: SKILL.md surfaces latent_factor with that caveat, plus a "many
  contemporaneous edges -> deconfound" step in the playbook.
- notebook: new section 5, sections 5-9 renumbered. CDNOTS reports 23 spurious
  lag-0 edges; .deconfound() removes all 23 and keeps every true edge
  (F1 0.20 -> 0.86). Also fixes three stale spots: run_cdnots_gated unpacked as
  a 3-tuple, the p-value demo needing return_pvals=True, and a wrap_graph table
  that predates GraceResult inheriting the DoWhy methods.
- llms.txt: adds LUCID; also fixes the GRACE snippets, which unpacked
  run_cdnots_gated / run_stability_selection as 3-tuples (both return a single
  GraceResult, so the documented code raised TypeError).

Also corrects two LucidResult docstrings that conflated the router's
"pervasive" label with any detected factor: `R > tau` selects sf or pervasive
(only regime says which), and n_factors counts eigenvalues above the MP bulk
regardless of regime (sf -> 1, pervasive -> 2, sparse -> 0).

315/315 tests (7 new), notebook runs clean, lint clean.
@fesanghary
fesanghary requested a review from a team as a code owner August 28, 2026 02:59
@github-actions

Copy link
Copy Markdown

⚠️ Deprecation Warning: The deny-licenses option is deprecated for possible removal in the next major release. For more information, see issue 997.

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@fesanghary
fesanghary merged commit 677d118 into main Aug 28, 2026
10 checks passed
@fesanghary
fesanghary deleted the lucid-integration branch August 30, 2026 00:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant