mirror of
https://github.com/Comfy-Org/github-workflows.git
synced 2026-11-05 00:17:37 +00:00
[PR #297] [MERGED] feat(groom): split sandbox preflight into its own step before the agent step #297
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#297
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/297
Author: @mattmillerai
Created: 9/16/2026
Status: ✅ Merged
Merged: 9/17/2026
Merged by: @mattmillerai
Base:
main← Head:matt/be-14756-groom-sandbox-preflight-split📝 Commits (6)
ad1036dfeat(groom): run the finder/verifier/builder agents inside the sandbox + key brokereff84d9fix(groom): address cursor-review panel findings on the sandbox+broker wiring4e80b8eMerge origin/main into matt/be-4303-groom-sandbox-wirec4a8fd1feat(groom): split sandbox preflight into its own step before Run finder/verifier/builder3005fabfix(groom): make --preflight-only fail loud on misuse and drop the misleading --selftest alias2b2539fMerge remote-tracking branch 'origin/main' into matt/be-14756-groom-sandbox-preflight-split📊 Changes
4 files changed (+163 additions, -2 deletions)
View changed files
📝
.github/groom/agent-sandbox.sh(+33 -1)📝
.github/groom/tests/sandbox-tests.sh(+43 -0)📝
.github/groom/tests/test_interval.py(+32 -0)📝
.github/workflows/groom.yml(+55 -1)📄 Description
STACKED — merging lands on
matt/be-4303-groom-sandbox-wire(owned by @mattmillerai, PR #293), NOTmain. This is NOT safe to merge tomainon its own: its diff builds on the sandbox invocation that only exists on #293's branch. Do not merge until #293 lands; GitHub auto-retargets this tomainwhen #293 merges.ELI-5
The groomer runs an AI agent inside a locked-down sandbox. Setting that sandbox up used to happen inside the same step that runs the agent. If the setup failed (no sandbox tool, a blocked kernel feature), the whole step failed — and a bookkeeping check read that failure as "we already spent this run's audit," so it stopped grooming for a whole interval even though no agent actually ran. This PR moves the sandbox setup into its own step before the agent step. Now a setup failure fails the setup step, the agent step never starts, and the bookkeeping correctly sees "the agent never ran" — so grooming isn't suppressed.
What changed
agent-sandbox.sh— new--preflight-onlyflag (alias--selftest): runs only the mutating sandbox bring-up (preflight()— install bubblewrap, the AppArmor profile, the sysctl fallback) and exits0if a working jail is usable, non-zero otherwise. Takes no--clone/--out-dir/-- <command>; it short-circuits before those requirement checks.preflight()itself is unchanged and already idempotent + fail-loud.groom.yml— a new, distinctly-namedPreflight the sandboxstep added before theRun <agent>step inaudit_find,audit_verifyandbuild, runningagent-sandbox.sh --preflight-only. Because the bring-up now lives in its own step, a no-agent-budget setup failure fails that step;Run <agent>is never reached, so the runs-jobs API reports itqueued/skippedandinterval.py'sagent_step_startedreads it as unstarted → the cadence clock is not advanced. The realRun <agent>step's ownpreflight()then hits its fast path (already usable → instant return, no side effects). The load-bearing comment aboveRun finderwas updated to note the split.interval.py— unchanged;_AGENT_STEP_NAME = "Run finder"stays.sandbox-tests.shgains section 8 (--preflight-only/--selftestexit0with no command/clone/out-dir on a working host; fail-loud with a stubbed failingbwrap+ no-opsudo).test_interval.pyextends theaudit_findstructural pin (a preflight step exists, precedesRun finder, and its name ≠agent_step_name()) and adds arun_auditedcase (aqueued/skippedRun finderstep alongside acompleted/failurepreflight step → not a spent audit).Only audit_find gates the clock
interval.pyis consulted only for the finder job. The verifier/builder splits do not affect cadence — they mirror the finder for consistency and theStart the key brokerprecedent, and keep a no-spend bring-up failure off the agent step in either job.Testing
python3 -m unittest discover -s .github/groom/tests -p 'test_*.py'→ 399 tests OK.shellcheck -x .github/groom/agent-sandbox.sh .github/groom/tests/sandbox-tests.sh→ clean.check_workflow_pins.py→ OK;check_agents_md.py --root .→ passed (pre-existing warnings on untouchedAGENTS.md).groom.ymlparses as YAML; all threePreflight the sandboxsteps verified to precede their agent step.sandbox-tests.shsection 8 verified directly:--preflight-only/--selftest→ exit0; stubbed-broken-bwrap→ non-zero; a normal invocation missing--out-dirstill dies (exit2).Residual
mainbefore #293; the base is #293's branch and GitHub retargets tomainon #293's merge.nodeinside the jail) fails here because this host'snodelives outside/usrand the jail binds only/usrread-only — a host-env limitation, not a regression from this diff (section 5 is unchanged by it). CI's ubuntu runner installsnodeunder/usr, so section 5 passes there. The new section 8 was verified independently (see Testing).claudethat starts but bills ~nothing. This PR is the cheaper structural split and deliberately does not close that broader case — the two are complementary.gh pr listthat no open PR in this repo implements this preflight split (only #293 touches the sandbox; #295 is unrelated gate-path validation). A human should still glance for a sibling ticket before merge, as the ticket noted.Provenance
groom.ymlYAML parse + step-ordering check, and direct verification of the new--preflight-only/--selftest/fail-loud behavior. The full confinement suite could not complete on this host (section 5 needsnodeunder/usr); noted under Residual.🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.