Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions .github/workflows/docs-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,12 @@ permissions:
jobs:
doc-snippets:
name: Validate RST code snippets
# Skip unrelated label churn: a non-ready-for-ci label add/remove won't run this job.
if: >-
github.event_name != 'pull_request'
|| contains(github.event.pull_request.labels.*.name, 'ready-for-ci')
|| (contains(github.event.pull_request.labels.*.name, 'ready-for-ci')
&& (github.event.action != 'labeled' && github.event.action != 'unlabeled'
|| github.event.label.name == 'ready-for-ci'))
runs-on: ubuntu-latest

steps:
Expand All @@ -63,15 +66,18 @@ jobs:

- name: Run doc snippet tests in pure Python mode
# PYTHONPATH=. lets the test import diff_diff directly from
# source without invoking the maturin/Rust build (mirrors Pure
# Python Fallback at rust-test.yml:189-193).
# source without invoking the maturin/Rust build (mirrors the
# `python-fallback` job in rust-test.yml).
run: PYTHONPATH=. DIFF_DIFF_BACKEND=python pytest tests/test_doc_snippets.py -v

sphinx-build:
name: Sphinx HTML build (-W warnings as errors)
# Skip unrelated label churn: a non-ready-for-ci label add/remove won't run this job.
if: >-
github.event_name != 'pull_request'
|| contains(github.event.pull_request.labels.*.name, 'ready-for-ci')
|| (contains(github.event.pull_request.labels.*.name, 'ready-for-ci')
&& (github.event.action != 'labeled' && github.event.action != 'unlabeled'
|| github.event.label.name == 'ready-for-ci'))
runs-on: ubuntu-latest

steps:
Expand Down Expand Up @@ -104,9 +110,12 @@ jobs:

docs-deps-py39-smoke:
name: Validate docs deps install on Python 3.9 (floor compat)
# Skip unrelated label churn: a non-ready-for-ci label add/remove won't run this job.
if: >-
github.event_name != 'pull_request'
|| contains(github.event.pull_request.labels.*.name, 'ready-for-ci')
|| (contains(github.event.pull_request.labels.*.name, 'ready-for-ci')
&& (github.event.action != 'labeled' && github.event.action != 'unlabeled'
|| github.event.label.name == 'ready-for-ci'))
runs-on: ubuntu-latest

steps:
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/notebooks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@ permissions:
jobs:
execute-notebooks:
name: Execute tutorial notebooks
# Skip unrelated label churn: a non-ready-for-ci label add/remove won't run this job.
if: >-
github.event_name != 'pull_request'
|| contains(github.event.pull_request.labels.*.name, 'ready-for-ci')
|| (contains(github.event.pull_request.labels.*.name, 'ready-for-ci')
&& (github.event.action != 'labeled' && github.event.action != 'unlabeled'
|| github.event.label.name == 'ready-for-ci'))
runs-on: ubuntu-latest

