Improve execution preflight diagnostics
This commit is contained in:
80
tools/web/check-execution-health.mjs
Normal file
80
tools/web/check-execution-health.mjs
Normal file
@@ -0,0 +1,80 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import {
|
||||
buildTaskContext,
|
||||
parseQueue,
|
||||
readIndexedTask,
|
||||
verifyTaskIndex,
|
||||
} from "./task-context-lib.mjs";
|
||||
import { collectGeneratedGapPreflight } from "./generated-gap-preflight.mjs";
|
||||
|
||||
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
||||
const requested = process.argv.indexOf("--task");
|
||||
const requestedTask = requested >= 0 ? process.argv[requested + 1] : undefined;
|
||||
const issues = [];
|
||||
const add = (code, detail) => issues.push({ code, detail });
|
||||
const relative = (file) => path.relative(repoRoot, file).replaceAll(path.sep, "/");
|
||||
|
||||
let queue;
|
||||
let index;
|
||||
let entry;
|
||||
try {
|
||||
queue = parseQueue();
|
||||
index = verifyTaskIndex();
|
||||
const task = requestedTask ?? queue.currentTask;
|
||||
const checkingCurrent = requestedTask === undefined;
|
||||
entry = readIndexedTask(task);
|
||||
if (!entry) add("TASK_NOT_INDEXED", task);
|
||||
|
||||
const parentPath = path.resolve(repoRoot, queue.parentManifest);
|
||||
if (checkingCurrent && !fs.existsSync(parentPath)) add("PARENT_MANIFEST_MISSING", queue.parentManifest);
|
||||
else if (checkingCurrent) {
|
||||
const parent = JSON.parse(fs.readFileSync(parentPath, "utf8"));
|
||||
if (parent.nextTask !== queue.currentTask) add("PARENT_NEXT_TASK_MISMATCH", `${parent.nextTask ?? "NONE"}!=${queue.currentTask}`);
|
||||
}
|
||||
|
||||
if (index) {
|
||||
if (checkingCurrent && index.activeTask !== queue.currentTask) add("INDEX_ACTIVE_TASK_MISMATCH", `${index.activeTask ?? "NONE"}!=${queue.currentTask}`);
|
||||
const catalogPath = path.resolve(repoRoot, index.catalog.path);
|
||||
const active = fs.readFileSync(catalogPath, "utf8").trimEnd().split("\n").filter(Boolean)
|
||||
.map((line) => JSON.parse(line)).filter((record) => record.state === "active");
|
||||
if (checkingCurrent && active.length !== 1) add("CATALOG_ACTIVE_TASK_COUNT", `count=${active.length}`);
|
||||
else if (checkingCurrent && active[0].id !== queue.currentTask) add("CATALOG_ACTIVE_TASK_MISMATCH", `${active[0].id}!=${queue.currentTask}`);
|
||||
}
|
||||
|
||||
const cardPath = path.join(repoRoot, "docs/tasks", `${task}.md`);
|
||||
if (!fs.existsSync(cardPath) || fs.statSync(cardPath).size === 0) add("TASK_CARD_MISSING", relative(cardPath));
|
||||
else if (checkingCurrent) {
|
||||
const context = buildTaskContext(task);
|
||||
if (context.context.task !== task) add("TASK_CONTEXT_MISMATCH", `${context.context.task}!=${task}`);
|
||||
}
|
||||
|
||||
for (const issue of collectGeneratedGapPreflight({ root: repoRoot, task: requestedTask ?? queue.currentTask, entry })) {
|
||||
add(issue.code, issue.detail);
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
add("HEALTH_CHECK_ERROR", error instanceof Error ? error.message : String(error));
|
||||
}
|
||||
|
||||
const report = {
|
||||
schemaVersion: 1,
|
||||
operation: "WEB_EXECUTION_HEALTH",
|
||||
status: issues.length === 0 ? "PASS" : "BLOCKED",
|
||||
queueTask: queue?.currentTask ?? null,
|
||||
checkedTask: requestedTask ?? queue?.currentTask ?? null,
|
||||
indexActiveTask: index?.activeTask ?? null,
|
||||
issueCount: issues.length,
|
||||
issues,
|
||||
remediation: [
|
||||
...(issues.some(({ code }) => ["INDEX_ACTIVE_TASK_MISMATCH", "CATALOG_ACTIVE_TASK_MISMATCH", "CATALOG_ACTIVE_TASK_COUNT", "PARENT_NEXT_TASK_MISMATCH"].includes(code))
|
||||
? ["repair the queue/index/catalog pointer through the repository generator"] : []),
|
||||
...(issues.some(({ code }) => code === "TASK_CARD_MISSING")
|
||||
? ["generate the compact task card before running a gap checker"] : []),
|
||||
...(issues.some(({ code }) => ["TASK_NOT_RUNNABLE", "INPUT_MISSING", "INPUT_NOT_FILE"].includes(code))
|
||||
? ["do not start Blender or load WASM until the task state and inputs are ready"] : []),
|
||||
],
|
||||
};
|
||||
process.stdout.write(`${JSON.stringify(report)}\n`);
|
||||
if (issues.length !== 0) process.exitCode = 2;
|
||||
Reference in New Issue
Block a user