test: validate WP5 task lineage for WP4-07 gate
Dada P0-A isolated Windows CI / validate-and-package (push) Failing after 3m23s

This commit is contained in:
suyx
2026-08-03 19:26:39 +08:00
parent 40ecf0414a
commit dc83408ec2
4 changed files with 90 additions and 9 deletions
+49 -6
View File
@@ -4,9 +4,10 @@ import { existsSync, readFileSync } from "node:fs";
import { WP4_07_RED_RESOURCE_VERSION, WP4_07_SOURCE_HASHES, assertWp407Fixture } from "../../tests/visual-performance/wp4-07-fixture.mjs";
export const WP4_07_REQUIRED_WP5_BRANCHES = Object.freeze(
Array.from({ length: 7 }, (_, index) => `codex/wp5-0${index + 1}`),
export const WP4_07_REQUIRED_WP5_TASKS = Object.freeze(
Array.from({ length: 7 }, (_, index) => `TASK-WP5-0${index + 1}`),
);
export const WP4_07_FINAL_WP5_BRANCH = "codex/wp5-07";
export function validateWp407FrozenInputs() {
const mismatches = [];
@@ -26,6 +27,28 @@ export function validateWp407FrozenInputs() {
return assertWp407Fixture();
}
export function inspectWp5TaskLineage(heads, commits) {
const candidate_branch = [...WP4_07_REQUIRED_WP5_TASKS]
.reverse()
.map((taskId) => taskId.replace("TASK-WP5-", "codex/wp5-"))
.find((branch) => /^[0-9a-f]{40}$/.test(heads[branch] ?? "")) ?? null;
const task_shas = Object.fromEntries(WP4_07_REQUIRED_WP5_TASKS.flatMap((taskId) => {
const commit = commits.find((entry) => entry.subject.includes(taskId));
return commit && /^[0-9a-f]{40}$/.test(commit.sha) ? [[taskId, commit.sha]] : [];
}));
const missing_tasks = WP4_07_REQUIRED_WP5_TASKS.filter((taskId) => !task_shas[taskId]);
return {
candidate_baseline_branch: candidate_branch,
candidate_baseline_sha: candidate_branch ? heads[candidate_branch] : null,
complete: candidate_branch === WP4_07_FINAL_WP5_BRANCH && missing_tasks.length === 0,
final_branch_sha: heads[WP4_07_FINAL_WP5_BRANCH] ?? null,
missing_tasks,
required_final_branch: WP4_07_FINAL_WP5_BRANCH,
required_tasks: WP4_07_REQUIRED_WP5_TASKS,
task_shas,
};
}
export function readWp5RemoteGate() {
const result = spawnSync("git", ["ls-remote", "--heads", "origin", "codex/wp5-*"], { encoding: "utf8", timeout: 30_000 });
if ((result.status ?? 1) !== 0) {
@@ -37,12 +60,32 @@ export function readWp5RemoteGate() {
const [sha, reference] = line.split(/\s+/);
return [reference.replace("refs/heads/", ""), sha];
}));
const missing_branches = WP4_07_REQUIRED_WP5_BRANCHES.filter((branch) => !/^[0-9a-f]{40}$/.test(heads[branch] ?? ""));
const candidateBranch = [...WP4_07_REQUIRED_WP5_TASKS]
.reverse()
.map((taskId) => taskId.replace("TASK-WP5-", "codex/wp5-"))
.find((branch) => /^[0-9a-f]{40}$/.test(heads[branch] ?? ""));
let commits = [];
if (candidateBranch) {
const fetch = spawnSync("git", ["fetch", "--quiet", "--no-tags", "origin", `refs/heads/${candidateBranch}`], { encoding: "utf8", timeout: 60_000 });
if ((fetch.status ?? 1) !== 0) {
const error = new Error("WP4_07_GITEA_BASELINE_FETCH_FAILED");
error.details = { branch: candidateBranch, exit_code: fetch.status ?? 1 };
throw error;
}
const log = spawnSync("git", ["log", "--format=%H%x09%s", heads[candidateBranch]], { encoding: "utf8", timeout: 30_000 });
if ((log.status ?? 1) !== 0) {
const error = new Error("WP4_07_GITEA_BASELINE_HISTORY_UNREADABLE");
error.details = { branch: candidateBranch, exit_code: log.status ?? 1 };
throw error;
}
commits = log.stdout.trim().split(/\r?\n/).filter(Boolean).map((line) => {
const separator = line.indexOf("\t");
return { sha: line.slice(0, separator), subject: line.slice(separator + 1) };
});
}
return {
complete: missing_branches.length === 0,
heads,
missing_branches,
required_branches: WP4_07_REQUIRED_WP5_BRANCHES,
...inspectWp5TaskLineage(heads, commits),
};
}