fix: pre-landing review fixes (pass 2)

An unclosed receipt fence makes the body from that line on one section
the merge never matches, so posted leading prose cannot replace it and a
closed receipt before it stays a receipt; the by-tree pregate mirror must
hold the tests stage (what --stage tests --remote writes) rather than
every check; empty sha/tree strings in a train note are not evidence;
(v1.2.3-rc1 #301) is a version word, not a repository.

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 16:38:08 +00:00
1 parent 90f08a3eb3
commit b8373e2bfc
10 files changed
+49 -31

No files matched your search

+7 -6
View File
@@ -145,10 +145,11 @@ interface Section { key: string; label: string; text: string }
* a key of its own, so it is never replaced. A fence closes only on a run of
* its own character at least as long as the opener with nothing after it
* (CommonMark), so a ``` line inside a ```` block and a ```js line close
* nothing; a receipt fence that never closes is an ordinary unclosed fence,
* so the rest of the body stays one kept section instead of a receipt.
* nothing; a receipt fence that never closes makes the body from that line
* on one section the merge never matches (`unclosed-receipt`), so it is kept
* byte for byte instead of being read as a receipt or as replaceable text.
*/
function splitSections(body: string, receipts = true): Section[] {
function splitSections(body: string): Section[] {
const out: Section[] = [];
let fence: string | null = null;
let plain = 0;
@@ -159,7 +160,7 @@ function splitSections(body: string, receipts = true): Section[] {
for (const line of body.split(/(?<=\n)/)) {
bare = line.replace(/\r?\n$/, "");
const fenceOpen: RegExpExecArray | null = fence === null ? /^ {0,3}(`{3,}|~{3,})/.exec(bare) : null;
if (fenceOpen && receipts && bare.trim() === "```" + RECEIPT_FENCE) { open("receipt", "ship receipt"); fence = "receipt"; }
if (fenceOpen && bare.trim() === "```" + RECEIPT_FENCE) { open("receipt", "ship receipt"); fence = "receipt"; }
else if (fence === "receipt") { out.at(-1)!.text += line; if (closes("```")) { fence = null; openText(); } continue; }
else if (fenceOpen) fence = fenceOpen[1]!;
else if (fence && closes(fence)) fence = null;
@@ -167,7 +168,7 @@ function splitSections(body: string, receipts = true): Section[] {
if (out.length === 0) openText();
out.at(-1)!.text += line;
}
if (fence === "receipt") return splitSections(body, false);
if (fence === "receipt") Object.assign(out.at(-1)!, { key: "unclosed-receipt", label: "unclosed receipt fence" });
return out.filter(s => s.text !== "");
}
@@ -190,7 +191,7 @@ export function mergeBodySections(current: string, incoming: string): { body: st
const used = new Set<Section>();
const replaced: string[] = [], kept: string[] = [], added: string[] = [];
const merged: Section[] = now.map(s => {
const match = next.find(n => !used.has(n) && n.key === s.key);
const match = s.key === "unclosed-receipt" ? undefined : next.find(n => !used.has(n) && n.key === s.key);
if (!match) { if (s.text.trim()) kept.push(s.label); return s; }
used.add(match); replaced.push(s.label); return match;
});
+1 -1
View File
@@ -48,7 +48,7 @@ const BARE = /(?<![A-Za-z0-9_./-])#(\d+)\b/g;
/** `(name #N[, #M]…)`, `(name PR #N)`, `(name issue #N)`: the name, then every number. */
const NAMED = /\(([A-Za-z][\w.-]*(?:\/[\w.-]+)?)\s+(?:(?:PR|issue)\s+)?(#\d+(?:,\s*#\d+)*)\)/gi;
/** Words that open a reference in parentheses without naming a repository. */
const NOT_A_NAME = /^(?:fix(?:es|ed|ing)?|clos(?:e[sd]?|ing)|resolv(?:e[sd]?|ing)|address(?:es|ed|ing)?|implement(?:s|ed|ing)?|supersed(?:es|ed|ing)|replac(?:es|ed|ing)|track(?:s|ed|ing)?|block(?:s|ed|ing)?|dup|duplicates?|bugs?|upstream|refs?|see|related|partial(?:ly)?|part|context|follow-?up|defer(?:red)?|prs?|issues?|gh|via|from|after|since|with|in|by|for|also|cf\.?|e\.?g\.?|i\.?e\.?|and|or|per|of|to|on|at|as|is|was|the|an?|this|that|not|no|vs\.?|like|v\d+(?:\.\d+)*)$/i;
const NOT_A_NAME = /^(?:fix(?:es|ed|ing)?|clos(?:e[sd]?|ing)|resolv(?:e[sd]?|ing)|address(?:es|ed|ing)?|implement(?:s|ed|ing)?|supersed(?:es|ed|ing)|replac(?:es|ed|ing)|track(?:s|ed|ing)?|block(?:s|ed|ing)?|dup|duplicates?|bugs?|upstream|refs?|see|related|partial(?:ly)?|part|context|follow-?up|defer(?:red)?|prs?|issues?|gh|via|from|after|since|with|in|by|for|also|cf\.?|e\.?g\.?|i\.?e\.?|and|or|per|of|to|on|at|as|is|was|the|an?|this|that|not|no|vs\.?|like|v\d[\w.-]*)$/i;
/** Mentions in one commit message: trailer lines carry closure intent, everything else is a reference. */
export function mentionsIn(message: string, source = 'commit'): IssueMention[] {
+10 -8
View File
@@ -28,7 +28,7 @@
import * as fs from 'node:fs';
import * as path from 'node:path';
import type { PregateFile } from './headless-artifacts';
import { CHECK_IDS, pregateMirrorPath, readPregateFile, verifyPregate, PREGATE_OUT_REL } from './pregate/index';
import { CHECKS, pregateMirrorPath, readPregateFile, verifyPregate, PREGATE_OUT_REL } from './pregate/index';
import { ensureTmpExcluded, restamp, versionAtRef } from './restamp';
import type { ResultCodeName } from './result-codes';
import { bindReceipt, extractReceipt } from './ship-receipt';
@@ -187,17 +187,19 @@ function gateEvidence(ctx: QueueContext, pr: string, head: string, attempt: Atte
}
/**
* Why a by-tree mirror cannot stand in for this checkout's own record, or
* null. The mirror is keyed by tree alone, so any pregate run anywhere mints
* one; only a complete run (every registered check, so no `--only` or single
* stage) against the same base under a reviewed policy (not `--policy-from
* head`) is publication evidence for this PR.
* Why a by-tree pregate mirror cannot stand in for this checkout's own
* record, or null. The mirror is keyed by tree alone, so any pregate run
* anywhere mints one; what the lane case needs from it is the test tier that
* `gstack-pregate --stage tests --remote` ran in the clone, so the mirror
* must hold every tests-stage check (a `--only timing` or preflight-only run
* is not evidence), be recorded against the same base, and not come from
* `--policy-from head`.
*/
function mirrorGap(file: PregateFile, base: string): string | null {
if (!(file.base ?? '').startsWith(`origin/${base}@`)) return `recorded against ${file.base ?? 'no base'}, not origin/${base}`;
if (file.policy?.startsWith('head ')) return 'recorded under the unreviewed head policy';
const missing = CHECK_IDS.filter(id => !file.checks.some(c => c.id === id));
return missing.length ? `a partial run without ${missing.join(', ')}` : null;
const missing = CHECKS.filter(c => c.stage === 'tests' && !file.checks.some(k => k.id === c.id)).map(c => c.id);
return missing.length ? `a run without the tests stage (${missing.join(', ')})` : null;
}
function gateLine(policy: LoadedPolicy, attempt: AttemptRecord | null): string {