fix: pre-landing review fixes (ready at the stamp commit, screen on a stale merge ref, ship-run.json)

- ready accepts the pin's receipt at a slot's stamp commit (plus the slot-2
  merge of main), as verify --train already did; a real edit stays STALE
- ready --screen refuses QUEUE_SCREEN_STALE_REF when refs/pull/<n>/merge is
  missing or merges an older head; a finished screen that planned 0 cases is
  never followed, and train build seats that slot unscreened (GSTA-95 on #3431)
- gstack-ship-receipt result writes ship-run.json (a /ship record, not a run
  v1 manifest), validates --head, and prints status=incomplete on gh failures
- bindReceipt takes an optional pr and renders one-line SHIP_RECEIPT lines
- tests for every state-matrix cell the review named; the train fixture's
  merge ref is a real merge commit

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
garrytanandcapy-ai[bot] committed 2026-10-26 02:07:23 +00:00
1 parent 268b0125a5
commit ec438fe8b1
17 files changed
+368 -44

No files matched your search

+15
View File
@@ -69,6 +69,21 @@ export function downloadJson(ctx: QueueContext, slug: string, run: number, name:
}
/** The named check run on a commit (the newest when several); null when absent or unreadable. */
/**
* A finished screen run that planned no cases is not a screen: evals.yml plans
* 0 cases and reports success when the merge ref it was dispatched for was
* superseded (GSTA-95 on #3431). Returns the reason when the run is hollow,
* null when it is live, still running, or its census cannot be read.
*/
export function hollowScreen(ctx: QueueContext, slug: string, run: number, artifact: string, scratch: string): string | null {
const view = runView(ctx, slug, run);
if (!view || view.status !== 'completed') return null;
const rec = downloadJson(ctx, slug, run, artifact, scratch) as { census?: { planned?: { rule?: unknown; judge?: unknown } } } | null;
const planned = rec?.census?.planned;
if (!planned || typeof planned.rule !== 'number' || typeof planned.judge !== 'number') return null;
return planned.rule + planned.judge === 0 ? `run ${run} planned 0 cases (concluded ${view.conclusion ?? 'unknown'})` : null;
}
export function checkRun(ctx: QueueContext, sha: string, name: string): CheckInfo | null {
const r = json<{ check_runs?: Array<{ name?: string; status?: string; conclusion?: string | null }> }>(
ctx.gh(['api', `repos/{owner}/{repo}/commits/${sha}/check-runs?check_name=${encodeURIComponent(name)}`]));