Skip to content

Commit 30caf75

Browse files
committed
fix(scripts/pm): H59 reads state_reason so a deliberately REOPENED card is not called a platform failure
H59's FALSE OPEN row said 「GitHub did not perform the closure the PR declared」 for every open card a merged PR bound a closing keyword to — including a card that was closed and then REOPENED on purpose. The discriminator is already on the open-listing payload the row holds (`state_reason: 'reopened'`), so the arm costs no request. Keeps the row (a declared closure that is not in force is still worth reading) and changes the sentence for that one case: it names the reopen as the act to read, declares that it buys no timeline and therefore does not place the reopen against the merge, and points the remedy at the reopen's own reason rather than at GitHub. Every other `state_reason`, null included, keeps today's sentence. Claude-Session: https://claude.ai/code/session_017ETYWqMQD4qMtZzAGovWNi Co-authored-by: Claude <noreply@anthropic.com>
1 parent a0e62e6 commit 30caf75

1 file changed

Lines changed: 29 additions & 0 deletions

File tree

‎scripts/pm/check-half-states.mjs‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14485,8 +14485,24 @@ export function h59FalseCloseRow({ pr, card, attribution, closedEvent, closedAtM
1448514485
*
1448614486
* The card's presence in the open listing IS the reading, so a truncated
1448714487
* listing can only lose a row and never invent one.
14488+
*
14489+
* ⭐ The row also carries `state_reason`, the whole discriminator for the
14490+
* REOPENED arm: a card open because somebody REOPENED it is a deliberate act,
14491+
* ⛔ never GitHub failing to close it, so the arm changes the SENTENCE only.
1448814492
*/
1448914493
export function h59FalseOpenRow({ pr, card, keyword }) {
14494+
if (String(card?.state_reason ?? '') === 'reopened') {
14495+
return (
14496+
`FALSE OPEN (reopened): merged PR #${pr?.number} binds \`${keyword} #${card?.number}\` in its body and ` +
14497+
'the card is open carrying `state_reason: reopened` — it was CLOSED at some point and REOPENED since, a ' +
14498+
'deliberate act and ⛔ never the platform failure the plain row names. ⚠️ This row buys no timeline, so it ' +
14499+
'does not PLACE that reopen against the merge: whether the declared closure fired and was reversed, or ' +
14500+
'never fired on an already-reopened card, is unread here — what the payload settles is that a REOPEN ' +
14501+
'happened, and that is the act to read. Remedy, and it belongs to the SEAT THAT OWNS the card: read the ' +
14502+
'reopen\'s own reason — the comment that made it, or the decision-box label it carries — and ⛔ do not ' +
14503+
'close a card somebody reopened on purpose. ⛔ This row closes nothing and writes no label.'
14504+
);
14505+
}
1449014506
return (
1449114507
`FALSE OPEN: merged PR #${pr?.number} binds \`${keyword} #${card?.number}\` in its body, and the card ` +
1449214508
'is STILL OPEN after that merge — GitHub did not perform the closure the PR declared. ' +
@@ -34745,6 +34761,19 @@ Doubles as the fire's **write self-check** (step 0). \`201\` is not the reading.
3474534761
t('H59 (b): ⛔ no angle-bracket placeholder reaches the row body', /[<>]/.test(row59b), false);
3474634762
t('H59 (b): not a loud finding', isLoudFinding(row59b), false);
3474734763

34764+
// ⭐ Direction (b), REOPENED — the discriminator rides the same open listing row, so the arm buys nothing.
34765+
const row59bBy = (state_reason) => h59FalseOpenRow({ pr: pr59FalseOpen, card: { ...card59Open, state_reason }, keyword: 'Fixes' });
34766+
const row59bReopened = row59bBy('reopened');
34767+
t('H59 (b) reopened: ⛔ the platform-failure sentence is NOT printed at all', row59bReopened.includes('GitHub did not perform the closure'), false);
34768+
t('H59 (b) reopened: …it quotes the field it read off the payload it already held', row59bReopened.includes('`state_reason: reopened`'), true);
34769+
t('H59 (b) reopened: it says the card was closed and REOPENED since, a deliberate act', row59bReopened.includes('CLOSED at some point and REOPENED since'), true);
34770+
t('H59 (b) reopened: ⛔ it refuses to PLACE the reopen against the merge, buying no timeline', row59bReopened.includes('buys no timeline'), true);
34771+
t('H59 (b) reopened: the remedy points at the REOPEN\'s own reason', row59bReopened.includes('read the reopen\'s own reason'), true);
34772+
t('H59 (b) reopened: …and ⛔ warns off closing a card somebody reopened on purpose', row59bReopened.includes('do not close a card somebody reopened on purpose'), true);
34773+
t('H59 (b) reopened: the row still FIRES — this changed the SENTENCE, ⛔ not the population', row59bReopened.startsWith('FALSE OPEN (reopened):'), true);
34774+
t('H59 (b) reopened: ⛔ no angle-bracket placeholder reaches this one either', /[<>]/.test(row59bReopened), false);
34775+
t('H59 (b) reopened: ⛔ every OTHER state_reason keeps today\'s sentence, null included', [null, undefined, 'completed', 'not_planned'].every((r) => row59bBy(r).includes('GitHub did not perform the closure')), true);
34776+
3474834777
// The two directions are DISTINCT sentences — neither restates the other.
3474934778
t('H59 directions: the two rows do not share an opening', row59a.slice(0, 20) === row59b.slice(0, 20), false);
3475034779

0 commit comments

Comments
 (0)