按text25.txt规划,实现L4-PYTHON-REMAP接入数控系统仿真系统

结论:已接入Python remap runtime proof chain,覆盖native、WASM、browser与release gate证据链;继续保持promotion_allowed=0,不批量解锁L4-PYTHON-REMAP。
This commit is contained in:
2026-06-19 18:52:24 +08:00
parent 51ae5d9a9a
commit fbf9dade9c
38 changed files with 2252 additions and 335 deletions

View File

@@ -986,7 +986,7 @@ TOOL_TABLE = browser-shell-tool.tbl
);
assertEqual(
workflowOverviewReleaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "promotion-candidate-layers")?.value,
"evidence-ready=8 inventory-ready=20",
"evidence-ready=8 inventory-ready=19",
"shell workflow overview release artifact URL workflow candidate layers",
);
assertEqual(

View File

@@ -421,7 +421,7 @@
preferredGcodePath: "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc",
blockedCandidateIds: [],
explicitBrowserDiagnosticsCount: 8,
inventoryBaseline: "executed=28 passed=28 skipped=131 unexpected_fail=0",
inventoryBaseline: "executed=29 passed=29 skipped=130 unexpected_fail=0",
},
virtualHalSimConfigMacroLoadFixtures: createVirtualHalSimConfigMacroLoadFixtureReport({
manifestEntries: [
@@ -637,7 +637,7 @@
);
assertEqual(
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "promotion-candidate-layers")?.value,
"evidence-ready=8 inventory-ready=20",
"evidence-ready=8 inventory-ready=19",
"workflow overview release artifact URL workflow candidate layers",
);
assertEqual(
@@ -772,7 +772,7 @@
);
assertEqual(
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "virtual-hal-promotion-candidate-baseline")?.value,
"executed=28 passed=28 skipped=131 unexpected_fail=0",
"executed=29 passed=29 skipped=130 unexpected_fail=0",
"workflow overview release artifact URL workflow candidate baseline",
);
assertEqual(
@@ -948,7 +948,7 @@
);
assertEqual(
workflowDoc.querySelector('[data-workflow-overview-release-readiness-artifact-url-workflow-value="promotion-candidate-layers"]').textContent,
"evidence-ready=8 inventory-ready=20",
"evidence-ready=8 inventory-ready=19",
"workflow overview fixed URL workflow form candidate layer row",
);
assertEqual(

View File

@@ -0,0 +1,45 @@
self.linuxCncPythonRemapRuntimeProvider = {
async start() {},
async initializePython() {
return { value: "python-runtime-initialized" };
},
async applyIniPythonPath(message) {
return { value: message.pythonPathPrepend };
},
async executeTopLevel(message) {
return { value: message.topLevelPath };
},
async importModule(message) {
return { value: message.modulePath };
},
async lookupCallable(message) {
return { value: message.callableName };
},
async invokeGenerator() {
return { value: "generator-returned" };
},
async observeFirstYield(message) {
return { value: message.expectedYield };
},
async finishGenerator() {
return { value: "generator-finished" };
},
async exportInterpreterState() {
return { value: "interpreter-state-bound" };
},
async exportDiagnostics() {
return { value: "diagnostics-exported" };
},
async close() {},
};

View File

@@ -0,0 +1,114 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>LinuxCNC Python Remap Runtime Browser Smoke</title>
</head>
<body>
<pre id="status">running</pre>
<script type="module">
import {
createLinuxCncPythonRemapBrowserWorkerAdapter,
createLinuxCncPythonRemapRuntimePort,
createPythonRemapRuntimeDiagnostics,
validatePythonRemapLifecycleTranscript,
} from "../../runtime/sdk/src/index.js";
const status = document.getElementById("status");
function assertEqual(actual, expected, label) {
if (actual !== expected) {
throw new Error(`${label}: expected ${expected}, got ${actual}`);
}
}
try {
const contractOnlyPort = createLinuxCncPythonRemapRuntimePort({
runtimeMode: "contract-only",
});
const contractOnlyStart = await contractOnlyPort.start();
assertEqual(contractOnlyStart.runtimeExecutionReady, false, "contract-only runtime execution");
const contractOnlyPlan = await contractOnlyPort.runLifecyclePlan();
assertEqual(contractOnlyPlan.status, "blocked_runtime_adapter_required", "contract-only lifecycle plan");
assertEqual(contractOnlyPlan.promotionAllowed, false, "contract-only promotion guard");
await contractOnlyPort.close();
const workerAdapter = createLinuxCncPythonRemapBrowserWorkerAdapter({
workerUrl: new URL("../../runtime/workers/python-remap-worker.js", import.meta.url),
});
const workerPort = createLinuxCncPythonRemapRuntimePort({
runtimeMode: workerAdapter.runtimeMode,
runtimeAdapter: workerAdapter,
});
const workerStart = await workerPort.start();
assertEqual(workerStart.runtimeMode, "browser-python-wasm-worker", "worker runtime mode");
assertEqual(workerStart.runtimeExecutionReady, false, "worker Python runtime readiness");
assertEqual(workerStart.status, "blocked_browser_python_wasm_runtime_missing", "worker runtime status");
const workerPlan = await workerPort.runLifecyclePlan();
assertEqual(workerPlan.status, "blocked_browser_python_wasm_runtime_missing", "worker plan blocked");
assertEqual(workerPlan.promotionAllowed, false, "worker promotion guard");
await workerPort.close();
const missingModuleAdapter = createLinuxCncPythonRemapBrowserWorkerAdapter({
workerUrl: new URL("../../runtime/workers/python-remap-worker.js", import.meta.url),
pythonRuntimeModuleUrl: new URL("./missing_python_remap_runtime_provider.js", import.meta.url),
});
const missingModulePort = createLinuxCncPythonRemapRuntimePort({
runtimeMode: missingModuleAdapter.runtimeMode,
runtimeAdapter: missingModuleAdapter,
});
const missingModuleStart = await missingModulePort.start();
assertEqual(missingModuleStart.runtimeExecutionReady, false, "missing module runtime readiness");
assertEqual(
missingModuleStart.status,
"blocked_browser_python_wasm_runtime_load_failed",
"missing module runtime status",
);
await missingModulePort.close();
const fakeRuntimeAdapter = createLinuxCncPythonRemapBrowserWorkerAdapter({
workerUrl: new URL("../../runtime/workers/python-remap-worker.js", import.meta.url),
pythonRuntimeModuleUrl: new URL("./python_remap_fake_runtime_worker.js", import.meta.url),
});
const fakeRuntimePort = createLinuxCncPythonRemapRuntimePort({
runtimeMode: fakeRuntimeAdapter.runtimeMode,
runtimeAdapter: fakeRuntimeAdapter,
});
const fakeRuntimeStart = await fakeRuntimePort.start();
assertEqual(fakeRuntimeStart.runtimeExecutionReady, true, "fake provider runtime readiness");
assertEqual(fakeRuntimeStart.status, "browser_python_remap_wasm_runtime_ready", "fake provider runtime status");
const fakeRuntimePlan = await fakeRuntimePort.runLifecyclePlan();
assertEqual(fakeRuntimePlan.status, "runtime_adapter_lifecycle_plan_executed", "fake provider lifecycle plan");
assertEqual(fakeRuntimePlan.promotionAllowed, false, "fake provider promotion guard");
assertEqual(fakeRuntimePlan.bulkPromotionAllowed, false, "fake provider bulk promotion guard");
const transcript = fakeRuntimePort.exportTranscript();
assertEqual(validatePythonRemapLifecycleTranscript(transcript).ready, true, "lifecycle transcript readiness");
const diagnostics = createPythonRemapRuntimeDiagnostics({
runtimeMode: fakeRuntimeAdapter.runtimeMode,
runtimeExecutionReady: fakeRuntimeStart.runtimeExecutionReady,
transcript,
});
assertEqual(diagnostics.fixtureFamily, "axis/remap/stop-lookahead/nc_files", "diagnostics fixture family");
assertEqual(diagnostics.iniPath, "axis/remap/stop-lookahead/demo.ini", "diagnostics INI path");
assertEqual(diagnostics.pythonPathPrepend, "python", "diagnostics Python path");
assertEqual(diagnostics.topLevelPath, "python/toplevel.py", "diagnostics TOPLEVEL");
assertEqual(diagnostics.lifecycleTranscriptReady, true, "diagnostics transcript");
assertEqual(diagnostics.callableLookupReady, true, "diagnostics callable lookup");
assertEqual(diagnostics.generatorLifecycleReady, true, "diagnostics generator lifecycle");
assertEqual(diagnostics.interpreterStateBindingReady, true, "diagnostics interpreter binding");
assertEqual(diagnostics.linuxCncOwnedLifecycle, true, "diagnostics LinuxCNC lifecycle owner");
assertEqual(diagnostics.jsCncSemantics, false, "diagnostics JS CNC semantic guard");
assertEqual(diagnostics.ngcOnlySubroutinePromoted, false, "diagnostics NGC-only guard");
assertEqual(diagnostics.executionEnabled, false, "diagnostics execution guard");
assertEqual(diagnostics.promotionAllowed, false, "diagnostics promotion guard");
assertEqual(diagnostics.bulkPromotionAllowed, false, "diagnostics bulk promotion guard");
await fakeRuntimePort.close();
status.textContent = "browser_python_remap_runtime_smoke=ok";
} catch (error) {
status.textContent = `browser_python_remap_runtime_smoke=fail\n${error.stack || error}`;
throw error;
}
</script>
</body>
</html>

View File

@@ -521,13 +521,13 @@
diagnosticsArtifact.virtualHalPromotionCandidateSummary?.candidateCount !== 8 ||
diagnosticsArtifact.virtualHalPromotionCandidateSummary?.readyCandidateCount !== 8 ||
diagnosticsArtifact.virtualHalPromotionCandidateSummary?.sourceFileCount !== 17 ||
diagnosticsArtifact.virtualHalPromotionCandidateSummary?.inventoryBaseline !== "executed=28 passed=28 skipped=131 unexpected_fail=0" ||
diagnosticsArtifact.virtualHalPromotionCandidateSummary?.inventoryBaseline !== "executed=29 passed=29 skipped=130 unexpected_fail=0" ||
promotionCandidateSummary.ready !== true ||
promotionCandidateSummary.preferredIniPath !== "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini" ||
doc.body.dataset.promotionCandidateReady !== "true" ||
doc.body.dataset.promotionCandidatePreferred !== "qtdragon-multi-joint-on-abort" ||
doc.querySelector('[data-promotion-candidate-summary-value="preferred-candidate"]')?.textContent !== "qtdragon-multi-joint-on-abort" ||
doc.querySelector('[data-promotion-candidate-summary-value="candidate-layers"]')?.textContent !== "evidence-ready=8 inventory-ready=20" ||
doc.querySelector('[data-promotion-candidate-summary-value="candidate-layers"]')?.textContent !== "evidence-ready=8 inventory-ready=19" ||
doc.querySelector('[data-promotion-candidate-summary-value="inventory-baseline"]')?.textContent !== "28/28 pass; 131 skip unchanged" ||
doc.querySelector('[data-promotion-candidate-summary-value="promotion-allowed"]')?.textContent !== "0 baseline changes" ||
doc.querySelector('[data-promotion-candidate-summary-value="candidate-artifact"]')?.textContent !== "promotion-candidates.tsv" ||

View File

@@ -0,0 +1,74 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
CHROMIUM="${CHROMIUM:-$(command -v chromium || command -v chromium-browser || command -v google-chrome || command -v google-chrome-stable || true)}"
if [[ -z "$CHROMIUM" ]]; then
echo "missing Chromium-compatible browser; set CHROMIUM=/path/to/browser" >&2
exit 1
fi
TMP_DIR="$(mktemp -d)"
PORT_FILE="$TMP_DIR/port"
SERVER_LOG="$TMP_DIR/server.log"
CHROME_PROFILE="$TMP_DIR/chrome-profile"
mkdir -p "$CHROME_PROFILE"
cleanup() {
if [[ -n "${SERVER_PID:-}" ]]; then
kill "$SERVER_PID" 2>/dev/null || true
wait "$SERVER_PID" 2>/dev/null || true
fi
rm -rf "$TMP_DIR"
}
trap cleanup EXIT
python3 - <<'PY' "$ROOT_DIR" "$PORT_FILE" >"$SERVER_LOG" 2>&1 &
import functools
import http.server
import pathlib
import socketserver
import sys
root = pathlib.Path(sys.argv[1])
port_file = pathlib.Path(sys.argv[2])
handler = functools.partial(http.server.SimpleHTTPRequestHandler, directory=str(root))
with socketserver.TCPServer(("127.0.0.1", 0), handler) as httpd:
port_file.write_text(str(httpd.server_address[1]), encoding="ascii")
httpd.serve_forever()
PY
SERVER_PID=$!
for _ in $(seq 1 100); do
[[ -s "$PORT_FILE" ]] && break
sleep 0.05
done
if [[ ! -s "$PORT_FILE" ]]; then
echo "Python remap runtime browser smoke HTTP server did not start" >&2
cat "$SERVER_LOG" >&2 || true
exit 1
fi
PORT="$(cat "$PORT_FILE")"
URL="http://127.0.0.1:$PORT/tests/browser/python_remap_runtime_browser_smoke.html"
OUT="$TMP_DIR/chromium.out"
"$CHROMIUM" \
--headless=new \
--disable-gpu \
--no-sandbox \
--user-data-dir="$CHROME_PROFILE" \
--virtual-time-budget=10000 \
--dump-dom \
"$URL" >"$OUT" 2>&1
if ! grep -Fq "browser_python_remap_runtime_smoke=ok" "$OUT"; then
echo "Python remap runtime browser smoke failed" >&2
sed -n '1,220p' "$OUT" >&2
exit 1
fi
echo "browser_python_remap_runtime_smoke=ok"

View File

@@ -35,9 +35,9 @@ const trackerText = readFileSync(resolve(root, "../PROJECT_COMPLETION_TRACKER.md
for (const phrase of [
"Sim-config coverage release handoff",
"sim_configs_wasm_node_inventory_executed=28",
"sim_configs_wasm_node_inventory_passed=28",
"sim_configs_wasm_node_inventory_skipped=131",
"sim_configs_wasm_node_inventory_executed=29",
"sim_configs_wasm_node_inventory_passed=29",
"sim_configs_wasm_node_inventory_skipped=130",
"sim_configs_wasm_node_inventory_unexpected_fail=0",
"sim_configs_wasm_node_inventory_skip_ASSET_ONLY=65",
"sim_configs_wasm_node_inventory_skip_L4_PYTHON_REMAP=53",
@@ -59,9 +59,9 @@ for (const phrase of [
for (const phrase of [
"Sim Config Coverage Promotion Analysis",
"virtual HAL",
"sim_configs_wasm_node_inventory_executed=28",
"sim_configs_wasm_node_inventory_passed=28",
"sim_configs_wasm_node_inventory_skipped=131",
"sim_configs_wasm_node_inventory_executed=29",
"sim_configs_wasm_node_inventory_passed=29",
"sim_configs_wasm_node_inventory_skipped=130",
"qtdragon/qtdragon_multi_joint/on_abort.ngc",
"axis/vismach/puma/puma_seam_weld.ngc",
"axis/rose_engine/rcone_demo.ngc",

View File

@@ -20,8 +20,8 @@ assert.equal(validation.phase, "ready");
assert.deepEqual(validation.missing, []);
assert.equal(validation.artifactApiName, "project-release-readiness-report");
assert.equal(validation.artifactVersion, 1);
assert.equal(validation.gateCount, 12);
assert.equal(validation.expectedGateCount, 12);
assert.equal(validation.gateCount, 13);
assert.equal(validation.expectedGateCount, 13);
assert.equal(validation.gateManifestReady, true);
assert.equal(validation.gateExecutionManifestReady, true);
assert.equal(validation.gateExecutionSummaryReady, true);
@@ -41,6 +41,7 @@ assert.deepEqual(validation.expectedGateIds, [
"sim-config-inventory",
"ini-panel-browser",
"opfs-session-browser",
"tool-db-process-proof",
"release-artifact-url-browser",
"project-batch-acceptance",
"ui-node-smokes",
@@ -49,9 +50,9 @@ assert.deepEqual(validation.expectedGateIds, [
]);
assert.equal(artifact.gateManifest.apiName, "project-release-gate-manifest");
assert.equal(artifact.gateExecutionManifest.apiName, "project-release-gate-execution-manifest");
assert.equal(artifact.gateExecutionManifest.passedCount, 12);
assert.equal(artifact.gateExecutionManifest.passedCount, 13);
assert.equal(artifact.gateExecutionSummaryViewModel.apiName, "project-release-gate-execution-summary-view-model");
assert.equal(artifact.gateExecutionSummaryViewModel.rows[0].value, "12/12 passed");
assert.equal(artifact.gateExecutionSummaryViewModel.rows[0].value, "13/13 passed");
assert.equal(artifact.gateResultMatrix.apiName, "project-release-gate-result-matrix");
assert.equal(artifact.gateActionPlan.apiName, "project-release-gate-action-plan");
assert.equal(artifact.gateActionPlan.pendingCount, 0);
@@ -98,7 +99,7 @@ assert.equal(
);
assert.equal(
artifact.rows.find(({ id }) => id === "hard-block-runtime-lock")?.value,
"locked (3 families)",
"locked (2 families)",
);
assert.equal(
artifact.rows.find(({ id }) => id === "promoted-blocked-family-count")?.value,
@@ -143,12 +144,12 @@ assert.equal(
row.promotionAllowed === false &&
row.excludedFromPositiveFixtures === true &&
row.boundaryEvidenceReady === true &&
row.boundaryEvidence.baselineSummary.executed === 28 &&
row.boundaryEvidence.baselineSummary.passed === 28 &&
row.boundaryEvidence.baselineSummary.skipped === 131 &&
row.boundaryEvidence.baselineSummary.executed === 29 &&
row.boundaryEvidence.baselineSummary.passed === 29 &&
row.boundaryEvidence.baselineSummary.skipped === 130 &&
row.boundaryEvidence.baselineSummary.unexpectedFail === 0 &&
row.boundaryEvidence.sourceArtifactHashes["wasm-port/build/wasm/sim-configs-inventory/boundary-summary.tsv"] === "de6cf57b7c07182e3bcb32e22dbdf202b618cabc14620d6dff1ef815587950b9" &&
row.boundaryEvidence.sourceArtifactHashes["wasm-port/build/wasm/sim-configs-inventory/ini-boundary-summary.tsv"] === "b0afe27224e97a82fbecbbd75a7c86233c98fe957d9c1ba20f0656f8745a5eae" &&
row.boundaryEvidence.sourceArtifactHashes["wasm-port/build/wasm/sim-configs-inventory/boundary-summary.tsv"] === "6cc15052cad03d04eff4506cd0a9d651cd45a2bd5da4d9f38633e9535826b9f3" &&
row.boundaryEvidence.sourceArtifactHashes["wasm-port/build/wasm/sim-configs-inventory/ini-boundary-summary.tsv"] === "17bff95b57c55ff4201a23c7286e733550e4df513470c66dd5f24329e7781a35" &&
row.boundaryEvidence.boundarySummary.dependencies.includes("missing_vendored_ini:configs/sim/gscreen/industrial_lathe_wear/industrial_lathe_wear.ini") &&
row.boundaryEvidence.iniBoundarySummary.vendored === 0
),
@@ -158,12 +159,12 @@ assert.equal(
artifact.virtualHalSimConfigMacroLoadFixtures.blockedRows.some((row) =>
row.id === "silverdragon-tool-sensor-python-ui-boundary" &&
row.boundaryEvidenceReady === true &&
row.boundaryEvidence.baselineSummary.executed === 28 &&
row.boundaryEvidence.baselineSummary.passed === 28 &&
row.boundaryEvidence.baselineSummary.skipped === 131 &&
row.boundaryEvidence.baselineSummary.executed === 29 &&
row.boundaryEvidence.baselineSummary.passed === 29 &&
row.boundaryEvidence.baselineSummary.skipped === 130 &&
row.boundaryEvidence.baselineSummary.unexpectedFail === 0 &&
row.boundaryEvidence.sourceArtifactHashes["wasm-port/build/wasm/sim-configs-inventory/boundary-summary.tsv"] === "de6cf57b7c07182e3bcb32e22dbdf202b618cabc14620d6dff1ef815587950b9" &&
row.boundaryEvidence.sourceArtifactHashes["wasm-port/build/wasm/sim-configs-inventory/ini-boundary-summary.tsv"] === "b0afe27224e97a82fbecbbd75a7c86233c98fe957d9c1ba20f0656f8745a5eae" &&
row.boundaryEvidence.sourceArtifactHashes["wasm-port/build/wasm/sim-configs-inventory/boundary-summary.tsv"] === "6cc15052cad03d04eff4506cd0a9d651cd45a2bd5da4d9f38633e9535826b9f3" &&
row.boundaryEvidence.sourceArtifactHashes["wasm-port/build/wasm/sim-configs-inventory/ini-boundary-summary.tsv"] === "17bff95b57c55ff4201a23c7286e733550e4df513470c66dd5f24329e7781a35" &&
row.boundaryEvidence.boundarySummary.dependencies.includes("missing_vendored_ini:configs/sim/gscreen/silverdragon/silverdragon.ini") &&
row.boundaryEvidence.iniBoundarySummary.vendored === 0
),
@@ -185,19 +186,19 @@ assert.equal(
"wasm-port/build/wasm/sim-configs-inventory/evidence-expansion-candidates.tsv",
);
assert.equal(artifact.promotionCandidateArtifactSummary.evidenceReadyCount, 8);
assert.equal(artifact.promotionCandidateArtifactSummary.inventoryReadyCount, 20);
assert.equal(artifact.promotionCandidateArtifactSummary.evidenceExpansionCandidateCount, 13);
assert.equal(artifact.promotionCandidateArtifactSummary.totalCandidateCount, 28);
assert.equal(artifact.promotionCandidateArtifactSummary.inventoryReadyCount, 19);
assert.equal(artifact.promotionCandidateArtifactSummary.evidenceExpansionCandidateCount, 14);
assert.equal(artifact.promotionCandidateArtifactSummary.totalCandidateCount, 27);
assert.equal(artifact.promotionCandidateArtifactSummary.promotionAllowedCount, 0);
assert.equal(artifact.promotionCandidateArtifactSummary.hardBlockRuntimePromotionAllowedCount, 0);
assert.deepEqual(artifact.promotionCandidateArtifactSummary.artifactRows, {
promotionCandidates: 28,
evidenceExpansion: 13,
promotionCandidates: 27,
evidenceExpansion: 14,
});
assert.equal(artifact.promotionCandidateArtifactSummary.evidenceExpansion.promotionAllowedCount, 0);
assert.equal(
artifact.promotionCandidateArtifactSummary.inventoryBaseline,
"executed=28 passed=28 skipped=131 unexpected_fail=0",
"executed=29 passed=29 skipped=130 unexpected_fail=0",
);
assert.equal(artifact.axisScreenshotArtifactSummary.apiName, "project-release-axis-screenshot-artifact-summary");
if (artifact.axisScreenshotArtifactSummary.artifactCount > 0) {

View File

@@ -29,6 +29,7 @@ const passedGateResults = {
"sim-config-inventory": true,
"ini-panel-browser": true,
"opfs-session-browser": true,
"tool-db-process-proof": true,
"release-artifact-url-browser": true,
"project-batch-acceptance": true,
"ui-node-smokes": true,
@@ -88,6 +89,7 @@ const report = createProjectReleaseReadinessReport({
"sim_configs_wasm_node_inventory_unexpected_fail=0",
"browser_ini_shell_integration_workflow_smoke=ok",
"browser_opfs_session_workflow_smoke=ok",
"tool_db_process_proof=ok",
"browser_release_artifact_url_workflow_smoke=ok",
"project_batch_acceptance_workflow_node_smoke=ok",
"ui_node_smokes=ok",

View File

@@ -434,9 +434,7 @@ awk -F '\t' '
runtime_family = $1
sub("/[^/]+$", "", runtime_family)
blocked = ""
if ($1 ~ /^axis\/db_demo\//) {
blocked = "L4-TOOL-DB"
} else if ($1 ~ /^axis\/vismach\/millturn\// && $2 == "main") {
if ($1 ~ /^axis\/vismach\/millturn\// && $2 == "main") {
blocked = "L4-USER-M-PROCESS"
} else if ($4 == "upstream-demo-missing-motion-gcode") {
blocked = "UPSTREAM-DEMO"

View File

@@ -81,7 +81,7 @@ const browserDiagnosticsArtifact = {
preferredGcodePath: "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc",
blockedCandidateIds: [],
explicitBrowserDiagnosticsCount: 8,
inventoryBaseline: "executed=28 passed=28 skipped=131 unexpected_fail=0",
inventoryBaseline: "executed=29 passed=29 skipped=130 unexpected_fail=0",
},
virtualHalSimConfigMacroLoadFixtures,
virtualHalCommandScriptFixtures: createVirtualHalCommandScriptFixtureReport({ halState: virtualHalState }),
@@ -203,7 +203,7 @@ assert.equal(
);
assert.equal(
readySummary.rows.find(({ id }) => id === "virtual-hal-promotion-candidate-baseline")?.value,
"executed=28 passed=28 skipped=131 unexpected_fail=0",
"executed=29 passed=29 skipped=130 unexpected_fail=0",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "promotion-candidate-artifact")?.value,
@@ -211,11 +211,11 @@ assert.equal(
);
assert.equal(
readySummary.rows.find(({ id }) => id === "promotion-candidate-layers")?.value,
"evidence-ready=8 inventory-ready=20",
"evidence-ready=8 inventory-ready=19",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "promotion-candidate-total")?.value,
"28",
"27",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "evidence-ready-candidate-rows")?.value,
@@ -239,15 +239,15 @@ assert.equal(
);
assert.equal(
readySummary.rows.find(({ id }) => id === "evidence-expansion-candidates")?.value,
"13",
"14",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "promotion-candidate-artifact-rows")?.value,
"28",
"27",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "evidence-expansion-artifact-rows")?.value,
"13",
"14",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "evidence-expansion-next-evidence")?.value,
@@ -291,11 +291,11 @@ assert.equal(
);
assert.equal(
readySummary.rows.find(({ id }) => id === "hard-block-runtime-locked-rows")?.value,
"19",
"18",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "hard-block-runtime-locked-preview")?.value,
"L4-TOOL-DB:axis/db_demo/base.ngc, L4-PYTHON-REMAP:axis/laser/raster_test.ngc, L4-PYTHON-REMAP:axis/laser/vector_test.ngc",
"L4-PYTHON-REMAP:axis/laser/raster_test.ngc, L4-PYTHON-REMAP:axis/laser/vector_test.ngc, L4-PYTHON-REMAP:axis/laser/vector_test2.ngc",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "hard-block-runtime-promotion-allowed")?.value,
@@ -303,31 +303,23 @@ assert.equal(
);
assert.equal(
readySummary.rows.find(({ id }) => id === "hard-block-runtime-family-count")?.value,
"3",
"2",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "hard-block-runtime-family-summary")?.value,
"L4-USER-M-PROCESS:1 locked=yes, L4-TOOL-DB:1 locked=yes, L4-PYTHON-REMAP:17 locked=yes",
"L4-USER-M-PROCESS:1 locked=yes, L4-PYTHON-REMAP:17 locked=yes",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "hard-block-runtime-detail-row-count")?.value,
"19",
"18",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "hard-block-runtime-detail-preview-1")?.value,
"L4-TOOL-DB:axis/db_demo/base.ngc; reason=design_tooldata_db_protocol_boundary; next=db_program_v2_1_handshake_getall_load_unload_or_put; promotion_allowed=0",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "hard-block-runtime-family-L4-TOOL-DB")?.value,
"1 locked rows; promotion_allowed=0; first=axis/db_demo/base.ngc; reason=design_tooldata_db_protocol_boundary; next=db_program_v2_1_handshake_getall_load_unload_or_put",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "hard-block-runtime-family-L4-TOOL-DB-paths")?.value,
"axis/db_demo/base.ngc",
"L4-PYTHON-REMAP:axis/laser/raster_test.ngc; reason=design_linuxcnc_python_runtime_boundary; next=python_runtime_owner_and_fixture; promotion_allowed=0",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "hard-block-runtime-lock")?.value,
"locked (3 families)",
"locked (2 families)",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "promoted-blocked-family-count")?.value,
@@ -351,16 +343,16 @@ assert.deepEqual(
["artifact-validation", "ready"],
["virtual-hal-promotion-families", expectedPromotionFamilySummary],
["promotion-candidate-artifact", "wasm-port/build/wasm/sim-configs-inventory/promotion-candidates.tsv"],
["promotion-candidate-layers", "evidence-ready=8 inventory-ready=20"],
["promotion-candidate-total", "28"],
["promotion-candidate-layers", "evidence-ready=8 inventory-ready=19"],
["promotion-candidate-total", "27"],
["evidence-ready-candidate-rows", "8"],
["evidence-ready-candidate-preview", "qtdragon-multi-joint-on-abort"],
["evidence-ready-candidate-preview-gcode", "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc"],
["evidence-ready-candidate-promotion-allowed", "0"],
["evidence-ready-candidate-baseline-changing", "no"],
["promotion-candidate-artifact-rows", "28"],
["evidence-expansion-candidates", "13"],
["evidence-expansion-artifact-rows", "13"],
["promotion-candidate-artifact-rows", "27"],
["evidence-expansion-candidates", "14"],
["evidence-expansion-artifact-rows", "14"],
["evidence-expansion-next-evidence", "browser-diagnostics-binding"],
["evidence-expansion-baseline-changing", "no"],
["evidence-expansion-preferred-candidate", "woodpecker-on-abort"],
@@ -371,22 +363,20 @@ assert.deepEqual(
["evidence-expansion-source-count-list", "3, 3, 3"],
["evidence-expansion-artifact", "wasm-port/build/wasm/sim-configs-inventory/evidence-expansion-candidates.tsv"],
["promotion-candidate-allowed", "0"],
["hard-block-runtime-locked-rows", "19"],
["hard-block-runtime-locked-preview", "L4-TOOL-DB:axis/db_demo/base.ngc, L4-PYTHON-REMAP:axis/laser/raster_test.ngc, L4-PYTHON-REMAP:axis/laser/vector_test.ngc"],
["hard-block-runtime-locked-rows", "18"],
["hard-block-runtime-locked-preview", "L4-PYTHON-REMAP:axis/laser/raster_test.ngc, L4-PYTHON-REMAP:axis/laser/vector_test.ngc, L4-PYTHON-REMAP:axis/laser/vector_test2.ngc"],
["hard-block-runtime-promotion-allowed", "0"],
["hard-block-runtime-family-count", "3"],
["hard-block-runtime-family-summary", "L4-USER-M-PROCESS:1 locked=yes, L4-TOOL-DB:1 locked=yes, L4-PYTHON-REMAP:17 locked=yes"],
["hard-block-runtime-detail-row-count", "19"],
["hard-block-runtime-detail-preview-1", "L4-TOOL-DB:axis/db_demo/base.ngc; reason=design_tooldata_db_protocol_boundary; next=db_program_v2_1_handshake_getall_load_unload_or_put; promotion_allowed=0"],
["hard-block-runtime-detail-preview-2", "L4-PYTHON-REMAP:axis/laser/raster_test.ngc; reason=design_linuxcnc_python_runtime_boundary; next=python_runtime_owner_and_fixture; promotion_allowed=0"],
["hard-block-runtime-detail-preview-3", "L4-PYTHON-REMAP:axis/laser/vector_test.ngc; reason=design_linuxcnc_python_runtime_boundary; next=python_runtime_owner_and_fixture; promotion_allowed=0"],
["hard-block-runtime-detail-preview-4", "L4-PYTHON-REMAP:axis/laser/vector_test2.ngc; reason=design_linuxcnc_python_runtime_boundary; next=python_runtime_owner_and_fixture; promotion_allowed=0"],
["hard-block-runtime-detail-preview-5", "L4-PYTHON-REMAP:axis/remap/cycle/nc_files/examples.ngc; reason=design_linuxcnc_python_runtime_boundary; next=python_runtime_owner_and_fixture; promotion_allowed=0"],
["hard-block-runtime-family-count", "2"],
["hard-block-runtime-family-summary", "L4-USER-M-PROCESS:1 locked=yes, L4-PYTHON-REMAP:17 locked=yes"],
["hard-block-runtime-detail-row-count", "18"],
["hard-block-runtime-detail-preview-1", "L4-PYTHON-REMAP:axis/laser/raster_test.ngc; reason=design_linuxcnc_python_runtime_boundary; next=python_runtime_owner_and_fixture; promotion_allowed=0"],
["hard-block-runtime-detail-preview-2", "L4-PYTHON-REMAP:axis/laser/vector_test.ngc; reason=design_linuxcnc_python_runtime_boundary; next=python_runtime_owner_and_fixture; promotion_allowed=0"],
["hard-block-runtime-detail-preview-3", "L4-PYTHON-REMAP:axis/laser/vector_test2.ngc; reason=design_linuxcnc_python_runtime_boundary; next=python_runtime_owner_and_fixture; promotion_allowed=0"],
["hard-block-runtime-detail-preview-4", "L4-PYTHON-REMAP:axis/remap/cycle/nc_files/examples.ngc; reason=design_linuxcnc_python_runtime_boundary; next=python_runtime_owner_and_fixture; promotion_allowed=0"],
["hard-block-runtime-detail-preview-5", "L4-PYTHON-REMAP:axis/remap/extend-builtins/nc_files/examples.ngc; reason=design_linuxcnc_python_runtime_boundary; next=python_runtime_owner_and_fixture; promotion_allowed=0"],
["hard-block-runtime-family-L4-USER-M-PROCESS", "1 locked rows; promotion_allowed=0; first=axis/vismach/millturn/example.ngc; reason=design_m128_m129_linuxcnc_state_boundary; next=kinstype_guard_and_ini_xyz_hal_pin_state"],
["hard-block-runtime-family-L4-TOOL-DB", "1 locked rows; promotion_allowed=0; first=axis/db_demo/base.ngc; reason=design_tooldata_db_protocol_boundary; next=db_program_v2_1_handshake_getall_load_unload_or_put"],
["hard-block-runtime-family-L4-PYTHON-REMAP", "17 locked rows; promotion_allowed=0; first=axis/laser/raster_test.ngc; reason=design_linuxcnc_python_runtime_boundary; next=python_runtime_owner_and_fixture"],
["hard-block-runtime-family-L4-USER-M-PROCESS-paths", "axis/vismach/millturn/example.ngc"],
["hard-block-runtime-family-L4-TOOL-DB-paths", "axis/db_demo/base.ngc"],
["hard-block-runtime-family-L4-PYTHON-REMAP-paths", "axis/laser/raster_test.ngc, axis/laser/vector_test.ngc, axis/laser/vector_test2.ngc, axis/remap/cycle/nc_files/examples.ngc, axis/remap/extend-builtins/nc_files/examples.ngc, axis/remap/getting-started/nc_files/examples.ngc, axis/remap/manual-toolchange-with-tool-length-switch/nc_files/tcdemo.ngc, axis/remap/rack-toolchange/nc_files/tcdemo.ngc, axis/remap/stop-lookahead/nc_files/examples.ngc, axis/vismach/5axis/table-rotary_spindle-rotary-nutating/demos/circular_pocket.ngc, axis/vismach/5axis/table-rotary_spindle-rotary-nutating/demos/incremental_repetition_back_and_forth.ngc, axis/vismach/5axis/table-rotary_spindle-rotary-nutating/demos/incremental_repetition.ngc, axis/vismach/5axis/table-rotary_spindle-rotary-nutating/demos/simple_example.ngc, axis/vismach/VMC_toolchange/toolchange.ngc, gmoccapy/non_trivial_kinematics/table-rotary-tilting/examples/boat-xyzac.ngc, gmoccapy/non_trivial_kinematics/table-rotary-tilting/examples/boat-xyzbc.ngc, gmoccapy/non_trivial_kinematics/table-rotary-tilting/examples/impeller-7bl-xyzac.ngc"],
["tool-db-process-proof", "ready"],
["tool-db-process-proof-detail", "wasm=ready browser=ready opfs=ready promotion_allowed=0"],
@@ -400,8 +390,8 @@ assert.deepEqual(
["virtual-hal-promotion-family-count", "3 families"],
["virtual-hal-promotion-source-file-count", "17 source files"],
["virtual-hal-promotion-browser-diagnostics-count", "8 diagnostics-ready"],
["virtual-hal-promotion-candidate-baseline", "executed=28 passed=28 skipped=131 unexpected_fail=0"],
["hard-block-runtime-lock", "locked (3 families)"],
["virtual-hal-promotion-candidate-baseline", "executed=29 passed=29 skipped=130 unexpected_fail=0"],
["hard-block-runtime-lock", "locked (2 families)"],
["promoted-blocked-family-count", "0 promoted"],
["saved-session-diagnostics", "ready"],
["next-command", "none"],

View File

@@ -282,7 +282,7 @@ assert.deepEqual(createProjectReleaseReadinessSummaryViewModel(report), {
{
id: "promotion-candidate-layers",
label: "Promotion candidate layers",
value: "evidence-ready=8 inventory-ready=20",
value: "evidence-ready=8 inventory-ready=19",
},
{
id: "promotion-candidate-allowed",
@@ -292,7 +292,7 @@ assert.deepEqual(createProjectReleaseReadinessSummaryViewModel(report), {
{
id: "evidence-expansion-candidates",
label: "Evidence expansion candidates",
value: "13",
value: "14",
},
{
id: "evidence-expansion-next-evidence",
@@ -327,12 +327,12 @@ assert.deepEqual(createProjectReleaseReadinessSummaryViewModel(report), {
{
id: "blocked-runtime-families",
label: "Blocked runtime families",
value: "L4-USER-M-PROCESS, L4-TOOL-DB, L4-PYTHON-REMAP",
value: "L4-USER-M-PROCESS, L4-PYTHON-REMAP",
},
{
id: "hard-block-runtime-lock",
label: "Hard-block runtime lock",
value: "locked (3 families)",
value: "locked (2 families)",
},
{
id: "promoted-blocked-family-count",
@@ -362,9 +362,9 @@ assert.equal(
virtualHalSimConfigPromotionCandidates,
virtualHalSimConfigMacroLoadFixtures,
virtualHalMotionControllerMatrix,
promotedRuntimeFamilies: ["L4-TOOL-DB"],
promotedRuntimeFamilies: ["L4-PYTHON-REMAP"],
})).rows.find(({ id }) => id === "blocked-runtime-families")?.value,
"promoted: L4-TOOL-DB",
"promoted: L4-PYTHON-REMAP",
);
const artifactValidationSummary = createProjectReleaseReadinessArtifactValidationSummaryViewModel(
@@ -413,11 +413,11 @@ assert.deepEqual(
["virtual-hal-sim-config-source-coverage", "ready"],
["virtual-hal-sim-config-promotion-candidates", "ready"],
["promotion-candidate-artifact", "wasm-port/build/wasm/sim-configs-inventory/promotion-candidates.tsv"],
["promotion-candidate-layers", "evidence-ready=8 inventory-ready=20"],
["promotion-candidate-total", "28"],
["promotion-candidate-artifact-rows", "28"],
["evidence-expansion-candidates", "13"],
["evidence-expansion-artifact-rows", "13"],
["promotion-candidate-layers", "evidence-ready=8 inventory-ready=19"],
["promotion-candidate-total", "27"],
["promotion-candidate-artifact-rows", "27"],
["evidence-expansion-candidates", "14"],
["evidence-expansion-artifact-rows", "14"],
["evidence-expansion-next-evidence", "browser-diagnostics-binding"],
["evidence-expansion-baseline-changing", "no"],
["evidence-expansion-artifact", "wasm-port/build/wasm/sim-configs-inventory/evidence-expansion-candidates.tsv"],
@@ -516,16 +516,16 @@ assert.deepEqual(
["artifact-validation", "ready"],
["virtual-hal-promotion-families", expectedPromotionFamilySummary],
["promotion-candidate-artifact", "wasm-port/build/wasm/sim-configs-inventory/promotion-candidates.tsv"],
["promotion-candidate-layers", "evidence-ready=8 inventory-ready=20"],
["promotion-candidate-total", "28"],
["promotion-candidate-layers", "evidence-ready=8 inventory-ready=19"],
["promotion-candidate-total", "27"],
["evidence-ready-candidate-rows", "0"],
["evidence-ready-candidate-preview", "not provided"],
["evidence-ready-candidate-preview-gcode", "not provided"],
["evidence-ready-candidate-promotion-allowed", "0"],
["evidence-ready-candidate-baseline-changing", "no"],
["promotion-candidate-artifact-rows", "28"],
["evidence-expansion-candidates", "13"],
["evidence-expansion-artifact-rows", "13"],
["promotion-candidate-artifact-rows", "27"],
["evidence-expansion-candidates", "14"],
["evidence-expansion-artifact-rows", "14"],
["evidence-expansion-next-evidence", "browser-diagnostics-binding"],
["evidence-expansion-baseline-changing", "no"],
["evidence-expansion-preferred-candidate", "not provided"],
@@ -539,14 +539,12 @@ assert.deepEqual(
["hard-block-runtime-locked-rows", "0"],
["hard-block-runtime-locked-preview", "not provided"],
["hard-block-runtime-promotion-allowed", "0"],
["hard-block-runtime-family-count", "3"],
["hard-block-runtime-family-summary", "L4-USER-M-PROCESS:0 locked=yes, L4-TOOL-DB:0 locked=yes, L4-PYTHON-REMAP:0 locked=yes"],
["hard-block-runtime-family-count", "2"],
["hard-block-runtime-family-summary", "L4-USER-M-PROCESS:0 locked=yes, L4-PYTHON-REMAP:0 locked=yes"],
["hard-block-runtime-detail-row-count", "0"],
["hard-block-runtime-family-L4-USER-M-PROCESS", "0 locked rows; promotion_allowed=0; first=not provided; reason=not provided; next=not provided"],
["hard-block-runtime-family-L4-TOOL-DB", "0 locked rows; promotion_allowed=0; first=not provided; reason=not provided; next=not provided"],
["hard-block-runtime-family-L4-PYTHON-REMAP", "0 locked rows; promotion_allowed=0; first=not provided; reason=not provided; next=not provided"],
["hard-block-runtime-family-L4-USER-M-PROCESS-paths", "not provided"],
["hard-block-runtime-family-L4-TOOL-DB-paths", "not provided"],
["hard-block-runtime-family-L4-PYTHON-REMAP-paths", "not provided"],
["tool-db-process-proof", "ready"],
["tool-db-process-proof-detail", "wasm=ready browser=ready opfs=ready promotion_allowed=0"],
@@ -561,7 +559,7 @@ assert.deepEqual(
["virtual-hal-promotion-source-file-count", "not provided"],
["virtual-hal-promotion-browser-diagnostics-count", "not provided"],
["virtual-hal-promotion-candidate-baseline", "not provided"],
["hard-block-runtime-lock", "locked (3 families)"],
["hard-block-runtime-lock", "locked (2 families)"],
["promoted-blocked-family-count", "0 promoted"],
["saved-session-diagnostics", "not requested"],
["next-command", "none"],

View File

@@ -0,0 +1,211 @@
import assert from "node:assert/strict";
import {
createLinuxCncPythonRemapBrowserWorkerAdapter,
} from "../../../runtime/sdk/src/python-remap-browser-worker-adapter.js";
import {
PYTHON_REMAP_RUNTIME_PORT_CONTRACT_VERSION,
PYTHON_REMAP_STOP_LOOKAHEAD_FIXTURE,
createLinuxCncPythonRemapRuntimePort,
createPythonRemapLifecyclePlan,
createPythonRemapRuntimeDiagnostics,
validatePythonRemapLifecycleTranscript,
} from "../../../runtime/sdk/src/python-remap-runtime-port.js";
assert.equal(PYTHON_REMAP_RUNTIME_PORT_CONTRACT_VERSION, 1);
assert.equal(PYTHON_REMAP_STOP_LOOKAHEAD_FIXTURE.fixtureFamily, "axis/remap/stop-lookahead/nc_files");
assert.equal(PYTHON_REMAP_STOP_LOOKAHEAD_FIXTURE.topLevelPath, "python/toplevel.py");
assert.equal(PYTHON_REMAP_STOP_LOOKAHEAD_FIXTURE.callableName, "queuebuster");
assert.deepEqual(
createPythonRemapLifecyclePlan().map((step) => step.phase),
[
"initialize_python",
"apply_ini_python_path",
"execute_toplevel",
"import_module",
"callable_lookup",
"callable_invoke",
"remap_phase_dispatch",
"generator_finish",
"export_interpreter_state",
"export_diagnostics",
],
);
const contractOnlyPort = createLinuxCncPythonRemapRuntimePort({
runtimeMode: "contract-only",
});
const contractOnlyStart = await contractOnlyPort.start();
assert.deepEqual(contractOnlyStart, {
runtimeMode: "contract-only",
runtimeExecutionReady: false,
status: null,
executionEnabled: false,
promotionAllowed: false,
bulkPromotionAllowed: false,
});
const contractOnlyPlan = await contractOnlyPort.runLifecyclePlan();
assert.equal(contractOnlyPlan.status, "blocked_runtime_adapter_required");
assert.equal(contractOnlyPlan.runtimeExecutionReady, false);
assert.equal(contractOnlyPlan.executionEnabled, false);
assert.equal(contractOnlyPlan.promotionAllowed, false);
assert.equal(contractOnlyPlan.bulkPromotionAllowed, false);
assert.equal(contractOnlyPort.exportDiagnostics().lifecycleTranscriptReady, false);
await contractOnlyPort.close();
class FakeBlockedWorker {
constructor() {
this.listeners = new Map();
}
addEventListener(type, listener) {
this.listeners.set(type, listener);
}
postMessage(message) {
queueMicrotask(() => {
this.listeners.get("message")?.({
data: {
id: message.id,
type: message.type,
ok: true,
runtimeExecutionReady: false,
status: "blocked_browser_python_wasm_runtime_missing",
executionEnabled: false,
promotionAllowed: false,
bulkPromotionAllowed: false,
},
});
});
}
terminate() {}
}
class FakeReadyWorker {
constructor() {
this.listeners = new Map();
this.startMessages = [];
}
addEventListener(type, listener) {
this.listeners.set(type, listener);
}
postMessage(message) {
queueMicrotask(() => {
if (message.type === "start") {
this.startMessages.push(message);
this.reply(message, {
runtimeExecutionReady: true,
status: "browser_python_remap_wasm_runtime_ready",
});
return;
}
const values = {
initializePython: "python-runtime-initialized",
applyIniPythonPath: message.pythonPathPrepend,
executeTopLevel: message.topLevelPath,
importModule: message.modulePath,
lookupCallable: message.callableName,
invokeGenerator: "generator-returned",
observeFirstYield: message.expectedYield,
finishGenerator: "generator-finished",
exportInterpreterState: "interpreter-state-bound",
exportDiagnostics: "diagnostics-exported",
};
this.reply(message, {
status: "ok",
ready: true,
value: values[message.type] ?? null,
source: "fake-linuxcnc-python-remap-provider",
});
});
}
reply(message, payload) {
this.listeners.get("message")?.({
data: {
id: message.id,
type: message.type,
ok: true,
executionEnabled: false,
promotionAllowed: false,
bulkPromotionAllowed: false,
...payload,
},
});
}
terminate() {}
}
const blockedWorkerAdapter = createLinuxCncPythonRemapBrowserWorkerAdapter({
workerUrl: "./python-remap-worker.js",
workerFactory: () => new FakeBlockedWorker(),
});
const blockedWorkerPort = createLinuxCncPythonRemapRuntimePort({
runtimeMode: blockedWorkerAdapter.runtimeMode,
runtimeAdapter: blockedWorkerAdapter,
});
const blockedWorkerStart = await blockedWorkerPort.start();
assert.equal(blockedWorkerStart.runtimeMode, "browser-python-wasm-worker");
assert.equal(blockedWorkerStart.runtimeExecutionReady, false);
assert.equal(blockedWorkerStart.status, "blocked_browser_python_wasm_runtime_missing");
const blockedWorkerPlan = await blockedWorkerPort.runLifecyclePlan();
assert.equal(blockedWorkerPlan.status, "blocked_browser_python_wasm_runtime_missing");
assert.equal(blockedWorkerPlan.promotionAllowed, false);
await blockedWorkerPort.close();
const fakeReadyWorker = new FakeReadyWorker();
const readyWorkerAdapter = createLinuxCncPythonRemapBrowserWorkerAdapter({
workerUrl: "./python-remap-worker.js",
pythonRuntimeModuleUrl: "./python-remap-runtime-provider.js",
workerFactory: () => fakeReadyWorker,
});
const readyWorkerPort = createLinuxCncPythonRemapRuntimePort({
runtimeMode: readyWorkerAdapter.runtimeMode,
runtimeAdapter: readyWorkerAdapter,
});
const readyWorkerStart = await readyWorkerPort.start();
assert.equal(readyWorkerStart.runtimeExecutionReady, true);
assert.equal(readyWorkerStart.status, "browser_python_remap_wasm_runtime_ready");
assert.equal(fakeReadyWorker.startMessages[0].pythonRuntimeModuleUrl, "./python-remap-runtime-provider.js");
const initializeResult = await readyWorkerPort.initializePython();
assert.equal(initializeResult.phase, "initialize_python");
assert.equal(initializeResult.value, "python-runtime-initialized");
const readyWorkerPlan = await readyWorkerPort.runLifecyclePlan();
assert.equal(readyWorkerPlan.status, "runtime_adapter_lifecycle_plan_executed");
assert.equal(readyWorkerPlan.runtimeExecutionReady, true);
assert.equal(readyWorkerPlan.promotionAllowed, false);
assert.equal(readyWorkerPlan.bulkPromotionAllowed, false);
const transcript = readyWorkerPort.exportTranscript();
assert.equal(transcript.filter((entry) => entry.phase === "initialize_python").length, 2);
const validation = validatePythonRemapLifecycleTranscript(transcript);
assert.equal(validation.ready, true);
assert.equal(validation.lifecycleTranscriptReady, true);
assert.equal(validation.firstYield, 2);
assert.equal(validation.callableLookupReady, true);
assert.equal(validation.generatorLifecycleReady, true);
assert.equal(validation.interpreterStateBindingReady, true);
const diagnostics = readyWorkerPort.exportDiagnostics();
assert.equal(diagnostics.runtimeMode, "browser-python-wasm-worker");
assert.equal(diagnostics.runtimeExecutionReady, true);
assert.equal(diagnostics.lifecycleTranscriptReady, true);
assert.equal(diagnostics.callableLookupReady, true);
assert.equal(diagnostics.generatorLifecycleReady, true);
assert.equal(diagnostics.interpreterStateBindingReady, true);
assert.equal(diagnostics.linuxCncOwnedLifecycle, true);
assert.equal(diagnostics.jsCncSemantics, false);
assert.equal(diagnostics.ngcOnlySubroutinePromoted, false);
assert.equal(diagnostics.executionEnabled, false);
assert.equal(diagnostics.promotionAllowed, false);
assert.equal(diagnostics.bulkPromotionAllowed, false);
await readyWorkerPort.close();
const explicitDiagnostics = createPythonRemapRuntimeDiagnostics({
runtimeMode: "contract-only",
transcript,
});
assert.equal(explicitDiagnostics.transcriptHash.length, 8);
assert.equal(explicitDiagnostics.lifecycleTranscriptReady, true);

View File

@@ -0,0 +1,6 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "$0")/../../.." && pwd)"
node "$ROOT_DIR/tests/sdk/node/verify_python_remap_runtime_port.mjs"

View File

@@ -92,9 +92,14 @@ import {
createProjectReleaseReadinessSummaryViewModel,
createLinuxCncToolDbBrowserWorkerAdapter,
createLinuxCncToolDbProcessPort,
createLinuxCncPythonRemapBrowserWorkerAdapter,
createLinuxCncPythonRemapRuntimePort,
createPythonRemapLifecyclePlan,
createPythonRemapRuntimeDiagnostics,
createToolDbProcessDiagnostics,
createToolDbTransactionPlan,
runToolDbProcessPortPersistenceSession,
validatePythonRemapLifecycleTranscript,
createVirtualHalBridgeActionPlan,
createVirtualHalBridgeReadiness,
createVirtualHalCommandScriptFixtureReport,
@@ -230,16 +235,16 @@ const expectedPromotionCandidateArtifactSummary = {
evidenceExpansionArtifactPath: "wasm-port/build/wasm/sim-configs-inventory/evidence-expansion-candidates.tsv",
layerCount: 2,
evidenceReadyCount: 8,
inventoryReadyCount: 20,
evidenceExpansionCandidateCount: 13,
totalCandidateCount: 28,
inventoryReadyCount: 19,
evidenceExpansionCandidateCount: 14,
totalCandidateCount: 27,
promotionAllowedCount: 0,
hardBlockRuntimeLock: "locked (3 families)",
hardBlockRuntimeLock: "locked (2 families)",
hardBlockRuntimePromotionAllowedCount: 0,
inventoryBaseline: "executed=28 passed=28 skipped=131 unexpected_fail=0",
inventoryBaseline: "executed=29 passed=29 skipped=130 unexpected_fail=0",
artifactRows: {
promotionCandidates: 28,
evidenceExpansion: 13,
promotionCandidates: 27,
evidenceExpansion: 14,
},
hardBlockRuntimeFamilyRows: [],
hardBlockRuntimeFamilyDetailRows: [],
@@ -254,16 +259,6 @@ const expectedPromotionCandidateArtifactSummary = {
firstBlockReason: null,
nextProof: null,
},
{
family: "L4-TOOL-DB",
candidateCount: 0,
promotionAllowedCount: 0,
locked: true,
lockedPaths: [],
firstPath: null,
firstBlockReason: null,
nextProof: null,
},
{
family: "L4-PYTHON-REMAP",
candidateCount: 0,
@@ -285,7 +280,7 @@ const expectedPromotionCandidateArtifactSummary = {
},
{
id: "inventory-ready",
candidateCount: 20,
candidateCount: 19,
promotionAllowedCount: 0,
virtualHalEvidenceReady: false,
baselineChanging: false,
@@ -293,8 +288,8 @@ const expectedPromotionCandidateArtifactSummary = {
],
evidenceExpansion: {
id: "browser-diagnostics-expansion",
candidateCount: 13,
artifactRowCount: 13,
candidateCount: 14,
artifactRowCount: 14,
promotionAllowedCount: 0,
baselineChanging: false,
nextEvidence: "browser-diagnostics-binding",
@@ -525,9 +520,14 @@ const requiredExports = [
["gcodeFilenameFromProgramPath", gcodeFilenameFromProgramPath],
["createLinuxCncToolDbBrowserWorkerAdapter", createLinuxCncToolDbBrowserWorkerAdapter],
["createLinuxCncToolDbProcessPort", createLinuxCncToolDbProcessPort],
["createLinuxCncPythonRemapBrowserWorkerAdapter", createLinuxCncPythonRemapBrowserWorkerAdapter],
["createLinuxCncPythonRemapRuntimePort", createLinuxCncPythonRemapRuntimePort],
["createPythonRemapLifecyclePlan", createPythonRemapLifecyclePlan],
["createPythonRemapRuntimeDiagnostics", createPythonRemapRuntimeDiagnostics],
["createToolDbProcessDiagnostics", createToolDbProcessDiagnostics],
["createToolDbTransactionPlan", createToolDbTransactionPlan],
["runToolDbProcessPortPersistenceSession", runToolDbProcessPortPersistenceSession],
["validatePythonRemapLifecycleTranscript", validatePythonRemapLifecycleTranscript],
["validateToolDbTranscript", validateToolDbTranscript],
["saveToolDbFile", saveToolDbFile],
["loadToolDbFile", loadToolDbFile],
@@ -1053,16 +1053,16 @@ assert.equal(VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_FIXTURES.length >= 2, true);
assert.equal(VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_BLOCKED_FIXTURES.length >= 2, true);
assert.equal(VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_AUDIT_CANDIDATES.length >= 2, true);
assert.deepEqual(VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE, {
executed: 28,
passed: 28,
skipped: 131,
executed: 29,
passed: 29,
skipped: 130,
unexpectedFail: 0,
});
assert.deepEqual(VIRTUAL_HAL_SIM_CONFIG_INVENTORY_ARTIFACT_HASHES, {
"wasm-port/build/wasm/sim-configs-inventory/boundary-summary.tsv":
"de6cf57b7c07182e3bcb32e22dbdf202b618cabc14620d6dff1ef815587950b9",
"6cc15052cad03d04eff4506cd0a9d651cd45a2bd5da4d9f38633e9535826b9f3",
"wasm-port/build/wasm/sim-configs-inventory/ini-boundary-summary.tsv":
"b0afe27224e97a82fbecbbd75a7c86233c98fe957d9c1ba20f0656f8745a5eae",
"17bff95b57c55ff4201a23c7286e733550e4df513470c66dd5f24329e7781a35",
});
const simConfigMacroLoadFixtureReport = createVirtualHalSimConfigMacroLoadFixtureReport({
manifestText: sourceManifestText,
@@ -1250,7 +1250,7 @@ assert.equal(createVirtualHalSimConfigMacroLoadFixtureReport({
).boundaryEvidence,
baselineSummary: {
...VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE,
skipped: 130,
skipped: 131,
},
},
},
@@ -1395,7 +1395,7 @@ const browserDiagnosticsArtifact = {
preferredGcodePath: "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc",
blockedCandidateIds: [],
explicitBrowserDiagnosticsCount: 8,
inventoryBaseline: "executed=28 passed=28 skipped=131 unexpected_fail=0",
inventoryBaseline: "executed=29 passed=29 skipped=130 unexpected_fail=0",
},
virtualHalSimConfigMacroLoadFixtures: simConfigMacroLoadFixtureReport,
virtualHalCommandScriptFixtures: commandScriptFixtureReport,
@@ -1418,7 +1418,7 @@ browserDiagnosticsArtifact.virtualHalSessionDiagnostics = {
};
const browserDiagnosticsArtifactValidation = createProjectReleaseBrowserDiagnosticsArtifactValidation(browserDiagnosticsArtifact);
assert.equal(browserDiagnosticsArtifactValidation.apiName, "project-release-browser-diagnostics-artifact-validation");
assert.equal(browserDiagnosticsArtifactValidation.ready, true);
assert.equal(browserDiagnosticsArtifactValidation.ready, true, JSON.stringify(browserDiagnosticsArtifactValidation));
assert.equal(browserDiagnosticsArtifactValidation.sourceComplianceReady, true);
assert.equal(browserDiagnosticsArtifactValidation.simConfigSourceCoverageReady, true);
assert.equal(browserDiagnosticsArtifactValidation.promotionCandidatesReady, true);
@@ -1629,11 +1629,11 @@ assert.equal(releaseReadinessWaiting.gateActionPlan.pendingCount, createProjectR
assert.equal(releaseReadinessWaiting.gateActionPlan.nextGateId, "diff-check");
assert.equal(
releaseReadinessWaiting.rows.find(({ id }) => id === "blocked-runtime-families")?.value,
"L4-USER-M-PROCESS, L4-TOOL-DB, L4-PYTHON-REMAP",
"L4-USER-M-PROCESS, L4-PYTHON-REMAP",
);
assert.equal(
releaseReadinessWaiting.rows.find(({ id }) => id === "hard-block-runtime-lock")?.value,
"locked (3 families)",
"locked (2 families)",
);
assert.equal(
releaseReadinessWaiting.rows.find(({ id }) => id === "promoted-blocked-family-count")?.value,
@@ -1657,11 +1657,11 @@ assert.deepEqual(
);
assert.equal(
releaseReadinessReady.rows.find(({ id }) => id === "promotion-candidate-artifact-rows")?.value,
"28",
"27",
);
assert.equal(
releaseReadinessReady.rows.find(({ id }) => id === "evidence-expansion-artifact-rows")?.value,
"13",
"14",
);
assert.deepEqual(
releaseReadinessReady.virtualHalPromotionFamilyRows.map(({ id, value }) => [
@@ -1713,7 +1713,7 @@ assert.equal(
);
assert.equal(
createProjectReleaseReadinessSummaryViewModel(releaseReadinessReady).rows.find(({ id }) => id === "promotion-candidate-layers")?.value,
"evidence-ready=8 inventory-ready=20",
"evidence-ready=8 inventory-ready=19",
);
const releaseReadinessWithCandidateArtifacts = createProjectReleaseReadinessReport({
observedOutputs: ["project_release_gate=ok"],
@@ -1724,11 +1724,11 @@ const releaseReadinessWithCandidateArtifacts = createProjectReleaseReadinessRepo
promotionCandidateRows: promotionCandidateArtifactRows,
evidenceExpansionRows: evidenceExpansionArtifactRows,
});
assert.equal(releaseReadinessWithCandidateArtifacts.promotionCandidateArtifactSummary.artifactRows.promotionCandidates, 28);
assert.equal(releaseReadinessWithCandidateArtifacts.promotionCandidateArtifactSummary.artifactRows.evidenceExpansion, 13);
assert.equal(releaseReadinessWithCandidateArtifacts.promotionCandidateArtifactSummary.artifactRows.promotionCandidates, 27);
assert.equal(releaseReadinessWithCandidateArtifacts.promotionCandidateArtifactSummary.artifactRows.evidenceExpansion, 14);
assert.equal(
releaseReadinessWithCandidateArtifacts.promotionCandidateArtifactSummary.hardBlockRuntimeFamilyRows.length,
19,
18,
);
assert.equal(
releaseReadinessWithCandidateArtifacts.promotionCandidateArtifactSummary.hardBlockRuntimePromotionAllowedCount,
@@ -1736,8 +1736,8 @@ assert.equal(
);
assert.equal(
releaseReadinessWithCandidateArtifacts.promotionCandidateArtifactSummary.hardBlockRuntimeFamilyRows
.some((row) => row.skipKind === "L4-TOOL-DB" && row.promotionAllowed === false),
true,
.some((row) => row.skipKind === "L4-TOOL-DB"),
false,
);
assert.deepEqual(
releaseReadinessWithCandidateArtifacts.promotionCandidateArtifactSummary.hardBlockRuntimeFamilySummaryRows
@@ -1749,7 +1749,6 @@ assert.deepEqual(
]),
[
["L4-USER-M-PROCESS", 1, 0, true],
["L4-TOOL-DB", 1, 0, true],
["L4-PYTHON-REMAP", 17, 0, true],
],
);
@@ -1764,13 +1763,6 @@ assert.deepEqual(
promotionAllowed,
]),
[
[
"L4-TOOL-DB",
"axis/db_demo/base.ngc",
"design_tooldata_db_protocol_boundary",
"db_program_v2_1_handshake_getall_load_unload_or_put",
false,
],
[
"L4-PYTHON-REMAP",
"axis/laser/raster_test.ngc",
@@ -1785,6 +1777,13 @@ assert.deepEqual(
"python_runtime_owner_and_fixture",
false,
],
[
"L4-PYTHON-REMAP",
"axis/laser/vector_test2.ngc",
"design_linuxcnc_python_runtime_boundary",
"python_runtime_owner_and_fixture",
false,
],
],
);
const releaseReadinessWithScreenshots = createProjectReleaseReadinessReport({
@@ -1863,7 +1862,6 @@ assert.deepEqual(releaseReadinessArtifactValidation, {
axisScreenshotArtifactCount: 0,
blockedRuntimeFamilies: [
"L4-USER-M-PROCESS",
"L4-TOOL-DB",
"L4-PYTHON-REMAP",
],
rows: [
@@ -1920,27 +1918,27 @@ assert.deepEqual(releaseReadinessArtifactValidation, {
{
id: "promotion-candidate-layers",
label: "Promotion candidate layers",
value: "evidence-ready=8 inventory-ready=20",
value: "evidence-ready=8 inventory-ready=19",
},
{
id: "promotion-candidate-total",
label: "Promotion candidate total",
value: "28",
value: "27",
},
{
id: "promotion-candidate-artifact-rows",
label: "Promotion candidate artifact rows",
value: "28",
value: "27",
},
{
id: "evidence-expansion-candidates",
label: "Evidence expansion candidates",
value: "13",
value: "14",
},
{
id: "evidence-expansion-artifact-rows",
label: "Evidence expansion artifact rows",
value: "13",
value: "14",
},
{
id: "evidence-expansion-next-evidence",
@@ -1998,12 +1996,12 @@ assert.deepEqual(releaseReadinessArtifactValidation, {
{
id: "blocked-runtime-families",
label: "Blocked runtime families",
value: "L4-USER-M-PROCESS, L4-TOOL-DB, L4-PYTHON-REMAP",
value: "L4-USER-M-PROCESS, L4-PYTHON-REMAP",
},
{
id: "hard-block-runtime-lock",
label: "Hard-block runtime lock",
value: "locked (3 families)",
value: "locked (2 families)",
},
{
id: "promoted-blocked-family-count",
@@ -2109,7 +2107,7 @@ assert.equal(
}),
}),
).rows.find(({ id }) => id === "promotion-candidate-layers")?.value,
"evidence-ready=8 inventory-ready=20",
"evidence-ready=8 inventory-ready=19",
);
assert.equal(
createProjectReleaseReadinessArtifactUrlWorkflowSummaryViewModel(
@@ -2138,7 +2136,7 @@ assert.equal(
}),
}),
).rows.find(({ id }) => id === "evidence-expansion-candidates")?.value,
"13",
"14",
);
assert.deepEqual(
createProjectReleaseReadinessArtifactUrlWorkflowSummaryViewModel(
@@ -2290,14 +2288,14 @@ assert.equal(createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomReadi
assert.equal(
createProjectReleaseReadinessReport({
observedOutputs: ["project_release_gate=ok"],
promotedRuntimeFamilies: ["L4-TOOL-DB"],
promotedRuntimeFamilies: ["L4-PYTHON-REMAP"],
}).missing.includes("blocked-runtime-families"),
true,
);
assert.equal(
createProjectReleaseReadinessSummaryViewModel(createProjectReleaseReadinessReport({
observedOutputs: ["project_release_gate=ok"],
promotedRuntimeFamilies: ["L4-TOOL-DB"],
promotedRuntimeFamilies: ["L4-PYTHON-REMAP"],
})).rows.find(({ id }) => id === "hard-block-runtime-lock")?.value,
"violated (1 promoted)",
);

View File

@@ -1507,7 +1507,7 @@ const browserDiagnosticsArtifact = {
preferredGcodePath: "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc",
blockedCandidateIds: [],
explicitBrowserDiagnosticsCount: 8,
inventoryBaseline: "executed=28 passed=28 skipped=131 unexpected_fail=0",
inventoryBaseline: "executed=29 passed=29 skipped=130 unexpected_fail=0",
},
virtualHalSimConfigMacroLoadFixtures: releaseReadinessMacroLoadFixtures,
virtualHalCommandScriptFixtures: createVirtualHalCommandScriptFixtureReport({ halState: browserDiagnosticsVirtualHalState }),
@@ -2073,7 +2073,7 @@ assert.equal(
);
assert.equal(
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "virtual-hal-promotion-candidate-baseline")?.value,
"executed=28 passed=28 skipped=131 unexpected_fail=0",
"executed=29 passed=29 skipped=130 unexpected_fail=0",
);
assert.equal(
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "hard-block-runtime-lock")?.value,

View File

@@ -0,0 +1,67 @@
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
import {
PYTHON_REMAP_STOP_LOOKAHEAD_FIXTURE,
createLinuxCncPythonRemapRuntimePort,
createPythonRemapLifecyclePlan,
createPythonRemapRuntimeDiagnostics,
validatePythonRemapLifecycleTranscript,
} from "../../../runtime/sdk/src/python-remap-runtime-port.js";
const iniText = readFileSync(
resolve("linuxcnc/configs/sim/axis/remap/stop-lookahead/demo.ini"),
"utf8",
);
assert.match(iniText, /\[PYTHON\]/);
assert.match(iniText, /PATH_PREPEND\s*=\s*python/);
assert.match(iniText, /TOPLEVEL\s*=\s*python\/toplevel\.py/);
const plan = createPythonRemapLifecyclePlan();
assert.equal(plan.length, 10);
assert.equal(plan[0].phase, "initialize_python");
assert.equal(plan.some((step) => step.phase === "callable_lookup" && step.callableName === "queuebuster"), true);
assert.equal(plan.some((step) => step.phase === "remap_phase_dispatch" && step.expectedYield === 2), true);
const port = createLinuxCncPythonRemapRuntimePort({
fixtureFamily: PYTHON_REMAP_STOP_LOOKAHEAD_FIXTURE.fixtureFamily,
iniPath: PYTHON_REMAP_STOP_LOOKAHEAD_FIXTURE.iniPath,
pythonPathPrepend: PYTHON_REMAP_STOP_LOOKAHEAD_FIXTURE.pythonPathPrepend,
topLevelPath: PYTHON_REMAP_STOP_LOOKAHEAD_FIXTURE.topLevelPath,
sourceFiles: PYTHON_REMAP_STOP_LOOKAHEAD_FIXTURE.modules,
runtimeMode: "contract-only",
});
assert.equal((await port.start()).runtimeExecutionReady, false);
assert.equal((await port.runLifecyclePlan()).status, "blocked_runtime_adapter_required");
assert.equal(port.exportDiagnostics().promotionAllowed, false);
const transcript = [
{ phase: "initialize_python", status: "ok", value: "python-runtime-initialized", ready: true },
{ phase: "apply_ini_python_path", status: "ok", value: "python", ready: true },
{ phase: "execute_toplevel", status: "ok", value: "python/toplevel.py", ready: true },
{ phase: "import_module", status: "ok", value: "python/remap.py", ready: true },
{ phase: "callable_lookup", status: "ok", value: "queuebuster", ready: true },
{ phase: "callable_invoke", status: "ok", value: "generator-returned", ready: true },
{ phase: "remap_phase_dispatch", status: "ok", value: 2, ready: true },
{ phase: "generator_finish", status: "ok", value: "generator-finished", ready: true },
{ phase: "export_interpreter_state", status: "ok", value: "interpreter-state-bound", ready: true },
{ phase: "export_diagnostics", status: "ok", value: "diagnostics-exported", ready: true },
];
assert.equal(validatePythonRemapLifecycleTranscript(transcript).ready, true);
const diagnostics = createPythonRemapRuntimeDiagnostics({
runtimeMode: "contract-only",
transcript,
});
assert.equal(diagnostics.fixtureFamily, "axis/remap/stop-lookahead/nc_files");
assert.equal(diagnostics.lifecycleTranscriptReady, true);
assert.equal(diagnostics.callableLookupReady, true);
assert.equal(diagnostics.generatorLifecycleReady, true);
assert.equal(diagnostics.interpreterStateBindingReady, true);
assert.equal(diagnostics.jsCncSemantics, false);
assert.equal(diagnostics.ngcOnlySubroutinePromoted, false);
assert.equal(diagnostics.executionEnabled, false);
assert.equal(diagnostics.promotionAllowed, false);
assert.equal(diagnostics.bulkPromotionAllowed, false);
console.log("python_remap_runtime_port_wasm=ok");

View File

@@ -0,0 +1,7 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "$0")/../../.." && pwd)"
cd "$ROOT_DIR/.."
node "$ROOT_DIR/tests/wasm/node/verify_python_remap_runtime_port_wasm.mjs"

View File

@@ -556,12 +556,12 @@ function verifyTrackedBaselineText(markdownText, nativeRecords, inventory, skipR
"tracked matrix Node executed drift",
);
assert.equal(
numberFromTrackedBaseline(markdownText, /`passed ([0-9]+)`/, "Node passed"),
numberFromTrackedBaseline(markdownText, /Current Node inventory: `executed [0-9]+`, `passed ([0-9]+)`/, "Node passed"),
inventory.passed,
"tracked matrix Node passed drift",
);
assert.equal(
numberFromTrackedBaseline(markdownText, /`skipped ([0-9]+)`/, "Node skipped"),
numberFromTrackedBaseline(markdownText, /Current Node inventory: `executed [0-9]+`, `passed [0-9]+`, `skipped ([0-9]+)`/, "Node skipped"),
inventory.skipped,
"tracked matrix Node skipped drift",
);
@@ -605,7 +605,6 @@ function verifyRequiredClassRepresentatives(records) {
"gmoccapy/macros/on_abort.ngc",
];
const requiredFullProcessBlocked = new Map([
["axis/db_demo/base.ngc", "L4-TOOL-DB"],
["axis/vismach/millturn/example.ngc", "L4-USER-M-PROCESS"],
]);
@@ -2937,13 +2936,13 @@ function linuxCncOwnerForBlockedKind(blocked) {
}
function blockedDependencySummaryRow(record, pathMatrixByPath) {
const blocked = pathMatrixByPath.get(record.path)?.blocked ?? "-";
const matrixBlocked = pathMatrixByPath.get(record.path)?.blocked ?? "-";
const sourceAvailable = sourceConfigPathExists(record.ini);
if (!sourceAvailable) {
return [
record.path,
record.ini,
blocked,
matrixBlocked,
posix.dirname(record.path),
"0",
"-",
@@ -2993,6 +2992,7 @@ function blockedDependencySummaryRow(record, pathMatrixByPath) {
const uiProcess = displayValues.some((value) => !/^axis$/i.test(value));
const haluiMdiProcess = iniValues(entries, "HALUI", "MDI_COMMAND").length > 0;
const dbProgram = iniValues(entries, "EMCIO", "DB_PROGRAM")[0] ?? "";
const blocked = matrixBlocked === "-" && dbProgram ? "L4-TOOL-DB" : matrixBlocked;
const toolDbEvidence = toolDbProtocolEvidence({ iniText, dbProgram });
const userMCodes = uniqueSorted(sourceExecutionTextsForBlocked(record).flatMap(userMCodesInExecutionText));
const userMProcessFiles = userMProcessFilesForCodes(record.ini, entries, userMCodes);
@@ -3195,31 +3195,6 @@ function verifyFullProcessBoundaryDesign(markdownText, rows) {
"`USER_M_COMMAND` event alone is not sufficient",
],
},
{
path: "axis/db_demo/base.ngc",
blocked: "L4-TOOL-DB",
tokens: [
"Tool Database Boundary",
"configs/sim/axis/db_demo/db_nonran.ini",
"configs/sim/axis/db_demo/db.py",
"src/emc/task/taskclass.cc",
"src/emc/tooldata/tooldata_db.cc",
"src/emc/tooldata/tooldata_common.cc",
"tool-db-process-boundary-summary.tsv",
"v2.1",
"`g`, `l`, `u`, and `p`",
"user_get_tool",
"user_put_tool",
"user_load_spindle_nonran_tc",
"user_unload_spindle_nonran_tc",
"T10..T19",
"/tmp/db_nonran_file",
"tno+100",
"promotion_allowed=0",
"does not replace `DB_PROGRAM`",
"fallback `.tbl`",
],
},
];
for (const required of requiredRows) {
@@ -3256,7 +3231,6 @@ function verifyFullProcessBoundaryDesign(markdownText, rows) {
"native-proof-alignment-summary.tsv",
"consumed by generated worklist and native proof-gate",
"`external_user_m_process` for `axis/vismach/millturn/example.ngc`",
"`tool_database_process` for `axis/db_demo/base.ngc`",
"Python runtime family rows follow as inventory-only targets",
]) {
assert.ok(
@@ -3268,6 +3242,19 @@ function verifyFullProcessBoundaryDesign(markdownText, rows) {
markdownText.includes("Do not implement HAL, task, HALUI, Tcl, Python, tool-database, or external"),
"full-process boundary design must preserve non-goal guard",
);
for (const token of [
"`axis/db_demo/base.ngc`",
"Tool Database Boundary",
"runtime_protocol_probe_passed",
"tool_db_process_proof=ok",
"does not replace `DB_PROGRAM`",
"fallback `.tbl`",
]) {
assert.ok(
markdownText.includes(token),
`full-process boundary design missing completed tool DB proof token ${token}`,
);
}
}
function fullProcessBoundarySummaryRow(row) {
@@ -5240,6 +5227,14 @@ function boundaryPhaseCompletionSummaryRows({
const blockedFamiliesUnpromotedOk = hardBlockedRows.every((row) => {
const tracked = trackedByPath.get(row.path);
const inventory = inventoryByPath.get(row.path);
if (
row.blocked === "L4-TOOL-DB" &&
row.path === "axis/db_demo/base.ngc" &&
tracked?.layer4Node === "INV" &&
inventory?.inventoryStatus === "PASS"
) {
return true;
}
return (
tracked &&
inventory &&
@@ -5554,15 +5549,15 @@ function boundaryPhaseCompletionSummaryRows({
const runtimeBoundaryPostNativePassGatesOk = (
runtimeBoundaryPostNativePassGateRows.length === 3 &&
runtimeBoundaryPostNativePassGateRows.every((row) =>
row.native_pass_ready === "0" &&
row.native_evidence_ready === "0" &&
row.node_gate_status === "blocked_until_native_pass_evidence" &&
["0", "1"].includes(row.native_pass_ready) &&
["0", "1"].includes(row.native_evidence_ready) &&
["blocked_until_native_pass_evidence", "pending_node_inventory_promotion_gate"].includes(row.node_gate_status) &&
row.browser_gate_status === "blocked_until_node_gate_complete" &&
row.manual_lock_update_required === "1" &&
row.promotion_lock_active === "1" &&
row.execution_enabled === "0" &&
row.promotion_allowed === "0" &&
row.gate_status === "blocked_before_native_pass",
["blocked_before_native_pass", "waiting_for_node_browser_manual_promotion"].includes(row.gate_status),
)
);
const runtimeBoundaryHostPreflightOk = (
@@ -5707,15 +5702,18 @@ function boundaryPhaseCompletionSummaryRows({
(row.host_action === "ready_for_manual_opt_in_native_probe" &&
row.skip_reason === "-" &&
row.missing_host_requirements === "-" &&
row.skip_evidence_status === "skip_contract_not_applicable_dispatch_allowed") ||
[
"skip_contract_not_applicable_dispatch_allowed",
"native_pass_evidence_observed_skip_contract_closed",
].includes(row.skip_evidence_status)) ||
(row.host_action === "skip_missing_host_requirements" &&
row.skip_reason === "missing_host_requirements" &&
row.missing_host_requirements !== "-" &&
row.current_probe_status === "skipped_missing_host_runtime" &&
row.skip_evidence_status === "skip_valid_until_host_requirements_available")
) &&
row.evidence_required_now === "0" &&
row.observed_evidence_ready === "0" &&
/^[0-9]+$/.test(row.evidence_required_now) &&
/^[0-9]+$/.test(row.observed_evidence_ready) &&
row.execution_enabled === "0" &&
row.promotion_allowed === "0",
)
@@ -5726,10 +5724,10 @@ function boundaryPhaseCompletionSummaryRows({
row.scope === "blocked_runtime_opt_in_probe_skip_evidence" &&
row.probe_count === "3" &&
/^[0-9]+$/.test(row.skip_count) &&
row.evidence_required_now_count === "0" &&
row.observed_evidence_ready_count === "0" &&
/^[0-9]+$/.test(row.evidence_required_now_count) &&
/^[0-9]+$/.test(row.observed_evidence_ready_count) &&
row.skip_evidence_statuses !== "-" &&
row.evidence_rollup_status === "no_native_pass_evidence_accepted_while_host_blocked" &&
["no_native_pass_evidence_accepted_while_host_blocked", "native_pass_evidence_present"].includes(row.evidence_rollup_status) &&
row.execution_enabled === "0" &&
row.promotion_allowed === "0",
)
@@ -5737,11 +5735,15 @@ function boundaryPhaseCompletionSummaryRows({
const runtimeBoundaryNativeEvidenceAcceptanceGateOk = (
runtimeBoundaryNativeEvidenceAcceptanceGateRows.length === 3 &&
runtimeBoundaryNativeEvidenceAcceptanceGateRows.every((row) =>
row.native_evidence_status === "pending_until_native_pass" &&
row.evidence_required_now === "0" &&
row.observed_evidence_ready === "0" &&
["blocked_until_host_requirements_available", "blocked_until_native_pass_evidence"].includes(row.native_evidence_gate) &&
row.evidence_acceptance_allowed === "0" &&
["pending_until_native_pass", "native_pass_evidence_observed"].includes(row.native_evidence_status) &&
/^[0-1]$/.test(row.evidence_required_now) &&
/^[0-1]$/.test(row.observed_evidence_ready) &&
[
"blocked_until_host_requirements_available",
"blocked_until_native_pass_evidence",
"native_pass_evidence_accepted",
].includes(row.native_evidence_gate) &&
["0", "1"].includes(row.evidence_acceptance_allowed) &&
row.promotion_ready === "0" &&
row.execution_enabled === "0" &&
row.promotion_allowed === "0",
@@ -5771,7 +5773,7 @@ function boundaryPhaseCompletionSummaryRows({
row.promotion_allowed === "0",
) &&
runtimeBoundaryNativeEvidenceAcceptanceGateRows.every((row) =>
row.evidence_acceptance_allowed === "0" &&
["0", "1"].includes(row.evidence_acceptance_allowed) &&
row.execution_enabled === "0" &&
row.promotion_allowed === "0",
) &&
@@ -7865,10 +7867,13 @@ function runtimeBoundaryOptInProbeSkipEvidenceContractRows({
return dispatchPlanRows.map((row) => {
const evidence = evidenceByClass.get(row.boundary_class);
const skipReason = row.dispatch_allowed === "1" ? "-" : "missing_host_requirements";
const skipEvidenceStatus = row.dispatch_allowed === "1"
? "skip_contract_not_applicable_dispatch_allowed"
: "skip_valid_until_host_requirements_available";
const nativeEvidenceObserved = evidence?.evidence_status === "native_pass_evidence_observed";
const skipReason = nativeEvidenceObserved || row.dispatch_allowed === "1" ? "-" : "missing_host_requirements";
const skipEvidenceStatus = nativeEvidenceObserved
? "native_pass_evidence_observed_skip_contract_closed"
: row.dispatch_allowed === "1"
? "skip_contract_not_applicable_dispatch_allowed"
: "skip_valid_until_host_requirements_available";
return [
row.boundary_class,
@@ -7951,18 +7956,29 @@ function verifyRuntimeBoundaryOptInProbeSkipEvidenceContractRows({
assert.equal(row.host_action, dispatch.host_action, `${row.boundary_class}: skip evidence host action drift`);
assert.equal(row.missing_host_requirements, dispatch.missing_host_requirements, `${row.boundary_class}: skip evidence missing requirements drift`);
assert.equal(row.current_probe_status, evidence.current_probe_status, `${row.boundary_class}: skip evidence probe status must match pass evidence contract`);
assert.equal(row.evidence_required_now, "0", `${row.boundary_class}: skipped probe must not require evidence now`);
assert.equal(row.evidence_required_now, evidence.evidence_required_now, `${row.boundary_class}: skip evidence required-now drift`);
assert.equal(row.observed_evidence_ready, "0", `${row.boundary_class}: skipped probe must not report evidence ready`);
assert.equal(row.observed_evidence_ready, evidence.observed_evidence_ready, `${row.boundary_class}: skip evidence readiness drift`);
assert.equal(row.native_evidence_status, "pending_until_native_pass", `${row.boundary_class}: skip evidence status drift`);
assert.equal(row.native_evidence_status, evidence.evidence_status, `${row.boundary_class}: skip evidence native status drift`);
if (dispatch.dispatch_allowed === "1") {
if (evidence.evidence_status === "native_pass_evidence_observed") {
assert.equal(row.evidence_required_now, "1", `${row.boundary_class}: native pass evidence should be required now`);
assert.equal(row.observed_evidence_ready, "1", `${row.boundary_class}: native pass evidence must be observed`);
assert.equal(row.native_evidence_status, "native_pass_evidence_observed", `${row.boundary_class}: native pass evidence status drift`);
assert.equal(row.host_action, "ready_for_manual_opt_in_native_probe", `${row.boundary_class}: native pass skip evidence action drift`);
assert.equal(row.skip_reason, "-", `${row.boundary_class}: native pass skip evidence reason drift`);
assert.equal(row.missing_host_requirements, "-", `${row.boundary_class}: native pass skip evidence missing requirements drift`);
assert.equal(row.skip_evidence_status, "native_pass_evidence_observed_skip_contract_closed", `${row.boundary_class}: native pass skip evidence status drift`);
} else if (dispatch.dispatch_allowed === "1") {
assert.equal(row.evidence_required_now, "0", `${row.boundary_class}: pending probe must not require evidence now`);
assert.equal(row.observed_evidence_ready, "0", `${row.boundary_class}: pending probe must not report evidence ready`);
assert.equal(row.native_evidence_status, "pending_until_native_pass", `${row.boundary_class}: pending evidence status drift`);
assert.equal(row.host_action, "ready_for_manual_opt_in_native_probe", `${row.boundary_class}: ready skip evidence action drift`);
assert.equal(row.skip_reason, "-", `${row.boundary_class}: ready dispatch must not have skip reason`);
assert.equal(row.missing_host_requirements, "-", `${row.boundary_class}: ready dispatch must not list missing host requirements`);
assert.equal(row.skip_evidence_status, "skip_contract_not_applicable_dispatch_allowed", `${row.boundary_class}: ready skip evidence status drift`);
} else {
assert.equal(row.evidence_required_now, "0", `${row.boundary_class}: skipped probe must not require evidence now`);
assert.equal(row.observed_evidence_ready, "0", `${row.boundary_class}: skipped probe must not report evidence ready`);
assert.equal(row.native_evidence_status, "pending_until_native_pass", `${row.boundary_class}: skip evidence status drift`);
assert.equal(row.host_action, "skip_missing_host_requirements", `${row.boundary_class}: blocked skip evidence action drift`);
assert.equal(row.skip_reason, "missing_host_requirements", `${row.boundary_class}: blocked skip evidence reason drift`);
assert.notEqual(row.missing_host_requirements, "-", `${row.boundary_class}: blocked skip evidence must list missing host requirements`);
@@ -8042,15 +8058,21 @@ function verifyRuntimeBoundaryOptInProbeSkipEvidenceRollupRows({
assert.equal(row.scope, "blocked_runtime_opt_in_probe_skip_evidence", "opt-in probe skip evidence rollup scope drift");
assert.equal(row.probe_count, String(skipEvidenceContractRows.length), "opt-in probe skip evidence rollup probe count drift");
assert.equal(row.skip_count, String(skippedRows.length), "opt-in probe skip evidence rollup skip count drift");
assert.equal(row.evidence_required_now_count, "0", "opt-in probe skip evidence rollup must not require evidence now");
assert.equal(row.observed_evidence_ready_count, "0", "opt-in probe skip evidence rollup must not report evidence ready");
assert.equal(row.evidence_required_now_count, String(skipEvidenceContractRows.filter((contract) => contract.evidence_required_now === "1").length), "opt-in probe skip evidence rollup required-now count drift");
assert.equal(row.observed_evidence_ready_count, String(skipEvidenceContractRows.filter((contract) => contract.observed_evidence_ready === "1").length), "opt-in probe skip evidence rollup observed evidence count drift");
assert.equal(row.skipped_families, listValue(uniqueSorted(skippedRows.map((contract) => contract.boundary_class))), "opt-in probe skip evidence rollup family drift");
assert.equal(row.skip_reasons, listValue(uniqueSorted(skippedRows.map((contract) => contract.skip_reason))), "opt-in probe skip evidence rollup reason drift");
assert.equal(row.missing_host_requirements, listValue(expectedMissingRequirements), "opt-in probe skip evidence rollup missing requirements drift");
assert.equal(row.current_probe_statuses, listValue(uniqueSorted(skipEvidenceContractRows.map((contract) => contract.current_probe_status))), "opt-in probe skip evidence rollup probe status drift");
assert.equal(row.native_evidence_statuses, "pending_until_native_pass", "opt-in probe skip evidence rollup native evidence status drift");
assert.equal(row.native_evidence_statuses, listValue(uniqueSorted(skipEvidenceContractRows.map((contract) => contract.native_evidence_status))), "opt-in probe skip evidence rollup native evidence status drift");
assert.equal(row.skip_evidence_statuses, listValue(uniqueSorted(skipEvidenceContractRows.map((contract) => contract.skip_evidence_status))), "opt-in probe skip evidence rollup skip evidence status drift");
assert.equal(row.evidence_rollup_status, "no_native_pass_evidence_accepted_while_host_blocked", "opt-in probe skip evidence rollup status drift");
assert.equal(
row.evidence_rollup_status,
skipEvidenceContractRows.some((contract) => contract.observed_evidence_ready === "1")
? "native_pass_evidence_present"
: "no_native_pass_evidence_accepted_while_host_blocked",
"opt-in probe skip evidence rollup status drift",
);
assert.equal(row.execution_enabled, "0", "opt-in probe skip evidence rollup must not enable execution");
assert.equal(row.promotion_allowed, "0", "opt-in probe skip evidence rollup must not allow promotion");
assert.ok(row.notes.includes("no_automatic_promotion"), "opt-in probe skip evidence rollup note drift");
@@ -8163,27 +8185,39 @@ function verifyRuntimeBoundaryNativeEvidenceAcceptanceGateRows({
assert.equal(row.blocked, skip.blocked, `${row.boundary_class}: native evidence gate blocked drift`);
assert.equal(row.runtime_probe, skip.runtime_probe, `${row.boundary_class}: native evidence gate runtime probe drift`);
assert.equal(row.current_probe_status, skip.current_probe_status, `${row.boundary_class}: native evidence gate skip status drift`);
assert.equal(row.native_evidence_status, "pending_until_native_pass", `${row.boundary_class}: native evidence gate evidence status drift`);
assert.equal(row.native_evidence_status, skip.native_evidence_status, `${row.boundary_class}: native evidence gate native evidence status drift`);
assert.equal(row.evidence_required_now, "0", `${row.boundary_class}: native evidence gate must not require evidence now`);
assert.equal(row.evidence_required_now, skip.evidence_required_now, `${row.boundary_class}: native evidence gate required-now drift`);
assert.equal(row.observed_evidence_ready, "0", `${row.boundary_class}: native evidence gate must not observe evidence ready`);
assert.equal(row.observed_evidence_ready, skip.observed_evidence_ready, `${row.boundary_class}: native evidence gate readiness drift`);
assert.equal(row.skip_evidence_status, skip.skip_evidence_status, `${row.boundary_class}: native evidence gate skip status drift`);
assert.equal(row.promotion_ready, "0", `${row.boundary_class}: native evidence gate must not be promotion-ready`);
assert.equal(row.promotion_ready, readiness.promotion_ready, `${row.boundary_class}: native evidence gate promotion readiness drift`);
assert.equal(row.node_gate_status, "blocked_until_native_pass_evidence", `${row.boundary_class}: native evidence gate Node status drift`);
assert.equal(row.node_gate_status, postNativeGate.node_gate_status, `${row.boundary_class}: native evidence gate post-native Node status drift`);
assert.equal(row.browser_gate_status, "blocked_until_node_gate_complete", `${row.boundary_class}: native evidence gate browser status drift`);
assert.equal(row.browser_gate_status, postNativeGate.browser_gate_status, `${row.boundary_class}: native evidence gate post-native browser status drift`);
if (skip.skip_reason === "missing_host_requirements") {
if (skip.native_evidence_status === "native_pass_evidence_observed") {
assert.equal(row.evidence_required_now, "1", `${row.boundary_class}: native evidence gate should require observed evidence`);
assert.equal(row.observed_evidence_ready, "1", `${row.boundary_class}: native evidence gate should observe evidence ready`);
assert.equal(row.node_gate_status, "pending_node_inventory_promotion_gate", `${row.boundary_class}: native evidence gate Node status drift`);
assert.equal(row.native_evidence_gate, "native_pass_evidence_accepted", `${row.boundary_class}: native evidence gate status drift`);
assert.equal(row.evidence_acceptance_allowed, "1", `${row.boundary_class}: native evidence gate acceptance drift`);
assert.equal(row.next_action, "run_opt_in_native_runtime_probe_and_collect_evidence", `${row.boundary_class}: native evidence gate next action drift`);
} else if (skip.skip_reason === "missing_host_requirements") {
assert.equal(row.native_evidence_status, "pending_until_native_pass", `${row.boundary_class}: native evidence gate evidence status drift`);
assert.equal(row.evidence_required_now, "0", `${row.boundary_class}: native evidence gate must not require evidence now`);
assert.equal(row.observed_evidence_ready, "0", `${row.boundary_class}: native evidence gate must not observe evidence ready`);
assert.equal(row.node_gate_status, "blocked_until_native_pass_evidence", `${row.boundary_class}: native evidence gate Node status drift`);
assert.equal(row.native_evidence_gate, "blocked_until_host_requirements_available", `${row.boundary_class}: native evidence gate status drift`);
assert.ok(row.next_action.includes(skip.missing_host_requirements), `${row.boundary_class}: native evidence gate next action must name missing requirements`);
assert.equal(row.evidence_acceptance_allowed, "0", `${row.boundary_class}: native evidence gate must not allow evidence acceptance`);
} else {
assert.equal(row.native_evidence_status, "pending_until_native_pass", `${row.boundary_class}: native evidence gate evidence status drift`);
assert.equal(row.evidence_required_now, "0", `${row.boundary_class}: native evidence gate must not require evidence now`);
assert.equal(row.observed_evidence_ready, "0", `${row.boundary_class}: native evidence gate must not observe evidence ready`);
assert.equal(row.node_gate_status, "blocked_until_native_pass_evidence", `${row.boundary_class}: native evidence gate Node status drift`);
assert.equal(row.native_evidence_gate, "blocked_until_native_pass_evidence", `${row.boundary_class}: native evidence gate status drift`);
assert.equal(row.next_action, "run_opt_in_native_runtime_probe_and_collect_evidence", `${row.boundary_class}: native evidence gate next action drift`);
assert.equal(row.evidence_acceptance_allowed, "0", `${row.boundary_class}: native evidence gate must not allow evidence acceptance`);
}
assert.equal(row.evidence_acceptance_allowed, "0", `${row.boundary_class}: native evidence gate must not allow evidence acceptance`);
assert.equal(row.execution_enabled, "0", `${row.boundary_class}: native evidence gate must not enable execution`);
assert.equal(row.promotion_allowed, "0", `${row.boundary_class}: native evidence gate must not allow promotion`);
assert.ok(row.notes.includes("no_automatic_promotion"), `${row.boundary_class}: native evidence gate note drift`);
@@ -8313,7 +8347,11 @@ function verifyBlockedRuntimeOptInGateConsistency({
assert.equal(dispatch.missing_host_requirements, execution.missing_requirements, `${boundaryClass}: dispatch missing requirements drift`);
assert.equal(skipEvidence.missing_host_requirements, execution.missing_requirements, `${boundaryClass}: skip-evidence missing requirements drift`);
assert.equal(blocker.missing_runtime_requirements, execution.missing_requirements, `${boundaryClass}: blocker missing requirements drift`);
assert.equal(evidenceGate.evidence_acceptance_allowed, "0", `${boundaryClass}: evidence acceptance must remain blocked`);
assert.equal(
evidenceGate.evidence_acceptance_allowed,
evidenceGate.native_evidence_gate === "native_pass_evidence_accepted" ? "1" : "0",
`${boundaryClass}: evidence acceptance flag drift`,
);
assert.equal(dispatch.dispatch_allowed, execution.runtime_ready, `${boundaryClass}: dispatch readiness drift`);
assert.equal(readiness.promotion_lock_active, "1", `${boundaryClass}: readiness must keep promotion lock active`);
assert.equal(postNative.promotion_lock_active, "1", `${boundaryClass}: post-native gate must keep promotion lock active`);
@@ -8324,7 +8362,11 @@ function verifyBlockedRuntimeOptInGateConsistency({
} else {
assert.equal(blocker.blocker_keys.includes("host_runtime_requirements_missing"), false, `${boundaryClass}: ready runtime must not keep host runtime blocker`);
}
assert.ok(evidenceGate.native_evidence_gate.includes("blocked"), `${boundaryClass}: evidence gate must be blocked`);
assert.ok(
evidenceGate.native_evidence_gate.includes("blocked") ||
evidenceGate.native_evidence_gate === "native_pass_evidence_accepted",
`${boundaryClass}: evidence gate status drift`,
);
}
}
@@ -8401,8 +8443,17 @@ function verifyBlockedRuntimeProbeExecutionConsistency({
assert.equal(execution.source_proof_ready, "1", `${execution.boundary_class}: source proof should remain ready before opt-in runtime`);
assert.ok(["0", "1"].includes(execution.runtime_ready), `${execution.boundary_class}: invalid runtime readiness`);
if (execution.runtime_ready === "1") {
assert.equal(execution.current_probe_status, "ready_disabled_by_default", `${execution.boundary_class}: ready probe must remain opt-in`);
assert.equal(execution.plan_status, "ready_to_run_opt_in_probe", `${execution.boundary_class}: execution plan must remain opt-in`);
assert.ok(
[execution.expected_pass_status, "ready_disabled_by_default"].includes(execution.current_probe_status),
`${execution.boundary_class}: ready probe status drift`,
);
assert.equal(
execution.plan_status,
execution.current_probe_status === execution.expected_pass_status
? "native_probe_passed_waiting_for_node_browser_promotion_proof"
: "ready_to_run_opt_in_probe",
`${execution.boundary_class}: execution plan opt-in/pass status drift`,
);
assert.equal(execution.missing_requirements, "-", `${execution.boundary_class}: ready execution plan must not list missing requirements`);
} else {
assert.equal(execution.current_probe_status, "skipped_missing_host_runtime", `${execution.boundary_class}: probe should remain skipped on missing host`);
@@ -8422,14 +8473,27 @@ function verifyBlockedRuntimeProbeExecutionConsistency({
assert.equal(skip.host_action, "skip_missing_host_requirements", `${execution.boundary_class}: skip evidence host action drift`);
assert.equal(skip.skip_reason, "missing_host_requirements", `${execution.boundary_class}: skip reason drift`);
}
assert.equal(pass.evidence_required_now, "0", `${execution.boundary_class}: pass evidence must not be required yet`);
assert.equal(skip.evidence_required_now, "0", `${execution.boundary_class}: skip evidence must not be required yet`);
assert.equal(pass.observed_evidence_ready, "0", `${execution.boundary_class}: pass evidence must not be ready yet`);
assert.equal(skip.observed_evidence_ready, "0", `${execution.boundary_class}: skip evidence must not be ready yet`);
assert.equal(pass.evidence_status, "pending_until_native_pass", `${execution.boundary_class}: pass evidence status drift`);
assert.equal(skip.native_evidence_status, "pending_until_native_pass", `${execution.boundary_class}: skip evidence native status drift`);
if (execution.current_probe_status === execution.expected_pass_status) {
assert.equal(pass.evidence_required_now, "1", `${execution.boundary_class}: pass evidence should be required after native pass`);
assert.equal(skip.evidence_required_now, "1", `${execution.boundary_class}: skip evidence should reflect native pass evidence`);
assert.equal(pass.observed_evidence_ready, "1", `${execution.boundary_class}: pass evidence must be ready after native pass`);
assert.equal(skip.observed_evidence_ready, "1", `${execution.boundary_class}: skip evidence must reflect ready native evidence`);
assert.equal(pass.evidence_status, "native_pass_evidence_observed", `${execution.boundary_class}: pass evidence status drift`);
assert.equal(skip.native_evidence_status, "native_pass_evidence_observed", `${execution.boundary_class}: skip evidence native status drift`);
} else {
assert.equal(pass.evidence_required_now, "0", `${execution.boundary_class}: pass evidence must not be required yet`);
assert.equal(skip.evidence_required_now, "0", `${execution.boundary_class}: skip evidence must not be required yet`);
assert.equal(pass.observed_evidence_ready, "0", `${execution.boundary_class}: pass evidence must not be ready yet`);
assert.equal(skip.observed_evidence_ready, "0", `${execution.boundary_class}: skip evidence must not be ready yet`);
assert.equal(pass.evidence_status, "pending_until_native_pass", `${execution.boundary_class}: pass evidence status drift`);
assert.equal(skip.native_evidence_status, "pending_until_native_pass", `${execution.boundary_class}: skip evidence native status drift`);
}
assert.ok(
["skip_valid_until_host_requirements_available", "skip_contract_not_applicable_dispatch_allowed"].includes(skip.skip_evidence_status),
[
"skip_valid_until_host_requirements_available",
"skip_contract_not_applicable_dispatch_allowed",
"native_pass_evidence_observed_skip_contract_closed",
].includes(skip.skip_evidence_status),
`${execution.boundary_class}: skip evidence contract status drift`,
);
@@ -8466,8 +8530,8 @@ function verifyBlockedRuntimeRollupConsistency({
assert.equal(host.host_ready_family_count, dispatch.dispatch_allowed_count, "blocked runtime rollup ready/dispatch-allowed count drift");
assert.equal(host.host_blocked_family_count, dispatch.dispatch_blocked_count, "blocked runtime rollup blocked/dispatch-blocked count drift");
assert.equal(dispatch.dispatch_blocked_count, skipEvidence.skip_count, "blocked runtime rollup dispatch-blocked/skip count drift");
assert.equal(skipEvidence.evidence_required_now_count, "0", "blocked runtime rollup must not require evidence on host-blocked probes");
assert.equal(skipEvidence.observed_evidence_ready_count, "0", "blocked runtime rollup must not accept observed evidence on host-blocked probes");
assert.ok(/^[0-9]+$/.test(skipEvidence.evidence_required_now_count), "blocked runtime rollup evidence required count drift");
assert.ok(/^[0-9]+$/.test(skipEvidence.observed_evidence_ready_count), "blocked runtime rollup evidence ready count drift");
assert.equal(host.blocked_families, dispatch.blocked_families, "blocked runtime rollup blocked family drift");
assert.equal(dispatch.blocked_families, skipEvidence.skipped_families, "blocked runtime rollup skipped family drift");
assert.equal(host.missing_host_requirements, dispatch.missing_host_requirements, "blocked runtime rollup host/dispatch missing requirement drift");
@@ -8490,9 +8554,12 @@ function verifyBlockedRuntimeRollupConsistency({
].includes(dispatch.dispatch_status),
"blocked runtime rollup dispatch status drift",
);
assert.equal(skipEvidence.evidence_rollup_status, "no_native_pass_evidence_accepted_while_host_blocked", "blocked runtime rollup evidence status drift");
assert.ok(
["no_native_pass_evidence_accepted_while_host_blocked", "native_pass_evidence_present"].includes(skipEvidence.evidence_rollup_status),
"blocked runtime rollup evidence status drift",
);
assert.notEqual(skipEvidence.current_probe_statuses, "-", "blocked runtime rollup probe status drift");
assert.equal(skipEvidence.native_evidence_statuses, "pending_until_native_pass", "blocked runtime rollup native evidence status drift");
assert.notEqual(skipEvidence.native_evidence_statuses, "-", "blocked runtime rollup native evidence status drift");
assert.notEqual(skipEvidence.skip_evidence_statuses, "-", "blocked runtime rollup skip evidence status drift");
for (const [label, row] of [
@@ -8699,27 +8766,53 @@ function verifyBlockedRuntimePromotionGateConsistency({
assert.equal(evidenceGate.node_gate_status, postNative.node_gate_status, `${boundaryClass}: evidence gate Node status drift`);
assert.equal(evidenceGate.browser_gate_status, postNative.browser_gate_status, `${boundaryClass}: evidence gate browser status drift`);
assert.equal(readiness.native_pass_ready, "0", `${boundaryClass}: current host must not report native pass ready`);
assert.equal(readiness.native_evidence_ready, "0", `${boundaryClass}: current host must not report native evidence ready`);
if (readiness.current_probe_status === readiness.expected_pass_status) {
assert.equal(readiness.native_pass_ready, "1", `${boundaryClass}: native pass flag drift`);
assert.equal(readiness.native_evidence_ready, "1", `${boundaryClass}: native evidence flag drift`);
} else {
assert.equal(readiness.native_pass_ready, "0", `${boundaryClass}: current host must not report native pass ready`);
assert.equal(readiness.native_evidence_ready, "0", `${boundaryClass}: current host must not report native evidence ready`);
}
assert.equal(readiness.node_inventory_gate_complete, "0", `${boundaryClass}: Node promotion gate must remain incomplete`);
assert.equal(readiness.browser_smoke_gate_complete, "0", `${boundaryClass}: browser promotion gate must remain incomplete`);
assert.equal(readiness.promotion_lock_active, "1", `${boundaryClass}: promotion lock must remain active`);
assert.equal(readiness.manual_lock_update_required, "1", `${boundaryClass}: manual lock update must remain required`);
assert.equal(readiness.promotion_ready, "0", `${boundaryClass}: promotion must remain not ready`);
assert.ok(blocker.blocker_keys.includes("native_runtime_probe_not_passed"), `${boundaryClass}: native pass blocker missing`);
assert.ok(blocker.blocker_keys.includes("native_pass_evidence_not_ready"), `${boundaryClass}: native evidence blocker missing`);
if (readiness.native_pass_ready !== "1") {
assert.ok(blocker.blocker_keys.includes("native_runtime_probe_not_passed"), `${boundaryClass}: native pass blocker missing`);
}
if (readiness.native_evidence_ready !== "1") {
assert.ok(blocker.blocker_keys.includes("native_pass_evidence_not_ready"), `${boundaryClass}: native evidence blocker missing`);
}
assert.ok(blocker.blocker_keys.includes("node_inventory_gate_not_complete"), `${boundaryClass}: Node gate blocker missing`);
assert.ok(blocker.blocker_keys.includes("browser_smoke_gate_not_complete"), `${boundaryClass}: browser gate blocker missing`);
assert.ok(blocker.blocker_keys.includes("promotion_lock_active"), `${boundaryClass}: promotion lock blocker missing`);
assert.ok(blocker.blocker_keys.includes("manual_lock_update_required"), `${boundaryClass}: manual lock blocker missing`);
assert.equal(postNative.node_gate_status, "blocked_until_native_pass_evidence", `${boundaryClass}: post-native Node gate must wait for native evidence`);
assert.equal(postNative.browser_gate_status, "blocked_until_node_gate_complete", `${boundaryClass}: post-native browser gate must wait for Node gate`);
assert.equal(postNative.gate_status, "blocked_before_native_pass", `${boundaryClass}: post-native gate status drift`);
assert.ok(
["blocked_until_host_requirements_available", "blocked_until_native_pass_evidence"].includes(evidenceGate.native_evidence_gate),
`${boundaryClass}: native evidence gate must remain blocked`,
assert.equal(
postNative.node_gate_status,
readiness.native_evidence_ready === "1"
? "pending_node_inventory_promotion_gate"
: "blocked_until_native_pass_evidence",
`${boundaryClass}: post-native Node gate status drift`,
);
assert.equal(evidenceGate.evidence_acceptance_allowed, "0", `${boundaryClass}: native evidence acceptance must remain blocked`);
assert.equal(postNative.browser_gate_status, "blocked_until_node_gate_complete", `${boundaryClass}: post-native browser gate must wait for Node gate`);
assert.equal(
postNative.gate_status,
readiness.native_evidence_ready === "1"
? "waiting_for_node_browser_manual_promotion"
: "blocked_before_native_pass",
`${boundaryClass}: post-native gate status drift`,
);
if (readiness.native_evidence_ready === "1") {
assert.equal(evidenceGate.native_evidence_gate, "native_pass_evidence_accepted", `${boundaryClass}: native evidence gate acceptance drift`);
assert.equal(evidenceGate.evidence_acceptance_allowed, "1", `${boundaryClass}: native evidence acceptance flag drift`);
} else {
assert.ok(
["blocked_until_host_requirements_available", "blocked_until_native_pass_evidence"].includes(evidenceGate.native_evidence_gate),
`${boundaryClass}: native evidence gate must remain blocked`,
);
assert.equal(evidenceGate.evidence_acceptance_allowed, "0", `${boundaryClass}: native evidence acceptance must remain blocked`);
}
for (const row of [readiness, blocker, postNative, evidenceGate, passEvidence, lock]) {
assert.equal(row.execution_enabled, "0", `${boundaryClass}: promotion consistency row must not enable execution`);
@@ -11583,6 +11676,21 @@ function executionModeFor(record) {
function verifyInventoryCase(record, output, executionMode) {
if (record.status === "PASS") {
if (record.path === "axis/db_demo/base.ngc") {
verifyExpectedOutput(
`inventory_${record.path}`,
output,
[
"file_open=0",
"file_saw_error=0",
"canon_event=MESSAGE: fini",
"canon_event=FINISH",
"absent=file_error_text=",
].join("\n"),
);
return;
}
if (executionMode === "fiveAxisRemap") {
verifyExpectedOutput(
`inventory_${record.path}`,
@@ -11773,7 +11881,7 @@ const iniBoundarySummaryRecords = verifyIniBoundarySummaryRows(
const blockedDependencyRecords = nativeRecords.filter((record) =>
["L4-PYTHON-REMAP", "L4-TOOL-DB", "L4-USER-M-PROCESS"].includes(
pathMatrixByPath.get(record.path)?.blocked ?? "-",
),
) || record.path === "axis/db_demo/base.ngc",
);
const blockedDependencySummaryRows = blockedDependencyRecords.map((record) =>
blockedDependencySummaryRow(record, pathMatrixByPath),
@@ -12287,7 +12395,7 @@ function verifyEvidenceExpansionCandidateRows(rows, summaryRows, boundaryRows, t
expectedPaths,
"evidence expansion candidates must cover every non-hard-block PASS main candidate outside evidence-ready",
);
assert.equal(parsedRows.length, 13, "current evidence expansion candidate count drift");
assert.equal(parsedRows.length, 14, "current evidence expansion candidate count drift");
for (const row of parsedRows) {
const boundary = boundaryByPath.get(row.path);
assert.ok(boundary, `${row.path}: evidence expansion candidate lacks boundary evidence`);
@@ -12365,7 +12473,7 @@ function verifyPromotionCandidateRows(rows, summaryRows, boundaryRows) {
0,
"current baseline has no direct skipped-main inventory promotion candidate",
);
for (const lockedKind of ["L4-PYTHON-REMAP", "L4-TOOL-DB", "L4-USER-M-PROCESS", "UPSTREAM-DEMO"]) {
for (const lockedKind of ["L4-PYTHON-REMAP", "L4-USER-M-PROCESS", "UPSTREAM-DEMO"]) {
const lockedRows = parsedInventoryReady.filter((row) => row.skip_kind === lockedKind);
assert.ok(lockedRows.length > 0, `${lockedKind}: promotion-candidates missing locked inventory rows`);
assert.equal(
@@ -12394,7 +12502,7 @@ function verifyPromotionCandidateRows(rows, summaryRows, boundaryRows) {
assert.equal(row.blocked_kind, row.skip_kind, `${row.path}: skipped inventory blocked kind drift`);
assert.equal(row.virtual_hal_evidence_ready, "0", `${row.path}: skipped inventory row must not claim virtual HAL evidence ready`);
assert.ok(
["L4-PYTHON-REMAP", "L4-TOOL-DB", "L4-USER-M-PROCESS", "UPSTREAM-DEMO"].includes(row.skip_kind),
["L4-PYTHON-REMAP", "L4-USER-M-PROCESS", "UPSTREAM-DEMO"].includes(row.skip_kind),
`${row.path}: direct promotion candidate must remain hard-blocked or upstream-demo`,
);
const boundary = boundaryByPath.get(row.path);

View File

@@ -6,6 +6,8 @@ NATIVE_SUMMARY="$ROOT_DIR/build/native/sim-configs/summary.tsv"
NATIVE_CLASS_SUMMARY="$ROOT_DIR/build/native/sim-configs/class-summary.tsv"
NATIVE_PATH_MATRIX="$ROOT_DIR/build/native/sim-configs/path-matrix.tsv"
NATIVE_SOURCE_PROOF_SUMMARY="$ROOT_DIR/build/native/native-source-proof-summary.tsv"
NATIVE_RUNTIME_PROBE_SUMMARY="$ROOT_DIR/build/native/native-runtime-probe-summary.tsv"
PYTHON_REMAP_LIFECYCLE_STDOUT="$ROOT_DIR/build/native/python-remap-runtime/python_lifecycle.stdout.log"
NATIVE_BUILD_DIR="$ROOT_DIR/build/native/sim-configs"
NATIVE_SOURCE_PROOF_INPUTS=(
"$ROOT_DIR/tools/build_native_probes.sh"
@@ -27,11 +29,38 @@ native_source_proof_refresh_required() {
return 1
}
python_remap_lifecycle_pass_observed() {
[[ -f "$PYTHON_REMAP_LIFECYCLE_STDOUT" ]] || return 1
grep -Fq "python_remap_lifecycle_interpreter_sentinel_ok=1" "$PYTHON_REMAP_LIFECYCLE_STDOUT" &&
grep -Fq "python_remap_lifecycle_toplevel_imported=1" "$PYTHON_REMAP_LIFECYCLE_STDOUT" &&
grep -Fq "python_remap_lifecycle_remap_imported=1" "$PYTHON_REMAP_LIFECYCLE_STDOUT" &&
grep -Fq "python_remap_lifecycle_callable_lookup_ok=1" "$PYTHON_REMAP_LIFECYCLE_STDOUT" &&
grep -Fq "python_remap_lifecycle_generator_first_yield=2" "$PYTHON_REMAP_LIFECYCLE_STDOUT" &&
grep -Fq "python_remap_runtime_lifecycle_probe_ok=1" "$PYTHON_REMAP_LIFECYCLE_STDOUT"
}
native_runtime_probe_refresh_required() {
python_remap_lifecycle_pass_observed || return 1
if [[ ! -f "$NATIVE_RUNTIME_PROBE_SUMMARY" ]]; then
return 0
fi
if [[ "$PYTHON_REMAP_LIFECYCLE_STDOUT" -nt "$NATIVE_RUNTIME_PROBE_SUMMARY" ]]; then
return 0
fi
! grep -Fq $'L4-PYTHON-REMAP\tpython_runtime\taxis/remap/stop-lookahead/nc_files\tlinuxcnc_python_remap_runtime_probe\tlinuxcnc_python_runtime_lifecycle_probe_required\tENABLE_PYTHON_REMAP_RUNTIME_PROBE=1\t1\t1\truntime_lifecycle_probe_passed' "$NATIVE_RUNTIME_PROBE_SUMMARY"
}
if [[ ! -f "$NATIVE_SUMMARY" || ! -f "$NATIVE_CLASS_SUMMARY" || ! -f "$NATIVE_PATH_MATRIX" ]]; then
"$ROOT_DIR/tests/native/verify_sim_configs.sh"
fi
if native_source_proof_refresh_required; then
"$ROOT_DIR/tools/build_native_probes.sh"
if python_remap_lifecycle_pass_observed; then
ENABLE_PYTHON_REMAP_RUNTIME_PROBE=1 "$ROOT_DIR/tools/build_native_probes.sh"
else
"$ROOT_DIR/tools/build_native_probes.sh"
fi
elif native_runtime_probe_refresh_required; then
ENABLE_PYTHON_REMAP_RUNTIME_PROBE=1 "$ROOT_DIR/tools/build_native_probes.sh"
fi
mkdir -p "$NATIVE_BUILD_DIR"