mirror of
https://github.com/Comfy-Org/github-workflows.git
synced 2026-11-05 00:17:37 +00:00
[PR #165] [MERGED] fix(pr-risk): let the reducibility clause speak on a fully-attributed reversibility tie (BE-7419) #174
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#174
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/165
Author: @mattmillerai
Created: 8/13/2026
Status: ✅ Merged
Merged: 8/13/2026
Merged by: @mattmillerai
Base:
main← Head:matt/be-7419-reducibility-rev-tie📝 Commits (2)
04a0d07fix(pr-risk): let the reducibility clause speak on a fully-attributed reversibility tie (BE-7419)5d3ad09fix(pr-risk): bound the reducibility exception by where the axis actually lands (BE-7419)📊 Changes
5 files changed (+317 additions, -33 deletions)
View changed files
📝
scripts/pr-risk/README.md(+40 -8)📝
scripts/pr-risk/grade-pr-risk.sh(+25 -1)📝
scripts/pr-risk/publish-risk-surfaces.sh(+118 -15)📝
scripts/pr-risk/tests/test_grade_pr_risk.sh(+35 -1)📝
scripts/pr-risk/tests/test_publish_risk_surfaces.sh(+99 -8)📄 Description
ELI-5
The risk comment sometimes offers "split this PR and the leftovers grade cheaper." It refused to make that offer whenever another axis matched the headline tier. For provenance that refusal is right — provenance is about who wrote the PR, so it follows the leftovers into the split and the split buys nothing. For reversibility it was often wrong: reversibility is about specific files, and those files are frequently the exact ones the split proposes peeling off. So one R3 migration under 600 lines of R0 docs got no offer at all, while the identical file set with a lower reversibility tier got the full offer. Same peel, two different answers. Now the two ties are judged separately, and a reversibility tie steps aside when the grader's own attribution proves the peel takes it with it.
What changed
scripts/pr-risk/publish-risk-surfaces.sh, all three surfaces in one commit (they share the predicate today precisely so they cannot disagree):$prov_tie/$rev_tiereplace the single$driverslist where gating is concerned.$driversitself stays as the combined list — the$conc_tailattribution's wording ("the provenance and reversibility axis proposes R3") is about which axes tied and is correct either way.$rev_removable—$rev_tieANDaxes.reversibility.filesis a non-empty array AND every entry is in[$topf[].path].$path_decidedbecomesgraded AND headline == floor AND (NOT $prov_tie) AND (NOT $rev_tie OR $rev_removable). The clause keeps its existing$comp_tier/$below_pctguards untouched.$drivergains a first branch: under$path_decided AND $rev_tieit namespath and reversibilityand carries reversibility's reason, so the<details>split pitch never sits under a headline crediting reversibility alone.$conc_short's gate fires for that combined driver as well as plainpath.scripts/pr-risk/README.md's reducibility-clause paragraph now documents the per-axis tie reading, the full-subset requirement and why it is load-bearing, thenullfail-safe, and the combined headline driver.Why the full-subset test, and not "does reversibility name any peeled file?"
A consumer map override can put an irreversible-class file below the path floor — remap
migrationsto path R1 while leaving it inirreversible_classes— and there peeling$topfleaves the reversibility reason exactly where it was. A weaker "any" test would speak wrongly on precisely that record. There is a dedicated fixture for it.filesabsent ornull— the R2 rung ("no green rollup", a property of the head commit) and the R1 rung ("no test touched", a property of the whole change set), plus every record graded before BE-7418 added the field — reads as not removable. That is a deliberate fail-safe back to today's unconditional suppression, and it is pinned as a test rather than left implicit.Verification
Per
.github/workflows/test-pr-risk.yml, run fromscripts/pr-risk/:shellcheck -x(all 11 files)tests/test_grade_pr_risk.shtests/test_apply_risk_label.shtests/test_grade_targets.shtests/test_pin_contract.shtests/test_publish_risk_surfaces.shtests/test_resolve_enabled.shRed-before-green, measured: the new suite was run against
HEAD:scripts/pr-risk/publish-risk-surfaces.sh(the pre-change script) and returned 87 passed, 4 failed — failing exactly the four positive assertions (clause prints, caveat attached, headline names both axes,$conc_shortfires) and passing every silence assertion. That is the ticket's reproduction confirmed against the shipped code, and it also proves the new SILENT assertions pin pre-existing behavior rather than behavior this PR introduces.Malformed-input probe.
axes.reversibility.fileswas driven with"a string",42,true,{"a":1},[null],[42], and a partial-subset["…", null]. Every one renders silently at exit 0 with no clause and no jq error — jq'sandshort-circuits ahead of the$rf[]iteration, so a non-array can never reach it.Test coverage added
The
record/file_entryhelpers now carryaxes.reversibility.filesand per-fileclasses, both defaulting to what every pre-existing fixture used (nulland["cls"]), so no existing assertion changes meaning. New cases:files: ["migrations/0042_drop.sql"]⊆$topf→ clause prints with the remainder's floor, caveat attached, headlinepath and reversibility,$conc_shortfiresfiles: null→ silent (backward compatibility pinned)files: []→ silent (an empty list is a subset of everything; rejected by the non-empty test)The existing provenance-tie assertion is untouched; only the comment above it was narrowed to say "provenance tie", since the blanket claim is no longer true of both axes.
Judgment calls
$driverskept as the combined list rather than removed. The ticket allowed either; keeping it means$conc_tailis byte-identical, and$conc_tailand the new clause are mutually exclusive by construction anyway ($conc_tailneedstier > floor,$path_decidedneedstier == floor).tkey was dropped from$driversentries now that membership is decided by the pre-computed booleans. Verified by grep that nothing reads.t— the two consumers use.aand[0].ronly.ties($t; $headline)takes the headline as a parameter instead of closing over$tier: thedefblock is compiled before the record is destructured, so a lexical reference would not resolve.not supported/unavailable/STOPstrings, no throw/deny path, and no test was flipped to assert a dead-end (the new SILENT assertions pin behavior that is green on both the old and new script, as the red-before-green run above shows).Provenance
Ticket BE-7419, deferred from #162 review thread
r3774678317; origin spike BE-7414. Depends on #162 (merged,14ea7d5) for$path_decided/$drivers/ the clause, and on BE-7418 / #163 (merged,c67a2a4) foraxes.reversibility.files. Both are onmain, so this is a plain PR againstmain, not a stacked one.🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.