Skip to content

Commit 7679f8b

Browse files
Jack Qclaude
andauthored
fix(pm-tooling): drop caller-specific nouns from shared transport verdicts (#10445)
check-half-states.mjs's classifyTransportProbe/classifyRepoRead classifier is shared with ci-failure.mjs (#9966), a caller that runs no "sweep" and reads no "board". The repo-scope-refused verdict and host-unreachable's fix text (both branches that return it) named "the sweep" / "the board read" as their subject; both now speak caller-neutral prose describing what the container cannot do, with no per-caller parameter. rate-limited's existing `how`-clause parameterization is untouched (already caller-correct). Self-test pins the neutral wording as a regression (637 -> 641 cases). Part of #10156 Co-authored-by: Claude <noreply@anthropic.com>
1 parent c725c47 commit 7679f8b

1 file changed

Lines changed: 44 additions & 9 deletions

File tree

scripts/pm/check-half-states.mjs

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3006,7 +3006,7 @@ function classifyRepoRead(tok, primary, repo) {
30063006
return {
30073007
kind: 'repo-scope-refused',
30083008
headline:
3009-
'the transport authenticates but repo-scoped reads are refused — the sweep cannot list one page',
3009+
'the transport authenticates but repo-scoped reads are refused — this container cannot make one repo-scoped request',
30103010
detail: [
30113011
`\`GET /rate_limit\` -> ${describeProbe(primary)}.`,
30123012
`\`GET /repos/${OWNER_REPO}\` -> HTTP ${repo.status}${
@@ -3024,12 +3024,13 @@ function classifyRepoRead(tok, primary, repo) {
30243024
``,
30253025
`This is reported instead of a green precisely because the stage-1 reading here`,
30263026
`is INDISTINGUISHABLE from the healthy Routine runner's. Before this stage`,
3027-
`existed the probe said the prerequisite was met and the sweep then 403'd on its`,
3028-
`first page — the #4690 inversion, inside the mechanism built to prevent it.`,
3027+
`existed the probe said the prerequisite was met and the first repo-scoped`,
3028+
`request then 403'd — the #4690 inversion, inside the mechanism built to`,
3029+
`prevent it.`,
30293030
],
30303031
fix: [
3031-
'run the sweep from a container whose egress allows repo-scoped reads (CI, or',
3032-
'the Routine seat class); in a proxy-mediated seat the board read stays on the',
3032+
'run this from a container whose egress allows repo-scoped reads (CI, or the',
3033+
'Routine seat class); in a proxy-mediated seat, repo-scoped reads stay on the',
30333034
'`mcp__github__*` tools, which take a different path and do work here.',
30343035
],
30353036
};
@@ -3086,8 +3087,9 @@ export function classifyTransportProbe(obs) {
30863087
`script's transport.`,
30873088
],
30883089
fix: [
3089-
'run the sweep from a container with direct egress to api.github.com (CI, or',
3090-
'the Routine seat class); in an MCP-only seat the board read stays manual.',
3090+
'run this from a container with direct egress to api.github.com (CI, or the',
3091+
'Routine seat class); in an MCP-only seat this stays manual — the',
3092+
'`mcp__github__*` tools take a different path and may still work.',
30913093
],
30923094
};
30933095
}
@@ -3183,8 +3185,9 @@ export function classifyTransportProbe(obs) {
31833185
`\`curl\` and the \`mcp__github__*\` tools take a different path and may still work.`,
31843186
],
31853187
fix: [
3186-
'run the sweep from a container with direct egress to api.github.com (CI, or',
3187-
'the Routine seat class); in an MCP-only seat the board read stays manual.',
3188+
'run this from a container with direct egress to api.github.com (CI, or the',
3189+
'Routine seat class); in an MCP-only seat this stays manual — the',
3190+
'`mcp__github__*` tools take a different path and may still work.',
31883191
],
31893192
};
31903193
}
@@ -5386,6 +5389,22 @@ function selfTest() {
53865389
kind({ token: 'prox_placeholder', authed: { status: 403, rateLimitRemaining: 59 }, anon: { status: 403, rateLimitRemaining: 59 } }),
53875390
'host-unreachable',
53885391
);
5392+
// #10156: the shared classifier is imported by ci-failure.mjs (#9966), a
5393+
// caller that runs no "sweep" and reads no "board" — so `host-unreachable`'s
5394+
// fix text must not name either, in EITHER branch that returns this kind
5395+
// (network error, and the 403-in-both-directions case pinned just above).
5396+
t(
5397+
"…and host-unreachable's fix (403-both-ways branch) names neither the sweep nor the board read",
5398+
/the sweep|the board read/.test(
5399+
classifyTransportProbe({ token: 'prox_placeholder', authed: { status: 403, rateLimitRemaining: 59 }, anon: { status: 403, rateLimitRemaining: 59 } }).fix.join(' '),
5400+
),
5401+
false,
5402+
);
5403+
t(
5404+
"…and host-unreachable's fix (network-error branch) names neither the sweep nor the board read",
5405+
/the sweep|the board read/.test(classifyTransportProbe({ token: '', anon: { networkError: 'ENOTFOUND' } }).fix.join(' ')),
5406+
false,
5407+
);
53895408
// Class 2 — triage Routine container: reachable with a real credential.
53905409
t(
53915410
'#7412 class 2 (Routine): authed 200 -> reachable',
@@ -5448,6 +5467,22 @@ function selfTest() {
54485467
classifyTransportProbe(class4).detail.join(' ').includes('contradict'),
54495468
true,
54505469
);
5470+
// #10156: repo-scope-refused is shared with ci-failure.mjs (#9966), a caller
5471+
// that runs no "sweep" and reads no "board" — its headline/detail/fix must
5472+
// describe what the CONTAINER cannot do, not what a caller-specific "sweep"
5473+
// or "board read" cannot do.
5474+
t(
5475+
"…and none of its prose (headline, detail, fix) names the sweep or the board read",
5476+
/the sweep|the board read/.test(
5477+
[classifyTransportProbe(class4).headline, ...classifyTransportProbe(class4).detail, ...classifyTransportProbe(class4).fix].join(' '),
5478+
),
5479+
false,
5480+
);
5481+
t(
5482+
'…and its headline instead speaks caller-neutrally about the container',
5483+
classifyTransportProbe(class4).headline.includes('this container cannot make one repo-scoped request'),
5484+
true,
5485+
);
54515486
// Direction B, refused on the card: no vendor string is matched. The fixture
54525487
// carries a status and a header count and NOTHING else — no response body is
54535488
// observed at all — so a body-matching classifier could not have fired here.

0 commit comments

Comments
 (0)