先提交到云仓库
结论:已提交当前 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");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user