fix(liveness): make the sweep importable when run by file path - #3199
Conversation
The health-40 liveness job has never worked. Its first real CI run died on
ModuleNotFoundError: No module named 'scripts'
health-40 runs `python scripts/workflow_startup_failure_diagnostic.py
--sweep`, and docs/INTEGRATION_GUIDE.md documents the same file-path form.
Running a file by path does not put the repo root on sys.path, so
`from scripts import api_client` cannot resolve. The documented per-run
recipe was broken the same way, and predates this module's sweep support.
I verified the sweep locally with PYTHONPATH set and via `python -m`, then
wrote a workflow step that used neither. Every local check passed while the
job failed on every run. A module whose entire purpose is noticing that a
workflow stopped executing, shipped in a form that could not execute.
Uses the same bootstrap as the other ten scripts here that import
`from scripts import ...` while being invoked by path
(scripts/docs_drift_fix_agent.py:33-37).
The regression guard runs the REAL invocation - the script by path, in a
subprocess, with PYTHONPATH stripped from the environment - rather than the
convenient one. Removing the bootstrap fails it; reverting restores 36/36.
Separately observed while verifying, NOT fixed here and not caused by this:
health-42-actionlint.yml:31-32 evaluates
`fromJson(github.event.inputs || '{}')`. On workflow_dispatch WITH inputs,
github.event.inputs is an object rather than a JSON string, so fromJson
fails with "Unexpected character encountered while parsing value: O". It
only breaks the dispatch-with-inputs path; scheduled runs pass because
inputs is null. Present since at least 2026-06.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 42 minutes Limit details: You’ve used the included review currently available. Your 75 included PR review attempts over the past 7 days set your current allowance at 1 review per hour. Your organization has reached its usage spending cap. Adjust your spending cap in the billing tab. How can I continue?Wait for the limit to reset, then comment An organization admin can change what happens after included review limits in Billing. How do review limits work?CodeRabbit enforces per-developer PR review limits within each organization. For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 251f341a12
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| """ | ||
| root = Path(__file__).resolve().parents[2] | ||
| script = root / "scripts" / "workflow_startup_failure_diagnostic.py" | ||
| env = {k: v for k, v in os.environ.items() if k != "PYTHONPATH"} |
There was a problem hiding this comment.
Test the file-path invocation without undeclared packages
In the checked health-40-sweep.yml workflow, the liveness job only runs actions/setup-python before invoking this script; it never installs project dependencies. This test removes only PYTHONPATH, so under the normal pytest environment it inherits the installed requests package and passes, whereas a clean setup-python interpreter gets past the new path bootstrap and immediately fails in scripts/api_client.py with ModuleNotFoundError: No module named 'requests'. Thus the scheduled liveness job remains unable to run; either install the dependency in that job, remove the diagnostic's third-party runtime dependency, or exercise the subprocess with an actually clean Python environment.
Useful? React with 👍 / 👎.
Automated Status SummaryHead SHA: fd5a508
Coverage Overview
Coverage Trend
Top Coverage Hotspots (lowest coverage)
Low Coverage Files (<50.0%)
Updated automatically; will refresh on subsequent CI/Docker completions. Keepalive checklistScopeNo scope information available Tasks
Acceptance criteria
|
Second CI failure of the liveness job, same class as the first. With the sys.path bootstrap in (#3199) the import resolves, and the job then died on ModuleNotFoundError: No module named 'requests' scripts/api_client imports requests; the job checked out the repo, set up Python, and ran the sweep without installing anything. My machine had requests, the runner did not. Installs only that one package, with the pin read from requirements.txt rather than written out again: `pip install -r requirements.txt` would drag langchain, faiss, pandas and numpy onto a read-only sweep, and a second literal pin is exactly the drift that file's own header warns about (#2404). Fails loudly if the pin disappears rather than silently installing floating requests. Verified in a reproduction of the runner instead of my shell: fresh venv, only requests==2.34.2 installed, PYTHONPATH stripped, script invoked by path. It runs and reports correctly - 2 held, both the deliberately unapproved probes, with the review verdicts intact. Co-authored-by: Tim Stranske <tim@stranskemo.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
The liveness job has never worked
Its first real CI run died immediately:
health-40runspython scripts/workflow_startup_failure_diagnostic.py --sweep, anddocs/INTEGRATION_GUIDE.mddocuments the same file-path form. Running a file by path does not put the repo root onsys.path, sofrom scripts import api_clientcannot resolve. The documented per-run recipe was broken the same way, and that predates the sweep.How I shipped it broken
I verified the sweep locally with
PYTHONPATHset and viapython -m, then wrote a workflow step that used neither. Every local check passed while the job failed on every run.A module whose entire purpose is noticing that a workflow stopped executing, shipped in a form that could not execute. Same class of defect, one level up.
The fix
The bootstrap already used by the other ten scripts here that import
from scripts import …while being invoked by path (scripts/docs_drift_fix_agent.py:33-37):This also repairs the documented
--run-idrecipe, which had the same defect.The guard runs the real invocation
test_script_runs_when_invoked_by_path_without_pythonpathexecutes the script by path, in a subprocess, withPYTHONPATHstripped from the environment — deliberately the invocation CI uses rather than the convenient one that hid this. Removing the bootstrap fails it; reverting restores 36/36.Also observed, not fixed here, not caused by this
health-42-actionlint.yml:31-32evaluatesfromJson(github.event.inputs || '{}'). Onworkflow_dispatchwith inputs,github.event.inputsis an object rather than a JSON string, sofromJsonfails withUnexpected character encountered while parsing value: O(theOisObject). It breaks only the dispatch-with-inputs path — scheduled runs pass becauseinputsis null — and has been present since at least 2026-06. Surfaced because I dispatched health-40 withrun_branch_protection=falseto verify the liveness job in isolation.🤖 Generated with Claude Code