mirror of
https://github.com/Comfy-Org/github-workflows.git
synced 2026-11-05 00:17:37 +00:00
[PR #163] [MERGED] feat(pr-risk): record which files supplied the reversibility tier (BE-7418) #172
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#172
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/163
Author: @mattmillerai
Created: 8/13/2026
Status: ✅ Merged
Merged: 8/13/2026
Merged by: @mattmillerai
Base:
main← Head:matt/be-7418-reversibility-files📝 Commits (2)
c73a829feat(pr-risk): record which files supplied the reversibility tier (BE-7418)aea46cdfix(pr-risk): attribute reversibility across BOTH R3 rungs, not just the first (BE-7418)📊 Changes
3 files changed (+198 additions, -10 deletions)
View changed files
📝
scripts/pr-risk/README.md(+13 -1)📝
scripts/pr-risk/grade-pr-risk.sh(+79 -9)📝
scripts/pr-risk/tests/test_grade_pr_risk.sh(+106 -0)📄 Description
ELI-5
The risk grader already tells you which files made the path-floor axis land where it did. The reversibility axis just said "R3 — touches migrations" without naming the migration. This adds
axes.reversibility.files: the changed paths that actually supplied that tier. It's a label on the record, nothing more — no tier moves.What changed
grade-pr-risk.shAXIS 3 now emitsfilesin its record ({tier, status, reason, files, flag_gated, deleted_files}), populated on the two rungs where the tier is attributable to specific files:$A1.filesrows whose per-fileclassesintersect the matched irreversible classes. The rows already carryclasses, matched on destination and origin, so this is a pure derivation over what the path axis already computed — no second matching pass.auth/file also carries classauthand removed nothing; naming it here would send the publisher peeling a file that cannot change the branch. A row qualifies when the path it removed (.pathforDELETED,previous_pathforRENAMED— the same two halves that build$deleted) matches a rule in adelete_sensitiveclass. The destination path is recorded, so the publisher's subset test againstaxes.path_floor.files[].pathcompares like with like.nullon the other three rungs. "No green rollup" is a property of the head commit and "no test touched" of the whole change set — neither is removable by dropping files, sonullreads as "not attributable, keep suppressing", which an empty array would not.Nothing existing was renamed or moved:
publish-risk-surfaces.shandapply-risk-label.shread this record and their suites are unchanged and green.Why it's safe (the report-only contract)
Same guard the per-file path floors use. The list is derived after the tier decision
$dand is read nowhere else in the grader, so it cannot become a second input to grading. To make that mechanical rather than aspirational, each branch of the decision ladder now carries aktag naming itself, and the attribution keys on$d.kinstead of re-testing the same conditions — a re-test is a second copy of the ladder that can drift out of step with it, and afileslist that disagrees with thereasonprinted beside it is worse than no list at all.knever reaches$d.t.Empirically pinned: graded a 10-record corpus (both R3 branches, all three null rungs, a fork, an unknown path axis, an uncollected rollup) with the pre-change grader from
origin/mainand with this one, deletedgraded_atand the newfileskey from both, and diffed — byte-identical. No tier moved anywhere.Judgment calls
A DELETED file that is not under a sensitive class is not attributed. The ticket's wording ("the
.pathof rows withchange_type == DELETED, orRENAMEDwhose origin matched a class indelete_sensitive_classes") can be read as attributing every deleted row. I read the class filter as applying to both, because the field's purpose is "which files supplied the tier": deletingREADME.mdalongsidesrc/auth/x.godoes not supply the R3 — peeling the README leaves the reason standing, peeling the auth file removes it. This also gives the branch a useful invariant: the list is empty exactly when$del_sensitiveis false, i.e. never on this branch. Pinned by a test fixture (README.mdDELETED alongside a DELETED auth file → only the auth file is attributed). Easy to flip if the phase-2 consumer wants the broader set.Tests
New phase 23 in
tests/test_grade_pr_risk.sh(122 assertions total, all green):migrations/**+ a docs file) → only the migration is attributeddeleted_filescount untouchedfilesisnullunknownbefore attribution runs, so no list is emitted from a file list nobody readaxes.reversibility.tierasserted against the values the grader emitted before the field existedaxes.path_floor.files[].pathAlso ran the rest of the pr-risk suites (
apply_risk_label,grade_targets,resolve_enabled,pin_contract,publish_risk_surfaces) plus the CI shellcheck invocation and the default map/registry validation — all green.Provenance
Ticket BE-7418. Deferred from review of #162 (discussion r3774678317); phase 1 of the BE-7414 spike's plan. Base is current
main— this does not depend on #162.🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.
uses:ref is SHA-pinned, and pin the last two #310