Skip to content

feat(groom): pilot ci-groom.yml caller — groomer-only, dry-run parity dispatch (BE-3873)#53

Merged
mattmillerai merged 2 commits into
mainfrom
matt/be-3873-groom-pilot-caller
Jul 21, 2026
Merged

feat(groom): pilot ci-groom.yml caller — groomer-only, dry-run parity dispatch (BE-3873)#53
mattmillerai merged 2 commits into
mainfrom
matt/be-3873-groom-pilot-caller

Conversation

@mattmillerai

Copy link
Copy Markdown
Contributor

ELI-5

The "groom" bot used to only run on Matt's Mac Studio, hunting a repo for
tidy-up work (duplication, dead code, complexity) and filing it as tickets.
Phase 2 turned that bot into a reusable GitHub Actions workflow (groom.yml)
that lives in this repo. This PR adds the first caller that switches it on
for one real repo — this one — so we can prove it works in CI before rolling
it out anywhere else. It runs once a week, files groom-labeled GitHub issues,
and can be dry-run by hand to eyeball its findings first. It never writes code,
opens PRs, or merges anything — finds only.

What this PR does

Adds .github/workflows/ci-groom.yml: a thin, SHA-pinned caller of the reusable
groom.yml (landed in #49 / BE-3872), enrolling github-workflows itself as
the first groom pilot repo
(Groom Phase 3, BE-3873).

  • Groomer-only. The reusable finds + files groom-labeled GitHub issues —
    no commits, no PRs, no auto-builder, never merges. Zero prod risk.
  • Schedule: weekly, Mon 09:17 UTC (never on-PR). Plus a workflow_dispatch
    with a dry_run toggle to spot-check parity against a studio groom run on
    the same commit before trusting live filing.
  • Pinned by full commit SHA (07154fb, the merge that added groom.yml +
    the .github/groom/ briefs/ledger) with workflows_ref kept in lock-step, so
    the run always loads the briefs that match the workflow filing them.
  • Files as cloud-code-bot (vars.APP_ID + secrets.CLOUD_CODE_BOT_PRIVATE_KEY,
    already provisioned here for cursor-review), so groom's issues are a distinct,
    queryable actor and the caller keeps contents: read least-privilege.
  • Volume gate cadence: 7 matches the weekly cron, so a week with nothing
    merged skips the expensive audit.

Why this repo as the pilot (judgment call — Matt, your veto)

The ticket suggests Comfy-Org/comfy-toolbox or another low-risk repo you
pick
. I piloted on github-workflows itself because:

  1. This repo already dogfoods its own reusables (ci-cursor-review.yml,
    ci-detect-unreviewed-merge.yml) — ci-groom.yml is the exact same
    self-enrollment pattern, lowest-friction and lowest-risk.
  2. The one-PR scope of this task lives in this clone; the caller is identical
    whichever repo hosts it.

If you'd rather pilot on comfy-toolbox (it's active and already an
agents-md-integrity caller, so enrolling it is trivial), this same file drops
in verbatim — say the word and I'll retarget. Either way, live issue-filing
begins only after this merges to the default branch
(GitHub only runs
scheduled workflows from the default branch).

Acceptance criteria — status (read before merging)

