chore: structure v02 check runner

This commit is contained in:
Codex
2026-05-29 01:34:39 +08:00
parent 6094ba36bb
commit 5827e9b5b9
5 changed files with 444 additions and 2 deletions
+5 -2
View File
File diff suppressed because one or more lines are too long
+11
View File
@@ -0,0 +1,11 @@
#!/usr/bin/env node
import { runCheckRunner } from "./src/check-runner-lib.mjs";
try {
const result = await runCheckRunner(process.argv.slice(2));
process.exit(result.exitCode);
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
process.stderr.write(JSON.stringify({ ok: false, command: "check-runner", error: message }, null, 2) + "\n");
process.exit(1);
}
+53
View File
@@ -0,0 +1,53 @@
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import test from "node:test";
import { checkProfiles } from "./src/check-plan.mjs";
import { parseCheckRunnerArgs, runCheckRunner, selectTasks } from "./src/check-runner-lib.mjs";
test("package scripts delegate to structured check runner", () => {
const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
assert.equal(pkg.scripts.check, "node scripts/check-runner.mjs --profile check");
assert.equal(pkg.scripts.validate, "node scripts/check-runner.mjs --profile validate");
assert.ok(!pkg.scripts.check.includes("&&"));
assert.ok(!pkg.scripts.validate.includes("&&"));
});
test("check plan exposes grouped tasks", () => {
assert.ok(checkProfiles.check.length > 80);
assert.ok(checkProfiles.validate.length > 5);
assert.ok(checkProfiles.check.some((task) => task.group === "cloud-api"));
assert.ok(checkProfiles.check.some((task) => task.group === "cloud-web"));
});
test("runner filters profile tasks by group", () => {
const options = parseCheckRunnerArgs(["--profile", "check", "--group", "cloud-api"]);
const tasks = selectTasks(options);
assert.ok(tasks.length > 0);
assert.ok(tasks.every((task) => task.group === "cloud-api"));
});
test("runner rejects unknown group and id instead of reporting an empty successful plan", () => {
assert.throws(
() => selectTasks(parseCheckRunnerArgs(["--profile", "check", "--group", "missing-group"])),
/unknown check group/u
);
assert.throws(
() => selectTasks(parseCheckRunnerArgs(["--profile", "check", "--id", "missing-id"])),
/unknown check task id/u
);
});
test("dry-run returns structured JSON without executing tasks", async () => {
let stdout = "";
const result = await runCheckRunner(["--profile", "validate", "--group", "repo", "--dry-run"], {
stdout: { write(chunk) { stdout += chunk; } },
stderr: { write() {} }
});
assert.equal(result.exitCode, 0);
const payload = JSON.parse(stdout);
assert.equal(payload.mode, "dry-run");
assert.equal(payload.profile, "validate");
assert.ok(payload.tasks.length > 0);
assert.ok(payload.tasks.every((task) => task.group === "repo"));
});
+179
View File
@@ -0,0 +1,179 @@
// Mechanical translation of the former root package.json check/validate scripts for #536.
// Keep each task as structured argv so future reviews can see semantic changes.
export const CHECK_PLAN_VERSION = "v02-structured-check-runner-v1";
export const checkProfiles = Object.freeze({
validate: Object.freeze([
{ id: "validate-001-repo-repo-reports-guard", group: "repo", command: ["node","scripts/repo-reports-guard.mjs"] },
{ id: "validate-002-repo-run-bun", group: "repo", command: ["node","scripts/run-bun.mjs","scripts/validate-contract.mjs"] },
{ id: "validate-003-deploy-run-bun", group: "deploy", command: ["node","scripts/run-bun.mjs","scripts/deploy-contract-plan.mjs","--check"] },
{ id: "validate-004-deploy-run-bun", group: "deploy", command: ["node","scripts/run-bun.mjs","scripts/deploy-desired-state-plan.mjs","--check"] },
{ id: "validate-005-dev-runtime-run-bun", group: "dev-runtime", command: ["node","scripts/run-bun.mjs","scripts/dev-runtime-provisioning.mjs","--check"] },
{ id: "validate-006-dev-runtime-run-bun", group: "dev-runtime", command: ["node","scripts/run-bun.mjs","scripts/dev-runtime-migration.mjs","--check"] },
{ id: "validate-007-dev-runtime-dev-runtime-postflight", group: "dev-runtime", command: ["node","scripts/dev-runtime-postflight.mjs","--check"] },
{ id: "validate-008-dev-runtime-dev-runtime-hotfix-audit", group: "dev-runtime", command: ["node","scripts/dev-runtime-hotfix-audit.mjs"] },
{ id: "validate-009-smoke-run-bun", group: "smoke", command: ["node","scripts/run-bun.mjs","scripts/rpt004-mvp-e2e-harness.mjs","--check","--no-write"] },
{ id: "validate-010-artifact-artifact-runtime-readiness-guard", group: "artifact", command: ["node","--check","scripts/artifact-runtime-readiness-guard.mjs"] },
{ id: "validate-011-artifact-artifact-runtime-readiness-guard", group: "artifact", command: ["node","--check","scripts/src/artifact-runtime-readiness-guard.mjs"] },
{ id: "validate-012-dev-runtime-dev-runtime-hotfix-audit", group: "dev-runtime", command: ["node","--check","scripts/dev-runtime-hotfix-audit.mjs"] },
{ id: "validate-013-dev-runtime-dev-runtime-hotfix-audit", group: "dev-runtime", command: ["node","--check","scripts/src/dev-runtime-hotfix-audit.mjs"] },
{ id: "validate-014-artifact-artifact-runtime-readiness-guard-test", group: "artifact", command: ["node","--test","scripts/artifact-runtime-readiness-guard.test.mjs","scripts/src/dev-runtime-hotfix-audit.test.mjs"] }
]),
check: Object.freeze([
{ id: "check-001-check-runner-check-runner", group: "check-runner", command: ["node","--check","scripts/check-runner.mjs"] },
{ id: "check-002-check-runner-lib", group: "check-runner", command: ["node","--check","scripts/src/check-runner-lib.mjs"] },
{ id: "check-003-check-runner-plan", group: "check-runner", command: ["node","--check","scripts/src/check-plan.mjs"] },
{ id: "check-004-check-runner-test-syntax", group: "check-runner", command: ["node","--check","scripts/check-runner.test.mjs"] },
{ id: "check-005-check-runner-test", group: "check-runner", command: ["node","--test","scripts/check-runner.test.mjs"] },
{ id: "check-006-repo-repo-reports-guard", group: "repo", command: ["node","scripts/repo-reports-guard.mjs"] },
{ id: "check-007-repo-repo-reports-guard", group: "repo", command: ["node","--check","scripts/repo-reports-guard.mjs"] },
{ id: "check-008-repo-report-paths", group: "repo", command: ["node","--check","scripts/src/report-paths.mjs"] },
{ id: "check-009-repo-index", group: "repo", command: ["node","--check","internal/protocol/index.mjs"] },
{ id: "check-010-repo-build-metadata", group: "repo", command: ["node","--check","internal/build-metadata.mjs"] },
{ id: "check-011-repo-index", group: "repo", command: ["node","--check","internal/agent/index.mjs"] },
{ id: "check-012-repo-runtime", group: "repo", command: ["node","--check","internal/agent/runtime.mjs"] },
{ id: "check-013-repo-index", group: "repo", command: ["node","--check","internal/audit/index.mjs"] },
{ id: "check-014-cloud-api-run-bun", group: "cloud-api", command: ["node","scripts/run-bun.mjs","build","internal/db/runtime-store.ts","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-015-cloud-api-run-bun", group: "cloud-api", command: ["node","scripts/run-bun.mjs","build","internal/db/runtime-store.test.ts","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-016-smoke-summary", group: "smoke", command: ["node","--check","internal/mvp-gate/summary.mjs"] },
{ id: "check-017-cloud-api-run-bun", group: "cloud-api", command: ["node","scripts/run-bun.mjs","build","internal/cloud/db-contract.ts","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-018-repo-cloud-web-routes", group: "repo", command: ["node","--check","internal/dev-entrypoint/cloud-web-routes.mjs"] },
{ id: "check-019-repo-cloud-web-proxy", group: "repo", command: ["node","--check","internal/dev-entrypoint/cloud-web-proxy.mjs"] },
{ id: "check-020-repo-cloud-web-proxy-test", group: "repo", command: ["node","--check","internal/dev-entrypoint/cloud-web-proxy.test.mjs"] },
{ id: "check-021-repo-http", group: "repo", command: ["node","--check","internal/dev-entrypoint/http.mjs"] },
{ id: "check-022-repo-http-test", group: "repo", command: ["node","--check","internal/dev-entrypoint/http.test.mjs"] },
{ id: "check-023-cloud-api-run-bun", group: "cloud-api", command: ["node","scripts/run-bun.mjs","build","internal/cloud/code-agent-contract.ts","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-024-cloud-api-run-bun", group: "cloud-api", command: ["node","scripts/run-bun.mjs","build","internal/cloud/code-agent-session-registry.ts","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-025-cloud-api-run-bun", group: "cloud-api", command: ["node","scripts/run-bun.mjs","build","internal/cloud/code-agent-session-registry.test.ts","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-026-cloud-api-run-bun", group: "cloud-api", command: ["node","scripts/run-bun.mjs","build","internal/cloud/code-agent-trace-store.ts","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-027-cloud-api-run-bun", group: "cloud-api", command: ["node","scripts/run-bun.mjs","build","internal/cloud/codex-stdio-session.ts","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-028-cloud-api-run-bun", group: "cloud-api", command: ["node","scripts/run-bun.mjs","build","internal/cloud/json-rpc.ts","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-029-cloud-api-run-bun", group: "cloud-api", command: ["node","scripts/run-bun.mjs","build","internal/cloud/code-agent-chat.ts","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-030-cloud-api-run-bun", group: "cloud-api", command: ["node","scripts/run-bun.mjs","build","internal/cloud/m3-io-control.ts","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-031-cloud-api-run-bun", group: "cloud-api", command: ["node","scripts/run-bun.mjs","build","internal/cloud/server.ts","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-032-cloud-api-run-bun", group: "cloud-api", command: ["node","scripts/run-bun.mjs","build","internal/cloud/server-test-helpers.ts","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-033-cloud-api-run-bun", group: "cloud-api", command: ["node","scripts/run-bun.mjs","build","internal/cloud/code-agent-trace-store.test.ts","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-034-cloud-api-run-bun", group: "cloud-api", command: ["node","scripts/run-bun.mjs","build","internal/cloud/server-live-builds.test.ts","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-035-cloud-api-run-bun", group: "cloud-api", command: ["node","scripts/run-bun.mjs","build","internal/cloud/server-health.test.ts","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-036-cloud-api-run-bun", group: "cloud-api", command: ["node","scripts/run-bun.mjs","build","internal/cloud/server-agent-chat.test.ts","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-037-cloud-api-run-bun", group: "cloud-api", command: ["node","scripts/run-bun.mjs","build","internal/cloud/server-m3-http.test.ts","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-038-repo-fake-data", group: "repo", command: ["node","--check","internal/device-pod/fake-data.mjs"] },
{ id: "check-039-repo-model", group: "repo", command: ["node","--check","internal/sim/model.mjs"] },
{ id: "check-040-repo-model-test", group: "repo", command: ["node","--check","internal/sim/model.test.mjs"] },
{ id: "check-041-repo-http", group: "repo", command: ["node","--check","internal/sim/http.mjs"] },
{ id: "check-042-smoke-l2-runtime", group: "smoke", command: ["node","--check","internal/sim/l2-runtime.mjs"] },
{ id: "check-043-repo-model", group: "repo", command: ["node","--check","internal/patchpanel/model.mjs"] },
{ id: "check-044-repo-runtime", group: "repo", command: ["node","--check","internal/patchpanel/runtime.mjs"] },
{ id: "check-045-cloud-api-run-bun", group: "cloud-api", command: ["node","scripts/run-bun.mjs","build","cmd/hwlab-cloud-api/main.ts","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-046-cloud-api-run-bun", group: "cloud-api", command: ["node","scripts/run-bun.mjs","build","cmd/hwlab-cloud-api/provision.ts","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-047-cloud-api-run-bun", group: "cloud-api", command: ["node","scripts/run-bun.mjs","build","cmd/hwlab-cloud-api/migrate.ts","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-048-repo-main", group: "repo", command: ["node","--check","cmd/hwlab-deepseek-responses-bridge/main.mjs"] },
{ id: "check-049-repo-main-test", group: "repo", command: ["node","--check","cmd/hwlab-deepseek-responses-bridge/main.test.mjs"] },
{ id: "check-050-repo-main-test", group: "repo", command: ["node","--test","cmd/hwlab-deepseek-responses-bridge/main.test.mjs"] },
{ id: "check-051-repo-main", group: "repo", command: ["node","--check","cmd/hwlab-edge-proxy/main.mjs"] },
{ id: "check-052-repo-main", group: "repo", command: ["node","--check","cmd/hwlab-agent-mgr/main.mjs"] },
{ id: "check-053-repo-main", group: "repo", command: ["node","--check","cmd/hwlab-agent-worker/main.mjs"] },
{ id: "check-054-repo-main", group: "repo", command: ["node","--check","cmd/hwlab-device-pod/main.mjs"] },
{ id: "check-055-repo-main", group: "repo", command: ["node","--check","cmd/hwlab-box-simu/main.mjs"] },
{ id: "check-056-repo-main", group: "repo", command: ["node","--check","cmd/hwlab-gateway/main.mjs"] },
{ id: "check-057-repo-main", group: "repo", command: ["node","--check","cmd/hwlab-gateway-simu/main.mjs"] },
{ id: "check-058-tools-hwlab-gateway-shell", group: "tools", command: ["node","--check","tools/hwlab-gateway-shell.mjs"] },
{ id: "check-059-tools-hwlab-gateway-tran", group: "tools", command: ["node","--check","tools/hwlab-gateway-tran.mjs"] },
{ id: "check-060-tools-tran", group: "tools", command: ["node","--check","tools/tran.mjs"] },
{ id: "check-061-tools-device-pod-cli", group: "tools", command: ["node","--check","tools/device-pod-cli.mjs"] },
{ id: "check-062-tools-device-pod-cli", group: "tools", command: ["node","--check","skills/device-pod-cli/scripts/device-pod-cli.mjs"] },
{ id: "check-063-tools-device-host-cli", group: "tools", command: ["node","--check","skills/device-pod-cli/assets/device-host-cli.mjs"] },
{ id: "check-064-cloud-api-run-bun", group: "cloud-api", command: ["node","scripts/run-bun.mjs","build","scripts/cloud-api-runtime-smoke.mjs","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-065-cloud-api-run-bun", group: "cloud-api", command: ["node","scripts/run-bun.mjs","build","scripts/code-agent-chat-smoke.mjs","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-066-dev-runtime-dev-edge-health-smoke", group: "dev-runtime", command: ["node","--check","scripts/dev-edge-health-smoke.mjs"] },
{ id: "check-067-dev-runtime-run-bun", group: "dev-runtime", command: ["node","scripts/run-bun.mjs","build","scripts/src/dev-edge-health-smoke-lib.mjs","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-068-repo-run-bun", group: "repo", command: ["node","scripts/run-bun.mjs","build","scripts/validate-contract.mjs","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-069-deploy-deploy-contract-plan-test", group: "deploy", command: ["node","--check","scripts/deploy-contract-plan.test.mjs"] },
{ id: "check-070-deploy-run-bun", group: "deploy", command: ["node","scripts/run-bun.mjs","build","scripts/deploy-desired-state-plan.mjs","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-071-deploy-run-bun", group: "deploy", command: ["node","scripts/run-bun.mjs","build","scripts/src/deploy-desired-state-plan.mjs","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-072-artifact-artifact-runtime-readiness-guard", group: "artifact", command: ["node","--check","scripts/artifact-runtime-readiness-guard.mjs"] },
{ id: "check-073-artifact-artifact-runtime-readiness-guard", group: "artifact", command: ["node","--check","scripts/src/artifact-runtime-readiness-guard.mjs"] },
{ id: "check-074-artifact-artifact-runtime-readiness-guard-test", group: "artifact", command: ["node","--check","scripts/artifact-runtime-readiness-guard.test.mjs"] },
{ id: "check-075-repo-report-lifecycle", group: "repo", command: ["node","--check","scripts/report-lifecycle.mjs"] },
{ id: "check-076-repo-report-lifecycle-test", group: "repo", command: ["node","--check","scripts/report-lifecycle.test.mjs"] },
{ id: "check-077-dev-runtime-validate-dev-gate-report", group: "dev-runtime", command: ["node","--check","scripts/validate-dev-gate-report.mjs"] },
{ id: "check-078-smoke-dev-m3-hardware-loop-smoke-test", group: "smoke", command: ["node","--check","scripts/dev-m3-hardware-loop-smoke.test.mjs"] },
{ id: "check-079-smoke-m3-io-control-e2e", group: "smoke", command: ["node","--check","scripts/m3-io-control-e2e.mjs"] },
{ id: "check-080-smoke-run-bun", group: "smoke", command: ["node","scripts/run-bun.mjs","build","scripts/src/m3-io-control-e2e.mjs","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-081-smoke-m3-io-control-e2e-test", group: "smoke", command: ["node","--check","scripts/m3-io-control-e2e.test.mjs"] },
{ id: "check-082-cloud-web-dev-cloud-workbench-smoke-test", group: "cloud-web", command: ["node","--check","scripts/dev-cloud-workbench-smoke.test.mjs"] },
{ id: "check-083-cloud-web-dev-cloud-workbench-layout-smoke", group: "cloud-web", command: ["node","--check","scripts/dev-cloud-workbench-layout-smoke.mjs"] },
{ id: "check-084-smoke-rpt004-mvp-e2e-harness", group: "smoke", command: ["node","--check","scripts/rpt004-mvp-e2e-harness.mjs"] },
{ id: "check-085-smoke-run-bun", group: "smoke", command: ["node","scripts/run-bun.mjs","build","scripts/src/rpt004-mvp-e2e-harness.mjs","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-086-smoke-rpt004-mvp-e2e-harness-test", group: "smoke", command: ["node","--check","scripts/src/rpt004-mvp-e2e-harness.test.mjs"] },
{ id: "check-087-smoke-validate-dev-m3-cardinality", group: "smoke", command: ["node","--check","scripts/validate-dev-m3-cardinality.mjs"] },
{ id: "check-088-smoke-validate-dev-m3-cardinality-test", group: "smoke", command: ["node","--check","scripts/validate-dev-m3-cardinality.test.mjs"] },
{ id: "check-089-deploy-validate-artifact-catalog", group: "deploy", command: ["node","--check","scripts/validate-artifact-catalog.mjs"] },
{ id: "check-090-deploy-refresh-artifact-catalog", group: "deploy", command: ["node","--check","scripts/refresh-artifact-catalog.mjs"] },
{ id: "check-091-deploy-refresh-artifact-catalog-test", group: "deploy", command: ["node","--check","scripts/refresh-artifact-catalog.test.mjs"] },
{ id: "check-092-artifact-artifact-publish", group: "artifact", command: ["node","--check","scripts/artifact-publish.mjs"] },
{ id: "check-093-artifact-g14-artifact-publish", group: "artifact", command: ["node","--check","scripts/g14-artifact-publish.mjs"] },
{ id: "check-094-artifact-dev-runtime-base-image", group: "artifact", command: ["node","--check","scripts/dev-runtime-base-image.mjs"] },
{ id: "check-095-artifact-dev-artifact-services", group: "artifact", command: ["node","--check","scripts/src/dev-artifact-services.mjs"] },
{ id: "check-096-artifact-registry-capabilities", group: "artifact", command: ["node","--check","scripts/src/registry-capabilities.mjs"] },
{ id: "check-097-artifact-preflight-dev-base-image", group: "artifact", command: ["node","--check","scripts/preflight-dev-base-image.mjs"] },
{ id: "check-098-artifact-dev-base-image-preflight", group: "artifact", command: ["node","--check","scripts/src/dev-base-image-preflight.mjs"] },
{ id: "check-099-smoke-dev-evidence-blocker-aggregator", group: "smoke", command: ["node","--check","scripts/dev-evidence-blocker-aggregator.mjs"] },
{ id: "check-100-smoke-dev-evidence-blocker-aggregator", group: "smoke", command: ["node","--check","scripts/src/dev-evidence-blocker-aggregator.mjs"] },
{ id: "check-101-smoke-dev-evidence-blocker-aggregator-test", group: "smoke", command: ["node","--check","scripts/src/dev-evidence-blocker-aggregator.test.mjs"] },
{ id: "check-102-smoke-dev-m4-agent-loop-smoke-lib-test", group: "smoke", command: ["node","--check","scripts/src/dev-m4-agent-loop-smoke-lib.test.mjs"] },
{ id: "check-103-repo-d601-k3s-readonly-observability", group: "repo", command: ["node","--check","scripts/d601-k3s-readonly-observability.mjs"] },
{ id: "check-104-repo-d601-k3s-readonly-observability", group: "repo", command: ["node","--check","scripts/src/d601-k3s-readonly-observability.mjs"] },
{ id: "check-105-dev-runtime-dev-runtime-provisioning", group: "dev-runtime", command: ["node","--check","scripts/dev-runtime-provisioning.mjs"] },
{ id: "check-106-dev-runtime-run-bun", group: "dev-runtime", command: ["node","scripts/run-bun.mjs","build","scripts/src/dev-runtime-provisioning.mjs","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-107-dev-runtime-run-bun", group: "dev-runtime", command: ["node","scripts/run-bun.mjs","build","scripts/src/dev-runtime-provisioning.test.mjs","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-108-dev-runtime-dev-runtime-migration", group: "dev-runtime", command: ["node","--check","scripts/dev-runtime-migration.mjs"] },
{ id: "check-109-dev-runtime-run-bun", group: "dev-runtime", command: ["node","scripts/run-bun.mjs","build","scripts/src/dev-runtime-migration.mjs","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-110-dev-runtime-run-bun", group: "dev-runtime", command: ["node","scripts/run-bun.mjs","build","scripts/src/dev-runtime-migration.test.mjs","--target=bun","--packages=external","--outdir=/tmp/hwlab-ts-check"] },
{ id: "check-111-dev-runtime-dev-runtime-postflight", group: "dev-runtime", command: ["node","--check","scripts/dev-runtime-postflight.mjs"] },
{ id: "check-112-dev-runtime-dev-runtime-postflight", group: "dev-runtime", command: ["node","--check","scripts/src/dev-runtime-postflight.mjs"] },
{ id: "check-113-dev-runtime-dev-runtime-postflight-test", group: "dev-runtime", command: ["node","--check","scripts/src/dev-runtime-postflight.test.mjs"] },
{ id: "check-114-dev-runtime-dev-runtime-hotfix-audit", group: "dev-runtime", command: ["node","--check","scripts/dev-runtime-hotfix-audit.mjs"] },
{ id: "check-115-dev-runtime-dev-runtime-hotfix-audit", group: "dev-runtime", command: ["node","--check","scripts/src/dev-runtime-hotfix-audit.mjs"] },
{ id: "check-116-dev-runtime-dev-runtime-hotfix-audit-test", group: "dev-runtime", command: ["node","--check","scripts/src/dev-runtime-hotfix-audit.test.mjs"] },
{ id: "check-117-dev-runtime-dev-runtime-hotfix-audit-test", group: "dev-runtime", command: ["node","--test","scripts/src/dev-runtime-hotfix-audit.test.mjs"] },
{ id: "check-118-smoke-l2-runtime-contract-smoke", group: "smoke", command: ["node","--check","scripts/l2-runtime-contract-smoke.mjs"] },
{ id: "check-119-smoke-patch-panel-runtime-smoke", group: "smoke", command: ["node","--check","scripts/patch-panel-runtime-smoke.mjs"] },
{ id: "check-120-smoke-l6-cli-web-smoke", group: "smoke", command: ["node","--check","scripts/l6-cli-web-smoke.mjs"] },
{ id: "check-121-tools-hwlab-agent-runtime-cli", group: "tools", command: ["node","--check","skills/hwlab-agent-runtime/scripts/hwlab-agent-runtime-cli.mjs"] },
{ id: "check-122-smoke-m3-io-skill-client", group: "smoke", command: ["node","--check","skills/hwlab-agent-runtime/scripts/src/m3-io-skill-client.mjs"] },
{ id: "check-123-tools-hwlab-cli", group: "tools", command: ["node","--check","tools/hwlab-cli/bin/hwlab-cli.mjs"] },
{ id: "check-124-tools-cli", group: "tools", command: ["node","--check","tools/hwlab-cli/lib/cli.mjs"] },
{ id: "check-125-tools-cli-test", group: "tools", command: ["node","--check","tools/hwlab-cli/lib/cli.test.mjs"] },
{ id: "check-126-cloud-web-check", group: "cloud-web", cwd: "web/hwlab-cloud-web", command: ["bun","run","check"] },
{ id: "check-127-repo-run-bun", group: "repo", command: ["node","scripts/run-bun.mjs","scripts/validate-contract.mjs"] },
{ id: "check-128-dev-runtime-validate-dev-gate-report", group: "dev-runtime", command: ["node","scripts/validate-dev-gate-report.mjs"] },
{ id: "check-129-repo-report-lifecycle-test", group: "repo", command: ["node","scripts/report-lifecycle.test.mjs"] },
{ id: "check-130-smoke-validate-dev-m3-cardinality", group: "smoke", command: ["node","scripts/validate-dev-m3-cardinality.mjs"] },
{ id: "check-131-deploy-validate-artifact-catalog", group: "deploy", command: ["node","scripts/validate-artifact-catalog.mjs"] },
{ id: "check-132-deploy-run-bun", group: "deploy", command: ["node","scripts/run-bun.mjs","scripts/deploy-desired-state-plan.mjs","--check"] },
{ id: "check-133-dev-runtime-run-bun", group: "dev-runtime", command: ["node","scripts/run-bun.mjs","scripts/dev-runtime-provisioning.mjs","--check"] },
{ id: "check-134-dev-runtime-run-bun", group: "dev-runtime", command: ["node","scripts/run-bun.mjs","scripts/dev-runtime-migration.mjs","--check"] },
{ id: "check-135-cloud-api-run-bun", group: "cloud-api", command: ["node","scripts/run-bun.mjs","cmd/hwlab-cloud-api/provision.ts","--check"] },
{ id: "check-136-cloud-api-run-bun", group: "cloud-api", command: ["node","scripts/run-bun.mjs","cmd/hwlab-cloud-api/migrate.ts","--check"] },
{ id: "check-137-dev-runtime-dev-runtime-postflight", group: "dev-runtime", command: ["node","scripts/dev-runtime-postflight.mjs","--check"] },
{ id: "check-138-smoke-rpt004-mvp-e2e-harness", group: "smoke", command: ["node","scripts/rpt004-mvp-e2e-harness.mjs","--check","--no-write"] },
{ id: "check-139-smoke-dev-evidence-blocker-aggregator", group: "smoke", command: ["node","scripts/dev-evidence-blocker-aggregator.mjs","--check"] },
{ id: "check-140-smoke-l2-runtime-contract-smoke", group: "smoke", command: ["node","scripts/l2-runtime-contract-smoke.mjs"] },
{ id: "check-141-smoke-l6-cli-web-smoke", group: "smoke", command: ["node","scripts/l6-cli-web-smoke.mjs"] },
{ id: "check-142-cloud-web-check", group: "cloud-web", cwd: "web/hwlab-cloud-web", command: ["bun","run","check"] },
{ id: "check-143-cloud-api-run-bun", group: "cloud-api", command: ["node","scripts/run-bun.mjs","scripts/code-agent-chat-smoke.mjs"] },
{ id: "check-144-cloud-api-run-bun", group: "cloud-api", command: ["node","scripts/run-bun.mjs","scripts/cloud-api-runtime-smoke.mjs"] },
{ id: "check-145-repo-bootstrap-skills-sh", group: "repo", command: ["sh","-n","scripts/bootstrap-skills.sh","scripts/worker-entrypoint.sh"] },
{ id: "check-146-cloud-api-run-bun", group: "cloud-api", command: ["node","scripts/run-bun.mjs","test","cmd/hwlab-cloud-api/runtime-options.test.ts","internal/cloud/code-agent-session-registry.test.ts","internal/cloud/json-rpc.test.ts","internal/cloud/m3-io-control.test.ts","internal/cloud/code-agent-trace-store.test.ts","internal/cloud/server-live-builds.test.ts","internal/cloud/server-health.test.ts","internal/cloud/server-agent-chat.test.ts","internal/cloud/server-m3-http.test.ts","internal/db/runtime-store.test.ts","internal/db/schema.test.ts"] }
])
});
export function listCheckTasks(profile) {
const tasks = checkProfiles[profile];
if (!tasks) {
throw new Error(`unknown check profile: ${profile}`);
}
return tasks;
}
+196
View File
@@ -0,0 +1,196 @@
import { spawn } from "node:child_process";
import { existsSync } from "node:fs";
import os from "node:os";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { CHECK_PLAN_VERSION, checkProfiles, listCheckTasks } from "./check-plan.mjs";
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
export async function runCheckRunner(argv, io = process) {
const options = parseCheckRunnerArgs(argv);
if (options.help) {
writeJson(io.stdout, helpPayload());
return { exitCode: 0 };
}
const selected = selectTasks(options);
const payload = {
ok: true,
command: "check-runner",
version: CHECK_PLAN_VERSION,
profile: options.profile,
groups: options.groups,
ids: options.ids,
taskCount: selected.length,
tasks: selected.map(serializeTask)
};
if (options.list || options.dryRun) {
writeJson(io.stdout, { ...payload, mode: options.list ? "list" : "dry-run" });
return { exitCode: 0 };
}
writeJson(io.stdout, { ...payload, mode: "run-start", tasks: undefined });
const startedAt = Date.now();
for (let index = 0; index < selected.length; index += 1) {
const task = selected[index];
const resolved = resolveTaskCommand(task);
writeJson(io.stdout, {
ok: true,
event: "task-start",
index: index + 1,
total: selected.length,
task: serializeTask(task),
resolvedCommand: resolved.command
});
const exitCode = await runTask(resolved);
if (exitCode !== 0) {
writeJson(io.stdout, {
ok: false,
event: "task-failed",
task: serializeTask(task),
exitCode,
elapsedMs: Date.now() - startedAt
});
return { exitCode };
}
}
writeJson(io.stdout, {
ok: true,
event: "run-complete",
profile: options.profile,
taskCount: selected.length,
elapsedMs: Date.now() - startedAt
});
return { exitCode: 0 };
}
export function parseCheckRunnerArgs(argv) {
const options = { profile: "check", groups: [], ids: [], list: false, dryRun: false, help: false };
for (let index = 0; index < argv.length; index += 1) {
const arg = argv[index];
const readValue = (name) => {
const inline = arg.match(new RegExp(`^${name}=(.+)$`, "u"));
if (inline) return inline[1];
const value = argv[index + 1];
if (!value || value.startsWith("--")) throw new Error(`${name} requires a value`);
index += 1;
return value;
};
if (arg === "--help" || arg === "-h") options.help = true;
else if (arg === "--profile" || arg.startsWith("--profile=")) options.profile = readValue("--profile");
else if (arg === "--group" || arg.startsWith("--group=")) options.groups.push(...readValue("--group").split(",").filter(Boolean));
else if (arg === "--id" || arg.startsWith("--id=")) options.ids.push(...readValue("--id").split(",").filter(Boolean));
else if (arg === "--list") options.list = true;
else if (arg === "--dry-run") options.dryRun = true;
else throw new Error(`unknown check-runner argument: ${arg}`);
}
if (!checkProfiles[options.profile]) throw new Error(`unknown check profile: ${options.profile}`);
return options;
}
export function selectTasks(options) {
const groups = new Set(options.groups);
const ids = new Set(options.ids);
const profileTasks = listCheckTasks(options.profile);
const availableGroups = new Set(profileTasks.map((task) => task.group));
const availableIds = new Set(profileTasks.map((task) => task.id));
for (const group of groups) {
if (!availableGroups.has(group)) throw new Error(`unknown check group for profile ${options.profile}: ${group}`);
}
for (const id of ids) {
if (!availableIds.has(id)) throw new Error(`unknown check task id for profile ${options.profile}: ${id}`);
}
const selected = profileTasks.filter((task) => {
if (groups.size > 0 && !groups.has(task.group)) return false;
if (ids.size > 0 && !ids.has(task.id)) return false;
return true;
});
if (selected.length === 0) throw new Error(`check-runner selected no tasks for profile ${options.profile}`);
return selected;
}
export function resolveTaskCommand(task) {
const [bin, ...args] = task.command;
if (!bin) throw new Error(`task has empty command: ${task.id}`);
const cwd = task.cwd ? path.resolve(repoRoot, task.cwd) : repoRoot;
return {
task,
command: bin === "bun" ? resolveBunCommand(cwd) : bin,
args,
cwd
};
}
function runTask(task) {
return new Promise((resolve) => {
const child = spawn(task.command, task.args, {
cwd: task.cwd,
env: process.env,
stdio: ["ignore", "inherit", "inherit"]
});
child.on("error", (error) => {
process.stderr.write(JSON.stringify({ ok: false, event: "task-spawn-error", task: serializeTask(task.task), error: error.message }, null, 2) + "\n");
resolve(127);
});
child.on("exit", (code, signal) => {
if (signal) {
process.stderr.write(JSON.stringify({ ok: false, event: "task-signal", task: serializeTask(task.task), signal }, null, 2) + "\n");
resolve(128);
return;
}
resolve(code ?? 0);
});
});
}
function resolveBunCommand(cwd) {
for (const candidate of bunCandidates(cwd)) {
if (!candidate) continue;
if (!candidate.includes(path.sep)) return candidate;
if (existsSync(candidate)) return candidate;
}
return "bun";
}
function bunCandidates(cwd) {
const exe = process.platform === "win32" ? "bun.exe" : "bun";
return [
process.env.HWLAB_BUN_COMMAND,
process.env.HWLAB_BUN_BINARY,
process.env.BUN_BINARY,
path.join(cwd, "node_modules", ".bin", exe),
path.join(repoRoot, "node_modules", ".bin", exe),
path.join(os.homedir(), ".bun", "bin", exe),
"/root/.bun/bin/bun",
"/usr/local/bin/bun",
"bun"
].filter(Boolean);
}
function serializeTask(task) {
return { id: task.id, group: task.group, cwd: task.cwd ?? ".", command: task.command };
}
function writeJson(stream, value) {
stream.write(JSON.stringify(value, null, 2) + "\n");
}
function helpPayload() {
return {
ok: true,
command: "check-runner",
usage: [
"node scripts/check-runner.mjs --profile check",
"node scripts/check-runner.mjs --profile validate",
"node scripts/check-runner.mjs --profile check --group cloud-api",
"node scripts/check-runner.mjs --profile check --list",
"node scripts/check-runner.mjs --profile check --dry-run"
],
profiles: Object.keys(checkProfiles),
groups: [...new Set(Object.values(checkProfiles).flat().map((task) => task.group))].sort()
};
}