steps:
Expand Down
29 changes: 26 additions & 3 deletions .github/workflows/rust-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ on:
- 'tools/**'
- 'pyproject.toml'
- '.github/workflows/rust-test.yml'
# docs-tests.yml / notebooks.yml / ci-gate.yml carry ready-for-ci label
# contracts locked by TestCiWorkflowLabelEventGuard in
# tests/test_openai_review.py; include them so a regression there triggers
# this suite (enforced by TestRustTestWorkflowPathFilter).
- '.github/workflows/docs-tests.yml'
- '.github/workflows/notebooks.yml'
- '.github/workflows/ci-gate.yml'
# The AI-review surfaces below are tested by
# tests/test_openai_review.py (TestWorkflowPromptHardening,
# TestAdaptReviewCriteria, etc.). Without these path filters, a
Expand All @@ -33,6 +40,13 @@ on:
- 'tools/**'
- 'pyproject.toml'
- '.github/workflows/rust-test.yml'
# docs-tests.yml / notebooks.yml / ci-gate.yml carry ready-for-ci label
# contracts locked by TestCiWorkflowLabelEventGuard in
# tests/test_openai_review.py; include them so a regression there triggers
# this suite (enforced by TestRustTestWorkflowPathFilter).
- '.github/workflows/docs-tests.yml'
- '.github/workflows/notebooks.yml'
- '.github/workflows/ci-gate.yml'
- '.github/workflows/ai_pr_review.yml'
- '.github/codex/prompts/pr_review.md'
- '.claude/scripts/openai_review.py'
Expand All @@ -47,9 +61,12 @@ jobs:
# Run Rust unit tests on all platforms
rust-tests:
name: Rust Unit Tests (${{ matrix.os }})
# Skip unrelated label churn: a non-ready-for-ci label add/remove won't run this job.
if: >-
github.event_name != 'pull_request'
|| contains(github.event.pull_request.labels.*.name, 'ready-for-ci')
|| (contains(github.event.pull_request.labels.*.name, 'ready-for-ci')
&& (github.event.action != 'labeled' && github.event.action != 'unlabeled'
|| github.event.label.name == 'ready-for-ci'))
runs-on: ${{ matrix.os }}
env:
PYO3_USE_ABI3_FORWARD_COMPATIBILITY: 1
Expand Down Expand Up @@ -83,9 +100,12 @@ jobs:
# Build and test with Python on multiple platforms
python-tests:
name: Python Tests (${{ matrix.os }}, py${{ matrix.python-version }})
# Skip unrelated label churn: a non-ready-for-ci label add/remove won't run this job.
if: >-
github.event_name != 'pull_request'
|| contains(github.event.pull_request.labels.*.name, 'ready-for-ci')
|| (contains(github.event.pull_request.labels.*.name, 'ready-for-ci')
&& (github.event.action != 'labeled' && github.event.action != 'unlabeled'
|| github.event.label.name == 'ready-for-ci'))
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
Expand Down Expand Up @@ -190,9 +210,12 @@ jobs:
# Test pure Python fallback (without Rust extension)
python-fallback:
name: Pure Python Fallback
# Skip unrelated label churn: a non-ready-for-ci label add/remove won't run this job.
if: >-
github.event_name != 'pull_request'
|| contains(github.event.pull_request.labels.*.name, 'ready-for-ci')
|| (contains(github.event.pull_request.labels.*.name, 'ready-for-ci')
&& (github.event.action != 'labeled' && github.event.action != 'unlabeled'
|| github.event.label.name == 'ready-for-ci'))
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
Expand Down
1 change: 0 additions & 1 deletion TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,6 @@ Deferred items from PR reviews that were not addressed before merge.
|-------|----------|----|----------|
| ImputationDiD event-study SEs recompute full conservative variance per horizon (should cache A0/A1 factorization) | `imputation.py` | #141 | Low |
| Rust faer SVD ndarray-to-faer conversion overhead (minimal vs SVD cost) | `rust/src/linalg.rs:67` | #115 | Low |
| Unrelated label events (e.g., adding `bug` label) re-trigger CI workflows when `ready-for-ci` is already present; filter `labeled`/`unlabeled` events to only `ready-for-ci` transitions | `.github/workflows/rust-test.yml`, `notebooks.yml`, `docs-tests.yml` | #269 | Low |
| `bread_inv` as a performance kwarg on `compute_robust_vcov` to avoid re-inverting `(X'WX)` when the caller already has it. Deferred from Phase 1a for scope. HC2 and HC2+BM both need the bread inverse, so a shared hint would save one `np.linalg.solve` per sandwich. | `linalg.py::compute_robust_vcov` | Phase 1a | Low |
| MPD cluster+hc2_bm path computes CR2 precomputes twice — once via `solve_ols` → `_compute_cr2_bm` for vcov + per-coefficient DOF, then again via `_compute_cr2_bm_contrast_dof` from `MultiPeriodDiD.fit()` for the post-period-average contrast DOF. Both rebuild `H = X bread_inv X'`, the residual-maker `M`, and the per-cluster `A_g = (I - H_gg)^{-1/2}` matrices. O(n²k) redundant work; acceptable for typical cluster-robust DiD panel sizes (n ≤ a few thousand). Fix would plumb the contrast DOF through the existing CR2 vcov path (intrusive API change) or share the precomputes via a cached helper. | `linalg.py::_compute_cr2_bm_contrast_dof`, `estimators.py::MultiPeriodDiD.fit` | follow-up | Low |
| Rust-backend HC2 implementation. Current Rust path only supports HC1; HC2 and CR2 Bell-McCaffrey fall through to the NumPy backend. For large-n fits this is noticeable. | `rust/src/linalg.rs` | Phase 1a | Low |
Expand Down
Loading
Loading