This ticket is a ~1–2 week pilot, so it splits into a code artifact (this PR)
and operational follow-ups that need runtime data no single PR can produce:

  • AC1 — working ci-groom.yml caller producing scheduled findings. The
    caller is complete and validated (YAML parses; every with:/secrets: key
    matches groom.yml's declared contract). Findings begin firing once (a) this
    merges to the default branch and (b) the ANTHROPIC_API_KEY prerequisite
    below is satisfied.
  • AC2 — findings quality ≈ studio parity; no duplicate re-filing. Dedup
    (no re-filing) is already implemented + unit-tested in the Phase 2 ledger
    (.github/groom/ledger.py, test_ledger.py). The parity observation
    against studio groom is the operational half — run the dry-run below on a
    couple of commits and compare. Not yet observed; gated on the run window.
  • AC3 — go/no-go writeup on expanding to more repos. Can't be written
    before there's pilot data. The rubric to produce it is below; the decision
    itself is a post-observation follow-up (keeping analysis out of a repo doc per
    our no-audit-docs norm).

Operator prerequisite (loud, so the pilot is never silently inert)

secrets.ANTHROPIC_API_KEY must be available to this repo (org- or repo-level) —
the finder + verifier agents bill through it. Repo-level secrets here currently
show only CLOUD_CODE_BOT_PRIVATE_KEY; if ANTHROPIC_API_KEY isn't inherited
from the org, provision it before the first scheduled run. Until then the run
fails loudly at the agent step (by design).

How to run the dry-run parity check (feeds AC2/AC3)

  1. Actions → CI - Groom → Run workflow, set dry_run = true. It runs the
    full audit + dedup and prints what it would file to the job summary — no
    issues opened.
  2. Compare that list against what a studio groom run surfaces for the same
    commit: do the CONFIRMED findings overlap in count and substance? Are the
    dedup signatures suppressing obvious repeats?
  3. Go/no-go rubric for expansion: GO if (a) confirmed findings are
    comparable in signal quality to studio groom (few false positives after the
    verifier pass), (b) re-running files zero duplicates, and (c) issue volume is
    sane (≤ max_findings, default 12). NO-GO / tune if the verifier lets noise
    through or dedup misses re-files — adjust themes/max_findings on the
    caller and re-observe.

Follow-ups (out of scope here — noted for the rollout decision)

  • No bump-groom-callers fleet automation yet (unlike cursor-review/pr-size/
    agents-md), so the SHA pin is frozen manually. Wiring groom into the
    bump-callers machinery + a GROOM_CALLERS variable is a rollout-phase task,
    appropriate once the pilot says GO.

Testing

Single new caller YAML, no backing script — the repo's path-filtered test-*.yml
suites don't map to it. Validated: python3 -c 'yaml.safe_load(...)' parses;
with:/secrets: keys cross-checked against groom.yml's workflow_call
contract; no actionlint/zizmor/pinact gate exists on this repo's own workflows.

… dispatch (BE-3873)

Enroll this repo as the first groom pilot (Groom Phase 3). A thin caller pins
the merged reusable groom.yml by full commit SHA, runs weekly on schedule
(never on-PR) in groomer-only mode (finds + files `groom`-labeled GitHub
issues; no commits/PRs/builder), and adds a manual dispatch with a dry_run
toggle for spot-checking parity against a studio groom run before trusting
live filing. Files issues as cloud-code-bot (App identity already provisioned
here for cursor-review), so the caller needs no issues:write of its own.
@mattmillerai mattmillerai added agent-coded Authored by the agent-work loop cursor-review Multi-model cursor review labels Jul 21, 2026
@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 5 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 0354fa73-fd72-443f-b833-ed950803f489

📥 Commits

Reviewing files that changed from the base of the PR and between 07154fb and 1d97374.

📒 Files selected for processing (1)
  • .github/workflows/ci-groom.yml
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch matt/be-3873-groom-pilot-caller
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch matt/be-3873-groom-pilot-caller

Comment @coderabbitai help to get the list of available commands.

@mattmillerai
mattmillerai marked this pull request as ready for review July 21, 2026 19:16

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Cursor Review — Consolidated panel

Triggered by @mattmillerai.

Found 3 finding(s).

Severity Count
🟠 High 1
🟡 Medium 1
🟢 Low 1

Panel: 8/8 reviewers contributed findings.

Comment thread .github/workflows/ci-groom.yml Outdated
Comment thread .github/workflows/ci-groom.yml
Comment thread .github/workflows/ci-groom.yml
…on dry-run (BE-3873)

Address cursor-review panel findings on the ci-groom.yml pilot caller:

- High: the caller declared `concurrency: groom-${{ github.repository }}`
  identical to the reusable groom.yml's own top-level group with
  cancel-in-progress:false. The caller run holds that group while its reusable
  `uses:` job waits to acquire the same group -> self-deadlock, run hangs to
  timeout, nothing filed. The reusable already serializes per-repo across ALL
  callers, so the caller block was redundant; remove it and document why the
  caller must stay out of the group.

- Medium: a manual dry-run dispatch inherited the reusable's default
  volume_gate:true + cadence:7, so a quiet week silently skipped the audit and
  produced no parity summary — defeating the Phase 3 dry-run parity gate. Pass
  volume_gate: ${{ github.event.inputs.dry_run != 'true' }} so a dry-run always
  runs the full audit while live/scheduled runs keep the gate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@mattmillerai
mattmillerai merged commit 72ca29e into main Jul 21, 2026
3 checks passed
@mattmillerai
mattmillerai deleted the matt/be-3873-groom-pilot-caller branch July 21, 2026 19:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent-coded Authored by the agent-work loop cursor-review Multi-model cursor review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant