先提交到云仓库
结论:已提交当前 Python-remap proof 链路、runtime/browser/UI/docs 相关变更;保持 L4-PYTHON-REMAP inventory baseline 不直接批量 PASS。
This commit is contained in:
@@ -777,7 +777,7 @@
|
||||
);
|
||||
assertEqual(
|
||||
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "hard-block-runtime-lock")?.value,
|
||||
"locked (3 families)",
|
||||
"locked (2 families)",
|
||||
"workflow overview release artifact URL workflow hard-block lock",
|
||||
);
|
||||
assertEqual(
|
||||
@@ -787,12 +787,12 @@
|
||||
);
|
||||
assertEqual(
|
||||
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "hard-block-runtime-locked-rows")?.value,
|
||||
"19",
|
||||
"18",
|
||||
"workflow overview release artifact URL workflow locked hard-block rows",
|
||||
);
|
||||
assertEqual(
|
||||
releaseArtifactUrlWorkflowSummary.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",
|
||||
"workflow overview release artifact URL workflow locked hard-block preview",
|
||||
);
|
||||
assertEqual(
|
||||
@@ -802,22 +802,22 @@
|
||||
);
|
||||
assertEqual(
|
||||
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "hard-block-runtime-family-count")?.value,
|
||||
"3",
|
||||
"2",
|
||||
"workflow overview release artifact URL workflow hard-block family count",
|
||||
);
|
||||
assertEqual(
|
||||
releaseArtifactUrlWorkflowSummary.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",
|
||||
"workflow overview release artifact URL workflow hard-block family summary",
|
||||
);
|
||||
assertEqual(
|
||||
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "hard-block-runtime-detail-row-count")?.value,
|
||||
"19",
|
||||
"18",
|
||||
"workflow overview release artifact URL workflow hard-block detail count",
|
||||
);
|
||||
assertEqual(
|
||||
releaseArtifactUrlWorkflowSummary.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",
|
||||
"L4-PYTHON-REMAP:axis/laser/raster_test.ngc; reason=design_linuxcnc_python_runtime_boundary; next=python_runtime_owner_and_fixture; promotion_allowed=0",
|
||||
"workflow overview release artifact URL workflow hard-block detail preview",
|
||||
);
|
||||
assertEqual(
|
||||
|
||||
@@ -98,6 +98,7 @@
|
||||
"next-boundary-recommendations.tsv",
|
||||
"next-boundary-worklist.tsv",
|
||||
"promotion-candidates.tsv",
|
||||
"python-remap-bulk-promotion-plan.tsv",
|
||||
"python-remap-boundary-summary.tsv",
|
||||
"python-remap-family-summary.tsv",
|
||||
"python-remap-native-runtime-alignment.tsv",
|
||||
@@ -105,6 +106,7 @@
|
||||
"python-remap-native-runtime-probe-gate.tsv",
|
||||
"python-remap-native-runtime-readiness.tsv",
|
||||
"python-remap-native-runtime-state-plan.tsv",
|
||||
"python-remap-row-runtime-proof.tsv",
|
||||
"python-remap-runtime-contract.tsv",
|
||||
"python-remap-runtime-gates.tsv",
|
||||
"runtime-boundary-contract-summary.tsv",
|
||||
@@ -151,7 +153,7 @@
|
||||
"build/native/source-probes.tsv",
|
||||
];
|
||||
|
||||
if (wasmArtifactNames.length !== 55 || new Set(wasmArtifactNames).size !== wasmArtifactNames.length) {
|
||||
if (wasmArtifactNames.length !== 57 || new Set(wasmArtifactNames).size !== wasmArtifactNames.length) {
|
||||
throw new Error("browser_generated_artifact_documentation_coverage: WASM artifact list drift");
|
||||
}
|
||||
if (nativeArtifactTokens.length !== 8 || new Set(nativeArtifactTokens).size !== nativeArtifactTokens.length) {
|
||||
@@ -1391,11 +1393,11 @@
|
||||
}
|
||||
if (
|
||||
row.required_native_proof !== "linuxcnc_python_runtime_lifecycle_probe_required" ||
|
||||
row.proof_status !== "pending" ||
|
||||
!["pending", "native_lifecycle_probe_passed"].includes(row.proof_status) ||
|
||||
row.execution_enabled !== "0" ||
|
||||
row.promotion_allowed !== "0"
|
||||
) {
|
||||
throw new Error(`${row.family}: Python runtime probe gate must remain pending and disabled`);
|
||||
throw new Error(`${row.family}: Python runtime probe gate proof status or disabled guards drift`);
|
||||
}
|
||||
if (!row.notes.includes("python3_alone_not_sufficient")) {
|
||||
throw new Error(`${row.family}: Python runtime probe gate must record python3-only guard`);
|
||||
@@ -1403,7 +1405,7 @@
|
||||
if (row.runtime_ready === "1") {
|
||||
if (
|
||||
row.missing_requirements !== "-" ||
|
||||
row.gate_status !== "ready_to_implement_lifecycle_probe"
|
||||
!["ready_to_implement_lifecycle_probe", "runtime_lifecycle_probe_passed"].includes(row.gate_status)
|
||||
) {
|
||||
throw new Error(`${row.family}: ready Python runtime probe gate drift`);
|
||||
}
|
||||
@@ -2608,9 +2610,12 @@
|
||||
) {
|
||||
throw new Error(`${row.boundary_class}: promotion readiness metadata drift`);
|
||||
}
|
||||
const pythonRuntimeProofChainReady = row.boundary_class === "L4-PYTHON-REMAP" &&
|
||||
row.native_pass_ready === "1" &&
|
||||
row.native_evidence_ready === "1";
|
||||
if (
|
||||
row.node_inventory_gate_complete !== "0" ||
|
||||
row.browser_smoke_gate_complete !== "0" ||
|
||||
row.node_inventory_gate_complete !== (pythonRuntimeProofChainReady ? "1" : "0") ||
|
||||
row.browser_smoke_gate_complete !== (pythonRuntimeProofChainReady ? "1" : "0") ||
|
||||
row.promotion_lock_active !== "1" ||
|
||||
row.manual_lock_update_required !== "1" ||
|
||||
row.promotion_ready !== "0" ||
|
||||
@@ -2623,6 +2628,9 @@
|
||||
if (row.native_pass_ready !== "1" || row.blocking_reason === "awaiting_native_runtime_probe_pass") {
|
||||
throw new Error(`${row.boundary_class}: passed promotion readiness state drift`);
|
||||
}
|
||||
if (pythonRuntimeProofChainReady && row.blocking_reason !== "promotion_lock_active_manual_review_required") {
|
||||
throw new Error(`${row.boundary_class}: completed promotion proof chain must wait on manual lock review`);
|
||||
}
|
||||
} else if (
|
||||
row.native_pass_ready !== "0" ||
|
||||
row.blocking_reason !== "awaiting_native_runtime_probe_pass"
|
||||
@@ -2696,12 +2704,22 @@
|
||||
if (!/^[1-9][0-9]*$/.test(row.blocker_count)) {
|
||||
throw new Error(`${row.boundary_class}: invalid promotion blocker count`);
|
||||
}
|
||||
for (const blocker of [
|
||||
"node_inventory_gate_not_complete",
|
||||
"browser_smoke_gate_not_complete",
|
||||
const requiredBlockers = [
|
||||
"promotion_lock_active",
|
||||
"manual_lock_update_required",
|
||||
]) {
|
||||
];
|
||||
if (row.boundary_class !== "L4-PYTHON-REMAP") {
|
||||
requiredBlockers.push("node_inventory_gate_not_complete");
|
||||
requiredBlockers.push("browser_smoke_gate_not_complete");
|
||||
} else {
|
||||
if (row.blocker_keys.includes("node_inventory_gate_not_complete")) {
|
||||
throw new Error(`${row.boundary_class}: completed Node gate must not remain a blocker`);
|
||||
}
|
||||
if (row.blocker_keys.includes("browser_smoke_gate_not_complete")) {
|
||||
throw new Error(`${row.boundary_class}: completed browser gate must not remain a blocker`);
|
||||
}
|
||||
}
|
||||
for (const blocker of requiredBlockers) {
|
||||
if (!row.blocker_keys.includes(blocker)) {
|
||||
throw new Error(`${row.boundary_class}: promotion blocker missing ${blocker}`);
|
||||
}
|
||||
@@ -2788,11 +2806,17 @@
|
||||
throw new Error(`${row.boundary_class}: post-native-pass gate must remain locked`);
|
||||
}
|
||||
if (row.native_evidence_ready === "1") {
|
||||
const nodeGateComplete = row.node_gate_status === "node_inventory_promotion_gate_complete";
|
||||
const browserGateComplete = row.browser_gate_status === "browser_smoke_promotion_gate_complete";
|
||||
if (
|
||||
row.native_pass_ready !== "1" ||
|
||||
row.node_gate_status !== "pending_node_inventory_promotion_gate" ||
|
||||
row.browser_gate_status !== "blocked_until_node_gate_complete" ||
|
||||
row.gate_status !== "waiting_for_node_browser_manual_promotion"
|
||||
!["pending_node_inventory_promotion_gate", "node_inventory_promotion_gate_complete"].includes(row.node_gate_status) ||
|
||||
!["blocked_until_node_gate_complete", "browser_smoke_promotion_gate_complete"].includes(row.browser_gate_status) ||
|
||||
row.gate_status !== (
|
||||
nodeGateComplete && browserGateComplete
|
||||
? "waiting_for_manual_promotion_lock_review"
|
||||
: "waiting_for_node_browser_manual_promotion"
|
||||
)
|
||||
) {
|
||||
throw new Error(`${row.boundary_class}: post-native-pass ready state drift`);
|
||||
}
|
||||
@@ -3725,22 +3749,39 @@
|
||||
if (row.target !== expectedRow.target || row.runtime_probe !== expectedRow.runtimeProbe) {
|
||||
throw new Error(`${row.boundary_class}: native evidence acceptance gate metadata drift`);
|
||||
}
|
||||
if (
|
||||
row.current_probe_status !== "skipped_missing_host_runtime" ||
|
||||
row.native_evidence_status !== "pending_until_native_pass" ||
|
||||
row.evidence_required_now !== "0" ||
|
||||
row.observed_evidence_ready !== "0" ||
|
||||
row.skip_evidence_status !== "skip_valid_until_host_requirements_available" ||
|
||||
row.promotion_ready !== "0" ||
|
||||
row.node_gate_status !== "blocked_until_native_pass_evidence" ||
|
||||
row.browser_gate_status !== "blocked_until_node_gate_complete" ||
|
||||
row.native_evidence_gate !== "blocked_until_host_requirements_available" ||
|
||||
row.evidence_acceptance_allowed !== "0"
|
||||
) {
|
||||
throw new Error(`${row.boundary_class}: native evidence acceptance gate status drift`);
|
||||
}
|
||||
if (!row.next_action.includes(expectedRow.missing)) {
|
||||
throw new Error(`${row.boundary_class}: native evidence acceptance gate next action must name missing requirements`);
|
||||
if (row.boundary_class === "L4-PYTHON-REMAP") {
|
||||
if (
|
||||
row.current_probe_status !== "runtime_lifecycle_probe_passed" ||
|
||||
row.native_evidence_status !== "native_pass_evidence_observed" ||
|
||||
row.evidence_required_now !== "1" ||
|
||||
row.observed_evidence_ready !== "1" ||
|
||||
row.skip_evidence_status !== "native_pass_evidence_observed_skip_contract_closed" ||
|
||||
row.promotion_ready !== "0" ||
|
||||
row.node_gate_status !== "node_inventory_promotion_gate_complete" ||
|
||||
row.browser_gate_status !== "browser_smoke_promotion_gate_complete" ||
|
||||
row.native_evidence_gate !== "native_pass_evidence_accepted" ||
|
||||
row.evidence_acceptance_allowed !== "1"
|
||||
) {
|
||||
throw new Error(`${row.boundary_class}: native evidence acceptance gate status drift`);
|
||||
}
|
||||
} else {
|
||||
if (
|
||||
row.current_probe_status !== "skipped_missing_host_runtime" ||
|
||||
row.native_evidence_status !== "pending_until_native_pass" ||
|
||||
row.evidence_required_now !== "0" ||
|
||||
row.observed_evidence_ready !== "0" ||
|
||||
row.skip_evidence_status !== "skip_valid_until_host_requirements_available" ||
|
||||
row.promotion_ready !== "0" ||
|
||||
row.node_gate_status !== "blocked_until_native_pass_evidence" ||
|
||||
row.browser_gate_status !== "blocked_until_node_gate_complete" ||
|
||||
row.native_evidence_gate !== "blocked_until_host_requirements_available" ||
|
||||
row.evidence_acceptance_allowed !== "0"
|
||||
) {
|
||||
throw new Error(`${row.boundary_class}: native evidence acceptance gate status drift`);
|
||||
}
|
||||
if (!row.next_action.includes(expectedRow.missing)) {
|
||||
throw new Error(`${row.boundary_class}: native evidence acceptance gate next action must name missing requirements`);
|
||||
}
|
||||
}
|
||||
if (row.execution_enabled !== "0" || row.promotion_allowed !== "0") {
|
||||
throw new Error(`${row.boundary_class}: native evidence acceptance gate must not enable execution or promotion`);
|
||||
@@ -4033,34 +4074,50 @@
|
||||
throw new Error(`${boundaryClass}: native evidence acceptance parity drift`);
|
||||
}
|
||||
|
||||
const pythonProofChainReady = boundaryClass === "L4-PYTHON-REMAP";
|
||||
if (
|
||||
readiness.native_pass_ready !== "0" ||
|
||||
readiness.native_evidence_ready !== "0" ||
|
||||
readiness.node_inventory_gate_complete !== "0" ||
|
||||
readiness.browser_smoke_gate_complete !== "0" ||
|
||||
readiness.native_pass_ready !== (pythonProofChainReady ? "1" : "0") ||
|
||||
readiness.native_evidence_ready !== (pythonProofChainReady ? "1" : "0") ||
|
||||
readiness.node_inventory_gate_complete !== (pythonProofChainReady ? "1" : "0") ||
|
||||
readiness.browser_smoke_gate_complete !== (pythonProofChainReady ? "1" : "0") ||
|
||||
readiness.promotion_lock_active !== "1" ||
|
||||
readiness.manual_lock_update_required !== "1" ||
|
||||
readiness.promotion_ready !== "0" ||
|
||||
postNative.node_gate_status !== "blocked_until_native_pass_evidence" ||
|
||||
postNative.browser_gate_status !== "blocked_until_node_gate_complete" ||
|
||||
postNative.gate_status !== "blocked_before_native_pass" ||
|
||||
evidenceGate.native_evidence_gate !== "blocked_until_host_requirements_available" ||
|
||||
evidenceGate.evidence_acceptance_allowed !== "0"
|
||||
postNative.node_gate_status !== (pythonProofChainReady ? "node_inventory_promotion_gate_complete" : "blocked_until_native_pass_evidence") ||
|
||||
postNative.browser_gate_status !== (pythonProofChainReady ? "browser_smoke_promotion_gate_complete" : "blocked_until_node_gate_complete") ||
|
||||
postNative.gate_status !== (pythonProofChainReady ? "waiting_for_manual_promotion_lock_review" : "blocked_before_native_pass") ||
|
||||
evidenceGate.native_evidence_gate !== (pythonProofChainReady ? "native_pass_evidence_accepted" : "blocked_until_host_requirements_available") ||
|
||||
evidenceGate.evidence_acceptance_allowed !== (pythonProofChainReady ? "1" : "0")
|
||||
) {
|
||||
throw new Error(`${boundaryClass}: promotion gate must remain host-blocked`);
|
||||
throw new Error(`${boundaryClass}: promotion gate lock state drift`);
|
||||
}
|
||||
for (const blockerKey of [
|
||||
"native_runtime_probe_not_passed",
|
||||
"native_pass_evidence_not_ready",
|
||||
"node_inventory_gate_not_complete",
|
||||
"browser_smoke_gate_not_complete",
|
||||
const requiredBlockers = [
|
||||
"promotion_lock_active",
|
||||
"manual_lock_update_required",
|
||||
]) {
|
||||
];
|
||||
if (!pythonProofChainReady) {
|
||||
requiredBlockers.push("native_runtime_probe_not_passed");
|
||||
requiredBlockers.push("native_pass_evidence_not_ready");
|
||||
requiredBlockers.push("node_inventory_gate_not_complete");
|
||||
requiredBlockers.push("browser_smoke_gate_not_complete");
|
||||
}
|
||||
for (const blockerKey of requiredBlockers) {
|
||||
if (!blocker.blocker_keys.includes(blockerKey)) {
|
||||
throw new Error(`${boundaryClass}: promotion blocker missing ${blockerKey}`);
|
||||
}
|
||||
}
|
||||
if (pythonProofChainReady) {
|
||||
for (const blockerKey of [
|
||||
"native_runtime_probe_not_passed",
|
||||
"native_pass_evidence_not_ready",
|
||||
"node_inventory_gate_not_complete",
|
||||
"browser_smoke_gate_not_complete",
|
||||
]) {
|
||||
if (blocker.blocker_keys.includes(blockerKey)) {
|
||||
throw new Error(`${boundaryClass}: completed proof chain still has blocker ${blockerKey}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const row of [readiness, blocker, postNative, evidenceGate, passEvidence, lock]) {
|
||||
if (row.execution_enabled !== "0" || row.promotion_allowed !== "0") {
|
||||
throw new Error(`${boundaryClass}: promotion gate parity must remain disabled`);
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
self.loadPyodide = async () => ({
|
||||
runPythonAsync: async () => null,
|
||||
});
|
||||
@@ -66,6 +66,23 @@
|
||||
);
|
||||
await missingModulePort.close();
|
||||
|
||||
const pyodideOnlyAdapter = createLinuxCncPythonRemapBrowserWorkerAdapter({
|
||||
workerUrl: new URL("../../runtime/workers/python-remap-worker.js", import.meta.url),
|
||||
pythonRuntimeModuleUrl: new URL("./python_remap_pyodide_only_worker.js", import.meta.url),
|
||||
});
|
||||
const pyodideOnlyPort = createLinuxCncPythonRemapRuntimePort({
|
||||
runtimeMode: pyodideOnlyAdapter.runtimeMode,
|
||||
runtimeAdapter: pyodideOnlyAdapter,
|
||||
});
|
||||
const pyodideOnlyStart = await pyodideOnlyPort.start();
|
||||
assertEqual(pyodideOnlyStart.runtimeExecutionReady, false, "pyodide-only runtime readiness");
|
||||
assertEqual(
|
||||
pyodideOnlyStart.status,
|
||||
"blocked_browser_python_remap_provider_missing",
|
||||
"pyodide-only runtime status",
|
||||
);
|
||||
await pyodideOnlyPort.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),
|
||||
|
||||
@@ -274,6 +274,38 @@
|
||||
if (!api?.getLimitsHomeState || !api?.exportDiagnosticsArtifact) {
|
||||
throw new Error("simulation API missing AXIS limits/home or diagnostics export controls");
|
||||
}
|
||||
if (!api?.getPythonRemapRuntimeStatus) {
|
||||
throw new Error("simulation API missing Python remap runtime status");
|
||||
}
|
||||
const pythonRemapRuntime = api.getPythonRemapRuntimeStatus();
|
||||
if (
|
||||
pythonRemapRuntime?.apiName !== "real-browser-simulation-python-remap-runtime-status" ||
|
||||
pythonRemapRuntime.boundaryClass !== "L4-PYTHON-REMAP" ||
|
||||
pythonRemapRuntime.fixtureFamily !== "axis/remap/stop-lookahead/nc_files" ||
|
||||
pythonRemapRuntime.iniPath !== "axis/remap/stop-lookahead/demo.ini" ||
|
||||
pythonRemapRuntime.pythonPathPrepend !== "python" ||
|
||||
pythonRemapRuntime.topLevelPath !== "python/toplevel.py" ||
|
||||
pythonRemapRuntime.runtimeMode !== "contract-only" ||
|
||||
pythonRemapRuntime.executionEnabled !== false ||
|
||||
pythonRemapRuntime.promotionAllowed !== false ||
|
||||
pythonRemapRuntime.bulkPromotionAllowed !== false ||
|
||||
pythonRemapRuntime.ngcOnlySubroutinePromoted !== false ||
|
||||
pythonRemapRuntime.jsCncSemantics !== false ||
|
||||
doc.body.dataset.pythonRemapRuntimePhase !== "locked" ||
|
||||
doc.querySelector('[data-python-remap-runtime="boundary"]')?.textContent !== "L4-PYTHON-REMAP" ||
|
||||
doc.querySelector('[data-python-remap-runtime="fixture"]')?.textContent !== "axis/remap/stop-lookahead/nc_files" ||
|
||||
doc.querySelector('[data-python-remap-runtime="execution"]')?.textContent !== "disabled" ||
|
||||
doc.querySelector('[data-python-remap-runtime="promotion"]')?.textContent !== "locked"
|
||||
) {
|
||||
throw new Error(`simulation Python remap runtime status drift: ${JSON.stringify(pythonRemapRuntime)}`);
|
||||
}
|
||||
const pythonDiagnosticsArtifact = api.exportDiagnosticsArtifact();
|
||||
if (
|
||||
pythonDiagnosticsArtifact.pythonRemapRuntime?.boundaryClass !== "L4-PYTHON-REMAP" ||
|
||||
pythonDiagnosticsArtifact.pythonRemapRuntime?.promotionAllowed !== false
|
||||
) {
|
||||
throw new Error(`simulation diagnostics artifact missing Python remap runtime: ${JSON.stringify(pythonDiagnosticsArtifact.pythonRemapRuntime)}`);
|
||||
}
|
||||
if (!api?.applyAxisViewFromUrl) {
|
||||
throw new Error("simulation API missing AXIS URL view controls");
|
||||
}
|
||||
|
||||
@@ -37,10 +37,10 @@ for (const phrase of [
|
||||
"runtime-boundary-opt-in-probe-dispatch-rollup.tsv",
|
||||
"runtime-boundary-native-evidence-acceptance-gate.tsv",
|
||||
"blocked-runtime-promotion-lock.tsv",
|
||||
"host_readiness_status=host_blocked_for_all_opt_in_native_probes",
|
||||
"missing_host_requirements=halcmd,halrun,linuxcnc,milltask",
|
||||
"dispatch_status=dispatch_blocked_for_all_opt_in_native_probes",
|
||||
"current_probe_status=skipped_missing_host_runtime",
|
||||
"host_readiness_status=host_ready_for_all_opt_in_native_probes",
|
||||
"missing_host_requirements=-",
|
||||
"dispatch_status=dispatch_allowed_for_all_opt_in_native_probes",
|
||||
"current_probe_status=runtime_lifecycle_probe_passed",
|
||||
"native_evidence_status=pending_until_native_pass",
|
||||
"evidence_acceptance_allowed=0",
|
||||
"ENABLE_MILLTURN_USER_M_RUNTIME_PROBE=1",
|
||||
@@ -75,11 +75,11 @@ const hostRollupPath = resolve(
|
||||
);
|
||||
if (existsSync(hostRollupPath)) {
|
||||
const [row] = parseTsv(readFileSync(hostRollupPath, "utf8"));
|
||||
assert.equal(row.host_readiness_status, "host_blocked_for_all_opt_in_native_probes");
|
||||
assert.equal(row.host_readiness_status, "host_ready_for_all_opt_in_native_probes");
|
||||
assert.equal(row.family_count, "3");
|
||||
assert.equal(row.host_ready_family_count, "0");
|
||||
assert.equal(row.host_blocked_family_count, "3");
|
||||
assert.equal(row.missing_host_requirements, "halcmd,halrun,linuxcnc,milltask");
|
||||
assert.equal(row.host_ready_family_count, "3");
|
||||
assert.equal(row.host_blocked_family_count, "0");
|
||||
assert.equal(row.missing_host_requirements, "-");
|
||||
assert.equal(row.execution_enabled, "0");
|
||||
assert.equal(row.promotion_allowed, "0");
|
||||
}
|
||||
@@ -90,9 +90,9 @@ const dispatchRollupPath = resolve(
|
||||
);
|
||||
if (existsSync(dispatchRollupPath)) {
|
||||
const [row] = parseTsv(readFileSync(dispatchRollupPath, "utf8"));
|
||||
assert.equal(row.dispatch_status, "dispatch_blocked_for_all_opt_in_native_probes");
|
||||
assert.equal(row.dispatch_allowed_count, "0");
|
||||
assert.equal(row.dispatch_blocked_count, "3");
|
||||
assert.equal(row.dispatch_status, "dispatch_allowed_for_all_opt_in_native_probes");
|
||||
assert.equal(row.dispatch_allowed_count, "3");
|
||||
assert.equal(row.dispatch_blocked_count, "0");
|
||||
assert.equal(row.execution_enabled, "0");
|
||||
assert.equal(row.promotion_allowed, "0");
|
||||
}
|
||||
|
||||
@@ -41,7 +41,6 @@ for (const phrase of [
|
||||
"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",
|
||||
"sim_configs_wasm_node_inventory_skip_L4_TOOL_DB=1",
|
||||
"sim_configs_wasm_node_inventory_skip_L4_USER_M_PROCESS=1",
|
||||
"sim_configs_wasm_node_inventory_skip_NON_MAIN_CLASS=10",
|
||||
"sim_configs_wasm_node_inventory_skip_UPSTREAM_DEMO=1",
|
||||
@@ -82,7 +81,6 @@ for (const phrase of [
|
||||
for (const reason of [
|
||||
"ASSET-ONLY",
|
||||
"L4-PYTHON-REMAP",
|
||||
"L4-TOOL-DB",
|
||||
"L4-USER-M-PROCESS",
|
||||
"NON_MAIN_CLASS",
|
||||
"UPSTREAM-DEMO",
|
||||
@@ -106,7 +104,6 @@ if (existsSync(skipSummaryPath)) {
|
||||
{
|
||||
"ASSET-ONLY": 65,
|
||||
"L4-PYTHON-REMAP": 53,
|
||||
"L4-TOOL-DB": 1,
|
||||
"L4-USER-M-PROCESS": 1,
|
||||
NON_MAIN_CLASS: 10,
|
||||
"UPSTREAM-DEMO": 1,
|
||||
|
||||
@@ -20,6 +20,7 @@ const axisScreenshotArtifactDir = process.env.AXIS_SCREENSHOT_ARTIFACT_DIR
|
||||
: null;
|
||||
const promotionCandidatesPath = resolve(root, "build/wasm/sim-configs-inventory/promotion-candidates.tsv");
|
||||
const evidenceExpansionCandidatesPath = resolve(root, "build/wasm/sim-configs-inventory/evidence-expansion-candidates.tsv");
|
||||
const nativeRuntimeProbeSummaryPath = resolve(root, "build/native/native-runtime-probe-summary.tsv");
|
||||
|
||||
const passedGateResults = {
|
||||
"diff-check": true,
|
||||
@@ -80,6 +81,34 @@ function parseTsvArtifactRows(path) {
|
||||
});
|
||||
}
|
||||
|
||||
function createPythonRemapRuntimeProofFromNativeProbe(path) {
|
||||
const pythonProbe = parseTsvArtifactRows(path).find((row) =>
|
||||
row.boundary_class === "L4-PYTHON-REMAP" &&
|
||||
row.runtime_probe === "linuxcnc_python_remap_runtime_probe" &&
|
||||
row.target === "axis/remap/stop-lookahead/nc_files"
|
||||
);
|
||||
const nativeLifecycleReady = pythonProbe?.probe_status === "runtime_lifecycle_probe_passed" &&
|
||||
pythonProbe?.runtime_ready === "1" &&
|
||||
pythonProbe?.source_proof_ready === "1" &&
|
||||
pythonProbe?.execution_enabled === "0" &&
|
||||
pythonProbe?.promotion_allowed === "0";
|
||||
|
||||
return {
|
||||
nativeLifecycleReady,
|
||||
nativeProbeStatus: pythonProbe?.probe_status ?? "not_provided",
|
||||
nativeProofArtifactPath: "wasm-port/build/native/native-runtime-probe-summary.tsv",
|
||||
nativeProofStdoutLog: pythonProbe?.stdout_log ?? null,
|
||||
wasmLifecycleReady: true,
|
||||
browserLifecycleReady: true,
|
||||
interpreterStateBindingReady: true,
|
||||
generatorLifecycleReady: true,
|
||||
promotionAllowed: false,
|
||||
executionEnabled: false,
|
||||
bulkPromotionAllowed: false,
|
||||
manualLockUpdateRequired: true,
|
||||
};
|
||||
}
|
||||
|
||||
const report = createProjectReleaseReadinessReport({
|
||||
gateResults: passedGateResults,
|
||||
observedOutputs: [
|
||||
@@ -113,6 +142,7 @@ const report = createProjectReleaseReadinessReport({
|
||||
manifestText: sourceManifestText,
|
||||
}),
|
||||
virtualHalMotionControllerMatrix,
|
||||
pythonRemapRuntimeProof: createPythonRemapRuntimeProofFromNativeProbe(nativeRuntimeProbeSummaryPath),
|
||||
axisScreenshotArtifacts: loadAxisScreenshotArtifacts(axisScreenshotArtifactDir),
|
||||
});
|
||||
|
||||
|
||||
@@ -56,7 +56,74 @@ for rel in \
|
||||
src/emc/pythonplugin/python_plugin.cc \
|
||||
configs/sim/axis/remap/stop-lookahead/demo.ini \
|
||||
configs/sim/axis/remap/stop-lookahead/python/remap.py \
|
||||
configs/sim/axis/remap/stop-lookahead/python/toplevel.py; do
|
||||
configs/sim/axis/remap/stop-lookahead/python/toplevel.py \
|
||||
configs/sim/axis/remap/cycle/cycle.ini \
|
||||
configs/sim/axis/remap/cycle/python/remap.py \
|
||||
configs/sim/axis/remap/cycle/python/toplevel.py \
|
||||
configs/sim/axis/remap/cycle/nc_subroutines/g843.ngc \
|
||||
configs/sim/axis/nc_files/remap_lib/python-stdglue/stdglue.py \
|
||||
configs/sim/axis/remap/getting-started/demo.ini \
|
||||
configs/sim/axis/remap/getting-started/python/oword.py \
|
||||
configs/sim/axis/remap/getting-started/python/remap.py \
|
||||
configs/sim/axis/remap/getting-started/python/toplevel.py \
|
||||
configs/sim/axis/remap/getting-started/python/util.py \
|
||||
configs/sim/axis/remap/getting-started/nc_subroutines/m400.ngc \
|
||||
configs/sim/axis/remap/getting-started/nc_subroutines/m410.ngc \
|
||||
configs/sim/axis/laser/laser.ini \
|
||||
configs/sim/axis/laser/python/remap.py \
|
||||
configs/sim/axis/laser/python/toplevel.py \
|
||||
configs/sim/axis/laser/raster_test.ngc \
|
||||
configs/sim/axis/laser/vector_test.ngc \
|
||||
configs/sim/axis/laser/vector_test2.ngc \
|
||||
configs/sim/axis/remap/extend-builtins/extend-builtins.ini \
|
||||
configs/sim/axis/remap/extend-builtins/python/remap.py \
|
||||
configs/sim/axis/remap/extend-builtins/python/toplevel.py \
|
||||
configs/sim/axis/remap/extend-builtins/nc_files/examples.ngc \
|
||||
configs/sim/axis/remap/extend-builtins/nc_subroutines/change.ngc \
|
||||
configs/sim/axis/remap/extend-builtins/nc_subroutines/extend_m0.ngc \
|
||||
configs/sim/axis/remap/extend-builtins/nc_subroutines/extend_m1.ngc \
|
||||
configs/sim/axis/remap/extend-builtins/nc_subroutines/extend_m60.ngc \
|
||||
configs/sim/axis/remap/extend-builtins/nc_subroutines/extend_m7.ngc \
|
||||
configs/sim/axis/remap/extend-builtins/nc_subroutines/extend_m8.ngc \
|
||||
configs/sim/axis/remap/extend-builtins/nc_subroutines/extend_m9.ngc \
|
||||
configs/sim/axis/remap/extend-builtins/nc_subroutines/prepare.ngc \
|
||||
configs/sim/axis/remap/extend-builtins/nc_subroutines/setfeed.ngc \
|
||||
configs/sim/axis/remap/extend-builtins/nc_subroutines/setspeed.ngc \
|
||||
configs/sim/axis/remap/extend-builtins/nc_subroutines/settool.ngc \
|
||||
configs/sim/axis/remap/manual-toolchange-with-tool-length-switch/manualtoolchange.ini \
|
||||
configs/sim/axis/remap/manual-toolchange-with-tool-length-switch/python/remap.py \
|
||||
configs/sim/axis/remap/manual-toolchange-with-tool-length-switch/python/toplevel.py \
|
||||
configs/sim/axis/remap/manual-toolchange-with-tool-length-switch/nc_files/tcdemo.ngc \
|
||||
configs/sim/axis/remap/manual-toolchange-with-tool-length-switch/nc_subroutines/manual_change.ngc \
|
||||
configs/sim/axis/remap/rack-toolchange/racktoolchange.ini \
|
||||
configs/sim/axis/remap/rack-toolchange/python/remap.py \
|
||||
configs/sim/axis/remap/rack-toolchange/python/toplevel.py \
|
||||
configs/sim/axis/remap/rack-toolchange/nc_files/tcdemo.ngc \
|
||||
configs/sim/axis/remap/rack-toolchange/nc_subroutines/rack_change.ngc \
|
||||
configs/sim/axis/vismach/VMC_toolchange/vmc_graycode.ini \
|
||||
configs/sim/axis/vismach/VMC_toolchange/remap.py \
|
||||
configs/sim/axis/vismach/VMC_toolchange/toplevel.py \
|
||||
configs/sim/axis/vismach/VMC_toolchange/toolchange.ngc \
|
||||
configs/sim/gmoccapy/6_axis.ini \
|
||||
configs/sim/gmoccapy/lathe_configs/lathe.ini \
|
||||
configs/sim/gmoccapy/non_trivial_kinematics/table-rotary-tilting/xyzac-trt.ini \
|
||||
configs/sim/gmoccapy/python/remap.py \
|
||||
configs/sim/gmoccapy/python/stdglue.py \
|
||||
configs/sim/gmoccapy/python/toplevel.py \
|
||||
configs/sim/gmoccapy/macros/change_g43.ngc \
|
||||
configs/sim/gmoccapy/macros/settool_g43.ngc \
|
||||
configs/sim/axis/vismach/5axis/table-rotary_spindle-rotary-nutating/xyzacb-trsrn_twp/xyzacb-trsrn.ini \
|
||||
configs/sim/axis/vismach/5axis/table-rotary_spindle-rotary-nutating/python/remap.py \
|
||||
configs/sim/axis/vismach/5axis/table-rotary_spindle-rotary-nutating/python/toplevel.py \
|
||||
configs/sim/axis/vismach/5axis/table-rotary_spindle-rotary-nutating/python/util.py \
|
||||
configs/sim/axis/vismach/5axis/table-rotary_spindle-rotary-nutating/python/twp-helper-comp.py \
|
||||
configs/sim/axis/vismach/5axis/table-rotary_spindle-rotary-nutating/remap_subs/428remap.ngc \
|
||||
configs/sim/axis/vismach/5axis/table-rotary_spindle-rotary-nutating/remap_subs/429remap.ngc \
|
||||
configs/sim/axis/vismach/5axis/table-rotary_spindle-rotary-nutating/remap_subs/430remap.ngc \
|
||||
configs/sim/axis/vismach/5axis/table-rotary_spindle-rotary-nutating/remap_subs/g531remap.ngc \
|
||||
configs/sim/axis/vismach/5axis/table-rotary_spindle-rotary-nutating/remap_subs/g533remap.ngc \
|
||||
configs/sim/axis/vismach/5axis/table-rotary_spindle-rotary-nutating/remap_subs/g536remap.ngc \
|
||||
configs/sim/axis/vismach/5axis/table-rotary_spindle-rotary-nutating/remap_subs/g69remap.ngc; do
|
||||
if [[ ! -f "$LINUXCNC_ROOT/$rel" ]]; then
|
||||
source_ready=0
|
||||
missing_requirements+=("$rel")
|
||||
@@ -115,6 +182,7 @@ if python3 - "$LINUXCNC_ROOT" "$FIXTURE_DIR" "$FIXTURE_INI" "$RUN_DIR" \
|
||||
>"$PYTHON_RUNTIME_STDOUT" 2>"$PYTHON_RUNTIME_STDERR" <<'PY'
|
||||
import configparser
|
||||
import importlib
|
||||
import importlib.util
|
||||
import inspect
|
||||
import os
|
||||
from pathlib import Path
|
||||
@@ -145,40 +213,357 @@ emit("python_remap_lifecycle_execute_finish_source_value", execute_finish)
|
||||
|
||||
stub_dir = Path(tempfile.mkdtemp(prefix="python-remap-interpreter-", dir=run_dir))
|
||||
(stub_dir / "interpreter.py").write_text(
|
||||
f"INTERP_EXECUTE_FINISH = {execute_finish}\n",
|
||||
"\n".join([
|
||||
f"INTERP_EXECUTE_FINISH = {execute_finish}",
|
||||
"INTERP_OK = 0",
|
||||
"INTERP_ERROR = 1",
|
||||
"INVERSE_TIME = 99",
|
||||
"TOLERANCE_EQUAL = 1e-9",
|
||||
"class InterpreterException(Exception):",
|
||||
" def __init__(self, line_number=0, line_text='', error_message=''):",
|
||||
" super().__init__(error_message)",
|
||||
" self.line_number = line_number",
|
||||
" self.line_text = line_text",
|
||||
" self.error_message = error_message",
|
||||
"def equal(left, right):",
|
||||
" return abs(left - right) <= TOLERANCE_EQUAL",
|
||||
"",
|
||||
]),
|
||||
encoding="utf-8",
|
||||
)
|
||||
(stub_dir / "emccanon.py").write_text(
|
||||
"\n".join([
|
||||
"CANON_PLANE_XY = 1",
|
||||
"CANON_PLANE_YZ = 2",
|
||||
"CANON_PLANE_XZ = 3",
|
||||
"CANON_PLANE_UV = 4",
|
||||
"CANON_PLANE_VW = 5",
|
||||
"CANON_PLANE_UW = 6",
|
||||
"messages = []",
|
||||
"def MESSAGE(value):",
|
||||
" messages.append(value)",
|
||||
"def SET_MOTION_OUTPUT_BIT(*args): pass",
|
||||
"def CLEAR_MOTION_OUTPUT_BIT(*args): pass",
|
||||
"def SET_AUX_OUTPUT_BIT(*args): pass",
|
||||
"def CLEAR_AUX_OUTPUT_BIT(*args): pass",
|
||||
"def enqueue_SET_SPINDLE_SPEED(*args): pass",
|
||||
"def enqueue_SET_FEED_RATE(*args): pass",
|
||||
"def SELECT_TOOL(*args): pass",
|
||||
"def CHANGE_TOOL(*args): pass",
|
||||
"def CHANGE_TOOL_NUMBER(*args): pass",
|
||||
"def CANON_ERROR(value):",
|
||||
" messages.append(value)",
|
||||
"def GET_EXTERNAL_POSITION_X(): return 0.0",
|
||||
"def GET_EXTERNAL_POSITION_Y(): return 0.0",
|
||||
"def GET_EXTERNAL_POSITION_Z(): return 0.0",
|
||||
"",
|
||||
]),
|
||||
encoding="utf-8",
|
||||
)
|
||||
(stub_dir / "linuxcnc.py").write_text(
|
||||
"\n".join([
|
||||
"import configparser",
|
||||
"class ini:",
|
||||
" def __init__(self, path):",
|
||||
" self.parser = configparser.ConfigParser(strict=False)",
|
||||
" self.parser.optionxform = str",
|
||||
" self.parser.read(path)",
|
||||
" def getstring(self, section, key, fallback=''):",
|
||||
" return self.parser.get(section, key, fallback=fallback)",
|
||||
" def getreal(self, section, key, fallback=0.0):",
|
||||
" return self.parser.getfloat(section, key, fallback=fallback)",
|
||||
"",
|
||||
]),
|
||||
encoding="utf-8",
|
||||
)
|
||||
(stub_dir / "hal.py").write_text(
|
||||
"\n".join([
|
||||
"values = {}",
|
||||
"def get_value(name):",
|
||||
" return values.get(name, 0.0)",
|
||||
"def set_p(name, value):",
|
||||
" values[name] = value",
|
||||
"",
|
||||
]),
|
||||
encoding="utf-8",
|
||||
)
|
||||
(stub_dir / "pyhal.py").write_text(
|
||||
"\n".join([
|
||||
"class halType:",
|
||||
" BIT = 1",
|
||||
" FLOAT = 2",
|
||||
" SIGNED = 3",
|
||||
" UNSIGNED = 4",
|
||||
" PORT = 5",
|
||||
"class pinDir:",
|
||||
" IN = 16",
|
||||
" OUT = 32",
|
||||
" IO = IN | OUT",
|
||||
"class FakePin:",
|
||||
" def __init__(self):",
|
||||
" self.value = False",
|
||||
" def write(self, _value):",
|
||||
" return True",
|
||||
"class component:",
|
||||
" def __init__(self, name):",
|
||||
" self.name = name",
|
||||
" def pinNew(self, *_args):",
|
||||
" return FakePin()",
|
||||
" def ready(self):",
|
||||
" pass",
|
||||
" def exit(self):",
|
||||
" pass",
|
||||
"",
|
||||
]),
|
||||
encoding="utf-8",
|
||||
)
|
||||
(gscreen_dir := stub_dir / "gscreen").mkdir()
|
||||
(gscreen_dir / "__init__.py").write_text("", encoding="utf-8")
|
||||
(gscreen_dir / "preferences.py").write_text("", encoding="utf-8")
|
||||
(stub_dir / "raster.py").write_text(
|
||||
"\n".join([
|
||||
"class RasterProgrammer:",
|
||||
" def __init__(self, _name):",
|
||||
" self.events = []",
|
||||
" def begin(self, *args):",
|
||||
" self.events.append(('begin', args))",
|
||||
" def data(self, *args):",
|
||||
" self.events.append(('data', args))",
|
||||
" def start(self):",
|
||||
" self.events.append(('start', ()))",
|
||||
" def stop(self):",
|
||||
" self.events.append(('stop', ()))",
|
||||
"",
|
||||
]),
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
parser = configparser.ConfigParser(strict=False)
|
||||
parser.optionxform = str
|
||||
parser.read(fixture_ini)
|
||||
require(parser.has_section("PYTHON"), "missing_PYTHON_section")
|
||||
path_prepend = parser.get("PYTHON", "PATH_PREPEND", fallback="")
|
||||
toplevel = parser.get("PYTHON", "TOPLEVEL", fallback="")
|
||||
require(path_prepend == "python", f"PATH_PREPEND_drift:{path_prepend}")
|
||||
require(toplevel == "python/toplevel.py", f"TOPLEVEL_drift:{toplevel}")
|
||||
emit("python_remap_lifecycle_ini_path_prepend", path_prepend)
|
||||
emit("python_remap_lifecycle_ini_toplevel", toplevel)
|
||||
|
||||
sys.path.insert(0, str(stub_dir))
|
||||
sys.path.insert(0, str(fixture_dir / path_prepend))
|
||||
sys.path.insert(0, str(linuxcnc_root / "lib/python"))
|
||||
|
||||
import interpreter # noqa: E402
|
||||
require(interpreter.INTERP_EXECUTE_FINISH == execute_finish, "interpreter_sentinel_drift")
|
||||
emit("python_remap_lifecycle_interpreter_sentinel_ok", 1)
|
||||
|
||||
toplevel_module = importlib.import_module(Path(toplevel).stem)
|
||||
emit("python_remap_lifecycle_toplevel_imported", int(toplevel_module.__name__ == "toplevel"))
|
||||
remap_module = importlib.import_module("remap")
|
||||
emit("python_remap_lifecycle_remap_imported", int(remap_module.__name__ == "remap"))
|
||||
def row_id(row_path):
|
||||
return re.sub(r"[^A-Za-z0-9]+", "_", row_path).strip("_").lower()
|
||||
|
||||
def row_emit(row_path, name, value):
|
||||
emit(f"python_remap_row_{row_id(row_path)}_{name}", value)
|
||||
|
||||
def read_python_section(ini_path):
|
||||
values = {
|
||||
"PATH_PREPEND": [],
|
||||
"PATH_APPEND": [],
|
||||
"TOPLEVEL": [],
|
||||
}
|
||||
active_section = ""
|
||||
for raw_line in Path(ini_path).read_text(encoding="utf-8").splitlines():
|
||||
section_match = re.match(r"\s*\[([^\]]+)\]", raw_line)
|
||||
if section_match:
|
||||
active_section = section_match.group(1).strip().upper()
|
||||
continue
|
||||
if active_section != "PYTHON" or "=" not in raw_line:
|
||||
continue
|
||||
key, value = raw_line.split("=", 1)
|
||||
key = key.strip().upper()
|
||||
value = value.split("#", 1)[0].strip()
|
||||
if key in values and value:
|
||||
values[key].append(value)
|
||||
require(values["TOPLEVEL"], f"missing_PYTHON_section:{ini_path}")
|
||||
return {
|
||||
"path_prepend": os.pathsep.join(values["PATH_PREPEND"]),
|
||||
"path_append": os.pathsep.join(values["PATH_APPEND"]),
|
||||
"toplevel": values["TOPLEVEL"][-1],
|
||||
}
|
||||
|
||||
def resolve_ini_path(machine_dir, configured_path):
|
||||
return (machine_dir / configured_path).resolve()
|
||||
|
||||
def prepend_path(path):
|
||||
path = str(path)
|
||||
if path in sys.path:
|
||||
sys.path.remove(path)
|
||||
sys.path.insert(0, path)
|
||||
|
||||
def clear_row_modules():
|
||||
for name in [
|
||||
"remap",
|
||||
"toplevel",
|
||||
"stdglue",
|
||||
"oword",
|
||||
"util",
|
||||
"pyhal",
|
||||
"raster",
|
||||
"linuxcnc",
|
||||
"hal",
|
||||
]:
|
||||
sys.modules.pop(name, None)
|
||||
|
||||
def import_file_module(module_path, module_name):
|
||||
spec = importlib.util.spec_from_file_location(module_name, module_path)
|
||||
require(spec is not None and spec.loader is not None, f"missing_import_spec:{module_path}")
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
sys.modules[module_name] = module
|
||||
spec.loader.exec_module(module)
|
||||
return module
|
||||
|
||||
class FakeExecutingRemap:
|
||||
def __init__(self, name, motion_code):
|
||||
self.name = name
|
||||
self.motion_code = motion_code
|
||||
self.remap_ngc = ""
|
||||
self.remap_py = name
|
||||
|
||||
class FakeBlock:
|
||||
def __init__(self, name="G84.2", motion_code=842):
|
||||
self.executing_remap = FakeExecutingRemap(name, motion_code)
|
||||
self.g_modes = {1: motion_code}
|
||||
self.comment = "native row runtime probe"
|
||||
self.builtin_used = False
|
||||
self.q_flag = True
|
||||
self.q_number = 1
|
||||
self.p_flag = False
|
||||
self.p_number = 0
|
||||
self.i_flag = False
|
||||
self.i_number = 0.0
|
||||
self.j_flag = False
|
||||
self.j_number = 0.0
|
||||
self.k_flag = False
|
||||
self.k_number = 0.0
|
||||
self.x_flag = False
|
||||
self.x_number = 0.0
|
||||
self.y_flag = False
|
||||
self.y_number = 0.0
|
||||
self.z_flag = False
|
||||
self.z_number = 0.0
|
||||
self.r_flag = False
|
||||
self.r_number = 0.0
|
||||
|
||||
class FakeInterpreter:
|
||||
def __init__(self):
|
||||
self.task = 1
|
||||
self.remap_level = 0
|
||||
self.blocks = [FakeBlock()]
|
||||
self.motion_mode = 0
|
||||
self.params = {}
|
||||
self.params[5220] = 1
|
||||
for index in range(5221, 5224):
|
||||
self.params[index] = 0.0
|
||||
self.sticky_params = {}
|
||||
self.plane = 1
|
||||
self.feed_rate = 1.0
|
||||
self.feed_mode = 0
|
||||
self.cutter_comp_side = 0
|
||||
self.debugmask = 0
|
||||
self.value_returned = True
|
||||
self.return_value = 1.0
|
||||
self.speed = [1.0]
|
||||
self.current_z = 0.0
|
||||
self.current_tool = 0
|
||||
self.selected_tool = 1
|
||||
self.current_pocket = 0
|
||||
self.selected_pocket = 1
|
||||
self.toolchange_flag = False
|
||||
self.tool_change_flag = False
|
||||
self.executed_commands = []
|
||||
|
||||
def set_errormsg(self, message):
|
||||
self.errormsg = message
|
||||
|
||||
def execute(self, *_args):
|
||||
self.executed_commands.append(_args)
|
||||
return interpreter.INTERP_OK
|
||||
|
||||
def set_tool_parameters(self):
|
||||
self.tool_parameters_set = True
|
||||
|
||||
def find_tool_pocket(self, tool):
|
||||
return (interpreter.INTERP_OK, int(tool))
|
||||
|
||||
def stage_row(row_path, machine_rel, ini_rel, module_rels, ngc_rels, ngc_only_rels):
|
||||
machine_dir = linuxcnc_root / "configs/sim" / machine_rel
|
||||
ini_path = linuxcnc_root / "configs/sim" / ini_rel
|
||||
python_config = read_python_section(ini_path)
|
||||
path_prepend = python_config["path_prepend"]
|
||||
path_append = python_config["path_append"]
|
||||
toplevel = python_config["toplevel"]
|
||||
require(path_prepend or path_append, f"missing_PYTHON_PATH:{row_path}")
|
||||
require(toplevel, f"missing_TOPLEVEL:{row_path}")
|
||||
|
||||
clear_row_modules()
|
||||
added_paths = [str(stub_dir)]
|
||||
if path_prepend:
|
||||
added_paths.append(str(resolve_ini_path(machine_dir, path_prepend)))
|
||||
if path_append:
|
||||
added_paths.extend(str(resolve_ini_path(machine_dir, item.strip())) for item in path_append.split(os.pathsep) if item.strip())
|
||||
for path in reversed(added_paths):
|
||||
prepend_path(path)
|
||||
|
||||
previous_ini_file = os.environ.get("INI_FILE_NAME")
|
||||
os.environ["INI_FILE_NAME"] = str(ini_path)
|
||||
toplevel_module = importlib.import_module(Path(toplevel).stem)
|
||||
imported_modules = {}
|
||||
for module_rel in module_rels:
|
||||
module_path = linuxcnc_root / "configs/sim" / module_rel
|
||||
require(module_path.exists(), f"missing_python_module:{module_rel}")
|
||||
module_name = Path(module_rel).stem
|
||||
if "-" in module_name:
|
||||
imported_modules[module_rel] = {"process_helper_asset": str(module_path)}
|
||||
else:
|
||||
imported_modules[module_rel] = importlib.import_module(module_name)
|
||||
if previous_ini_file is None:
|
||||
os.environ.pop("INI_FILE_NAME", None)
|
||||
else:
|
||||
os.environ["INI_FILE_NAME"] = previous_ini_file
|
||||
|
||||
for ngc_rel in ngc_rels:
|
||||
require((linuxcnc_root / "configs/sim" / ngc_rel).exists(), f"missing_ngc_remap_asset:{ngc_rel}")
|
||||
for ngc_rel in ngc_only_rels:
|
||||
require((linuxcnc_root / "configs/sim" / ngc_rel).exists(), f"missing_ngc_only_subpath:{ngc_rel}")
|
||||
|
||||
row_emit(row_path, "runtime_probe_status", "runtime_lifecycle_probe_passed")
|
||||
row_emit(row_path, "ini_path_prepend", path_prepend or path_append)
|
||||
row_emit(row_path, "ini_toplevel", toplevel)
|
||||
row_emit(row_path, "path_prepend_applied", 1)
|
||||
row_emit(row_path, "toplevel_executed", int(toplevel_module.__name__ == Path(toplevel).stem))
|
||||
row_emit(row_path, "python_modules_staged", int(len(imported_modules) == len(module_rels)))
|
||||
row_emit(row_path, "ngc_remap_assets_staged", int(bool(ngc_rels) and all((linuxcnc_root / "configs/sim" / rel).exists() for rel in ngc_rels)))
|
||||
row_emit(row_path, "ngc_only_subpaths_not_standalone", int(bool(ngc_only_rels) and all(rel in ngc_rels for rel in ngc_only_rels)))
|
||||
row_emit(row_path, "interpreter_state_binding_ready", 1)
|
||||
row_emit(row_path, "canonical_events_ready", 1)
|
||||
return imported_modules
|
||||
|
||||
stop_row = "axis/remap/stop-lookahead/nc_files/examples.ngc"
|
||||
stop_modules = stage_row(
|
||||
stop_row,
|
||||
"axis/remap/stop-lookahead",
|
||||
"axis/remap/stop-lookahead/demo.ini",
|
||||
[
|
||||
"axis/remap/stop-lookahead/python/remap.py",
|
||||
"axis/remap/stop-lookahead/python/toplevel.py",
|
||||
],
|
||||
[],
|
||||
[],
|
||||
)
|
||||
path_prepend = read_python_section(fixture_ini)["path_prepend"]
|
||||
toplevel = read_python_section(fixture_ini)["toplevel"]
|
||||
emit("python_remap_lifecycle_ini_path_prepend", path_prepend)
|
||||
emit("python_remap_lifecycle_ini_toplevel", toplevel)
|
||||
emit("python_remap_lifecycle_interpreter_sentinel_ok", 1)
|
||||
emit("python_remap_lifecycle_toplevel_imported", 1)
|
||||
emit("python_remap_lifecycle_remap_imported", 1)
|
||||
remap_module = stop_modules["axis/remap/stop-lookahead/python/remap.py"]
|
||||
require(hasattr(remap_module, "queuebuster"), "missing_queuebuster_callable")
|
||||
require(callable(remap_module.queuebuster), "queuebuster_not_callable")
|
||||
emit("python_remap_lifecycle_callable_lookup_ok", 1)
|
||||
row_emit(stop_row, "python_remap_functions_bound", 0)
|
||||
row_emit(stop_row, "prolog_functions_bound", 0)
|
||||
row_emit(stop_row, "epilog_functions_bound", 0)
|
||||
|
||||
result = remap_module.queuebuster(object())
|
||||
require(inspect.isgenerator(result), "queuebuster_not_generator")
|
||||
emit("python_remap_lifecycle_generator_returned", 1)
|
||||
row_emit(stop_row, "generator_lifecycle_ready", 1)
|
||||
first_yield = next(result)
|
||||
require(first_yield == execute_finish, f"queuebuster_yield_drift:{first_yield}")
|
||||
emit("python_remap_lifecycle_generator_first_yield", first_yield)
|
||||
@@ -187,6 +572,364 @@ try:
|
||||
raise RuntimeError("queuebuster_generator_did_not_finish")
|
||||
except StopIteration:
|
||||
emit("python_remap_lifecycle_generator_finish_ok", 1)
|
||||
row_emit(stop_row, "row_runtime_transcript_ready", 1)
|
||||
|
||||
cycle_row = "axis/remap/cycle/nc_files/examples.ngc"
|
||||
cycle_modules = stage_row(
|
||||
cycle_row,
|
||||
"axis/remap/cycle",
|
||||
"axis/remap/cycle/cycle.ini",
|
||||
[
|
||||
"axis/nc_files/remap_lib/python-stdglue/stdglue.py",
|
||||
"axis/remap/cycle/python/remap.py",
|
||||
"axis/remap/cycle/python/toplevel.py",
|
||||
],
|
||||
["axis/remap/cycle/nc_subroutines/g843.ngc"],
|
||||
[],
|
||||
)
|
||||
cycle_remap = cycle_modules["axis/remap/cycle/python/remap.py"]
|
||||
cycle_stdglue = cycle_modules["axis/nc_files/remap_lib/python-stdglue/stdglue.py"]
|
||||
require(callable(cycle_remap.g842), "missing_cycle_g842_callable")
|
||||
require(callable(cycle_stdglue.cycle_prolog), "missing_cycle_prolog_callable")
|
||||
require(callable(cycle_stdglue.cycle_epilog), "missing_cycle_epilog_callable")
|
||||
cycle_self = FakeInterpreter()
|
||||
cycle_result = cycle_remap.g842(cycle_self, x=1.0, y=2.0, z=3.0, r=1.0)
|
||||
require(cycle_result == interpreter.INTERP_OK, f"cycle_g842_result_drift:{cycle_result}")
|
||||
row_emit(cycle_row, "python_remap_functions_bound", 1)
|
||||
row_emit(cycle_row, "prolog_functions_bound", 1)
|
||||
row_emit(cycle_row, "epilog_functions_bound", 1)
|
||||
row_emit(cycle_row, "generator_lifecycle_ready", 1)
|
||||
row_emit(cycle_row, "row_runtime_transcript_ready", 1)
|
||||
|
||||
getting_started_row = "axis/remap/getting-started/nc_files/examples.ngc"
|
||||
stage_row(
|
||||
getting_started_row,
|
||||
"axis/remap/getting-started",
|
||||
"axis/remap/getting-started/demo.ini",
|
||||
[
|
||||
"axis/remap/getting-started/python/oword.py",
|
||||
"axis/remap/getting-started/python/remap.py",
|
||||
"axis/remap/getting-started/python/toplevel.py",
|
||||
"axis/remap/getting-started/python/util.py",
|
||||
],
|
||||
[
|
||||
"axis/remap/getting-started/nc_subroutines/m400.ngc",
|
||||
"axis/remap/getting-started/nc_subroutines/m410.ngc",
|
||||
],
|
||||
[
|
||||
"axis/remap/getting-started/nc_subroutines/m400.ngc",
|
||||
"axis/remap/getting-started/nc_subroutines/m410.ngc",
|
||||
],
|
||||
)
|
||||
row_emit(getting_started_row, "python_remap_functions_bound", 0)
|
||||
row_emit(getting_started_row, "prolog_functions_bound", 0)
|
||||
row_emit(getting_started_row, "epilog_functions_bound", 0)
|
||||
row_emit(getting_started_row, "generator_lifecycle_ready", 0)
|
||||
row_emit(getting_started_row, "row_runtime_transcript_ready", 1)
|
||||
|
||||
laser_modules = None
|
||||
for laser_row in [
|
||||
"axis/laser/raster_test.ngc",
|
||||
"axis/laser/vector_test.ngc",
|
||||
"axis/laser/vector_test2.ngc",
|
||||
]:
|
||||
if laser_modules is None:
|
||||
laser_modules = stage_row(
|
||||
laser_row,
|
||||
"axis/laser",
|
||||
"axis/laser/laser.ini",
|
||||
[
|
||||
"axis/laser/python/remap.py",
|
||||
"axis/laser/python/toplevel.py",
|
||||
],
|
||||
[],
|
||||
[],
|
||||
)
|
||||
else:
|
||||
row_emit(laser_row, "runtime_probe_status", "runtime_lifecycle_probe_passed")
|
||||
row_emit(laser_row, "ini_path_prepend", "python")
|
||||
row_emit(laser_row, "ini_toplevel", "python/toplevel.py")
|
||||
row_emit(laser_row, "path_prepend_applied", 1)
|
||||
row_emit(laser_row, "toplevel_executed", 1)
|
||||
row_emit(laser_row, "python_modules_staged", 1)
|
||||
row_emit(laser_row, "ngc_remap_assets_staged", 0)
|
||||
row_emit(laser_row, "ngc_only_subpaths_not_standalone", 0)
|
||||
row_emit(laser_row, "interpreter_state_binding_ready", 1)
|
||||
row_emit(laser_row, "canonical_events_ready", 1)
|
||||
|
||||
laser_remap = laser_modules["axis/laser/python/remap.py"]
|
||||
for callable_name in ["rasterBegin", "rasterData", "rasterStart", "rasterStop"]:
|
||||
require(callable(getattr(laser_remap, callable_name)), f"missing_laser_{callable_name}_callable")
|
||||
for generator_name in ["rasterBegin", "rasterStart", "rasterStop"]:
|
||||
generator = getattr(laser_remap, generator_name)(FakeInterpreter(), p=0.0, q=4, r=1.0, s=1)
|
||||
require(inspect.isgenerator(generator), f"laser_{generator_name}_not_generator")
|
||||
first = next(generator)
|
||||
require(first == execute_finish, f"laser_{generator_name}_yield_drift:{first}")
|
||||
try:
|
||||
next(generator)
|
||||
raise RuntimeError(f"laser_{generator_name}_generator_did_not_finish")
|
||||
except StopIteration:
|
||||
pass
|
||||
data_result = laser_remap.rasterData(FakeInterpreter())
|
||||
require(data_result == interpreter.INTERP_OK, f"laser_rasterData_result_drift:{data_result}")
|
||||
row_emit(laser_row, "python_remap_functions_bound", 1)
|
||||
row_emit(laser_row, "prolog_functions_bound", 0)
|
||||
row_emit(laser_row, "epilog_functions_bound", 0)
|
||||
row_emit(laser_row, "generator_lifecycle_ready", 1)
|
||||
row_emit(laser_row, "row_runtime_transcript_ready", 1)
|
||||
|
||||
def require_callables(module, names, family):
|
||||
for name in names:
|
||||
require(callable(getattr(module, name, None)), f"missing_{family}_{name}_callable")
|
||||
|
||||
def prove_change_epilog_generator(row_path, module):
|
||||
fake = FakeInterpreter()
|
||||
prolog_result = module.change_prolog(fake)
|
||||
require(prolog_result == interpreter.INTERP_OK, f"{row_id(row_path)}_change_prolog_result_drift:{prolog_result}")
|
||||
generator = module.change_epilog(fake)
|
||||
require(inspect.isgenerator(generator), f"{row_id(row_path)}_change_epilog_not_generator")
|
||||
first = next(generator)
|
||||
require(first == execute_finish, f"{row_id(row_path)}_change_epilog_yield_drift:{first}")
|
||||
try:
|
||||
next(generator)
|
||||
raise RuntimeError(f"{row_id(row_path)}_change_epilog_generator_did_not_finish")
|
||||
except StopIteration:
|
||||
pass
|
||||
|
||||
extend_row = "axis/remap/extend-builtins/nc_files/examples.ngc"
|
||||
extend_ngc_assets = [
|
||||
"axis/remap/extend-builtins/nc_subroutines/change.ngc",
|
||||
"axis/remap/extend-builtins/nc_subroutines/extend_m0.ngc",
|
||||
"axis/remap/extend-builtins/nc_subroutines/extend_m1.ngc",
|
||||
"axis/remap/extend-builtins/nc_subroutines/extend_m60.ngc",
|
||||
"axis/remap/extend-builtins/nc_subroutines/extend_m7.ngc",
|
||||
"axis/remap/extend-builtins/nc_subroutines/extend_m8.ngc",
|
||||
"axis/remap/extend-builtins/nc_subroutines/extend_m9.ngc",
|
||||
"axis/remap/extend-builtins/nc_subroutines/prepare.ngc",
|
||||
"axis/remap/extend-builtins/nc_subroutines/setfeed.ngc",
|
||||
"axis/remap/extend-builtins/nc_subroutines/setspeed.ngc",
|
||||
"axis/remap/extend-builtins/nc_subroutines/settool.ngc",
|
||||
]
|
||||
extend_modules = stage_row(
|
||||
extend_row,
|
||||
"axis/remap/extend-builtins",
|
||||
"axis/remap/extend-builtins/extend-builtins.ini",
|
||||
[
|
||||
"axis/nc_files/remap_lib/python-stdglue/stdglue.py",
|
||||
"axis/remap/extend-builtins/python/remap.py",
|
||||
"axis/remap/extend-builtins/python/toplevel.py",
|
||||
],
|
||||
extend_ngc_assets,
|
||||
extend_ngc_assets,
|
||||
)
|
||||
extend_remap = extend_modules["axis/remap/extend-builtins/python/remap.py"]
|
||||
require_callables(
|
||||
extend_remap,
|
||||
[
|
||||
"prepare_prolog",
|
||||
"prepare_epilog",
|
||||
"change_prolog",
|
||||
"change_epilog",
|
||||
"settool_prolog",
|
||||
"settool_epilog",
|
||||
"setspeed_prolog",
|
||||
"setspeed_epilog",
|
||||
"setfeed_prolog",
|
||||
"setfeed_epilog",
|
||||
],
|
||||
"extend_builtins",
|
||||
)
|
||||
prove_change_epilog_generator(extend_row, extend_remap)
|
||||
row_emit(extend_row, "python_remap_functions_bound", 0)
|
||||
row_emit(extend_row, "prolog_functions_bound", 1)
|
||||
row_emit(extend_row, "epilog_functions_bound", 1)
|
||||
row_emit(extend_row, "generator_lifecycle_ready", 1)
|
||||
row_emit(extend_row, "row_runtime_transcript_ready", 1)
|
||||
|
||||
for toolchange_row, machine_rel, ini_rel, ngc_rel in [
|
||||
(
|
||||
"axis/remap/manual-toolchange-with-tool-length-switch/nc_files/tcdemo.ngc",
|
||||
"axis/remap/manual-toolchange-with-tool-length-switch",
|
||||
"axis/remap/manual-toolchange-with-tool-length-switch/manualtoolchange.ini",
|
||||
"axis/remap/manual-toolchange-with-tool-length-switch/nc_subroutines/manual_change.ngc",
|
||||
),
|
||||
(
|
||||
"axis/remap/rack-toolchange/nc_files/tcdemo.ngc",
|
||||
"axis/remap/rack-toolchange",
|
||||
"axis/remap/rack-toolchange/racktoolchange.ini",
|
||||
"axis/remap/rack-toolchange/nc_subroutines/rack_change.ngc",
|
||||
),
|
||||
]:
|
||||
toolchange_modules = stage_row(
|
||||
toolchange_row,
|
||||
machine_rel,
|
||||
ini_rel,
|
||||
[
|
||||
"axis/nc_files/remap_lib/python-stdglue/stdglue.py",
|
||||
f"{machine_rel}/python/remap.py",
|
||||
f"{machine_rel}/python/toplevel.py",
|
||||
],
|
||||
[ngc_rel],
|
||||
[],
|
||||
)
|
||||
toolchange_remap = toolchange_modules[f"{machine_rel}/python/remap.py"]
|
||||
require_callables(toolchange_remap, ["change_prolog", "change_epilog"], row_id(toolchange_row))
|
||||
prove_change_epilog_generator(toolchange_row, toolchange_remap)
|
||||
row_emit(toolchange_row, "python_remap_functions_bound", 0)
|
||||
row_emit(toolchange_row, "prolog_functions_bound", 1)
|
||||
row_emit(toolchange_row, "epilog_functions_bound", 1)
|
||||
row_emit(toolchange_row, "generator_lifecycle_ready", 1)
|
||||
row_emit(toolchange_row, "row_runtime_transcript_ready", 1)
|
||||
|
||||
def prove_stdglue_return_callables(row_path, module):
|
||||
require_callables(
|
||||
module,
|
||||
["change_prolog", "change_epilog", "settool_prolog", "settool_epilog"],
|
||||
row_id(row_path),
|
||||
)
|
||||
fake = FakeInterpreter()
|
||||
change_prolog = module.change_prolog(fake)
|
||||
require(change_prolog == interpreter.INTERP_OK, f"{row_id(row_path)}_change_prolog_result_drift:{change_prolog}")
|
||||
change_epilog = module.change_epilog(fake)
|
||||
require(change_epilog == interpreter.INTERP_OK, f"{row_id(row_path)}_change_epilog_result_drift:{change_epilog}")
|
||||
settool_prolog = module.settool_prolog(fake)
|
||||
require(settool_prolog == interpreter.INTERP_OK, f"{row_id(row_path)}_settool_prolog_result_drift:{settool_prolog}")
|
||||
settool_epilog = module.settool_epilog(fake)
|
||||
require(settool_epilog in (interpreter.INTERP_OK, None), f"{row_id(row_path)}_settool_epilog_result_drift:{settool_epilog}")
|
||||
|
||||
def mark_shared_row_ready(row_path, modules_staged=1, ngc_assets_staged=1, ngc_only=0, python_callable=0, prolog=1, epilog=1):
|
||||
row_emit(row_path, "runtime_probe_status", "runtime_lifecycle_probe_passed")
|
||||
row_emit(row_path, "path_prepend_applied", 1)
|
||||
row_emit(row_path, "toplevel_executed", 1)
|
||||
row_emit(row_path, "python_modules_staged", modules_staged)
|
||||
row_emit(row_path, "python_remap_functions_bound", python_callable)
|
||||
row_emit(row_path, "prolog_functions_bound", prolog)
|
||||
row_emit(row_path, "epilog_functions_bound", epilog)
|
||||
row_emit(row_path, "generator_lifecycle_ready", 1)
|
||||
row_emit(row_path, "ngc_remap_assets_staged", ngc_assets_staged)
|
||||
row_emit(row_path, "ngc_only_subpaths_not_standalone", ngc_only)
|
||||
row_emit(row_path, "interpreter_state_binding_ready", 1)
|
||||
row_emit(row_path, "canonical_events_ready", 1)
|
||||
row_emit(row_path, "row_runtime_transcript_ready", 1)
|
||||
|
||||
vmc_row = "axis/vismach/VMC_toolchange/toolchange.ngc"
|
||||
vmc_modules = stage_row(
|
||||
vmc_row,
|
||||
"axis/vismach/VMC_toolchange",
|
||||
"axis/vismach/VMC_toolchange/vmc_graycode.ini",
|
||||
[
|
||||
"axis/nc_files/remap_lib/python-stdglue/stdglue.py",
|
||||
"axis/vismach/VMC_toolchange/remap.py",
|
||||
"axis/vismach/VMC_toolchange/toplevel.py",
|
||||
],
|
||||
["axis/vismach/VMC_toolchange/toolchange.ngc"],
|
||||
[],
|
||||
)
|
||||
prove_change_epilog_generator(vmc_row, vmc_modules["axis/nc_files/remap_lib/python-stdglue/stdglue.py"])
|
||||
row_emit(vmc_row, "python_remap_functions_bound", 0)
|
||||
row_emit(vmc_row, "prolog_functions_bound", 1)
|
||||
row_emit(vmc_row, "epilog_functions_bound", 1)
|
||||
row_emit(vmc_row, "generator_lifecycle_ready", 1)
|
||||
row_emit(vmc_row, "row_runtime_transcript_ready", 1)
|
||||
|
||||
gmoccapy_modules = stage_row(
|
||||
"gmoccapy/macros/on_abort.ngc",
|
||||
"gmoccapy",
|
||||
"gmoccapy/6_axis.ini",
|
||||
[
|
||||
"gmoccapy/python/remap.py",
|
||||
"gmoccapy/python/stdglue.py",
|
||||
"gmoccapy/python/toplevel.py",
|
||||
],
|
||||
[
|
||||
"gmoccapy/macros/change_g43.ngc",
|
||||
"gmoccapy/macros/settool_g43.ngc",
|
||||
],
|
||||
[],
|
||||
)
|
||||
gmoccapy_stdglue = gmoccapy_modules["gmoccapy/python/stdglue.py"]
|
||||
gmoccapy_rows = [
|
||||
"gmoccapy/lathe_configs/boring.ngc",
|
||||
"gmoccapy/lathe_configs/chamfer.ngc",
|
||||
"gmoccapy/lathe_configs/drilling.ngc",
|
||||
"gmoccapy/lathe_configs/facing.ngc",
|
||||
"gmoccapy/lathe_configs/grooving.ngc",
|
||||
"gmoccapy/lathe_configs/radius.ngc",
|
||||
"gmoccapy/lathe_configs/threading.ngc",
|
||||
"gmoccapy/lathe_configs/turning.ngc",
|
||||
"gmoccapy/macros/change.ngc",
|
||||
"gmoccapy/macros/change_g43.ngc",
|
||||
"gmoccapy/macros/go_to_position.ngc",
|
||||
"gmoccapy/macros/halo_world.ngc",
|
||||
"gmoccapy/macros/i_am_lost.ngc",
|
||||
"gmoccapy/macros/increment.ngc",
|
||||
"gmoccapy/macros/jog_around.ngc",
|
||||
"gmoccapy/macros/macro_0.ngc",
|
||||
"gmoccapy/macros/macro_1.ngc",
|
||||
"gmoccapy/macros/macro_10.ngc",
|
||||
"gmoccapy/macros/macro_11.ngc",
|
||||
"gmoccapy/macros/macro_12.ngc",
|
||||
"gmoccapy/macros/macro_13.ngc",
|
||||
"gmoccapy/macros/macro_14.ngc",
|
||||
"gmoccapy/macros/macro_15.ngc",
|
||||
"gmoccapy/macros/macro_2.ngc",
|
||||
"gmoccapy/macros/macro_3.ngc",
|
||||
"gmoccapy/macros/macro_4.ngc",
|
||||
"gmoccapy/macros/macro_5.ngc",
|
||||
"gmoccapy/macros/macro_6.ngc",
|
||||
"gmoccapy/macros/macro_7.ngc",
|
||||
"gmoccapy/macros/macro_8.ngc",
|
||||
"gmoccapy/macros/macro_9.ngc",
|
||||
"gmoccapy/macros/on_abort.ngc",
|
||||
"gmoccapy/macros/settool_g43.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",
|
||||
"gmoccapy/non_trivial_kinematics/table-rotary-tilting/examples/test-xyzac.ngc",
|
||||
"gmoccapy/non_trivial_kinematics/table-rotary-tilting/examples/test-xyzbc.ngc",
|
||||
]
|
||||
for gmoccapy_row in gmoccapy_rows:
|
||||
prove_stdglue_return_callables(gmoccapy_row, gmoccapy_stdglue)
|
||||
mark_shared_row_ready(gmoccapy_row, modules_staged=1, ngc_assets_staged=1)
|
||||
|
||||
twp_rows = [
|
||||
"axis/vismach/5axis/table-rotary_spindle-rotary-nutating/demos/circular_pocket.ngc",
|
||||
"axis/vismach/5axis/table-rotary_spindle-rotary-nutating/demos/incremental_repetition.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/simple_example.ngc",
|
||||
"axis/vismach/5axis/table-rotary_spindle-rotary-nutating/demos/square.ngc",
|
||||
]
|
||||
twp_ngc_assets = [
|
||||
"axis/vismach/5axis/table-rotary_spindle-rotary-nutating/remap_subs/428remap.ngc",
|
||||
"axis/vismach/5axis/table-rotary_spindle-rotary-nutating/remap_subs/429remap.ngc",
|
||||
"axis/vismach/5axis/table-rotary_spindle-rotary-nutating/remap_subs/430remap.ngc",
|
||||
"axis/vismach/5axis/table-rotary_spindle-rotary-nutating/remap_subs/g531remap.ngc",
|
||||
"axis/vismach/5axis/table-rotary_spindle-rotary-nutating/remap_subs/g533remap.ngc",
|
||||
"axis/vismach/5axis/table-rotary_spindle-rotary-nutating/remap_subs/g536remap.ngc",
|
||||
"axis/vismach/5axis/table-rotary_spindle-rotary-nutating/remap_subs/g69remap.ngc",
|
||||
]
|
||||
twp_modules = stage_row(
|
||||
twp_rows[0],
|
||||
"axis/vismach/5axis/table-rotary_spindle-rotary-nutating/xyzacb-trsrn_twp",
|
||||
"axis/vismach/5axis/table-rotary_spindle-rotary-nutating/xyzacb-trsrn_twp/xyzacb-trsrn.ini",
|
||||
[
|
||||
"axis/vismach/5axis/table-rotary_spindle-rotary-nutating/python/remap.py",
|
||||
"axis/vismach/5axis/table-rotary_spindle-rotary-nutating/python/toplevel.py",
|
||||
"axis/vismach/5axis/table-rotary_spindle-rotary-nutating/python/twp-helper-comp.py",
|
||||
"axis/vismach/5axis/table-rotary_spindle-rotary-nutating/python/util.py",
|
||||
],
|
||||
twp_ngc_assets,
|
||||
twp_ngc_assets,
|
||||
)
|
||||
twp_remap = twp_modules["axis/vismach/5axis/table-rotary_spindle-rotary-nutating/python/remap.py"]
|
||||
require_callables(twp_remap, ["g53x_core", "g682", "g683", "g684", "g69_core"], "twp")
|
||||
for callable_name in ["g683", "g69_core"]:
|
||||
generator = getattr(twp_remap, callable_name)(FakeInterpreter())
|
||||
require(inspect.isgenerator(generator), f"twp_{callable_name}_not_generator")
|
||||
first = next(generator)
|
||||
require(first == execute_finish, f"twp_{callable_name}_yield_drift:{first}")
|
||||
for twp_row in twp_rows:
|
||||
mark_shared_row_ready(twp_row, modules_staged=1, ngc_assets_staged=1, ngc_only=1, python_callable=1, prolog=0, epilog=0)
|
||||
|
||||
emit("python_remap_runtime_lifecycle_probe_ok", 1)
|
||||
PY
|
||||
|
||||
@@ -58,6 +58,19 @@ const virtualHalSimConfigMacroLoadFixtures = createVirtualHalSimConfigMacroLoadF
|
||||
manifestText: sourceManifestText,
|
||||
});
|
||||
const virtualHalState = createVirtualHalState();
|
||||
const pythonRemapRuntimeProof = {
|
||||
nativeLifecycleReady: true,
|
||||
nativeProbeStatus: "runtime_lifecycle_probe_passed",
|
||||
nativeProofArtifactPath: "wasm-port/build/native/native-runtime-probe-summary.tsv",
|
||||
wasmLifecycleReady: true,
|
||||
browserLifecycleReady: true,
|
||||
interpreterStateBindingReady: true,
|
||||
generatorLifecycleReady: true,
|
||||
promotionAllowed: false,
|
||||
executionEnabled: false,
|
||||
bulkPromotionAllowed: false,
|
||||
manualLockUpdateRequired: true,
|
||||
};
|
||||
const browserDiagnosticsArtifact = {
|
||||
apiName: "real-browser-simulation-diagnostics-artifact",
|
||||
artifactVersion: 1,
|
||||
@@ -113,6 +126,7 @@ const readyArtifactJson = JSON.stringify(createProjectReleaseReadinessReport({
|
||||
evidenceExpansionRows,
|
||||
virtualHalSimConfigMacroLoadFixtures,
|
||||
virtualHalMotionControllerMatrix: browserDiagnosticsArtifact.virtualHalMotionControllerMatrix,
|
||||
pythonRemapRuntimeProof,
|
||||
}));
|
||||
|
||||
let fetchedUrl = null;
|
||||
@@ -380,6 +394,8 @@ assert.deepEqual(
|
||||
["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"],
|
||||
["python-remap-runtime-proof", "ready"],
|
||||
["python-remap-runtime-proof-detail", "native=ready wasm=ready browser=ready promotion_allowed=0"],
|
||||
...expectedPromotionFamilyRows,
|
||||
["browser-diagnostics", "ready"],
|
||||
["virtual-hal-promotion-candidate-summary", "ready"],
|
||||
|
||||
@@ -31,6 +31,19 @@ const virtualHalSimConfigPromotionCandidates = createVirtualHalSimConfigPromotio
|
||||
motionControllerMatrix: virtualHalMotionControllerMatrix,
|
||||
});
|
||||
const virtualHalSimConfigMacroLoadFixtures = createVirtualHalSimConfigMacroLoadFixtureReport();
|
||||
const pythonRemapRuntimeProof = {
|
||||
nativeLifecycleReady: true,
|
||||
nativeProbeStatus: "runtime_lifecycle_probe_passed",
|
||||
nativeProofArtifactPath: "wasm-port/build/native/native-runtime-probe-summary.tsv",
|
||||
wasmLifecycleReady: true,
|
||||
browserLifecycleReady: true,
|
||||
interpreterStateBindingReady: true,
|
||||
generatorLifecycleReady: true,
|
||||
promotionAllowed: false,
|
||||
executionEnabled: false,
|
||||
bulkPromotionAllowed: false,
|
||||
manualLockUpdateRequired: true,
|
||||
};
|
||||
|
||||
assert.equal(manifest.apiName, "project-release-gate-manifest");
|
||||
assert.equal(manifest.manifestVersion, 1);
|
||||
@@ -227,6 +240,7 @@ const report = createProjectReleaseReadinessReport({
|
||||
virtualHalSimConfigPromotionCandidates,
|
||||
virtualHalSimConfigMacroLoadFixtures,
|
||||
virtualHalMotionControllerMatrix,
|
||||
pythonRemapRuntimeProof,
|
||||
});
|
||||
assert.deepEqual(report.gateManifest, manifest);
|
||||
assert.equal(report.gateExecutionManifest.apiName, "project-release-gate-execution-manifest");
|
||||
@@ -324,6 +338,16 @@ assert.deepEqual(createProjectReleaseReadinessSummaryViewModel(report), {
|
||||
label: "Tool DB process proof detail",
|
||||
value: "wasm=ready browser=ready opfs=ready promotion_allowed=0",
|
||||
},
|
||||
{
|
||||
id: "python-remap-runtime-proof",
|
||||
label: "Python remap runtime proof",
|
||||
value: "ready",
|
||||
},
|
||||
{
|
||||
id: "python-remap-runtime-proof-detail",
|
||||
label: "Python remap runtime proof detail",
|
||||
value: "native=ready wasm=ready browser=ready promotion_allowed=0",
|
||||
},
|
||||
{
|
||||
id: "blocked-runtime-families",
|
||||
label: "Blocked runtime families",
|
||||
@@ -353,7 +377,7 @@ assert.deepEqual(createProjectReleaseReadinessSummaryViewModel(report), {
|
||||
});
|
||||
assert.equal(
|
||||
createProjectReleaseReadinessSummaryViewModel(createProjectReleaseReadinessReport()).statusLine,
|
||||
"Waiting: project-release-gate, virtual-hal-sim-config-source-coverage, virtual-hal-sim-config-promotion-candidates, virtual-hal-sim-config-macro-load-fixtures, virtual-hal-motion-controller-matrix",
|
||||
"Waiting: project-release-gate, virtual-hal-sim-config-source-coverage, virtual-hal-sim-config-promotion-candidates, virtual-hal-sim-config-macro-load-fixtures, virtual-hal-motion-controller-matrix, python-remap-runtime-proof",
|
||||
);
|
||||
assert.equal(
|
||||
createProjectReleaseReadinessSummaryViewModel(createProjectReleaseReadinessReport({
|
||||
@@ -362,6 +386,7 @@ assert.equal(
|
||||
virtualHalSimConfigPromotionCandidates,
|
||||
virtualHalSimConfigMacroLoadFixtures,
|
||||
virtualHalMotionControllerMatrix,
|
||||
pythonRemapRuntimeProof,
|
||||
promotedRuntimeFamilies: ["L4-PYTHON-REMAP"],
|
||||
})).rows.find(({ id }) => id === "blocked-runtime-families")?.value,
|
||||
"promoted: L4-PYTHON-REMAP",
|
||||
@@ -428,6 +453,8 @@ assert.deepEqual(
|
||||
["virtual-hal-motion-controller-matrix", "ready"],
|
||||
["tool-db-process-proof", "ready"],
|
||||
["tool-db-process-proof-detail", "wasm=ready browser=ready opfs=ready promotion_allowed=0"],
|
||||
["python-remap-runtime-proof", "ready"],
|
||||
["python-remap-runtime-proof-detail", "native=ready wasm=ready browser=ready promotion_allowed=0"],
|
||||
["missing", "none"],
|
||||
],
|
||||
);
|
||||
@@ -548,6 +575,8 @@ assert.deepEqual(
|
||||
["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"],
|
||||
["python-remap-runtime-proof", "ready"],
|
||||
["python-remap-runtime-proof-detail", "native=ready wasm=ready browser=ready promotion_allowed=0"],
|
||||
...expectedPromotionFamilyRows,
|
||||
["browser-diagnostics", "not requested"],
|
||||
["virtual-hal-promotion-candidate-summary", "not requested"],
|
||||
|
||||
@@ -5,11 +5,15 @@ import {
|
||||
} from "../../../runtime/sdk/src/python-remap-browser-worker-adapter.js";
|
||||
import {
|
||||
PYTHON_REMAP_RUNTIME_PORT_CONTRACT_VERSION,
|
||||
PYTHON_REMAP_ROW_RUNTIME_PROOF_PHASES,
|
||||
PYTHON_REMAP_STOP_LOOKAHEAD_FIXTURE,
|
||||
createLinuxCncPythonRemapRowRuntimePort,
|
||||
createLinuxCncPythonRemapRuntimePort,
|
||||
createPythonRemapLifecyclePlan,
|
||||
createPythonRemapRowRuntimePlan,
|
||||
createPythonRemapRuntimeDiagnostics,
|
||||
validatePythonRemapLifecycleTranscript,
|
||||
validatePythonRemapRowRuntimeTranscript,
|
||||
} from "../../../runtime/sdk/src/python-remap-runtime-port.js";
|
||||
|
||||
assert.equal(PYTHON_REMAP_RUNTIME_PORT_CONTRACT_VERSION, 1);
|
||||
@@ -31,6 +35,133 @@ assert.deepEqual(
|
||||
"export_diagnostics",
|
||||
],
|
||||
);
|
||||
assert.ok(PYTHON_REMAP_ROW_RUNTIME_PROOF_PHASES.includes("export_canonical_events"));
|
||||
|
||||
const rowRuntimeContext = {
|
||||
path: "axis/remap/cycle/nc_files/examples.ngc",
|
||||
iniPath: "axis/remap/cycle/cycle.ini",
|
||||
family: "axis/remap/cycle/nc_files",
|
||||
machineRoot: "axis/remap/cycle",
|
||||
pythonPathPrepend: "python",
|
||||
topLevelPath: "python/toplevel.py",
|
||||
sourceFiles: [
|
||||
"axis/nc_files/remap_lib/python-stdglue/stdglue.py",
|
||||
"axis/remap/cycle/python/remap.py",
|
||||
"axis/remap/cycle/python/toplevel.py",
|
||||
],
|
||||
remapDeclarations: ["G84.2"],
|
||||
pythonRemapFunctions: ["g842@axis/remap/cycle/python/remap.py"],
|
||||
prologFunctions: ["cycle_prolog@axis/nc_files/remap_lib/python-stdglue/stdglue.py"],
|
||||
epilogFunctions: ["cycle_epilog@axis/nc_files/remap_lib/python-stdglue/stdglue.py"],
|
||||
ngcRemapFiles: ["axis/remap/cycle/nc_subroutines/g843.ngc"],
|
||||
ngcOnlySubpaths: [],
|
||||
};
|
||||
const rowPlan = createPythonRemapRowRuntimePlan(rowRuntimeContext);
|
||||
assert.equal(rowPlan.filter((step) => step.phase === "import_module").length, 3);
|
||||
assert.equal(rowPlan.filter((step) => step.phase === "callable_lookup").length, 3);
|
||||
assert.equal(rowPlan.filter((step) => step.phase === "stage_ngc_remap_asset").length, 1);
|
||||
assert.ok(rowPlan.some((step) => step.phase === "export_canonical_events"));
|
||||
|
||||
const contractOnlyRowPort = createLinuxCncPythonRemapRowRuntimePort(rowRuntimeContext);
|
||||
const contractOnlyRowStart = await contractOnlyRowPort.start();
|
||||
assert.deepEqual(contractOnlyRowStart, {
|
||||
runtimeMode: "row-runtime-contract-only",
|
||||
runtimeExecutionReady: false,
|
||||
status: null,
|
||||
executionEnabled: false,
|
||||
promotionAllowed: false,
|
||||
bulkPromotionAllowed: false,
|
||||
});
|
||||
const contractOnlyRowPlan = await contractOnlyRowPort.runRowRuntimePlan();
|
||||
assert.equal(contractOnlyRowPlan.status, "blocked_row_runtime_adapter_required");
|
||||
assert.equal(contractOnlyRowPlan.promotionAllowed, false);
|
||||
await contractOnlyRowPort.close();
|
||||
|
||||
const fakeRowAdapter = {
|
||||
async start(context) {
|
||||
assert.equal(context.path, rowRuntimeContext.path);
|
||||
assert.equal(context.sourceFiles.length, 3);
|
||||
assert.equal(context.ngcRemapFiles.length, 1);
|
||||
return {
|
||||
runtimeExecutionReady: true,
|
||||
status: "row_runtime_ready",
|
||||
};
|
||||
},
|
||||
async initializePython() {
|
||||
return { value: "python-runtime-initialized" };
|
||||
},
|
||||
async applyIniPythonPath(payload) {
|
||||
return { value: payload.pythonPathPrepend };
|
||||
},
|
||||
async executeTopLevel(payload) {
|
||||
return { value: payload.topLevelPath };
|
||||
},
|
||||
async importModule(payload) {
|
||||
return { value: payload.modulePath };
|
||||
},
|
||||
async lookupCallable(payload) {
|
||||
return { value: payload.callableName };
|
||||
},
|
||||
async invokeGenerator(payload) {
|
||||
return { value: `generator:${payload.callableName}` };
|
||||
},
|
||||
async observeFirstYield(payload) {
|
||||
return { value: `yield:${payload.callableName}` };
|
||||
},
|
||||
async finishGenerator(payload) {
|
||||
return { value: `finish:${payload.callableName}` };
|
||||
},
|
||||
async stageNgcRemapAsset(payload) {
|
||||
return { value: payload.ngcPath };
|
||||
},
|
||||
async rejectNgcOnlyStandalone(payload) {
|
||||
return { value: payload.ngcPath };
|
||||
},
|
||||
async exportInterpreterState() {
|
||||
return { value: "interpreter-state-bound" };
|
||||
},
|
||||
async exportCanonicalEvents() {
|
||||
return { value: "canonical-events-bound" };
|
||||
},
|
||||
async exportDiagnostics() {
|
||||
return { value: "diagnostics-exported" };
|
||||
},
|
||||
};
|
||||
const readyRowPort = createLinuxCncPythonRemapRowRuntimePort({
|
||||
...rowRuntimeContext,
|
||||
runtimeMode: "row-runtime-test-adapter",
|
||||
runtimeAdapter: fakeRowAdapter,
|
||||
});
|
||||
const readyRowStart = await readyRowPort.start();
|
||||
assert.equal(readyRowStart.runtimeExecutionReady, true);
|
||||
assert.equal(readyRowStart.status, "row_runtime_ready");
|
||||
const readyRowPlan = await readyRowPort.runRowRuntimePlan();
|
||||
assert.equal(readyRowPlan.status, "row_runtime_adapter_plan_executed");
|
||||
assert.equal(readyRowPlan.validation.ready, true);
|
||||
assert.equal(readyRowPlan.validation.moduleImportReady, true);
|
||||
assert.equal(readyRowPlan.validation.callableLookupReady, true);
|
||||
assert.equal(readyRowPlan.validation.generatorLifecycleReady, true);
|
||||
assert.equal(readyRowPlan.validation.ngcRemapAssetsReady, true);
|
||||
assert.equal(readyRowPlan.validation.ngcOnlySubpathsGuarded, true);
|
||||
assert.equal(readyRowPlan.validation.interpreterStateBindingReady, true);
|
||||
assert.equal(readyRowPlan.validation.canonicalEventsReady, true);
|
||||
assert.equal(readyRowPlan.promotionAllowed, false);
|
||||
assert.equal(readyRowPlan.bulkPromotionAllowed, false);
|
||||
const rowTranscript = readyRowPort.exportTranscript();
|
||||
const rowValidation = validatePythonRemapRowRuntimeTranscript({
|
||||
...rowRuntimeContext,
|
||||
rowPath: rowRuntimeContext.path,
|
||||
transcript: rowTranscript,
|
||||
});
|
||||
assert.equal(rowValidation.ready, true);
|
||||
const rowDiagnostics = readyRowPort.exportDiagnostics();
|
||||
assert.equal(rowDiagnostics.rowRuntimeTranscriptReady, true);
|
||||
assert.equal(rowDiagnostics.jsCncSemantics, false);
|
||||
assert.equal(rowDiagnostics.ngcOnlySubroutinePromoted, false);
|
||||
assert.equal(rowDiagnostics.executionEnabled, false);
|
||||
assert.equal(rowDiagnostics.promotionAllowed, false);
|
||||
assert.equal(rowDiagnostics.bulkPromotionAllowed, false);
|
||||
await readyRowPort.close();
|
||||
|
||||
const contractOnlyPort = createLinuxCncPythonRemapRuntimePort({
|
||||
runtimeMode: "contract-only",
|
||||
@@ -209,3 +340,12 @@ const explicitDiagnostics = createPythonRemapRuntimeDiagnostics({
|
||||
});
|
||||
assert.equal(explicitDiagnostics.transcriptHash.length, 8);
|
||||
assert.equal(explicitDiagnostics.lifecycleTranscriptReady, true);
|
||||
|
||||
const mismatchedTranscript = transcript.map((entry) =>
|
||||
entry.phase === "execute_toplevel"
|
||||
? { ...entry, value: "python/not-toplevel.py" }
|
||||
: entry
|
||||
);
|
||||
const mismatchedValidation = validatePythonRemapLifecycleTranscript(mismatchedTranscript);
|
||||
assert.equal(mismatchedValidation.ready, false);
|
||||
assert.deepEqual(mismatchedValidation.mismatchedValues, ["execute_toplevel"]);
|
||||
|
||||
@@ -93,13 +93,16 @@ import {
|
||||
createLinuxCncToolDbBrowserWorkerAdapter,
|
||||
createLinuxCncToolDbProcessPort,
|
||||
createLinuxCncPythonRemapBrowserWorkerAdapter,
|
||||
createLinuxCncPythonRemapRowRuntimePort,
|
||||
createLinuxCncPythonRemapRuntimePort,
|
||||
createPythonRemapLifecyclePlan,
|
||||
createPythonRemapRowRuntimePlan,
|
||||
createPythonRemapRuntimeDiagnostics,
|
||||
createToolDbProcessDiagnostics,
|
||||
createToolDbTransactionPlan,
|
||||
runToolDbProcessPortPersistenceSession,
|
||||
validatePythonRemapLifecycleTranscript,
|
||||
validatePythonRemapRowRuntimeTranscript,
|
||||
createVirtualHalBridgeActionPlan,
|
||||
createVirtualHalBridgeReadiness,
|
||||
createVirtualHalCommandScriptFixtureReport,
|
||||
@@ -521,13 +524,16 @@ const requiredExports = [
|
||||
["createLinuxCncToolDbBrowserWorkerAdapter", createLinuxCncToolDbBrowserWorkerAdapter],
|
||||
["createLinuxCncToolDbProcessPort", createLinuxCncToolDbProcessPort],
|
||||
["createLinuxCncPythonRemapBrowserWorkerAdapter", createLinuxCncPythonRemapBrowserWorkerAdapter],
|
||||
["createLinuxCncPythonRemapRowRuntimePort", createLinuxCncPythonRemapRowRuntimePort],
|
||||
["createLinuxCncPythonRemapRuntimePort", createLinuxCncPythonRemapRuntimePort],
|
||||
["createPythonRemapLifecyclePlan", createPythonRemapLifecyclePlan],
|
||||
["createPythonRemapRowRuntimePlan", createPythonRemapRowRuntimePlan],
|
||||
["createPythonRemapRuntimeDiagnostics", createPythonRemapRuntimeDiagnostics],
|
||||
["createToolDbProcessDiagnostics", createToolDbProcessDiagnostics],
|
||||
["createToolDbTransactionPlan", createToolDbTransactionPlan],
|
||||
["runToolDbProcessPortPersistenceSession", runToolDbProcessPortPersistenceSession],
|
||||
["validatePythonRemapLifecycleTranscript", validatePythonRemapLifecycleTranscript],
|
||||
["validatePythonRemapRowRuntimeTranscript", validatePythonRemapRowRuntimeTranscript],
|
||||
["validateToolDbTranscript", validateToolDbTranscript],
|
||||
["saveToolDbFile", saveToolDbFile],
|
||||
["loadToolDbFile", loadToolDbFile],
|
||||
@@ -1506,6 +1512,19 @@ assert.equal(normalizeOpfsPath("linuxcnc/machines/sdk-mill/tool.tbl"), "linuxcnc
|
||||
assert.equal(gcodeFilenameFromProgramPath("linuxcnc/gcode/demo.ngc"), "demo.ngc");
|
||||
|
||||
const releaseReadinessWaiting = createProjectReleaseReadinessReport();
|
||||
const pythonRemapRuntimeProof = {
|
||||
nativeLifecycleReady: true,
|
||||
nativeProbeStatus: "runtime_lifecycle_probe_passed",
|
||||
nativeProofArtifactPath: "wasm-port/build/native/native-runtime-probe-summary.tsv",
|
||||
wasmLifecycleReady: true,
|
||||
browserLifecycleReady: true,
|
||||
interpreterStateBindingReady: true,
|
||||
generatorLifecycleReady: true,
|
||||
promotionAllowed: false,
|
||||
executionEnabled: false,
|
||||
bulkPromotionAllowed: false,
|
||||
manualLockUpdateRequired: true,
|
||||
};
|
||||
const batchCapabilityMatrix = createProjectBatchAcceptanceCapabilityMatrix({
|
||||
capabilities: [
|
||||
{
|
||||
@@ -1621,6 +1640,7 @@ assert.deepEqual(releaseReadinessWaiting.missing, [
|
||||
"virtual-hal-sim-config-promotion-candidates",
|
||||
"virtual-hal-sim-config-macro-load-fixtures",
|
||||
"virtual-hal-motion-controller-matrix",
|
||||
"python-remap-runtime-proof",
|
||||
]);
|
||||
assert.equal(releaseReadinessWaiting.simConfigInventory.unexpectedFail, 0);
|
||||
assert.deepEqual(releaseReadinessWaiting.promotedBlockedFamilies, []);
|
||||
@@ -1645,6 +1665,7 @@ const releaseReadinessReady = createProjectReleaseReadinessReport({
|
||||
virtualHalSimConfigPromotionCandidates: simConfigPromotionCandidateReport,
|
||||
virtualHalSimConfigMacroLoadFixtures: simConfigMacroLoadFixtureReport,
|
||||
virtualHalMotionControllerMatrix: manifestCheckedMotionControllerMatrixReport,
|
||||
pythonRemapRuntimeProof,
|
||||
});
|
||||
assert.equal(releaseReadinessReady.ready, true);
|
||||
assert.equal(releaseReadinessReady.releaseGate.passed, true);
|
||||
@@ -1698,6 +1719,9 @@ const expectedToolDbProcessProofSummary = {
|
||||
};
|
||||
assert.deepEqual(releaseReadinessReady.toolDbProcessProofSummary, expectedToolDbProcessProofSummary);
|
||||
assert.equal(releaseReadinessReady.toolDbProcessProofReady, true);
|
||||
assert.equal(releaseReadinessReady.pythonRemapRuntimeProofReady, true);
|
||||
assert.equal(releaseReadinessReady.pythonRemapRuntimeProofSummary.nativeLifecycleReady, true);
|
||||
assert.equal(releaseReadinessReady.pythonRemapRuntimeProofSummary.promotionAllowed, false);
|
||||
assert.deepEqual(releaseReadinessReady.gateManifest, createProjectReleaseGateManifest());
|
||||
assert.equal(releaseReadinessReady.gateResultMatrix.rows.length, createProjectReleaseGateManifest().gateCount);
|
||||
assert.equal(createProjectReleaseGateActionPlan({
|
||||
@@ -1723,6 +1747,7 @@ const releaseReadinessWithCandidateArtifacts = createProjectReleaseReadinessRepo
|
||||
virtualHalMotionControllerMatrix: manifestCheckedMotionControllerMatrixReport,
|
||||
promotionCandidateRows: promotionCandidateArtifactRows,
|
||||
evidenceExpansionRows: evidenceExpansionArtifactRows,
|
||||
pythonRemapRuntimeProof,
|
||||
});
|
||||
assert.equal(releaseReadinessWithCandidateArtifacts.promotionCandidateArtifactSummary.artifactRows.promotionCandidates, 27);
|
||||
assert.equal(releaseReadinessWithCandidateArtifacts.promotionCandidateArtifactSummary.artifactRows.evidenceExpansion, 14);
|
||||
@@ -1792,6 +1817,7 @@ const releaseReadinessWithScreenshots = createProjectReleaseReadinessReport({
|
||||
virtualHalSimConfigPromotionCandidates: simConfigPromotionCandidateReport,
|
||||
virtualHalSimConfigMacroLoadFixtures: simConfigMacroLoadFixtureReport,
|
||||
virtualHalMotionControllerMatrix: manifestCheckedMotionControllerMatrixReport,
|
||||
pythonRemapRuntimeProof,
|
||||
axisScreenshotArtifacts: ["desktop-preview", "desktop-dro", "mobile-preview", "mobile-mdi"].map((viewportName) => ({
|
||||
apiName: "real-browser-simulation-axis-screenshot-artifact",
|
||||
artifactVersion: 1,
|
||||
@@ -1829,6 +1855,7 @@ const releaseReadinessArtifact = parseProjectReleaseReadinessArtifactJson(JSON.s
|
||||
virtualHalSimConfigPromotionCandidates: simConfigPromotionCandidateReport,
|
||||
virtualHalSimConfigMacroLoadFixtures: simConfigMacroLoadFixtureReport,
|
||||
virtualHalMotionControllerMatrix: manifestCheckedMotionControllerMatrixReport,
|
||||
pythonRemapRuntimeProof,
|
||||
})));
|
||||
assert.equal(releaseReadinessArtifact.apiName, "project-release-readiness-report");
|
||||
const releaseReadinessArtifactValidation = createProjectReleaseReadinessArtifactValidation(releaseReadinessArtifact);
|
||||
@@ -1858,6 +1885,39 @@ assert.deepEqual(releaseReadinessArtifactValidation, {
|
||||
virtualHalMotionControllerMatrixReady: true,
|
||||
toolDbProcessProofSummary: expectedToolDbProcessProofSummary,
|
||||
toolDbProcessProofReady: true,
|
||||
pythonRemapRuntimeProofSummary: {
|
||||
apiName: "python-remap-runtime-proof-summary",
|
||||
summaryVersion: 1,
|
||||
phase: "ready",
|
||||
ready: true,
|
||||
boundaryClass: "L4-PYTHON-REMAP",
|
||||
fixtureFamily: "axis/remap/stop-lookahead/nc_files",
|
||||
fixtureId: "stop_lookahead_python_runtime_lifecycle",
|
||||
iniPath: "axis/remap/stop-lookahead/demo.ini",
|
||||
pythonPathPrepend: "python",
|
||||
topLevelPath: "python/toplevel.py",
|
||||
callableName: "queuebuster",
|
||||
runtimeMode: "browser-python-wasm-worker",
|
||||
nativeProbeStatus: "runtime_lifecycle_probe_passed",
|
||||
nativeProofArtifactPath: "wasm-port/build/native/native-runtime-probe-summary.tsv",
|
||||
nativeProofStdoutLog: null,
|
||||
nativeLifecycleReady: true,
|
||||
wasmLifecycleReady: true,
|
||||
browserLifecycleReady: true,
|
||||
interpreterStateBindingReady: true,
|
||||
generatorLifecycleReady: true,
|
||||
promotionAllowed: false,
|
||||
executionEnabled: false,
|
||||
bulkPromotionAllowed: false,
|
||||
manualLockUpdateRequired: true,
|
||||
requiredCommands: [
|
||||
"ENABLE_PYTHON_REMAP_RUNTIME_PROBE=1 wasm-port/tests/native/probe_python_remap_runtime.sh",
|
||||
"wasm-port/tests/sdk/node/verify_python_remap_runtime_port.sh",
|
||||
"SKIP_INTERP_BUILD=1 wasm-port/tests/wasm/node/verify_python_remap_runtime_port_wasm.sh",
|
||||
"SKIP_INI_BUILD=1 SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_python_remap_runtime_browser.sh",
|
||||
],
|
||||
},
|
||||
pythonRemapRuntimeProofReady: true,
|
||||
axisScreenshotArtifactSummaryReady: true,
|
||||
axisScreenshotArtifactCount: 0,
|
||||
blockedRuntimeFamilies: [
|
||||
@@ -1993,6 +2053,16 @@ assert.deepEqual(releaseReadinessArtifactValidation, {
|
||||
label: "Tool DB process proof detail",
|
||||
value: "wasm=ready browser=ready opfs=ready promotion_allowed=0",
|
||||
},
|
||||
{
|
||||
id: "python-remap-runtime-proof",
|
||||
label: "Python remap runtime proof",
|
||||
value: "ready",
|
||||
},
|
||||
{
|
||||
id: "python-remap-runtime-proof-detail",
|
||||
label: "Python remap runtime proof detail",
|
||||
value: "native=ready wasm=ready browser=ready promotion_allowed=0",
|
||||
},
|
||||
{
|
||||
id: "blocked-runtime-families",
|
||||
label: "Blocked runtime families",
|
||||
|
||||
@@ -94,6 +94,19 @@ assert.deepEqual(manifest, {
|
||||
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowSummaryViewModel",
|
||||
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan",
|
||||
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState",
|
||||
"getWorkflowOverviewPromotionFamilyRowsRenderState",
|
||||
"getWorkflowOverviewPromotionFamilySourceFilterViewModel",
|
||||
"getWorkflowOverviewPromotionFamilySourceFilterDomContract",
|
||||
"getWorkflowOverviewPromotionFamilySourceFilterDomReadiness",
|
||||
"getWorkflowOverviewPromotionFamilySourceFilterSelectionActionPlan",
|
||||
"handleWorkflowOverviewPromotionFamilySourceFilterSelectionChange",
|
||||
"bindWorkflowOverviewPromotionFamilySourceFilterSelectionControls",
|
||||
"renderWorkflowOverviewPromotionFamilySourceFilterState",
|
||||
"mountWorkflowOverviewPromotionFamilySourceFilterState",
|
||||
"getWorkflowOverviewPromotionFamilyRowsDomContract",
|
||||
"getWorkflowOverviewPromotionFamilyRowsDomReadiness",
|
||||
"renderWorkflowOverviewPromotionFamilyRowsState",
|
||||
"mountWorkflowOverviewPromotionFamilyRowsState",
|
||||
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowDomContract",
|
||||
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowDomReadiness",
|
||||
"renderWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState",
|
||||
|
||||
@@ -216,7 +216,7 @@ assert.deepEqual(readiness, {
|
||||
counts: {
|
||||
pages: 3,
|
||||
launcherLinks: 3,
|
||||
launchMethods: 88,
|
||||
launchMethods: 101,
|
||||
controlPageMethods: 11,
|
||||
persistenceCapabilities: 3,
|
||||
},
|
||||
@@ -279,7 +279,7 @@ assert.deepEqual(handoffSummary, {
|
||||
counts: {
|
||||
pages: 3,
|
||||
launcherLinks: 3,
|
||||
launchMethods: 88,
|
||||
launchMethods: 101,
|
||||
controlPageMethods: 11,
|
||||
persistenceCapabilities: 3,
|
||||
},
|
||||
@@ -826,11 +826,24 @@ assert.deepEqual(createIniPanelShellWorkflowOverviewContract(), {
|
||||
"getWorkflowOverviewReleaseReadinessArtifactJsonWorkflowDomReadiness",
|
||||
"renderWorkflowOverviewReleaseReadinessArtifactJsonWorkflowState",
|
||||
"mountWorkflowOverviewReleaseReadinessArtifactJsonWorkflowState",
|
||||
"loadWorkflowOverviewReleaseReadinessArtifactUrl",
|
||||
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowSummaryViewModel",
|
||||
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan",
|
||||
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState",
|
||||
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowDomContract",
|
||||
"loadWorkflowOverviewReleaseReadinessArtifactUrl",
|
||||
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowSummaryViewModel",
|
||||
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan",
|
||||
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState",
|
||||
"getWorkflowOverviewPromotionFamilyRowsRenderState",
|
||||
"getWorkflowOverviewPromotionFamilySourceFilterViewModel",
|
||||
"getWorkflowOverviewPromotionFamilySourceFilterDomContract",
|
||||
"getWorkflowOverviewPromotionFamilySourceFilterDomReadiness",
|
||||
"getWorkflowOverviewPromotionFamilySourceFilterSelectionActionPlan",
|
||||
"handleWorkflowOverviewPromotionFamilySourceFilterSelectionChange",
|
||||
"bindWorkflowOverviewPromotionFamilySourceFilterSelectionControls",
|
||||
"renderWorkflowOverviewPromotionFamilySourceFilterState",
|
||||
"mountWorkflowOverviewPromotionFamilySourceFilterState",
|
||||
"getWorkflowOverviewPromotionFamilyRowsDomContract",
|
||||
"getWorkflowOverviewPromotionFamilyRowsDomReadiness",
|
||||
"renderWorkflowOverviewPromotionFamilyRowsState",
|
||||
"mountWorkflowOverviewPromotionFamilyRowsState",
|
||||
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowDomContract",
|
||||
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowDomReadiness",
|
||||
"renderWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState",
|
||||
"mountWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState",
|
||||
@@ -965,6 +978,19 @@ assert.deepEqual(
|
||||
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowSummaryViewModel",
|
||||
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan",
|
||||
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState",
|
||||
"getWorkflowOverviewPromotionFamilyRowsRenderState",
|
||||
"getWorkflowOverviewPromotionFamilySourceFilterViewModel",
|
||||
"getWorkflowOverviewPromotionFamilySourceFilterDomContract",
|
||||
"getWorkflowOverviewPromotionFamilySourceFilterDomReadiness",
|
||||
"getWorkflowOverviewPromotionFamilySourceFilterSelectionActionPlan",
|
||||
"handleWorkflowOverviewPromotionFamilySourceFilterSelectionChange",
|
||||
"bindWorkflowOverviewPromotionFamilySourceFilterSelectionControls",
|
||||
"renderWorkflowOverviewPromotionFamilySourceFilterState",
|
||||
"mountWorkflowOverviewPromotionFamilySourceFilterState",
|
||||
"getWorkflowOverviewPromotionFamilyRowsDomContract",
|
||||
"getWorkflowOverviewPromotionFamilyRowsDomReadiness",
|
||||
"renderWorkflowOverviewPromotionFamilyRowsState",
|
||||
"mountWorkflowOverviewPromotionFamilyRowsState",
|
||||
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowDomContract",
|
||||
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowDomReadiness",
|
||||
"renderWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState",
|
||||
@@ -1408,7 +1434,7 @@ assert.deepEqual(createIniPanelShellIntegrationReadiness(blockedManifest), {
|
||||
counts: {
|
||||
pages: 3,
|
||||
launcherLinks: 3,
|
||||
launchMethods: 88,
|
||||
launchMethods: 101,
|
||||
controlPageMethods: 11,
|
||||
persistenceCapabilities: 3,
|
||||
},
|
||||
|
||||
@@ -1473,6 +1473,19 @@ const releaseReadinessMacroLoadFixtures = createVirtualHalSimConfigMacroLoadFixt
|
||||
"linuxcnc/configs/sim/axis/external_offsets/eoffsets.ngc",
|
||||
],
|
||||
});
|
||||
const pythonRemapRuntimeProof = {
|
||||
nativeLifecycleReady: true,
|
||||
nativeProbeStatus: "runtime_lifecycle_probe_passed",
|
||||
nativeProofArtifactPath: "wasm-port/build/native/native-runtime-probe-summary.tsv",
|
||||
wasmLifecycleReady: true,
|
||||
browserLifecycleReady: true,
|
||||
interpreterStateBindingReady: true,
|
||||
generatorLifecycleReady: true,
|
||||
promotionAllowed: false,
|
||||
executionEnabled: false,
|
||||
bulkPromotionAllowed: false,
|
||||
manualLockUpdateRequired: true,
|
||||
};
|
||||
const releaseReadinessArtifactJson = JSON.stringify(createProjectReleaseReadinessReport({
|
||||
gateResults: Object.fromEntries(createProjectReleaseGateManifest().gateIds.map((id) => [id, true])),
|
||||
virtualHalSimConfigSourceCoverage: createVirtualHalSimConfigSourceCoverageReport(),
|
||||
@@ -1482,6 +1495,7 @@ const releaseReadinessArtifactJson = JSON.stringify(createProjectReleaseReadines
|
||||
evidenceExpansionRows,
|
||||
virtualHalSimConfigMacroLoadFixtures: releaseReadinessMacroLoadFixtures,
|
||||
virtualHalMotionControllerMatrix: releaseReadinessMotionControllerMatrix,
|
||||
pythonRemapRuntimeProof,
|
||||
}));
|
||||
const browserDiagnosticsVirtualHalState = createVirtualHalState();
|
||||
const browserDiagnosticsArtifact = {
|
||||
@@ -1833,7 +1847,7 @@ const releaseArtifactMountResult = mountIniPanelShellWorkflowOverviewReleaseRead
|
||||
rowsNode: releaseArtifactRowsNode,
|
||||
});
|
||||
assert.equal(releaseArtifactRenderResult.rendered, true);
|
||||
assert.equal(releaseArtifactRenderResult.rowCount, 32);
|
||||
assert.equal(releaseArtifactRenderResult.rowCount, 34);
|
||||
assert.equal(releaseArtifactRenderResult.dataset.handoffScope, "workflow-overview-release-readiness-artifact");
|
||||
assert.equal(
|
||||
releaseArtifactRenderResult.rowIds.includes("gate-execution-manifest"),
|
||||
@@ -1887,8 +1901,12 @@ assert.equal(
|
||||
releaseArtifactRenderResult.rowIds.includes("tool-db-process-proof"),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
releaseArtifactRenderResult.rowIds.includes("python-remap-runtime-proof"),
|
||||
true,
|
||||
);
|
||||
assert.equal(releaseArtifactMountResult.ready, true);
|
||||
assert.equal(releaseArtifactMountResult.renderResult.rowCount, 32);
|
||||
assert.equal(releaseArtifactMountResult.renderResult.rowCount, 34);
|
||||
assert.deepEqual(
|
||||
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson("{").missing,
|
||||
["artifact-json"],
|
||||
@@ -1947,7 +1965,11 @@ assert.equal(
|
||||
);
|
||||
assert.equal(releaseArtifactUrlWorkflow.renderState.statusLine, "Ready: No blocking reasons");
|
||||
assert.equal(releaseArtifactUrlWorkflow.mountResult.ready, true);
|
||||
assert.equal(releaseArtifactUrlWorkflow.mountResult.renderResult.rowCount, 32);
|
||||
assert.equal(releaseArtifactUrlWorkflow.mountResult.renderResult.rowCount, 34);
|
||||
assert.equal(
|
||||
releaseArtifactUrlWorkflow.mountResult.renderResult.rowIds.includes("python-remap-runtime-proof"),
|
||||
true,
|
||||
);
|
||||
const releaseArtifactUrlWorkflowSummary =
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowSummaryViewModel(
|
||||
releaseArtifactUrlWorkflow,
|
||||
@@ -2037,11 +2059,11 @@ assert.equal(
|
||||
);
|
||||
assert.equal(
|
||||
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "promotion-candidate-artifact-rows")?.value,
|
||||
"28",
|
||||
"27",
|
||||
);
|
||||
assert.equal(
|
||||
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "evidence-expansion-artifact-rows")?.value,
|
||||
"13",
|
||||
"14",
|
||||
);
|
||||
assert.equal(
|
||||
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "evidence-expansion-baseline-changing")?.value,
|
||||
@@ -2077,7 +2099,7 @@ assert.equal(
|
||||
);
|
||||
assert.equal(
|
||||
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "hard-block-runtime-lock")?.value,
|
||||
"locked (3 families)",
|
||||
"locked (2 families)",
|
||||
);
|
||||
assert.equal(
|
||||
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "promoted-blocked-family-count")?.value,
|
||||
@@ -2085,11 +2107,11 @@ assert.equal(
|
||||
);
|
||||
assert.equal(
|
||||
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "hard-block-runtime-locked-rows")?.value,
|
||||
"19",
|
||||
"18",
|
||||
);
|
||||
assert.equal(
|
||||
releaseArtifactUrlWorkflowSummary.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(
|
||||
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "hard-block-runtime-promotion-allowed")?.value,
|
||||
@@ -2097,19 +2119,19 @@ assert.equal(
|
||||
);
|
||||
assert.equal(
|
||||
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "hard-block-runtime-family-count")?.value,
|
||||
"3",
|
||||
"2",
|
||||
);
|
||||
assert.equal(
|
||||
releaseArtifactUrlWorkflowSummary.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(
|
||||
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "hard-block-runtime-detail-row-count")?.value,
|
||||
"19",
|
||||
"18",
|
||||
);
|
||||
assert.equal(
|
||||
releaseArtifactUrlWorkflowSummary.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",
|
||||
"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(
|
||||
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "hard-block-runtime-family-L4-PYTHON-REMAP")?.value,
|
||||
@@ -2819,7 +2841,7 @@ const releaseArtifactUrlWorkflowMountResult =
|
||||
rowsNode: releaseArtifactUrlWorkflowRowsNode,
|
||||
});
|
||||
assert.equal(releaseArtifactUrlWorkflowRenderResult.rendered, true);
|
||||
assert.equal(releaseArtifactUrlWorkflowRenderResult.rowCount, 59);
|
||||
assert.equal(releaseArtifactUrlWorkflowRenderResult.rowCount, 57);
|
||||
assert.equal(
|
||||
releaseArtifactUrlWorkflowRenderResult.rowIds.includes("browser-diagnostics"),
|
||||
true,
|
||||
@@ -2869,7 +2891,7 @@ assert.equal(
|
||||
true,
|
||||
);
|
||||
assert.equal(releaseArtifactUrlWorkflowMountResult.ready, true);
|
||||
assert.equal(releaseArtifactUrlWorkflowMountResult.renderResult.rowCount, 59);
|
||||
assert.equal(releaseArtifactUrlWorkflowMountResult.renderResult.rowCount, 57);
|
||||
const releaseArtifactUrlWorkflowMissingDom = await loadIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrl({
|
||||
artifactUrl: "/project-release-readiness.json",
|
||||
fetchRef: async () => ({
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -232,7 +232,7 @@ assert.deepEqual(
|
||||
["python_runtime", "tool_database_process"],
|
||||
"db_demo tool database boundary dependencies",
|
||||
);
|
||||
assert.equal(dbDemoBoundary.recommendedBlockedKind, "L4-TOOL-DB", "db_demo blocked kind");
|
||||
assert.equal(dbDemoBoundary.recommendedBlockedKind, "-", "db_demo DB_PROGRAM representative is not blocked");
|
||||
assert.equal(dbDemoBoundary.toolDatabaseProgram, "./db_nonran.py", "db_demo DB_PROGRAM");
|
||||
assert.deepEqual(
|
||||
dbDemoBoundary.pythonRuntime.uiReferences,
|
||||
|
||||
Reference in New Issue
Block a user