Skip to content
Merged
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
bump: patch
---

### Changed

- pr-verify reads the key's credit history only for a head it would judge: the `check-intent-credit` job is gone, and its gate and skipped-leg report run inside `check-intent` after the resolver, the trigger gate and the reads hand-on. A run that skips at the resolver (a judged head, a draft, a run red for anything but a hold, no single PR) no longer spends the gate's reads or its own VM. A key the gate skips runs no pre-judge setup and no judge, writes no "no verdict" failure, and hands on through the `skip-key` job output, so `check-intent-subscription` now takes the carried reads instead of reading the PR again.
- The gate now reads the key's credit stop from one artifact marker (ci-workflows check-key-credit at `bc62beb`): one artifact-list call per judged run instead of a run list and up to three job lists. After a judge step's credit-stop handoff, `check-intent` writes, scans and uploads the artifact the gate's `marker` output names, kept one day; the step that carried a record forward is gone, since the window counts from the marker's upload. pr-verify's other ci-workflows actions move to the same pin.
3 changes: 2 additions & 1 deletion .github/actions/resolve-config/callers.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2149,7 +2149,7 @@ test("no run-claude-cli plugin-dirs or add-dirs value names runner.temp, RUNNER_
// does; check-permission-mode.sh accepts default for dontAsk on that basis.
// 7b362428: lane.cjs:311-312; 164c2809: lane.cjs:355-358; d02b8697 and e5167fc2: lane.cjs:357-358;
// ba7af78d291f10bd75651857a0db2357c23df0fe, 30b251532b2e9f7e0c4215e1dee5be0d3c688743, 81a603a6e2b0319428c981bf28f3fe923032afb2
// and 2476d5dde8979eab34374150b7e4b0a2b99f4e88: lane.cjs:404-405; in cliArgs. The org requires
// 2476d5dde8979eab34374150b7e4b0a2b99f4e88 and bc62beb95a989641f30552a932a132ebb8ecd801: lane.cjs:404-405; in cliArgs. The org requires
// actions pinned to a full SHA, so a pin bump fails here until its lane.cjs is read and its SHA added.
const PERMISSION_PROMPTS_NONE_LAUNCHERS = new Set([
"7b362428c76085a160e28656cd2c75c3147a69ff",
Expand All @@ -2160,6 +2160,7 @@ const PERMISSION_PROMPTS_NONE_LAUNCHERS = new Set([
"30b251532b2e9f7e0c4215e1dee5be0d3c688743",
"81a603a6e2b0319428c981bf28f3fe923032afb2",
"2476d5dde8979eab34374150b7e4b0a2b99f4e88",
"bc62beb95a989641f30552a932a132ebb8ecd801",
]);

test("every run-claude-cli step pin in this repo's workflows is a launcher checked to pass --permission-prompts none", () => {
Expand Down
8 changes: 8 additions & 0 deletions .github/artifact-retention.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@
".github/workflows/pr-verify.yml#check-intent-fallback"
]
},
"key-credit-stop-pr-verify.yml-check-intent": {
"retention-days": 1,
"readers": [
".github/workflows/pr-verify.yml check-intent's \"Read the key's credit history\" step runs ci-workflows check-key-credit, which reads the newest marker of this exact name inside KEY_CREDIT_WINDOW_HOURS (1 hour unset, 24 at most for this retention)"
],
"reason": "The marker only says the key hit a credit stop; the gate counts it for its window, an hour by default, so a day covers any window up to 24 hours and an expired marker runs the key, as before the gate.",
"scan": "upload"
},
"pr-review-main-*": {
"retention-days": "max",
"readers": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -697,21 +697,22 @@ test("a verify run is read across all three legs: a fallback write held, a fallb
assert.deepEqual(records(lost.outputs), [`reconcile-rerun-201-2-${MAIN_TIP}`, "", ""]);
});

// With the key out of credit, the credit gate skips check-intent and the
// subscription leg judges: its own steps tell a write held from a run lost.
// With the key out of credit, check-intent's credit gate skips its key leg and
// the subscription leg judges: its own steps tell a write held from a run lost.
test("a verify run whose credit gate skipped the key is read on the subscription leg", async () => {
const gate = {
name: "check-intent-credit",
const key = {
name: "check-intent",
status: "completed",
conclusion: "success",
steps: [
{ name: "Set up job", status: "completed", conclusion: "success" },
{ name: "Hand the reads on", status: "completed", conclusion: "success" },
{ name: "Read the key's credit history", status: "completed", conclusion: "success" },
{ name: "Record the key's credit stop in run 200", status: "completed", conclusion: "success" },
{ name: JUDGE_PREDECESSOR, status: "completed", conclusion: "skipped" },
{ name: JUDGE_STEP, status: "completed", conclusion: "skipped" },
{ name: "Complete job", status: "completed", conclusion: "success" },
],
};
const key = { name: "check-intent", status: "completed", conclusion: "skipped", steps: [] };
const subscription = (write, upload) => ({
name: "check-intent-subscription",
status: "completed",
Expand All @@ -725,9 +726,9 @@ test("a verify run whose credit gate skipped the key is read on the subscription
{ name: "Complete job", status: "completed", conclusion: "success" },
],
});
const held = await reconcile({ pulls: [], runs: [{ ...verifyRun(201, { conclusion: "failure" }), jobs: [gate, key, subscription("success", "failure")] }] });
const held = await reconcile({ pulls: [], runs: [{ ...verifyRun(201, { conclusion: "failure" }), jobs: [key, subscription("success", "failure")] }] });
assert.deepEqual(held.reruns, []);
const lost = await reconcile({ pulls: [], runs: [{ ...verifyRun(201, { conclusion: "failure" }), jobs: [gate, key, subscription("skipped", "skipped")] }] });
const lost = await reconcile({ pulls: [], runs: [{ ...verifyRun(201, { conclusion: "failure" }), jobs: [key, subscription("skipped", "skipped")] }] });
assert.deepEqual(lost.reruns, [201]);
assert.deepEqual(records(lost.outputs), [`reconcile-rerun-201-2-${MAIN_TIP}`, "", ""]);
});
Expand Down
2 changes: 1 addition & 1 deletion .github/scripts/pr-verify/probe/replay.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ export const jobUrl = (runId, jobId) => `https://github.com/${REPOSITORY}/action
// apply-claude-managed-settings to. cliArgs, LEG_ENV, CLI_VERSION and
// MANAGED_SETTINGS were read from that SHA; the parity test fails when the
// pin moves, so they are read again.
export const RUN_CLAUDE_CLI_PIN = "2476d5dde8979eab34374150b7e4b0a2b99f4e88";
export const RUN_CLAUDE_CLI_PIN = "bc62beb95a989641f30552a932a132ebb8ecd801";
export const CLI_VERSION = "latest";
export const MANAGED_SETTINGS = Object.freeze({
apiKeyHelper: "",
Expand Down
Loading
Loading