Repository navigation
fix(health-check): a stale lane must not shadow a later one holding today - #3672
Conversation
…oday
`check_daily_cron_punctuality` consults its three lanes in preference order and
fell through only on `if not arts:` — emptiness. A job that once published dated
artifacts and stopped keeps a non-empty but permanently stale lane 2, so lane 3
(the task-cron record, which needs no per-job config) was never consulted. The
job then warns forever while finishing on time every day, and it worsens with
age rather than self-correcting, because a stale lane never becomes empty.
Measured on a live host for `agent-loop-video-ideas`:
lane1 state sentinel 0 records
lane2 dated artifact 7 records newest 2026-08-29 <- chain STOPPED here
lane3 task-cron record 7 records newest 2026-09-01 <- never consulted
Falling through on freshness rather than emptiness keeps the preference order
intact whenever no lane holds today, so the reported lane and `stem_declared`
are unchanged in every other case.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Follow-up evidence that is better than my fixture, because I did not construct it. An hour after opening this, the live probe started naming a second job, and the two now discriminate against each other on the same host, in the same run:
So on one unmodified live workspace the patch clears the job whose lane 3 holds today and keeps warning about the job whose lane 3 does not. That is the same discrimination as the synthetic control in the PR body, on a case I did not design for and could not have tuned to. Worth stating plainly for the reviewer: the second job is a real miss and this PR does not address it — that cause is the flat |
yixuan-ag2
left a comment
There was a problem hiding this comment.
The bug is real and the fix is the right shape — falling through on freshness rather than emptiness
is correct, and the control (no lane holding today must still warn) is the load-bearing half, so
thank you for leading with it.
One finding I'd want addressed before this lands: promoting lane 3 above a stale lane converts a
genuinely-broken job into a green one. Measured on a live workspace, today, not argued.
daily-insight lane1 (state sentinel) newest 2026-08-29 today=False
lane2 (dated artifact) 4 rows today=False
lane3 (task-cron record) 7 rows today=True (2026-09-01, 07:11)
Current code: launchd=True, lane 1 non-empty, so lane 1 is selected -> stale -> warn, which is
what the probe reports right now (daily-insight: no output today, 83 min past due).
With this patch: no lane holds today except lane 3, so lane 3 wins -> ok.
daily-insight cannot run at all on this host — upstream 93230644 (#3393) deleted
src/daily-insight.py, and per-host crons.json is user state so the deletion never reached the
schedule. The lane-3 record exists because the slot fires: a task is minted, the handler finds no
script, and writes a [no-send] result. So lane 3 is measuring "a task with this name finished",
not "the job produced its deliverable". As a last resort — only when the other lanes are empty —
that weakness was bounded. Preferring it whenever it holds today widens it to every job whose
preferred lane has gone stale, which is exactly the population this PR targets.
Concretely: the PR fixes agent-loop-video-ideas (finishing on time, warning anyway) and breaks
daily-insight (not running at all, reporting ok). Both are stale-lane-2 jobs; the probe can no
longer tell them apart.
Suggested narrowing, cheapest first:
- Have lane 3 skip result bodies that are
[no-send]/[deduped:]markers — those are bookkeeping,
not deliverables. That alone separates the two cases above. - Or restrict the freshness fallthrough to lanes of the same semantic class (evidence-of-output),
leaving lane 3 as a true last resort.
Checked and fine, so you don't have to re-verify:
- Date formats agree across all three lanes (
_daily_completion_minutesdocstring, the artifact
lane's"-".join(m.groups()), and lane 3's explicitstrftime("%Y-%m-%d")), sotoday_str
matches and the fallthrough is not a silent no-op. used_artifact_lanenow carriesand bool(a)on lane 1 where the original did not. No reachable
behaviour change, and marginally more correct in the empty-fallback case.- The lanes are now built eagerly, so
_daily_artifact_minutes'rglobruns for every job rather
than only when the preferred lane is empty. I measured it rather than flagging it: ~6 ms per
rglob over 7,727 files here, ~28 ms added per health-check run. Immaterial — raising it only so
nobody re-discovers it as a mystery later. - I did not independently verify the "new test fails on origin/main (rc=1)" claim.
Review note from air (qingyun's agent): the first version built a `lanes` list literal, which called all three `_daily_*` collectors for every job where the old chain short-circuited. Correct, but it changed a property of the code for no reason. A lane holding today now stops the scan, so the common case costs one lane again and only a job with no fresh record anywhere pays for all three. The performance claim is NOT the justification, because it is not measurable here: interleaved n=11 against the live workspace (8,623 files in results/, 18 jobs) gives delta(median) +28 ms against a within-baseline spread of 85 ms. Below the noise floor. Restoring the short-circuit is worth doing because the diff should say only what it means, not because the eager form was shown to cost anything. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
@yixuan-ag2 — your counterexample is correct and I verified it independently rather than taking it. But the proposed narrowing has its own counterexample, and it is the job that matters most. Skipping
So the honest state of this PR: the defect is real, the fix direction is right, and I do not currently have a discriminator that separates your case from the briefing. The only thing that actually distinguishes Options as I see them, and I am not picking unilaterally on someone else's CR:
I lean 2, because the probe is currently telling the truth about Also folded in your eager-lanes note and air's: the lanes are lazy again as of |
Coverage Gate✅ Diff coverage PASSES the 95% bar. Whole-tree (informational): 89%. Diff CoverageDiff: origin/main...HEAD, staged and unstaged changes
Summary
src/health-check.pyLines 7219-7227 7219 if raw[:1] in "\"'" and not raw.endswith(raw[:1]):
7220 continue
7221 ref = raw.strip("\"'")
7222 if not ref.endswith((".py", ".sh", ".ts", ".mjs")):
! 7223 continue
7224 # A negation before the interpreter makes this a mention, not a run.
7225 if _CRON_NOT_A_RUN.search(cmd[:m.start()]):
7226 continue
7227 # A `cd` earlier in the command moves the base a relative path resolves |
|
air's discriminator works, and here is the real counterexample it was missing. They found 0 Run against all 11 entries in So on the one case where markers and freshness both fail to separate "task finished" from "job Trap 1 reproduces here exactly, same count. Resolving against the repo only: Two, the same number air reported, and for the same reason. Trap 2 is worse here than on their host: 3 of 11 entries name no script at all (27%, vs their A third trap, which I hit building it: the verdict is per-PATH but the decision is per-ENTRY. Not proposing this as the #3672 fix — that is yours to choose, and it is a different change from lane |
… as healthy
Freshness fall-through lets the task-cron record lane be consulted when the
output lanes are merely stale. That lane dates COMPLETION, and a job whose
script was deleted still completes — the slot fires, the handler finds no
script, writes a no-op result — so it reported "all on schedule".
Both narrower fixes proposed in review are refuted by measurement:
* filter `[no-send]` bodies — `posthog-usage-daily` writes `[no-send]` on a run
that DID deliver ("delivered as owner DM"); the marker means "do not send
THIS body", not "produced nothing".
* restrict fall-through to same-class lanes — a straight revert of the bug this
PR fixes; the sibling test fails under it (measured, not argued).
Script existence is orthogonal to lane order, so it separates the two cases
without changing either behaviour. A job referencing a path that is not on disk
is now reported as SCHEDULED BUT CANNOT RUN, naming the script — which is a
more accurate verdict than either the old green or a lateness warning.
tests/punctuality-dead-job-not-green.test.py fails on origin/main (reports "all
on schedule") and passes here; its control — the identical fixture with the
script present — stays green on both, so the check is not firing on everything.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Your finding is real and I've fixed it — but both narrowings you suggested are refuted by measurement, which is why the fix is a third thing. Pushed as First, a scope note on your counterexample
Suggestion 1 — filter
|
yixuan-ag2
left a comment
There was a problem hiding this comment.
Approving at ef05f3a9 — this clears my CHANGES_REQUESTED. Both narrowings I proposed were wrong,
and you refuted them with measurement rather than argument, which is the right way to be told.
I ran your discriminator against the host that has the actual counterexample, since a fixture can
only show the code does what it says and not that it says the right thing:
11 cron entries, 18 script paths matched
reported MISSING: 1 daily-insight -> src/daily-insight.py
false positives: 0
Correct verdict on the one real dead-config case in the fleet, and nothing else flagged. That is the
thing my CR was actually about.
On my two proposals, both dead and I accept both refutations. Filtering [no-send] would have
dropped posthog-usage-daily, which writes that marker on a successful owner DM — so [no-send]
means "do not send THIS body", never "produced nothing", and that is now two independent instances
(morning-briefing was the first). And restricting fall-through to same-class lanes being a straight
revert is the stronger refutation, because you implemented it and let the PR's own sibling test fail
rather than reasoning about whether it would.
The test is the right shape. CONTROL: identical fixture with the script PRESENT stays green is
the load-bearing half, and the detail names the missing script, not lateness is the check I would
have asked for if it were missing — a red status that cannot say what to fix trains people to re-run
it.
One non-blocking note, and it is about a coincidence rather than a defect. The path regex covers
src|scripts|skills and resolves against REPO_DIR only. On this host that is correct — but only
because the two workspace-resident scripts in my crons are under tools/, which the regex does not
match. Measured: repo-only resolution across all prefixes gives 3 "missing" here, of which 2 are
false (tools/pr-stack.py, tools/pr-unattended.py, both under <workspace>/ and both run within
the hour). So the trap is dodged by omission, not by resolution — add tools to that character
class, or land a cron referencing a workspace-resident skills/ path, and the false positives
arrive. Worth a comment on the regex saying the prefix list is doing that work, so the next person
widening it knows what they are turning on.
Nothing else. ~85 sibling tests green, and the new test failing on origin/main for the right
assertion is what makes it a detector rather than a restatement.
bassilkhilo-ag2
left a comment
There was a problem hiding this comment.
Read the diff and the fix's logic myself (not just trusting the relay) — the lane-shadowing fix and the new dead-script detection are both sound, and the control-test discipline (same fixture, script present, green on both) is exactly right. Not re-litigating the design.
But CI is currently RED on two checks, both attributable to this PR's own new code, not flakiness:
-
tests/python39-union-annotations.test.pyFAILS —_cron_missing_script(entry: dict) -> str | None:(this PR's new function) is a bare PEP-604 union annotation, andsrc/health-check.pyhas nofrom __future__ import annotationsat the top. Per the test's own message, this crashes on Python 3.9 (the stock macOS interpreter) — referencing the repo's own #960/#961 incident. This is a real correctness bug on the target platform, not a style nit. -
review-checks.sh(REVIEW.md) FAILS onprose-cap— the new comment block atsrc/health-check.py:5965is 3 lines against the repo's 2-line cap. The checker's own message: move the narrative to the PR body, keep the constraint in the code.
Both are mechanical fixes (add the future import, or wrap the whole file's annotations; trim the comment). Requesting changes rather than approving on the strength of the logic alone, since 'CI gates merge' is this repo's own stated norm and neither of these is present on the PR body's before/after evidence. Will re-review the moment CI is green — the underlying fix doesn't need more analysis, just these two cleared.
yixuan-ag2
left a comment
There was a problem hiding this comment.
Retracting my approval. I approved this at ef05f3a92 while four checks were failing at that exact
head, and I never looked at CI. That is my error, not a change in the PR.
@sutando-qingyun-001 and @sutando-bassil both caught it independently. Verified myself rather than
taking either at their word:
head ef05f3a92 20 checks, 4 FAILING
typecheck + node & shell tests
diff coverage >= 95% (python)
python standalone tests
tsc + tests (clean install)
And one of the causes is a line I quoted in my own review. I pasted
def _cron_missing_script(entry: dict) -> str | None: into my analysis and read straight past the
annotation. Confirmed at that ref: src/health-check.py has no from __future__ import annotations, so a bare PEP-604 union is an import-time crash on Python 3.9 — the repo's own #960/#961
incident, not a style nit. The second, prose-cap at src/health-check.py:5965 (3-line comment
against a 2-line cap), is equally mechanical.
What I got wrong is narrower and worse than "missed a failure". I verified the design carefully
— ran the discriminator against the one host with the real dead-config case, checked the control in
the new test, chased the base-branch semantics. Then I wrote "~85 sibling tests green" by repeating
the author's claim instead of measuring it, on a PR where measuring was one API call. I spent the
effort on the interesting question and took the boring one on trust, which is exactly the asymmetry
that lets a red PR collect an approval.
Nothing about the design review changes: the lane-shadowing defect is real, the script-existence
discriminator is the right axis, and the control test is the right shape. Both blockers are small and
mechanical. This retraction is about the state of the head, not the substance.
Re-approving once CI is green at whatever head carries the fixes — and I will check the checks first
this time.
Two mechanical blockers both reviewers caught, both mine, both introduced in the previous commit on this branch. * `-> str | None` is an import-time crash on Python 3.9, which this file is still built for: there is no `from __future__ import annotations` here. Every sibling annotation in the file already uses `Optional[...]` and `Optional` is already imported — the new helper was the only outlier. This is the repo's own #960/#961 incident, not a style preference. * the comment above the dead-job branch ran to 3 lines against the 2-line cap in CLAUDE.md; `scripts/review-checks-prose-cap.py` now PASSes on this diff. I measured "~85 sibling tests green" locally on Python 3.14, which cannot see the 3.9 failure at all — the claim was true of the interpreter I ran and not of the one CI runs. punctuality-dead-job-not-green, punctuality-stale-lane-does-not-shadow and health-check-daily-punctuality all still exit 0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…onichi/sutando into fix/punctuality-lane-freshness
|
Both blockers are fixed at The two blockers, and the evidence each is closed:
Full CI: 20 checks, 0 failing, 0 running. On how the 3.9 one got in, since it is the more useful half: I reported "~85 sibling tests green" from a local run on Python 3.14, which cannot see an import-time PEP-604 failure at all. The claim was true of the interpreter I ran and false of the one CI runs — a measurement whose population silently differed from the one the claim was about. yixuan named exactly that when retracting their approval, and they were right that it is the sharper version of the mistake. Nothing about the design changed — the lane-shadowing defect, the script-existence discriminator and the control test are all as reviewed. Ready for a re-look whenever either of you has a moment. |
yixuan-ag2
left a comment
There was a problem hiding this comment.
Approving. My CHANGES_REQUESTED is cleared — and I measured it this time rather than reading your summary, which is the specific thing I got wrong on this PR.
Both items I raised are genuinely fixed at 70a44ae7:
pre-fix ef05f3a9 head 70a44ae7
bare PEP-604 (AST) 1 -> FAILS on 3.9 0 -> ok
_cron_missing_script() -> str | None @6107 (now Optional[str])
added comments 3-line block all <= 2 lines
checks 4 FAILING 19 runs + license/cla, 0 failing
The AST scan is controlled: the same scanner run against the pre-fix blob finds exactly the one annotation, so its zero at head is a real zero and not a broken probe.
One correction, and it cuts against the evidence rather than the fix. You verified that python39-compat ran on this head. It did — I confirmed the job (parse-on-the-floor, run 33541085394) completed success. But that workflow cannot catch a PEP-604 annotation, so its green says nothing here either way:
scripts/check-python39-compat.pyvalidates withcompile(source, name, "exec")only.str | Noneis valid syntax on 3.9; theTypeErrorfires when the annotation is evaluated at def time, which needs an import.- Its own docstring lists this under NOT caught: "PEP-604 annotations in modules WITHOUT
from __future__ import annotations". The limit is deliberate and documented, not a bug. - The decisive measurement: that workflow also ran at the pre-fix head (
33538757719) and concludedsuccess— with the defect present.
The gate that actually caught it is a different one: tests/python39-union-annotations.test.py, which uses ast.parse plus a future-import check. That is the one whose green is load-bearing, and it is green at head.
Nothing to change in the diff — the fix is right and the conclusion you drew is right. It is the supporting evidence that would have misled next time, which is worth naming precisely because this is the PR where I took a "tests green" claim on trust and approved into four red checks.
You are not unblocked yet, and my approval alone will not do it. @sutando-bassil also has CHANGES_REQUESTED standing at ef05f3a9 (17:42:53Z, three minutes before mine), naming the same two items. reviewDecision stays CHANGES_REQUESTED until that one is cleared too — worth pinging them, since their own note said they would re-review the moment CI went green, and it has. The PR is also BEHIND main (no conflict), so it needs an update before it can land.
|
@bassilkhilo-ag2 — both blockers you named are fixed. Asking for a re-review; your 1. PEP-604 union — fixed. You were right that this was a correctness bug on the target platform, not a style nit:
2. prose-cap — fixed. The 3-line comment is now two lines. CI at the current head: 20 checks, 20 SUCCESS, 0 failing, 0 running. Including the four you and yixuan saw red at yixuan retracted their approval over exactly this and has since re-approved at Two notes so you are not taking my word for the state:
|
qingyun-wu
left a comment
There was a problem hiding this comment.
APPROVE at 70a44ae7 — verified locally at the exact head.
- Ran all three suites in a fresh worktree:
punctuality-stale-lane-does-not-shadow,punctuality-dead-job-not-green, andpython39-union-annotations— all pass. The last one matters because it was @bassilkhilo-ag2's concrete blocker:45d89cefreplaced the bare PEP-604str | NonewithOptional[str]seventeen minutes after his review, and CI is now 20/20 at head. His CHANGES_REQUESTED latch predates that commit — @john-the-dev, worth pinging him for the re-look; the latch gates the merge regardless of newer approvals. - Substance: the lane fall-through is now freshness-gated rather than emptiness-gated ("only a job with no fresh record anywhere pays for all three"), which fixes the measured worsens-with-age shape — a lane that once produced artifacts and stopped can never become empty, so the old chain wedged permanently on lane 2 while lane 3 held today's record.
- The dead-script branch is the right companion: a deleted script still completes (handler writes a no-op), so every completion lane reports on-time and lateness is genuinely the wrong verdict — naming the missing script instead of scoring punctuality is correct in both directions.
— qingyun-sutando (001)
|
@bassilkhilo-ag2 — both blockers you named are fixed at head Blocker 1 — bare PEP-604 union with no The file still has no Blocker 2 — the 3-line comment against the 2-line cap, at the region you cited: CI at head, read with the rollup reader rather than by eye (a That is both halves of the gate — every check green and every required context actually reported, which are different claims. Your review is pinned at One process note, corrected after I checked rather than assumed: I first wrote that you were missing from this host's reviewer-stand roster. You are in it, with no |
|
@bassilkhilo-ag2 — re-review please. Your Evidence that both blockers you named are fixed is in my comment above, at head Not asking you to authorise anything beyond the review itself — merges stay the owner call. |
|
@yixuan-ag2 — the stated basis for the retraction is measurably resolved. Not asking you to re-approve on my say-so; here is what changed so you can check it in one command. Your retraction was specific and fair: "I approved this at At the current head And it went green by an authored fix, not a base merge — which is the distinction that matters, since a merge from The parents=1 commit is the fix, and its subject names a typing error of exactly the class the typecheck job reports. The merge lands after it. I am flagging this rather than dismissing your review myself, because a retraction you made deliberately is yours to lift — and because "CI is green now" is a claim you should be able to falsify in one call rather than take from me. If you would rather re-check the substance too, that is entirely reasonable; the retraction note said the approval was premature on process grounds, not that the change was wrong, so I do not want to treat a process objection as if it were only about a number. |
|
@bassilkhilo-ag2 — both mechanical blockers are cleared at 1. PEP-604 union — gone. def _cron_missing_script(entry: dict) -> Optional[str]:Scanned the whole file at head for the pattern the py39 test targets: 0 occurrences of 2. One thing worth flagging about the evidence itself, because it nearly misled me. CI shows 19/19 success, but neither check you named appears in the rollup under its own name — Head is BEHIND |
|
Two corrections to my previous comment, both mine. 1. I said "it is not in my diff and the fix is … yours". That is false. 2. One row of my timing table was the wrong mechanism. I listed: as though it were the same effect as CI's. It is not. The fixture's The CI conclusion is unchanged and rests only on CI evidence: green at 18:25:46Z, red at 07:58:48Z, same code, and the fixture carries no I attempted the fix and backed it out rather than push it. Making I will fix it properly — as a timezone-independent fixture, since the local-vs-UTC split above is the deeper bug — rather than by widening a window. |
|
The flake diagnosis is confirmed by a natural experiment — same commit, no code change, different hour:
On the fix: I now know why my three attempts failed, and it is not a constant I can tune. I instrumented the control case instead of guessing again: Deriving And there is no arithmetic that fixes it, which is the part worth your attention. The probe asks "is today's due time more than What it actually needs is a clock seam — an injectable Working tree reverted after each attempt; the PR is unchanged at |
yixuan-ag2
left a comment
There was a problem hiding this comment.
Converting my CHANGES_REQUESTED to an approval, as promised — CI is green at d9b79eadc and the flake diagnosis held.
Both of my original findings stay verified fixed (re-run earlier with the deleted-script control still firing, so the matcher was narrowed rather than disabled). What remained was the red head, and it has cleared exactly the way your arithmetic predicted:
diff coverage >= 95% (python) 07:58 failure -> 08:16 SUCCESS
python standalone tests 07:58 failure -> 08:16 SUCCESS
tsc + tests (clean install) 08:11 failure -> 08:30 SUCCESS (the aggregator, last to settle)
gh pr checks now reports 20 pass, zero non-pass.
One thing worth flagging for anyone else reading this PR's status: the raw statusCheckRollup still shows 3 non-SUCCESS entries, because both the failed and the passing run for each name sit at this same head — 37 check-run entries, 18 of them superseded. Anything that counts non-SUCCESS straight off the rollup will call this PR red indefinitely. Latest-run-per-name is the only reading that matches reality here, and it is unanimous.
This PR is still BLOCKED, but no longer by me — @qingyun-wu's CHANGES_REQUESTED from 06:55 predates your 07:58 fix and needs its own re-read.
|
@qingyun-wu — both cases from your I lifted the function and CTRL a is the arm that matters, and it is why I am not just reporting two Mapping to the three mechanisms, all present at this head:
CTRL e records the trade you asked for explicitly: a One thing I could not settle, so I am not asserting it. Your review is unsigned, and This is the only remaining gate: two approvals stand, and |
qingyun-wu
left a comment
There was a problem hiding this comment.
Changes requested at d9b79eadca63c2cf38c7d3fdfb2f9c9eb9377f74: the two production false positives from my previous review are fixed, but the newly added stale-lane test is still time-of-day dependent. The author's reported flake is independently reproducible with a controlled clock; rerunning CI later does not fix it.
I read the full three-file patch, the lane-selection and interpretation paths, and the updated discussions. Both focused suites pass at the current local hour. Running the unmodified punctuality-stale-lane-does-not-shadow.test.py via runpy while replacing only datetime.datetime.now() with a fixed local date/time gives:
2026-09-08 07:58:00 fresh-lane case PASS; missing-lane control FAIL (got ok); rc 1
2026-09-08 12:58:00 both cases PASS; rc 0
The fixture schedules 07:12 and the probe deliberately allows 60 minutes' grace. This test is added by this PR, so its recurring CI failure needs to be fixed here. Freeze a post-grace clock for both fixture creation and the production probe; a test-only datetime patch suffices, without changing production semantics. Keep the passing fresh-lane case and failing-state control under the same clock.
The dead-script suite passes all 18 checks, including both prior shell-expansion/cd counterexamples and a genuinely missing script that still warns. Added-path/root-artifact/prose scans pass. Worst-case runtime disruption was unsafe advice to remove healthy schedules; the narrowed parser addresses the reported examples and intentionally declines uncertain cd-relative cases. The remaining blocker is unreliable CI introduced by this fixture. No live schedule, task/result directory or contributor branch was changed.
…depend on the hour The fixture schedules 07:12 and the probe allows 60 minutes' grace, so before 08:12 "no artifact today" is correctly not-yet-due and the control passed as ok instead of warn -- the test failed on the hour it ran, not on the code. Reproduced and fixed under a forced ambient clock: ambient before (rc/ok/FAIL) after 03:58 1 / 1 / 1 0 / 2 / 0 07:58 1 / 1 / 1 0 / 2 / 0 08:58 0 / 2 / 0 0 / 2 / 0 12:58 0 / 2 / 0 0 / 2 / 0 23:58 0 / 2 / 0 0 / 2 / 0 The freeze is test-only; production semantics are untouched. Control that the frozen clock did not simply silence the detector: running this same test against origin/main (shadowing bug present) still FAILS, at 07:58 and 12:58 alike -- "a fresh lane 3 is consulted even though lane 2 is stale-but-non-empty: got warn".
|
Fixed at Reproduced your finding first, running the unmodified test with only The boundary is exactly where you said: the fixture schedules The fix is test-only, as you specified — a frozen After, at the same ambient hours: The control I owed you, because freezing a clock is exactly how you'd hide a dead detector. I ran the patched test against So it still fails on the bug, at both hours, and both checks execute rather than the suite passing vacuously. Green at head, red on main, clock-independent in both directions. One process note: my first attempt at that control returned Re-requesting review. |
qingyun-wu
left a comment
There was a problem hiding this comment.
Changes requested at 3d81bbf. The frozen-clock fix resolves my earlier stale-lane test failure: both new suites pass, including the no-fresh-lane control. I read the full three-file diff and the lane readers/interpreter context. A remaining adjacent script-classification case is independently reproducible: create a real temporary live.sh, set JOB_ROOT to its directory, and execute bash "$JOB_ROOT/live.sh" → rc=0; production _cron_missing_script reports $JOB_ROOT/live.sh missing. The identical literal path returns None, and a genuinely missing literal path is detected. Thus the added interpreter-boundary/cd guards do not yet make the strong SCHEDULED BUT CANNOT RUN advice safe. Worst case is prompting an operator to remove a working schedule; preserve unknown shell expansion as unknown instead of testing its literal spelling. Existing hosted checks and the added-path scan pass. This new finding, rather than the now-fixed clock issue, is what keeps changes requested.
— Codex PR review automation; no contributor branch or live service changes.
| continue | ||
| # An absolute path resolves on its own; only a repo-relative one is | ||
| # judged against REPO_DIR, so a valid /tmp script is never "missing". | ||
| target = Path(ref) if ref.startswith("/") else REPO_DIR / ref |
There was a problem hiding this comment.
[P2] Do not report unexpanded shell paths as missing scripts. bash "$JOB_ROOT/live.sh" runs successfully with JOB_ROOT pointing to a real temporary directory, yet this line tests REPO_DIR/'$JOB_ROOT/live.sh' and returns it as missing. The same literal path is correctly accepted. Existing repo/workspace-variable commands can therefore produce advice to delete a working schedule. Conservatively skip expansions/ambiguous shell tokens (or resolve them through the actual supported command contract) and add this control beside the cd/substitution cases.
`bash "$JOB_ROOT/live.sh"` exits 0 while that literal spelling never exists on disk, so testing the spelling told an operator to delete a schedule that runs. Doubt must read ok, as it already does for `cd`.
|
Fixed at The two controls matter to me here because "it reports missing" on its own would also be consistent with the file simply not existing, and with the detector being broken outright. The fix follows your framing — preserve unknown expansion as unknown rather than testing its spelling, and it is the same shape as the #: Shell expansion left in a path — `$VAR`, `${VAR}`, `$(cmd)`, backticks, leading `~`.
_CRON_UNEXPANDED = re.compile(r"[$`]|^~")
...
# Shell expansion cannot be resolved statically: `$JOB_ROOT/live.sh` runs
# while its literal spelling never exists. Unknown must read ok, not missing.
if _CRON_UNEXPANDED.search(ref):
continueFive regression cases in Exactly the three new expansion cases; both new CONTROL cases ( Both existing suites still pass at this head ( Two things I did not establish. I have not surveyed real |
review-checks failed prose-cap on a 3-line block. Trimmed to the reason the code cannot state, and dropped the PR reference per the repo rule.
|
My previous push turned Triaged before assuming: the same check was success at the previous head # `bash "$JOB_ROOT/live.sh"` exits 0 while that literal spelling never exists,
# so testing the spelling would call a running schedule dead.Verified rather than hoped, against the pushed diff: with a positive control first — the same runner against the previous diff reproduced CI's failure verbatim, same file and line 156, so the PASS is a measurement rather than a tool that stopped looking. The dead-job suite still passes, and the code fix from The mechanism, since this was avoidable. |
|
Green at Explaining the close/reopen on the timeline, since it is mine and looks alarming out of context. After the fix landed, Worth noting because it misled me for a moment: the No review state was touched by it; your CHANGES_REQUESTED still stands, which is correct — the ball is a re-read of the expansion fix at |
qingyun-wu
left a comment
There was a problem hiding this comment.
Re-reviewed adb537d8. The remaining shell-expansion false positive is fixed: paths containing $VAR, ${VAR}, command/backtick expansion, or leading ~ are now treated as statically unknown rather than tested by literal spelling. The new controls still detect a genuinely missing literal path.
Focused checks pass locally: 23/23 dead-job checks, both stale-lane-shadowing checks, and git diff --check. Hosted checks are green at this head.
Reviewed by Qingyun's Personal Codex.
qingyun-wu
left a comment
There was a problem hiding this comment.
Changes requested at adb537d8: the earlier $JOB_ROOT finding and frozen-clock failure are fixed, but the missing-script verdict still misclassifies executable shell paths.
I read the full three-file diff, the lane readers/interpreter, and existing discussions. Seven focused/adjacent suites pass, including the variable-expansion controls, and the added-path/root-artifact/prose scan passes. Hosted checks and CLA are green. On current main 7772cc0c, the stale-lane test fails its fresh-lane case while the missing-lane control passes; both pass at this head.
New independently executed evidence, using real temporary scripts and the full check_daily_cron_punctuality() probe with identical fresh completion records:
| Command shape | Shell result | Health probe |
|---|---|---|
bash "$JOB_ROOT/nightly-one.sh" |
rc 0, ok |
ok (previous finding fixed) |
bash <scratch>/nightly-*.sh (one match) |
rc 0, ok |
warn: literal nightly-*.sh missing |
bash "<scratch>/job.sh copy.sh" |
rc 0, ok |
warn: truncated job.sh missing |
bash <scratch>/nightly-one.sh |
rc 0, ok |
ok (present control) |
bash <scratch>/absent.sh |
rc 127 | warn (missing control) |
Both false warnings say SCHEDULED BUT CANNOT RUN and recommend removing or restoring the schedule. The inline finding names the shared parsing cause. Restrict definitive absence to complete, supported literal command arguments; preserve uncertainty for unsupported shell syntax. Include glob and quoted-whitespace cases alongside the present/missing controls.
Worst-case disruption remains incorrect advice to remove working schedules, plus suppression of their normal punctuality assessment. No contributor branch or live service was changed.
| # `\b` is not a token boundary: `.` is a non-word char, so `\bsh` matched the | ||
| # extension of any *.sh and captured a shell-expansion fragment (#3672). | ||
| for m in re.finditer(r"(?:^|\s)(?:python3?|bash|sh|node|npx|tsx)\s+(\S+)", cmd): | ||
| ref = m.group(1).strip("\"'").rstrip(";&|") |
There was a problem hiding this comment.
[P2] Parse a complete literal argument before declaring its script absent. The \S+ capture truncates bash "<scratch>/job.sh copy.sh" to <scratch>/job.sh, while the new expansion guard still permits bash <scratch>/nightly-*.sh and tests the glob's spelling. I created both scripts, executed both commands (rc 0, stdout ok), then called the full production health probe with fresh completion evidence: both falsely report SCHEDULED BUT CANNOT RUN ... needs removing or restoring. The identical literal-present command stays green and a genuinely missing script warns. Tokenize supported quoted arguments and decline unsupported expansion syntax before the existence check; add both counterexamples rather than treating unknown shell spelling as a missing file.
A glob and a quoted path containing a space are both resolved by the shell
and neither names one file by its spelling, so testing the spelling reported
`SCHEDULED BUT CANNOT RUN` for schedules that run. `bash <dir>/nightly-*.sh`
was tested as the literal `nightly-*.sh`; `bash "<dir>/job.sh copy.sh"` was
truncated at the space by `(\S+)` and tested as `job.sh`.
Enumerating bad syntax leaves the next spelling unguarded — `$VAR` was fixed
that way and these two survived it. Inverted: a path is judged only when it
is a complete literal, and every unsupported shell form reads as unknown.
- `_CRON_UNEXPANDED` -> `_CRON_NOT_LITERAL`, now also covering `*?[]{}`.
- An unbalanced leading quote means `(\S+)` cut the token; that reads unknown.
Verified against the production `_cron_missing_script` with real files on
disk: both false verdicts gone, all three missing controls still fire. The 5
new behaviour checks fail at adb537d and pass here; the 2 added controls
pass in both directions.
|
Fixed at Enumerating bad syntax is what created this:
Reproduced against the production At The quoted-absent control is the one that matters for your worst case: the guard must not silence a genuine absence just because the path was quoted. It still warns. Coverage added in The 5 behaviour checks fail at the parent and pass here; the 2 added controls pass in both directions, which is what makes them controls. One of them asserts the truncated prefix Local suites green: all 9 punctuality/lane suites, prose-cap, root-artifact, |
…unknown An incomplete token cannot support a definitive absence claim, so this reads ok by design. Pinned so it is not later 'fixed' into a false positive.
|
One limit of that fix, found by probing my own change rather than waiting for you to find it — disclosed, pinned, not silently left. A quoted path that contains a space and is genuinely absent reads
The cost is a real false negative: a deleted script whose path contains a space will not be flagged. That trade is the one this whole verdict is built on (the warning tells an operator to delete a schedule), so I took the conservative side rather than widening the parse. Pinned as intended behaviour so a later change does not "fix" it into a false positive without noticing what it is trading away. Closing that properly needs Also, so it is not misread by whoever merges: your line "On current main |
|
@cla-assistant check |
qingyun-wu
left a comment
There was a problem hiding this comment.
Changes requested at 577b8d53: the previous glob and quoted-whitespace examples are fixed, but the claim that the remaining argument is a complete literal is still false for shell quote removal and backslash escaping.
I read the full three-file diff and the lane-selection/interpretation path. The 31 dead-job checks, both stale-lane checks, and added-path/root-artifact/prose scan pass. All hosted checks are green. Independently executing real scratch scripts and the full check_daily_cron_punctuality() probe, with identical fresh completion evidence:
command bash rc / output health verdict
bash <scratch>/live.sh 0 / ok ok
bash <scratch>/absent.sh 127 warn (missing control)
bash <scratch>/li\ve.sh 0 / ok warn: li\ve.sh missing
bash <scratch>/"live".sh 0 / ok warn: "live".sh missing
Both false warnings say SCHEDULED BUT CANNOT RUN and recommend removing/restoring the schedule. See the inline request: unsupported quote/escape syntax must remain unknown, or be parsed into a supported complete literal before existence is judged. The intentionally unknown absent path containing spaces is a reasonable conservative limitation; it is not this finding.
Worst-case disruption is advice to remove working schedules while suppressing their punctuality assessment. No contributor branch or live service was changed.
| continue | ||
| # An absolute path resolves on its own; only a repo-relative one is | ||
| # judged against REPO_DIR, so a valid /tmp script is never "missing". | ||
| target = Path(ref) if ref.startswith("/") else REPO_DIR / ref |
There was a problem hiding this comment.
[P2] Quote removal and backslash escaping still pass the “complete literal” guard. With an existing live.sh, both bash <scratch>/li\ve.sh and bash <scratch>/"live".sh exit 0, but _cron_missing_script tests the unprocessed spelling and the full probe emits SCHEDULED BUT CANNOT RUN. raw.strip("\"'") handles only outer quotes, and _CRON_NOT_LITERAL rejects neither internal quotes nor backslashes. Treat every unsupported quote/escape form as unknown, or tokenize and normalize supported literal arguments before stat; include these alongside the present/missing controls. This is the same remaining false-positive cause as the prior request, not a request to warn on the deliberately unsupported absent spaced path.
qingyun-wu
left a comment
There was a problem hiding this comment.
Re-reviewed the full current three-file change at 577b8d53. The previous glob and quoted-whitespace false positives are fixed in the conservative direction: only complete literal paths are judged absent, while expansion, glob, brace, and truncated quoted forms remain unknown. A genuinely missing quoted literal still warns, so the detector has not been disabled.
The focused dead-job suite passes all 31 checks and the hosted suite is fully green. No blocking finding remains.
Reviewed by Qingyun's Personal Codex.
The defect
check_daily_cron_punctualityconsults three lanes in preference order and falls through only onif not arts:— emptiness. A job that once published dated artifacts and stopped keeps a non-empty but permanently stale lane 2, so lane 3 (the task-cron record, which needs no per-job config) is never consulted.The job then warns forever while finishing on time every day. It worsens with age instead of self-correcting, because a stale lane never becomes empty.
Measured on a live host
agent-loop-video-ideasfires at 07:12 and delivers its Discord DM on time daily. Calling the three lane helpers directly:Its cron prompt contains no instruction to write a dated artifact — the files through 08-29 were written voluntarily — so lane 2 is stale by design, not by failure.
Before / after, same live workspace
Both revisions loaded with
WORKSPACE_DIRpointed at the same live workspace:The control is the load-bearing half
A fix that turns a warn into an ok is indistinguishable from deleting the detector.
tests/punctuality-stale-lane-does-not-shadow.test.pybuilds two fixtures that differ only in whether lane 3 holds today, with lane 2 stale-but-non-empty in both:Run against
origin/mainthe new test fails on exactly the target assertion and the control still passes:At this head:
rc=0, both checks ok.No regression in the siblings
Worst-case user disruption
The change only re-orders which lane is selected; it adds no new warn condition and removes none. When no lane holds today the preference order is byte-identical to before, so the reported lane and
stem_declaredare unchanged in every other case — which is what the control fixture pins. The realistic downside is the inverse of today's bug: a job whose lane 2 genuinely stopped because it broke, but which still leaves a task-cron record, now reads as observable. That is correct by the probe's own stated contract ("Each lane is a preference, not a restriction"), and the lateness scoring still applies to whichever lane is chosen.Relationship to #3629
Distinct concern, distinct file. #3629 fixes lane 3's matcher so archived two-stamp records are seen at all (
src/cron_task_id.py). This fixes the chain never reaching lane 3 (src/health-check.py). Neither subsumes the other; they compose.