mirror of
https://github.com/Comfy-Org/github-workflows.git
synced 2026-11-05 00:17:37 +00:00
[PR #74] [MERGED] fix(groom): anchor the dedup signature to the finding's file path (BE-4460) #85
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#85
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/74
Author: @mattmillerai
Created: 7/24/2026
Status: ✅ Merged
Merged: 7/30/2026
Merged by: @mattmillerai
Base:
main← Head:matt/be-4460-groom-path-signature📝 Commits (4)
c3f86b9fix(groom): anchor the dedup signature to the finding's file path (BE-4460)5da5ba7fix(groom): scope the path backstop so it can't bury a security finding (BE-4460)e914096fix(groom): domain-separate the security lane, fail closed on the flag (BE-4460)2d02574Merge remote-tracking branch 'origin/main' into matt/be-4460-groom-path-signature📊 Changes
4 files changed (+635 additions, -12 deletions)
View changed files
📝
.github/groom/README.md(+83 -4)📝
.github/groom/ledger.py(+196 -7)📝
.github/groom/tests/test_ledger.py(+344 -0)📝
.github/groom/verifier.md(+12 -1)📄 Description
ELI-5
The groom robot files a GitHub issue for each code-cleanup finding, and remembers what it already filed by a "signature" string. That signature used to be built from the finding's title — but the model writes a fresh title every run, so re-wording "split tools.ts into modules" into "tools.ts is a monolith" produced a different signature, the ledger thought it was a brand-new finding, and the same finding got filed a second time. This anchors the signature to the finding's file path instead, because paths don't change when the wording does, and adds a backstop in the ledger that suppresses a candidate whose path is already covered by an issue we filed before.
What changed
.github/groom/verifier.md— the signature is now<repo-basename>:<scope-label>:<path-slug>where<path-slug>is the finding's PRIMARY file or directory path (lowercased, every run of non-alphanumeric characters collapsed to a single hyphen:src/tools.ts→src-tools-ts). Multi-file finding → the most representative path (the one the body's first evidence cites). Only a repo-wide pattern with no single anchor falls back to a normalized subject noun-phrase (not the full title). The brief states explicitly WHY: titles are re-generated every run, paths are stable across rewordings..github/groom/ledger.py— newpath_token()(everything after the second:;""when there is no third segment) plus a path-token backstop inpartition(): a candidate whose exact signature isunknownbut whose path segment is already covered — by a known signature, or by a candidate already routed toto_filein the same batch — is reported undersuppressedwith the distinct statuspath-collision.Ledger.should_file()and the--checkCLI agree withpartition(they reportpath-collisionand exit 1). The signature stays an opaque string for classification — no format change is required to classify, precedence is untouched, and the marker round-trip is unchanged.PathTokenTest+PathCollisionTest(path-collision suppression, exact-signature status not shadowed, no false suppression across different paths incl. same-basename-different-directory, intra-batch collision, rejection surviving a rekey,should_file/partitionagreement) and two acceptance-scenario tests (reworded-next-run files nothing; marker round-trip with a path-format signature). 74 tests pass..github/groom/README.md: the contract-tablesignaturerow now documents the path derivation and why, apath-collisionrow in the ledger-status table, and a new "path-token backstop" section covering the exact-match rule and the transition consequence.Acceptance criteria
partitionsuppresses it withledger_status: filed, visible indecision.json. Covered bytest_same_file_reworded_next_run_is_not_refiled. (The derivation lives in an LLM prompt, so it is as reliable as the brief is followed — hence the backstop below, and the explicit "keep it to the path ALONE" instruction.)split-tools-ts-into-focused-modulesortools-ts-monolithas covering the newsrc-tools-ts— the strings genuinely differ. I deliberately did not add substring/shared-token matching:src-index-tsvslib-index-tswould then collide and a real finding would be silently dropped forever, which is a worse failure than one duplicate. What the backstop does catch: the same path under a different<scope-label>, and a legacy slug that coincides with the path slug. The transition cost is therefore bounded at one extra issue per pre-existing legacy finding, after which it is stable forever; retire the legacy issue withgroom-superseded(or close as not planned). Pinned bytest_legacy_title_slug_embedding_the_path_is_not_matchedand documented in the README.ci-groom.yml/test-groom-scripts.ymlpass —test-groom-scripts.ymlruns the unit suite on this PR (green locally: 74 tests).ci-groom.ymlnever fires on a PR (schedule +workflow_dispatchonly) and is untouched by this diff —groom.yml's interface is unchanged.Judgment calls
pendingstatus exists for exactly that reason.groom.ymluntouched. The job-summary line countssuppressedwithout breaking it out by status, sopath-collisionentries are counted there and fully itemized indecision.json— no workflow change was needed, and keeping the diff inside.github/groom/**avoids spurious consumer SHA bumps.Follow-up (operator, post-merge)
ci-groom.ymlpinsworkflows_refto a merged-main SHA (07154fb), and the briefs +ledger.pyare loaded from that pinned ref at run time — so this fix takes effect for this repo's own groom (and for external consumers) only once that pin is bumped and the floatingv1tag is moved, per the repo's versioning policy.Verification
The
--checkCLI path was exercised directly against a stubbed ledger: a colliding signature printspath-collision/ exit 1, a new oneunknown/ exit 0, an exact matchfiled/ exit 1, a blank oneinvalid/ exit 1.Self-review note on the negative-claim rule: this diff's "denial" is a dedup suppression, not a product-capability dead-end — it adds no unsupported/unavailable path. Its risk is over-suppression, which is bounded by exact string equality and pinned by explicit no-false-suppression tests.
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.