mirror of
https://github.com/Comfy-Org/github-workflows.git
synced 2026-11-05 00:17:37 +00:00
[PR #84] [MERGED] fix(groom): a failed finder job counts as a spent audit only if the agent step ran (BE-4809) #93
Labels
No labels
cursor-review-catalog-drift
groom
groom
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Comfy-Org/github-workflows#93
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/Comfy-Org/github-workflows/pull/84
Author: @mattmillerai
Created: 7/28/2026
Status: ✅ Merged
Merged: 8/4/2026
Merged by: @mattmillerai
Base:
main← Head:matt/be-4809-groom-interval-agent-step📝 Commits (2)
2ed2cf7fix(groom): a failed finder job counts as a spent audit only if the agent step ran (BE-4809)63a6413fix(groom): judge the finder's spend across ALL run attempts (BE-4809)📊 Changes
4 files changed (+402 additions, -14 deletions)
View changed files
📝
.github/groom/README.md(+15 -0)📝
.github/groom/interval.py(+108 -10)📝
.github/groom/tests/test_interval.py(+273 -4)📝
.github/workflows/test-groom-scripts.yml(+6 -0)📄 Description
ELI-5
Groom is billed work, so the cadence gate asks "did a real groom already run recently?" by looking at whether the finder job ran. It counted a failed finder job as "yes, we spent the money" — sensible when the agent ran and the job died later while filing issues. But the finder does a bunch of cheap setup first (two checkouts,
npm install, building the prompt, chmod'ing the clone read-only), and if any of that flakes the job also fails — having spent nothing. The gate then believed a groom had happened and skipped every daily tick for a fullGROOM_INTERVAL_DAYS. One flakynpm installcost a whole cycle, silently. Now a failed finder job only counts if the billed step (Run finder) actually ran.What changed
run_audited(.github/groom/interval.py) — afailureconclusion is now eligible but not sufficient: it also needs_agent_step_ran(job).successstill counts unconditionally (the job cannot have succeeded without the agent). New_AGENT_STEP_HINTS = ("run finder",)sits next to_FINDER_JOB_HINTSand matches case-insensitively, mirroring the existing hint style._agent_step_ranreads the per-jobstepsarray ({name, status, conclusion, number}) thatGET /actions/runs/{id}/jobsalready returns. Three cases: agent step present with a real conclusion → ran; agent step absent from a non-empty array, or present asskipped/ no conclusion → did not run; no usablestepsat all → count it (fail-safe, see below).fetch_run_jobswas already unprojected (no--jq, no field filter), so nothing had to be threaded through — but its docstring now states thatstepsis load-bearing, because adding a field filter later would silently degrade the gate with no test failing.AgentStepNamePinTestparses.github/workflows/groom.yml, extracts theaudit_findjob's step names, and assertsRun finderis there and is the only step_AGENT_STEP_HINTSmatches. Producer and consumer live in different files; this is the only thing that keeps them honest..github/workflows/test-groom-scripts.ymlnow also path-filters ongroom.ymlso a rename there actually runs the pin (without that, the pin would sit dormant for exactly the change it guards).Verified the pin bites: renaming the step to
Run the agentin a scratch copy ofgroom.ymlfailstest_groom_yml_names_exactly_the_agent_step_this_module_matches; restoring it goes green.The one place the bias is deliberately inverted
Every other ambiguity in
interval.pyfails OPEN (groom more often). Missing step data does the opposite and counts thefailure, per the ticket: a job with no usablesteps(API shape change, truncated payload, an old hand-built fixture) keeps today's behavior, because making a genuinely-spent audit re-bill on the very next daily tick is the expensive direction. Called out explicitly in the code comment, the docstring, the README bullet and a test, since it reads as inconsistent otherwise.Judgment calls
skipped/ null agent-step conclusion counts as "did not run", not just "absent from the array". The ticket phrased the check as "the agent step reached a conclusion". GitHub reports steps after a failing one asconclusion: skippedrather than omitting them, so a literal "is it in the array with any conclusion?" test would still count a job that died innpm install, i.e. would not fix the bug on the more likely payload shape. Handling both renderings (truncated array and present-but-skipped) is what actually closes it.Run findercarries noif:, so it can never be legitimately skipped while the agent nonetheless ran.test_groom_yml_produces_exactly_the_marker_this_module_matchespins the(scoped: <path>)marker" — that test lives on #83's branch, which is unmerged, so it is not onmainto mirror. The pin here was written from scratch to the same principle (parse the producing workflow, assert the literal the module matches).main, not stacked on #83._AUDITED_CONCLUSIONSandrun_auditedpredate #83 (BE-4004, #56) and this change needs nothing from it, so it builds and is verified onmain.None); a tick that used to run still runs. This change can turn a skip into a run, never a run into a skip.Overlap with #83 (BE-4757) — expect a textual conflict, they compose cleanly
#83 rewrites
run_auditedto make the clock per-scope, so whichever of the two lands second needs a small manual reconcile. The two checks are orthogonal and #83 already converged on the same guard-clause shape, so the merged body is: job-name hint →_AUDITED_CONCLUSIONSeligibility →if conclusion == "failure" and not _agent_step_ran(job): continue(this PR) → scope-marker branch (#83)._agent_step_ran,_AGENT_STEP_HINTSand_UNRUN_STEP_CONCLUSIONSare additive and untouched by #83. The pre-agent steps #83 adds (scope.py contain, the empty-tracked-file-list guard) land beforeRun finder, so they are covered by this gate automatically once merged.Testing
python3 -m unittest discover -s .github/groom/tests -p 'test_*.py' -v→ 95 tests, all green (was 87). New coverage: failure-after-the-agent still counts (agentsuccess/failure/cancelled); failure whose steps stop beforeRun finderdoes NOT count; failure withRun finderpresent butskipped/null does NOT count; failure with nostepskey / empty array /steps: nullcounts;successunaffected by step data; a spent failure behind an unspent one still counts (job order doesn't decide it); an end-to-endevaluate()case where yesterday'snpm installfailure leaves today's tick due; and the groom.yml step-name pin.python3 .github/agents-md-integrity/check_agents_md.py --root .also passes (one pre-existing CODEOWNERS warning, unrelated).Closes BE-4809.
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.