Repository navigation
fix: record /daily runs before scanning and pause on interrupted runs - #163
Conversation
Between 2026-09-25 and 2026-10-03 seven /daily runs scanned a repo and then ended in curation (a model safety stop) before Phase 6. State was only written there, so last_run stayed stale, the one-scan-per-day rule never fired and every morning spent a fresh scan: seven scans lost, nothing published, nobody told for a week. - scanner/run_orphan_check.py: finds runs_recent entries left in-progress by an earlier day, and scan output newer than last_run with no post and no run record. Exit 2 on any orphan; --write-pause creates .daily-paused, --acknowledge closes them after review (dated state backup, atomic write) - daily command and Codex mirror: open the run record when Phase 2 picks a target, close it in Phase 6, run the check in Phase 0 - tests: 25 cases; 13 realistic mutations of the check are all caught - docs: CLAUDE.md, AGENTS.md, ROADMAP.md Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3297c09292
ℹ️ 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".
| that has neither a post nor a run record. | ||
| """ | ||
| today_day = date.fromisoformat(today) | ||
| entries = [entry for entry in state.get("runs_recent") or [] if isinstance(entry, dict)] |
There was a problem hiding this comment.
Reject a non-list
runs_recent value
If the manually maintained state contains runs_recent as an object or string rather than a list, this comprehension silently discards the malformed history and reports no open record. The fallback may also miss that run because opening a record sets last_run to the scan date and line 150 ignores output written on that same date, allowing the next autonomous scan to proceed without detecting the interruption. Validate the field type and fail closed instead of filtering it away.
AGENTS.md reference: AGENTS.md:L211-L216
Useful? React with 👍 / 👎.
|
|
||
| ## State | ||
| `reports/.daily_state.json` (gitignored): `{"last_run":"YYYY-MM-DD","last_slug":"...","runs":[...]}`. If `last_run == today`, rate-limit to status-only. | ||
| `reports/.daily_state.json` (gitignored): `{"last_run":"YYYY-MM-DD","last_slug":"...","runs":[...]}`. If `last_run == today`, rate-limit to status-only. The run record is opened as soon as Phase 2 picks a target and closed in Phase 6 (same `runs_recent` entry, real outcome; `halted: <reason>` on any early stop). |
There was a problem hiding this comment.
Show
runs_recent in the Codex state example
The Codex /daily state example still models run history under runs, although guardrail 8 calls that key vestigial and run_orphan_check.py reads only runs_recent. An agent following this JSON example can open and close the wrong list; since it also sets last_run, the same-day report-directory fallback will not detect the interrupted run later. Change the example key to runs_recent so the Codex and Claude workflows describe the same schema.
AGENTS.md reference: AGENTS.md:L3-L4
Useful? React with 👍 / 👎.
| for orphan in orphans: | ||
| if orphan.kind == UNRECORDED_SCAN: | ||
| entries.append({"date": today, "slug": orphan.slug, "outcome": note}) | ||
| changed += 1 |
There was a problem hiding this comment.
Preserve the scan date when acknowledging output
When an unrecorded scan created today is acknowledged, this appends a record dated today but leaves last_run unchanged. Phase 0 rate-limits exclusively through last_run, so after the user deletes the pause file and resumes on the same day, the pipeline treats the day as unused and can scan a second repository. Preserve the detected output date and advance last_run for a current-day acknowledged scan, without charging historical acknowledgments to today.
AGENTS.md reference: AGENTS.md:L249-L249
Useful? React with 👍 / 👎.
| ## Phase 2 — Candidate discovery + pre-check | ||
| `gh search repos --language=python --stars=1500..6000 --sort=updated` filtered to AI/agent/LLM/RAG/inference. Drop already-scanned slugs. Responsiveness check (recent closed issues + merged PRs from ≥2 contributors). Strict-norm detection → publication mode. Pick ONE; record why. | ||
| `gh search repos --language=python --stars=1500..6000 --sort=updated` filtered to AI/agent/LLM/RAG/inference. Drop already-scanned slugs. Responsiveness check (recent closed issues + merged PRs from ≥2 contributors). Strict-norm detection → publication mode. Pick ONE; record why. Then open the run record before Phase 3. |
There was a problem hiding this comment.
Skip record creation during Codex dry runs
This instruction unconditionally opens a run record after target selection, including in --dry-run, while the parallel Claude workflow explicitly says that dry runs open no record. Because opening the record also sets last_run = today, a Codex dry run consumes the daily quota and causes a later real invocation that day to downgrade to status-only. Add the same --dry-run exemption here to preserve runtime parity and dry-run semantics.
AGENTS.md reference: AGENTS.md:L3-L4
Useful? React with 👍 / 👎.
Why
Between 2026-09-25 and 2026-10-03 seven
/dailyruns scanned a repo and then ended in curation (a model safety stop; the headless logs end withAPI Error: ... safeguards flagged this session ... Details: [cyber]) before Phase 6 wrote any state.last_runstayed 2026-09-28, the one-scan-per-day rule never fired, and every morning spent a fresh scan: seven scans lost, nothing published, nobody told for a week. The pipeline has been paused (.daily-paused) since 2026-10-04.What
scanner/run_orphan_check.py(new CLI, exit 2 on any orphan, same convention asrun_verdict_check.py) findsruns_recententries leftin-progressby an earlier day, and scan output newer thanlast_runwith no post and no run record.--write-pausecreates.daily-pausednaming them (and never overwrites one);--acknowledgecloses them after review (atomic write, dated.bak-<date>backup of the state file)./daily(Claude command and Codex mirror): the run record is opened as soon as Phase 2 picks a target and closed in Phase 6; Phase 0 runs the check and stops on an orphan. Guardrail 10 documents the rule.Not in this PR, because it lives outside the repo: the scheduled wrapper
run-daily.ps1now exits 1 when Claude fails and 3 when the run ended with.daily-pausedpresent. It used to always exit 0, so Task Scheduler showed success for dead runs.Test plan
pytest tests/: 441 passed (25 new, intests/test_orphan_check.py)ruff checkandblack --checkcleanlast_runreset to 2026-09-28, it flags the five scans written after the last good run/dailyrun after merge, watchedLimits
The safety stop itself is platform-side. This makes a dead run visible the next morning and bounds the loss to one scan; it does not prevent the stop.
🤖 Generated with Claude Code