先提交到云仓库
结论:已提交当前 Python-remap proof 链路、runtime/browser/UI/docs 相关变更;保持 L4-PYTHON-REMAP inventory baseline 不直接批量 PASS。
This commit is contained in:
@@ -127,6 +127,10 @@ import {
|
||||
createProjectReleaseReadinessReport,
|
||||
createProjectReleaseReadinessSummaryViewModel,
|
||||
createLinuxCncToolDbProcessPort,
|
||||
createLinuxCncPythonRemapRowRuntimePort,
|
||||
createLinuxCncPythonRemapRuntimePort,
|
||||
createPythonRemapRowRuntimePlan,
|
||||
validatePythonRemapRowRuntimeTranscript,
|
||||
createToolDbProcessDiagnostics,
|
||||
createToolDbTransactionPlan,
|
||||
createSessionSnapshot,
|
||||
@@ -595,6 +599,13 @@ private module paths:
|
||||
contract around `axis/remap/stop-lookahead/nc_files`. Contract-only mode does
|
||||
not execute remap callables, does not promote NGC-only subroutines, and keeps
|
||||
execution and promotion disabled.
|
||||
- `createLinuxCncPythonRemapRowRuntimePort()`,
|
||||
`createPythonRemapRowRuntimePlan()`, and
|
||||
`validatePythonRemapRowRuntimeTranscript()` for the row-aware Python remap
|
||||
runtime proof substrate. The row port accepts an inventory path, INI path,
|
||||
Python modules, remap/prolog/epilog callables, NGC remap assets, and
|
||||
NGC-only subpaths, then records the runtime-adapter proof transcript while
|
||||
keeping execution and promotion disabled.
|
||||
- `createLinuxCncPythonRemapBrowserWorkerAdapter()` for the browser Worker
|
||||
transport boundary. The bundled worker reports
|
||||
`blocked_browser_python_wasm_runtime_missing` until a Python/WASM provider
|
||||
|
||||
@@ -104,12 +104,16 @@ export {
|
||||
} from "./tool-db-browser-worker-adapter.js";
|
||||
export {
|
||||
PYTHON_REMAP_LIFECYCLE_PLAN,
|
||||
PYTHON_REMAP_ROW_RUNTIME_PROOF_PHASES,
|
||||
PYTHON_REMAP_RUNTIME_PORT_CONTRACT_VERSION,
|
||||
PYTHON_REMAP_STOP_LOOKAHEAD_FIXTURE,
|
||||
createLinuxCncPythonRemapRowRuntimePort,
|
||||
createLinuxCncPythonRemapRuntimePort,
|
||||
createPythonRemapLifecyclePlan,
|
||||
createPythonRemapRowRuntimePlan,
|
||||
createPythonRemapRuntimeDiagnostics,
|
||||
validatePythonRemapLifecycleTranscript,
|
||||
validatePythonRemapRowRuntimeTranscript,
|
||||
} from "./python-remap-runtime-port.js";
|
||||
export {
|
||||
createLinuxCncPythonRemapBrowserWorkerAdapter,
|
||||
|
||||
@@ -322,6 +322,53 @@ function createToolDbProcessProofSummary(toolDbProcessProof = {}) {
|
||||
};
|
||||
}
|
||||
|
||||
function createPythonRemapRuntimeProofSummary(pythonRemapRuntimeProof = {}) {
|
||||
const proof = objectOrEmpty(pythonRemapRuntimeProof);
|
||||
const nativeLifecycleReady = proof.nativeLifecycleReady === true;
|
||||
const wasmLifecycleReady = proof.wasmLifecycleReady !== false;
|
||||
const browserLifecycleReady = proof.browserLifecycleReady !== false;
|
||||
const promotionAllowed = proof.promotionAllowed === true;
|
||||
const executionEnabled = proof.executionEnabled === true;
|
||||
const ready = nativeLifecycleReady &&
|
||||
wasmLifecycleReady &&
|
||||
browserLifecycleReady &&
|
||||
promotionAllowed === false &&
|
||||
executionEnabled === false;
|
||||
|
||||
return {
|
||||
apiName: "python-remap-runtime-proof-summary",
|
||||
summaryVersion: 1,
|
||||
phase: ready ? "ready" : "blocked",
|
||||
ready,
|
||||
boundaryClass: "L4-PYTHON-REMAP",
|
||||
fixtureFamily: proof.fixtureFamily ?? "axis/remap/stop-lookahead/nc_files",
|
||||
fixtureId: proof.fixtureId ?? "stop_lookahead_python_runtime_lifecycle",
|
||||
iniPath: proof.iniPath ?? "axis/remap/stop-lookahead/demo.ini",
|
||||
pythonPathPrepend: proof.pythonPathPrepend ?? "python",
|
||||
topLevelPath: proof.topLevelPath ?? "python/toplevel.py",
|
||||
callableName: proof.callableName ?? "queuebuster",
|
||||
runtimeMode: proof.runtimeMode ?? "browser-python-wasm-worker",
|
||||
nativeProbeStatus: proof.nativeProbeStatus ?? (nativeLifecycleReady ? "runtime_lifecycle_probe_passed" : "not_provided"),
|
||||
nativeProofArtifactPath: proof.nativeProofArtifactPath ?? "wasm-port/build/native/native-runtime-probe-summary.tsv",
|
||||
nativeProofStdoutLog: proof.nativeProofStdoutLog ?? null,
|
||||
nativeLifecycleReady,
|
||||
wasmLifecycleReady,
|
||||
browserLifecycleReady,
|
||||
interpreterStateBindingReady: proof.interpreterStateBindingReady !== false,
|
||||
generatorLifecycleReady: proof.generatorLifecycleReady !== false,
|
||||
promotionAllowed,
|
||||
executionEnabled,
|
||||
bulkPromotionAllowed: proof.bulkPromotionAllowed === true,
|
||||
manualLockUpdateRequired: proof.manualLockUpdateRequired !== false,
|
||||
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",
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
const BLOCKED_RUNTIME_FAMILIES = [
|
||||
"L4-USER-M-PROCESS",
|
||||
"L4-PYTHON-REMAP",
|
||||
@@ -2069,6 +2116,7 @@ export function createProjectReleaseReadinessReport({
|
||||
virtualHalSimConfigMacroLoadFixtures = null,
|
||||
virtualHalMotionControllerMatrix = null,
|
||||
toolDbProcessProof = {},
|
||||
pythonRemapRuntimeProof = {},
|
||||
blockedRuntimeFamilies = BLOCKED_RUNTIME_FAMILIES,
|
||||
promotedRuntimeFamilies = [],
|
||||
axisScreenshotArtifacts = [],
|
||||
@@ -2130,6 +2178,8 @@ export function createProjectReleaseReadinessReport({
|
||||
const axisScreenshotArtifactsReady = axisScreenshotArtifactSummary.ready;
|
||||
const toolDbProcessProofSummary = createToolDbProcessProofSummary(toolDbProcessProof);
|
||||
const toolDbProcessProofReady = toolDbProcessProofSummary.ready;
|
||||
const pythonRemapRuntimeProofSummary = createPythonRemapRuntimeProofSummary(pythonRemapRuntimeProof);
|
||||
const pythonRemapRuntimeProofReady = pythonRemapRuntimeProofSummary.ready;
|
||||
const ready = releaseGatePassed &&
|
||||
inventoryReady &&
|
||||
virtualHalSimConfigSourceCoverageReady &&
|
||||
@@ -2137,6 +2187,7 @@ export function createProjectReleaseReadinessReport({
|
||||
virtualHalSimConfigMacroLoadFixturesReady &&
|
||||
virtualHalMotionControllerMatrixReady &&
|
||||
toolDbProcessProofReady &&
|
||||
pythonRemapRuntimeProofReady &&
|
||||
blockedRuntimeReady &&
|
||||
axisScreenshotArtifactsReady;
|
||||
const missing = [
|
||||
@@ -2147,6 +2198,7 @@ export function createProjectReleaseReadinessReport({
|
||||
...(virtualHalSimConfigMacroLoadFixturesReady ? [] : ["virtual-hal-sim-config-macro-load-fixtures"]),
|
||||
...(virtualHalMotionControllerMatrixReady ? [] : ["virtual-hal-motion-controller-matrix"]),
|
||||
...(toolDbProcessProofReady ? [] : ["tool-db-process-proof"]),
|
||||
...(pythonRemapRuntimeProofReady ? [] : ["python-remap-runtime-proof"]),
|
||||
...(blockedRuntimeReady ? [] : ["blocked-runtime-families"]),
|
||||
...(axisScreenshotArtifactsReady ? [] : ["axis-screenshot-artifacts"]),
|
||||
];
|
||||
@@ -2177,6 +2229,8 @@ export function createProjectReleaseReadinessReport({
|
||||
virtualHalMotionControllerMatrixReady,
|
||||
toolDbProcessProofSummary,
|
||||
toolDbProcessProofReady,
|
||||
pythonRemapRuntimeProofSummary,
|
||||
pythonRemapRuntimeProofReady,
|
||||
blockedRuntimeFamilies: blockedFamilies,
|
||||
promotedRuntimeFamilies: promotedFamilies,
|
||||
promotedBlockedFamilies,
|
||||
@@ -2289,6 +2343,16 @@ export function createProjectReleaseReadinessReport({
|
||||
label: "Tool DB process proof detail",
|
||||
value: `wasm=${toolDbProcessProofSummary.wasmProtocolReady ? "ready" : "missing"} browser=${toolDbProcessProofSummary.browserProtocolReady ? "ready" : "missing"} opfs=${toolDbProcessProofSummary.opfsPersistenceReady ? "ready" : "missing"} promotion_allowed=${toolDbProcessProofSummary.promotionAllowed ? "1" : "0"}`,
|
||||
},
|
||||
{
|
||||
id: "python-remap-runtime-proof",
|
||||
label: "Python remap runtime proof",
|
||||
value: pythonRemapRuntimeProofReady ? "ready" : "locked",
|
||||
},
|
||||
{
|
||||
id: "python-remap-runtime-proof-detail",
|
||||
label: "Python remap runtime proof detail",
|
||||
value: `native=${pythonRemapRuntimeProofSummary.nativeLifecycleReady ? "ready" : "missing"} wasm=${pythonRemapRuntimeProofSummary.wasmLifecycleReady ? "ready" : "missing"} browser=${pythonRemapRuntimeProofSummary.browserLifecycleReady ? "ready" : "missing"} promotion_allowed=${pythonRemapRuntimeProofSummary.promotionAllowed ? "1" : "0"}`,
|
||||
},
|
||||
{
|
||||
id: "blocked-runtime-families",
|
||||
label: "Blocked runtime families",
|
||||
@@ -2328,6 +2392,8 @@ export function createProjectReleaseReadinessSummaryViewModel(
|
||||
const virtualHalMotionControllerMatrixReady = report?.virtualHalMotionControllerMatrixReady === true;
|
||||
const toolDbProcessProofSummary = objectOrEmpty(report?.toolDbProcessProofSummary);
|
||||
const toolDbProcessProofReady = report?.toolDbProcessProofReady === true;
|
||||
const pythonRemapRuntimeProofSummary = objectOrEmpty(report?.pythonRemapRuntimeProofSummary);
|
||||
const pythonRemapRuntimeProofReady = report?.pythonRemapRuntimeProofReady === true;
|
||||
const axisScreenshotArtifactSummary = objectOrEmpty(report?.axisScreenshotArtifactSummary);
|
||||
const blockedRuntimeFamilies = arrayOrEmpty(report?.blockedRuntimeFamilies);
|
||||
const promotedBlockedFamilies = arrayOrEmpty(report?.promotedBlockedFamilies);
|
||||
@@ -2430,6 +2496,18 @@ export function createProjectReleaseReadinessSummaryViewModel(
|
||||
? `wasm=${toolDbProcessProofSummary.wasmProtocolReady ? "ready" : "missing"} browser=${toolDbProcessProofSummary.browserProtocolReady ? "ready" : "missing"} opfs=${toolDbProcessProofSummary.opfsPersistenceReady ? "ready" : "missing"} promotion_allowed=${toolDbProcessProofSummary.promotionAllowed ? "1" : "0"}`
|
||||
: "missing",
|
||||
},
|
||||
{
|
||||
id: "python-remap-runtime-proof",
|
||||
label: "Python remap runtime proof",
|
||||
value: pythonRemapRuntimeProofReady ? "ready" : "locked",
|
||||
},
|
||||
{
|
||||
id: "python-remap-runtime-proof-detail",
|
||||
label: "Python remap runtime proof detail",
|
||||
value: pythonRemapRuntimeProofSummary.apiName
|
||||
? `native=${pythonRemapRuntimeProofSummary.nativeLifecycleReady ? "ready" : "missing"} wasm=${pythonRemapRuntimeProofSummary.wasmLifecycleReady ? "ready" : "missing"} browser=${pythonRemapRuntimeProofSummary.browserLifecycleReady ? "ready" : "missing"} promotion_allowed=${pythonRemapRuntimeProofSummary.promotionAllowed ? "1" : "0"}`
|
||||
: "missing",
|
||||
},
|
||||
{
|
||||
id: "blocked-runtime-families",
|
||||
label: "Blocked runtime families",
|
||||
@@ -2630,6 +2708,18 @@ export function createProjectReleaseReadinessArtifactValidationSummaryViewModel(
|
||||
? `wasm=${validation.toolDbProcessProofSummary.wasmProtocolReady ? "ready" : "missing"} browser=${validation.toolDbProcessProofSummary.browserProtocolReady ? "ready" : "missing"} opfs=${validation.toolDbProcessProofSummary.opfsPersistenceReady ? "ready" : "missing"} promotion_allowed=${validation.toolDbProcessProofSummary.promotionAllowed ? "1" : "0"}`
|
||||
: "missing",
|
||||
},
|
||||
{
|
||||
id: "python-remap-runtime-proof",
|
||||
label: "Python remap runtime proof",
|
||||
value: validation?.pythonRemapRuntimeProofSummary?.ready === true ? "ready" : "locked",
|
||||
},
|
||||
{
|
||||
id: "python-remap-runtime-proof-detail",
|
||||
label: "Python remap runtime proof detail",
|
||||
value: validation?.pythonRemapRuntimeProofSummary?.apiName
|
||||
? `native=${validation.pythonRemapRuntimeProofSummary.nativeLifecycleReady ? "ready" : "missing"} wasm=${validation.pythonRemapRuntimeProofSummary.wasmLifecycleReady ? "ready" : "missing"} browser=${validation.pythonRemapRuntimeProofSummary.browserLifecycleReady ? "ready" : "missing"} promotion_allowed=${validation.pythonRemapRuntimeProofSummary.promotionAllowed ? "1" : "0"}`
|
||||
: "missing",
|
||||
},
|
||||
{
|
||||
id: "missing",
|
||||
label: "Missing artifact evidence",
|
||||
@@ -3043,6 +3133,8 @@ export function createProjectReleaseReadinessArtifactUrlWorkflowSummaryViewModel
|
||||
workflow?.validation?.promotionCandidateArtifactSummaryReady === true;
|
||||
const toolDbProcessProofSummary = objectOrEmpty(workflow?.validation?.toolDbProcessProofSummary);
|
||||
const toolDbProcessProofReady = workflow?.validation?.toolDbProcessProofReady === true;
|
||||
const pythonRemapRuntimeProofSummary = objectOrEmpty(workflow?.validation?.pythonRemapRuntimeProofSummary);
|
||||
const pythonRemapRuntimeProofReady = workflow?.validation?.pythonRemapRuntimeProofReady === true;
|
||||
const promotionArtifactRows = objectOrEmpty(promotionCandidateArtifactSummary.artifactRows);
|
||||
const hardBlockRuntimeFamilyRows = arrayOrEmpty(promotionCandidateArtifactSummary.hardBlockRuntimeFamilyRows);
|
||||
const hardBlockRuntimeFamilySummaryRows = arrayOrEmpty(
|
||||
@@ -3321,6 +3413,18 @@ export function createProjectReleaseReadinessArtifactUrlWorkflowSummaryViewModel
|
||||
? `wasm=${toolDbProcessProofSummary.wasmProtocolReady ? "ready" : "missing"} browser=${toolDbProcessProofSummary.browserProtocolReady ? "ready" : "missing"} opfs=${toolDbProcessProofSummary.opfsPersistenceReady ? "ready" : "missing"} promotion_allowed=${toolDbProcessProofSummary.promotionAllowed ? "1" : "0"}`
|
||||
: "not provided",
|
||||
},
|
||||
{
|
||||
id: "python-remap-runtime-proof",
|
||||
label: "Python remap runtime proof",
|
||||
value: pythonRemapRuntimeProofSummary.ready === true ? "ready" : "locked",
|
||||
},
|
||||
{
|
||||
id: "python-remap-runtime-proof-detail",
|
||||
label: "Python remap runtime proof detail",
|
||||
value: pythonRemapRuntimeProofSummary.apiName
|
||||
? `native=${pythonRemapRuntimeProofSummary.nativeLifecycleReady ? "ready" : "missing"} wasm=${pythonRemapRuntimeProofSummary.wasmLifecycleReady ? "ready" : "missing"} browser=${pythonRemapRuntimeProofSummary.browserLifecycleReady ? "ready" : "missing"} promotion_allowed=${pythonRemapRuntimeProofSummary.promotionAllowed ? "1" : "0"}`
|
||||
: "not provided",
|
||||
},
|
||||
...arrayOrEmpty(workflow?.validation?.virtualHalPromotionFamilyRows).map((row) => ({
|
||||
id: `virtual-hal-promotion-family-${row.id}`,
|
||||
label: `Promotion family ${row.label}`,
|
||||
@@ -3523,6 +3627,7 @@ export function createProjectReleaseReadinessArtifactValidation(artifact = {}) {
|
||||
const virtualHalSimConfigMacroLoadFixtures = objectOrEmpty(artifactObject.virtualHalSimConfigMacroLoadFixtures);
|
||||
const virtualHalMotionControllerMatrix = objectOrEmpty(artifactObject.virtualHalMotionControllerMatrix);
|
||||
const toolDbProcessProofSummary = objectOrEmpty(artifactObject.toolDbProcessProofSummary);
|
||||
const pythonRemapRuntimeProofSummary = objectOrEmpty(artifactObject.pythonRemapRuntimeProofSummary);
|
||||
const gateManifest = objectOrEmpty(artifactObject.gateManifest);
|
||||
const gateExecutionManifest = objectOrEmpty(artifactObject.gateExecutionManifest);
|
||||
const gateExecutionSummaryViewModel = objectOrEmpty(artifactObject.gateExecutionSummaryViewModel);
|
||||
@@ -3649,6 +3754,31 @@ export function createProjectReleaseReadinessArtifactValidation(artifact = {}) {
|
||||
arrayOrEmpty(toolDbProcessProofSummary.requiredCommands).join("\n") ===
|
||||
expectedToolDbProcessProofSummary.requiredCommands.join("\n") &&
|
||||
artifactObject.toolDbProcessProofReady === true;
|
||||
const expectedPythonRemapRuntimeProofSummary =
|
||||
createPythonRemapRuntimeProofSummary(pythonRemapRuntimeProofSummary);
|
||||
const pythonRemapRuntimeProofReady =
|
||||
pythonRemapRuntimeProofSummary.apiName === "python-remap-runtime-proof-summary" &&
|
||||
pythonRemapRuntimeProofSummary.summaryVersion === 1 &&
|
||||
pythonRemapRuntimeProofSummary.boundaryClass === "L4-PYTHON-REMAP" &&
|
||||
pythonRemapRuntimeProofSummary.fixtureFamily === "axis/remap/stop-lookahead/nc_files" &&
|
||||
pythonRemapRuntimeProofSummary.fixtureId === "stop_lookahead_python_runtime_lifecycle" &&
|
||||
pythonRemapRuntimeProofSummary.iniPath === "axis/remap/stop-lookahead/demo.ini" &&
|
||||
pythonRemapRuntimeProofSummary.pythonPathPrepend === "python" &&
|
||||
pythonRemapRuntimeProofSummary.topLevelPath === "python/toplevel.py" &&
|
||||
pythonRemapRuntimeProofSummary.callableName === "queuebuster" &&
|
||||
pythonRemapRuntimeProofSummary.nativeProbeStatus === (
|
||||
pythonRemapRuntimeProofSummary.nativeLifecycleReady
|
||||
? "runtime_lifecycle_probe_passed"
|
||||
: "not_provided"
|
||||
) &&
|
||||
pythonRemapRuntimeProofSummary.nativeProofArtifactPath === "wasm-port/build/native/native-runtime-probe-summary.tsv" &&
|
||||
pythonRemapRuntimeProofSummary.promotionAllowed === false &&
|
||||
pythonRemapRuntimeProofSummary.executionEnabled === false &&
|
||||
pythonRemapRuntimeProofSummary.bulkPromotionAllowed === false &&
|
||||
pythonRemapRuntimeProofSummary.manualLockUpdateRequired === true &&
|
||||
arrayOrEmpty(pythonRemapRuntimeProofSummary.requiredCommands).join("\n") ===
|
||||
expectedPythonRemapRuntimeProofSummary.requiredCommands.join("\n") &&
|
||||
artifactObject.pythonRemapRuntimeProofReady === pythonRemapRuntimeProofSummary.ready;
|
||||
const axisScreenshotArtifacts = arrayOrEmpty(axisScreenshotArtifactSummary.artifacts);
|
||||
const blockedRuntimeFamilies = arrayOrEmpty(artifactObject.blockedRuntimeFamilies);
|
||||
const promotedBlockedFamilies = arrayOrEmpty(artifactObject.promotedBlockedFamilies);
|
||||
@@ -3741,6 +3871,8 @@ export function createProjectReleaseReadinessArtifactValidation(artifact = {}) {
|
||||
virtualHalMotionControllerMatrixReady,
|
||||
toolDbProcessProofSummary,
|
||||
toolDbProcessProofReady,
|
||||
pythonRemapRuntimeProofSummary,
|
||||
pythonRemapRuntimeProofReady,
|
||||
axisScreenshotArtifactSummaryReady: axisScreenshotSummaryReady,
|
||||
axisScreenshotArtifactCount: axisScreenshotArtifacts.length,
|
||||
blockedRuntimeFamilies,
|
||||
@@ -3891,6 +4023,18 @@ export function createProjectReleaseReadinessArtifactValidation(artifact = {}) {
|
||||
? `wasm=${toolDbProcessProofSummary.wasmProtocolReady ? "ready" : "missing"} browser=${toolDbProcessProofSummary.browserProtocolReady ? "ready" : "missing"} opfs=${toolDbProcessProofSummary.opfsPersistenceReady ? "ready" : "missing"} promotion_allowed=${toolDbProcessProofSummary.promotionAllowed ? "1" : "0"}`
|
||||
: "missing",
|
||||
},
|
||||
{
|
||||
id: "python-remap-runtime-proof",
|
||||
label: "Python remap runtime proof",
|
||||
value: pythonRemapRuntimeProofSummary.ready === true ? "ready" : "locked",
|
||||
},
|
||||
{
|
||||
id: "python-remap-runtime-proof-detail",
|
||||
label: "Python remap runtime proof detail",
|
||||
value: pythonRemapRuntimeProofSummary.apiName
|
||||
? `native=${pythonRemapRuntimeProofSummary.nativeLifecycleReady ? "ready" : "missing"} wasm=${pythonRemapRuntimeProofSummary.wasmLifecycleReady ? "ready" : "missing"} browser=${pythonRemapRuntimeProofSummary.browserLifecycleReady ? "ready" : "missing"} promotion_allowed=${pythonRemapRuntimeProofSummary.promotionAllowed ? "1" : "0"}`
|
||||
: "missing",
|
||||
},
|
||||
{
|
||||
id: "blocked-runtime-families",
|
||||
label: "Blocked runtime families",
|
||||
|
||||
@@ -27,6 +27,22 @@ export const PYTHON_REMAP_LIFECYCLE_PLAN = [
|
||||
{ phase: "export_diagnostics", method: "exportDiagnostics" },
|
||||
];
|
||||
|
||||
export const PYTHON_REMAP_ROW_RUNTIME_PROOF_PHASES = Object.freeze([
|
||||
"initialize_python",
|
||||
"apply_ini_python_path",
|
||||
"execute_toplevel",
|
||||
"import_module",
|
||||
"callable_lookup",
|
||||
"callable_invoke",
|
||||
"remap_phase_dispatch",
|
||||
"generator_finish",
|
||||
"stage_ngc_remap_asset",
|
||||
"reject_ngc_only_standalone",
|
||||
"export_interpreter_state",
|
||||
"export_canonical_events",
|
||||
"export_diagnostics",
|
||||
]);
|
||||
|
||||
function requireString(value, label) {
|
||||
if (typeof value !== "string" || value.length === 0) {
|
||||
throw new Error(`${label} must be a non-empty string.`);
|
||||
@@ -41,6 +57,22 @@ function normalizeSourceFiles(sourceFiles = []) {
|
||||
return sourceFiles.map((sourceFile) => requireString(sourceFile, "source file"));
|
||||
}
|
||||
|
||||
function normalizeStringList(values = [], label = "value") {
|
||||
if (values === "-" || values === null || values === undefined) {
|
||||
return [];
|
||||
}
|
||||
if (!Array.isArray(values)) {
|
||||
throw new Error(`${label} must be an array.`);
|
||||
}
|
||||
return values
|
||||
.filter((value) => value !== "-")
|
||||
.map((value) => requireString(value, label));
|
||||
}
|
||||
|
||||
function callableNameFromSpec(callableSpec) {
|
||||
return requireString(callableSpec, "callable").split("@")[0];
|
||||
}
|
||||
|
||||
function stableTextHash(text) {
|
||||
let hash = 0x811c9dc5;
|
||||
for (let index = 0; index < text.length; index += 1) {
|
||||
@@ -70,10 +102,95 @@ function normalizeLifecycleResult(phase, result = {}) {
|
||||
};
|
||||
}
|
||||
|
||||
function defaultRowRuntimePlan({
|
||||
sourceFiles,
|
||||
pythonRemapFunctions,
|
||||
prologFunctions,
|
||||
epilogFunctions,
|
||||
ngcRemapFiles,
|
||||
ngcOnlySubpaths,
|
||||
}) {
|
||||
const callables = [
|
||||
...pythonRemapFunctions,
|
||||
...prologFunctions,
|
||||
...epilogFunctions,
|
||||
];
|
||||
return [
|
||||
{ phase: "initialize_python", method: "initializePython" },
|
||||
{ phase: "apply_ini_python_path", method: "applyIniPythonPath" },
|
||||
{ phase: "execute_toplevel", method: "executeTopLevel" },
|
||||
...sourceFiles.map((modulePath) => ({
|
||||
phase: "import_module",
|
||||
method: "importModule",
|
||||
modulePath,
|
||||
})),
|
||||
...callables.flatMap((callableSpec) => {
|
||||
const callableName = callableNameFromSpec(callableSpec);
|
||||
return [
|
||||
{
|
||||
phase: "callable_lookup",
|
||||
method: "lookupCallable",
|
||||
callableName,
|
||||
callableSpec,
|
||||
},
|
||||
{
|
||||
phase: "callable_invoke",
|
||||
method: "invokeGenerator",
|
||||
callableName,
|
||||
callableSpec,
|
||||
},
|
||||
{
|
||||
phase: "remap_phase_dispatch",
|
||||
method: "observeFirstYield",
|
||||
callableName,
|
||||
callableSpec,
|
||||
},
|
||||
{
|
||||
phase: "generator_finish",
|
||||
method: "finishGenerator",
|
||||
callableName,
|
||||
callableSpec,
|
||||
},
|
||||
];
|
||||
}),
|
||||
...ngcRemapFiles.map((ngcPath) => ({
|
||||
phase: "stage_ngc_remap_asset",
|
||||
method: "stageNgcRemapAsset",
|
||||
ngcPath,
|
||||
})),
|
||||
...ngcOnlySubpaths.map((ngcPath) => ({
|
||||
phase: "reject_ngc_only_standalone",
|
||||
method: "rejectNgcOnlyStandalone",
|
||||
ngcPath,
|
||||
})),
|
||||
{ phase: "export_interpreter_state", method: "exportInterpreterState" },
|
||||
{ phase: "export_canonical_events", method: "exportCanonicalEvents" },
|
||||
{ phase: "export_diagnostics", method: "exportDiagnostics" },
|
||||
];
|
||||
}
|
||||
|
||||
export function createPythonRemapLifecyclePlan() {
|
||||
return clonePlan(PYTHON_REMAP_LIFECYCLE_PLAN);
|
||||
}
|
||||
|
||||
export function createPythonRemapRowRuntimePlan({
|
||||
sourceFiles = [],
|
||||
pythonRemapFunctions = [],
|
||||
prologFunctions = [],
|
||||
epilogFunctions = [],
|
||||
ngcRemapFiles = [],
|
||||
ngcOnlySubpaths = [],
|
||||
} = {}) {
|
||||
return clonePlan(defaultRowRuntimePlan({
|
||||
sourceFiles: normalizeStringList(sourceFiles, "source file"),
|
||||
pythonRemapFunctions: normalizeStringList(pythonRemapFunctions, "Python remap function"),
|
||||
prologFunctions: normalizeStringList(prologFunctions, "prolog function"),
|
||||
epilogFunctions: normalizeStringList(epilogFunctions, "epilog function"),
|
||||
ngcRemapFiles: normalizeStringList(ngcRemapFiles, "NGC remap file"),
|
||||
ngcOnlySubpaths: normalizeStringList(ngcOnlySubpaths, "NGC-only subpath"),
|
||||
}));
|
||||
}
|
||||
|
||||
export function validatePythonRemapLifecycleTranscript(transcript) {
|
||||
if (!Array.isArray(transcript)) {
|
||||
throw new Error("transcript must be an array.");
|
||||
@@ -85,11 +202,21 @@ export function validatePythonRemapLifecycleTranscript(transcript) {
|
||||
.filter((entry) => entry?.ready === false || entry?.status === "blocked" || entry?.status === "failed")
|
||||
.map((entry) => entry.phase);
|
||||
const firstYield = byPhase.get("remap_phase_dispatch")?.value ?? null;
|
||||
const expectedValues = {
|
||||
apply_ini_python_path: PYTHON_REMAP_STOP_LOOKAHEAD_FIXTURE.pythonPathPrepend,
|
||||
execute_toplevel: PYTHON_REMAP_STOP_LOOKAHEAD_FIXTURE.topLevelPath,
|
||||
import_module: "python/remap.py",
|
||||
callable_lookup: PYTHON_REMAP_STOP_LOOKAHEAD_FIXTURE.callableName,
|
||||
};
|
||||
const mismatchedValues = Object.entries(expectedValues)
|
||||
.filter(([phase, expectedValue]) => byPhase.get(phase)?.value !== expectedValue)
|
||||
.map(([phase]) => phase);
|
||||
const hasInterpreterState = byPhase.has("export_interpreter_state");
|
||||
const hasDiagnostics = byPhase.has("export_diagnostics");
|
||||
const ready = (
|
||||
missingPhases.length === 0 &&
|
||||
failedPhases.length === 0 &&
|
||||
mismatchedValues.length === 0 &&
|
||||
Number(firstYield) === PYTHON_REMAP_STOP_LOOKAHEAD_FIXTURE.expectedFirstYield &&
|
||||
hasInterpreterState &&
|
||||
hasDiagnostics
|
||||
@@ -103,6 +230,7 @@ export function validatePythonRemapLifecycleTranscript(transcript) {
|
||||
observedPhases: transcript.map((entry) => entry.phase),
|
||||
missingPhases,
|
||||
failedPhases,
|
||||
mismatchedValues,
|
||||
firstYield,
|
||||
hasInterpreterState,
|
||||
hasDiagnostics,
|
||||
@@ -155,6 +283,96 @@ export function createPythonRemapRuntimeDiagnostics({
|
||||
};
|
||||
}
|
||||
|
||||
export function validatePythonRemapRowRuntimeTranscript({
|
||||
rowPath,
|
||||
transcript,
|
||||
sourceFiles = [],
|
||||
pythonRemapFunctions = [],
|
||||
prologFunctions = [],
|
||||
epilogFunctions = [],
|
||||
ngcRemapFiles = [],
|
||||
ngcOnlySubpaths = [],
|
||||
} = {}) {
|
||||
requireString(rowPath, "rowPath");
|
||||
if (!Array.isArray(transcript)) {
|
||||
throw new Error("transcript must be an array.");
|
||||
}
|
||||
const expectedPlan = createPythonRemapRowRuntimePlan({
|
||||
sourceFiles,
|
||||
pythonRemapFunctions,
|
||||
prologFunctions,
|
||||
epilogFunctions,
|
||||
ngcRemapFiles,
|
||||
ngcOnlySubpaths,
|
||||
});
|
||||
const expectedPhases = expectedPlan.map((step) => step.phase);
|
||||
const observedPhases = transcript.map((entry) => entry.phase);
|
||||
const phaseCounts = new Map();
|
||||
for (const phase of observedPhases) {
|
||||
phaseCounts.set(phase, (phaseCounts.get(phase) ?? 0) + 1);
|
||||
}
|
||||
const failedPhases = transcript
|
||||
.filter((entry) => entry?.ready === false || entry?.status === "blocked" || entry?.status === "failed")
|
||||
.map((entry) => entry.phase);
|
||||
const missingPhases = [...new Set(expectedPhases)].filter((phase) => !phaseCounts.has(phase));
|
||||
const expectedModuleCount = normalizeStringList(sourceFiles, "source file").length;
|
||||
const expectedCallableCount = [
|
||||
...normalizeStringList(pythonRemapFunctions, "Python remap function"),
|
||||
...normalizeStringList(prologFunctions, "prolog function"),
|
||||
...normalizeStringList(epilogFunctions, "epilog function"),
|
||||
].length;
|
||||
const expectedNgcRemapCount = normalizeStringList(ngcRemapFiles, "NGC remap file").length;
|
||||
const expectedNgcOnlyCount = normalizeStringList(ngcOnlySubpaths, "NGC-only subpath").length;
|
||||
const countDrift = [
|
||||
["import_module", expectedModuleCount],
|
||||
["callable_lookup", expectedCallableCount],
|
||||
["callable_invoke", expectedCallableCount],
|
||||
["remap_phase_dispatch", expectedCallableCount],
|
||||
["generator_finish", expectedCallableCount],
|
||||
["stage_ngc_remap_asset", expectedNgcRemapCount],
|
||||
["reject_ngc_only_standalone", expectedNgcOnlyCount],
|
||||
].filter(([phase, expectedCount]) => (phaseCounts.get(phase) ?? 0) !== expectedCount)
|
||||
.map(([phase]) => phase);
|
||||
const hasInterpreterState = phaseCounts.has("export_interpreter_state");
|
||||
const hasCanonicalEvents = phaseCounts.has("export_canonical_events");
|
||||
const hasDiagnostics = phaseCounts.has("export_diagnostics");
|
||||
const ready = (
|
||||
missingPhases.length === 0 &&
|
||||
failedPhases.length === 0 &&
|
||||
countDrift.length === 0 &&
|
||||
hasInterpreterState &&
|
||||
hasCanonicalEvents &&
|
||||
hasDiagnostics
|
||||
);
|
||||
|
||||
return {
|
||||
contractVersion: PYTHON_REMAP_RUNTIME_PORT_CONTRACT_VERSION,
|
||||
rowPath,
|
||||
requiredPhases: [...new Set(expectedPhases)],
|
||||
observedPhases,
|
||||
missingPhases,
|
||||
failedPhases,
|
||||
countDrift,
|
||||
moduleImportReady: (phaseCounts.get("import_module") ?? 0) === expectedModuleCount,
|
||||
callableLookupReady: (phaseCounts.get("callable_lookup") ?? 0) === expectedCallableCount,
|
||||
generatorLifecycleReady: (
|
||||
(phaseCounts.get("callable_invoke") ?? 0) === expectedCallableCount &&
|
||||
(phaseCounts.get("remap_phase_dispatch") ?? 0) === expectedCallableCount &&
|
||||
(phaseCounts.get("generator_finish") ?? 0) === expectedCallableCount
|
||||
),
|
||||
ngcRemapAssetsReady: (phaseCounts.get("stage_ngc_remap_asset") ?? 0) === expectedNgcRemapCount,
|
||||
ngcOnlySubpathsGuarded: (phaseCounts.get("reject_ngc_only_standalone") ?? 0) === expectedNgcOnlyCount,
|
||||
interpreterStateBindingReady: hasInterpreterState,
|
||||
canonicalEventsReady: hasCanonicalEvents,
|
||||
diagnosticsReady: hasDiagnostics,
|
||||
rowRuntimeTranscriptReady: ready,
|
||||
ready,
|
||||
executionEnabled: false,
|
||||
promotionAllowed: false,
|
||||
bulkPromotionAllowed: false,
|
||||
};
|
||||
}
|
||||
|
||||
export function createLinuxCncPythonRemapRuntimePort({
|
||||
fixtureFamily = PYTHON_REMAP_STOP_LOOKAHEAD_FIXTURE.fixtureFamily,
|
||||
iniPath = PYTHON_REMAP_STOP_LOOKAHEAD_FIXTURE.iniPath,
|
||||
@@ -348,3 +566,241 @@ export function createLinuxCncPythonRemapRuntimePort({
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function createLinuxCncPythonRemapRowRuntimePort({
|
||||
path,
|
||||
iniPath,
|
||||
family = null,
|
||||
machineRoot = "",
|
||||
pythonPathPrepend = "-",
|
||||
topLevelPath = "-",
|
||||
sourceFiles = [],
|
||||
remapDeclarations = [],
|
||||
pythonRemapFunctions = [],
|
||||
prologFunctions = [],
|
||||
epilogFunctions = [],
|
||||
ngcRemapFiles = [],
|
||||
ngcOnlySubpaths = [],
|
||||
runtimeMode = "row-runtime-contract-only",
|
||||
runtimeAdapter = null,
|
||||
} = {}) {
|
||||
requireString(path, "path");
|
||||
requireString(iniPath, "iniPath");
|
||||
const normalizedFamily = family ?? path.split("/").slice(0, -1).join("/");
|
||||
requireString(normalizedFamily, "family");
|
||||
const normalizedMachineRoot = machineRoot === "-" ? "" : String(machineRoot ?? "");
|
||||
const normalizedPythonPathPrepend = pythonPathPrepend === "-" ? "" : String(pythonPathPrepend ?? "");
|
||||
const normalizedTopLevelPath = topLevelPath === "-" ? "" : String(topLevelPath ?? "");
|
||||
const normalizedSourceFiles = normalizeStringList(sourceFiles, "source file");
|
||||
const normalizedRemapDeclarations = normalizeStringList(remapDeclarations, "remap declaration");
|
||||
const normalizedPythonRemapFunctions = normalizeStringList(pythonRemapFunctions, "Python remap function");
|
||||
const normalizedPrologFunctions = normalizeStringList(prologFunctions, "prolog function");
|
||||
const normalizedEpilogFunctions = normalizeStringList(epilogFunctions, "epilog function");
|
||||
const normalizedNgcRemapFiles = normalizeStringList(ngcRemapFiles, "NGC remap file");
|
||||
const normalizedNgcOnlySubpaths = normalizeStringList(ngcOnlySubpaths, "NGC-only subpath");
|
||||
const transcript = [];
|
||||
let started = false;
|
||||
let closed = false;
|
||||
let runtimeExecutionReady = false;
|
||||
let startStatus = null;
|
||||
|
||||
function assertOpen() {
|
||||
if (closed) {
|
||||
throw new Error("PythonRemapRowRuntimePort is closed.");
|
||||
}
|
||||
}
|
||||
|
||||
async function callAdapterMethod(method, payload = {}) {
|
||||
if (!runtimeAdapter?.[method]) {
|
||||
return normalizeLifecycleResult(payload.phase ?? method, {
|
||||
status: "blocked",
|
||||
ready: false,
|
||||
source: "missing-runtime-adapter-method",
|
||||
});
|
||||
}
|
||||
return normalizeLifecycleResult(payload.phase ?? method, await runtimeAdapter[method](payload));
|
||||
}
|
||||
|
||||
async function runStep(step) {
|
||||
const payload = {
|
||||
...step,
|
||||
path,
|
||||
iniPath,
|
||||
family: normalizedFamily,
|
||||
machineRoot: normalizedMachineRoot,
|
||||
pythonPathPrepend: normalizedPythonPathPrepend,
|
||||
topLevelPath: normalizedTopLevelPath,
|
||||
sourceFiles: normalizedSourceFiles,
|
||||
remapDeclarations: normalizedRemapDeclarations,
|
||||
pythonRemapFunctions: normalizedPythonRemapFunctions,
|
||||
prologFunctions: normalizedPrologFunctions,
|
||||
epilogFunctions: normalizedEpilogFunctions,
|
||||
ngcRemapFiles: normalizedNgcRemapFiles,
|
||||
ngcOnlySubpaths: normalizedNgcOnlySubpaths,
|
||||
};
|
||||
const result = await callAdapterMethod(step.method, payload);
|
||||
transcript.push(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
function rowPlan() {
|
||||
return createPythonRemapRowRuntimePlan({
|
||||
sourceFiles: normalizedSourceFiles,
|
||||
pythonRemapFunctions: normalizedPythonRemapFunctions,
|
||||
prologFunctions: normalizedPrologFunctions,
|
||||
epilogFunctions: normalizedEpilogFunctions,
|
||||
ngcRemapFiles: normalizedNgcRemapFiles,
|
||||
ngcOnlySubpaths: normalizedNgcOnlySubpaths,
|
||||
});
|
||||
}
|
||||
|
||||
function validation() {
|
||||
return validatePythonRemapRowRuntimeTranscript({
|
||||
rowPath: path,
|
||||
transcript,
|
||||
sourceFiles: normalizedSourceFiles,
|
||||
pythonRemapFunctions: normalizedPythonRemapFunctions,
|
||||
prologFunctions: normalizedPrologFunctions,
|
||||
epilogFunctions: normalizedEpilogFunctions,
|
||||
ngcRemapFiles: normalizedNgcRemapFiles,
|
||||
ngcOnlySubpaths: normalizedNgcOnlySubpaths,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
path,
|
||||
iniPath,
|
||||
family: normalizedFamily,
|
||||
machineRoot: normalizedMachineRoot,
|
||||
pythonPathPrepend: normalizedPythonPathPrepend,
|
||||
topLevelPath: normalizedTopLevelPath,
|
||||
sourceFiles: normalizedSourceFiles,
|
||||
remapDeclarations: normalizedRemapDeclarations,
|
||||
pythonRemapFunctions: normalizedPythonRemapFunctions,
|
||||
prologFunctions: normalizedPrologFunctions,
|
||||
epilogFunctions: normalizedEpilogFunctions,
|
||||
ngcRemapFiles: normalizedNgcRemapFiles,
|
||||
ngcOnlySubpaths: normalizedNgcOnlySubpaths,
|
||||
runtimeMode,
|
||||
|
||||
createRowRuntimePlan: rowPlan,
|
||||
|
||||
async start() {
|
||||
assertOpen();
|
||||
started = true;
|
||||
let adapterStartResult = {};
|
||||
if (runtimeAdapter?.start) {
|
||||
adapterStartResult = await runtimeAdapter.start({
|
||||
path,
|
||||
iniPath,
|
||||
family: normalizedFamily,
|
||||
machineRoot: normalizedMachineRoot,
|
||||
pythonPathPrepend: normalizedPythonPathPrepend,
|
||||
topLevelPath: normalizedTopLevelPath,
|
||||
sourceFiles: normalizedSourceFiles,
|
||||
remapDeclarations: normalizedRemapDeclarations,
|
||||
pythonRemapFunctions: normalizedPythonRemapFunctions,
|
||||
prologFunctions: normalizedPrologFunctions,
|
||||
epilogFunctions: normalizedEpilogFunctions,
|
||||
ngcRemapFiles: normalizedNgcRemapFiles,
|
||||
ngcOnlySubpaths: normalizedNgcOnlySubpaths,
|
||||
});
|
||||
}
|
||||
runtimeExecutionReady = adapterStartResult.runtimeExecutionReady === true;
|
||||
startStatus = adapterStartResult.status ?? (runtimeExecutionReady ? "python_remap_row_runtime_adapter_started" : null);
|
||||
return {
|
||||
runtimeMode,
|
||||
runtimeExecutionReady,
|
||||
status: startStatus,
|
||||
executionEnabled: false,
|
||||
promotionAllowed: false,
|
||||
bulkPromotionAllowed: false,
|
||||
};
|
||||
},
|
||||
|
||||
async runRowRuntimePlan(plan = rowPlan()) {
|
||||
assertOpen();
|
||||
if (!started) {
|
||||
throw new Error("PythonRemapRowRuntimePort must be started before runRowRuntimePlan().");
|
||||
}
|
||||
if (!runtimeAdapter || runtimeExecutionReady !== true) {
|
||||
return {
|
||||
status: runtimeAdapter ? (startStatus ?? "blocked_row_runtime_execution_not_ready") : "blocked_row_runtime_adapter_required",
|
||||
plan: clonePlan(plan),
|
||||
runtimeExecutionReady: false,
|
||||
executionEnabled: false,
|
||||
promotionAllowed: false,
|
||||
bulkPromotionAllowed: false,
|
||||
};
|
||||
}
|
||||
for (const step of plan) {
|
||||
await runStep(step);
|
||||
}
|
||||
return {
|
||||
status: "row_runtime_adapter_plan_executed",
|
||||
plan: clonePlan(plan),
|
||||
transcript: this.exportTranscript(),
|
||||
validation: validation(),
|
||||
runtimeExecutionReady: true,
|
||||
executionEnabled: false,
|
||||
promotionAllowed: false,
|
||||
bulkPromotionAllowed: false,
|
||||
};
|
||||
},
|
||||
|
||||
exportTranscript() {
|
||||
return transcript.map((entry) => ({ ...entry }));
|
||||
},
|
||||
|
||||
exportDiagnostics() {
|
||||
const rowValidation = validation();
|
||||
return {
|
||||
contractVersion: PYTHON_REMAP_RUNTIME_PORT_CONTRACT_VERSION,
|
||||
runtimeMode,
|
||||
runtimeExecutionReady,
|
||||
path,
|
||||
iniPath,
|
||||
family: normalizedFamily,
|
||||
machineRoot: normalizedMachineRoot,
|
||||
pythonPathPrepend: normalizedPythonPathPrepend,
|
||||
topLevelPath: normalizedTopLevelPath,
|
||||
sourceFiles: [...normalizedSourceFiles],
|
||||
remapDeclarations: [...normalizedRemapDeclarations],
|
||||
pythonRemapFunctions: [...normalizedPythonRemapFunctions],
|
||||
prologFunctions: [...normalizedPrologFunctions],
|
||||
epilogFunctions: [...normalizedEpilogFunctions],
|
||||
ngcRemapFiles: [...normalizedNgcRemapFiles],
|
||||
ngcOnlySubpaths: [...normalizedNgcOnlySubpaths],
|
||||
rowRuntimeTranscriptReady: rowValidation.rowRuntimeTranscriptReady,
|
||||
moduleImportReady: rowValidation.moduleImportReady,
|
||||
callableLookupReady: rowValidation.callableLookupReady,
|
||||
generatorLifecycleReady: rowValidation.generatorLifecycleReady,
|
||||
ngcRemapAssetsReady: rowValidation.ngcRemapAssetsReady,
|
||||
ngcOnlySubpathsGuarded: rowValidation.ngcOnlySubpathsGuarded,
|
||||
interpreterStateBindingReady: rowValidation.interpreterStateBindingReady,
|
||||
canonicalEventsReady: rowValidation.canonicalEventsReady,
|
||||
transcriptHash: stableTextHash(transcriptText(transcript)),
|
||||
transcriptPhaseCount: transcript.length,
|
||||
linuxCncOwnedLifecycle: true,
|
||||
jsCncSemantics: false,
|
||||
ngcOnlySubroutinePromoted: false,
|
||||
executionEnabled: false,
|
||||
promotionAllowed: false,
|
||||
bulkPromotionAllowed: false,
|
||||
};
|
||||
},
|
||||
|
||||
async close() {
|
||||
if (runtimeAdapter?.close) {
|
||||
await runtimeAdapter.close();
|
||||
}
|
||||
closed = true;
|
||||
return {
|
||||
closed,
|
||||
executionEnabled: false,
|
||||
promotionAllowed: false,
|
||||
bulkPromotionAllowed: false,
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1726,6 +1726,12 @@ M2
|
||||
<dd>T<span data-machine-status="tool-current">0</span> selected <span data-machine-status="tool-selected">0</span> pocket <span data-machine-status="tool-pocket">0</span> TLO <span data-machine-status="tool-length-offset">z=0.000</span></dd>
|
||||
<dt>Tool Table</dt>
|
||||
<dd><span data-tool-table-summary="state">not-loaded</span> | <span data-tool-table-summary="paths">-</span> | <span data-tool-table-summary="tool">No tool table loaded</span></dd>
|
||||
<dt>Python Remap</dt>
|
||||
<dd><span data-python-remap-runtime="boundary">L4-PYTHON-REMAP</span> | <span data-python-remap-runtime="fixture">axis/remap/stop-lookahead/nc_files</span> | <span data-python-remap-runtime="lifecycle">locked</span></dd>
|
||||
<dt>Python Runtime</dt>
|
||||
<dd><span data-python-remap-runtime="mode">contract-only</span> | callable <span data-python-remap-runtime="callable">locked</span> | generator <span data-python-remap-runtime="generator">locked</span> | state <span data-python-remap-runtime="interpreter">locked</span></dd>
|
||||
<dt>Python Promotion</dt>
|
||||
<dd>execution <span data-python-remap-runtime="execution">disabled</span> | promotion <span data-python-remap-runtime="promotion">locked</span></dd>
|
||||
<dt>Limits/Home</dt>
|
||||
<dd data-limits-home-summary>source unavailable | X home no limit off/off fault none</dd>
|
||||
<dt>Overrides</dt>
|
||||
@@ -2794,6 +2800,7 @@ M2
|
||||
virtualHalSimConfigMacroLoadFixtures: createVirtualHalSimConfigMacroLoadFixtureReport(),
|
||||
virtualHalCommandScriptFixtures: createVirtualHalCommandScriptFixtureReport(),
|
||||
virtualHalMotionControllerMatrix: createVirtualHalMotionControllerMatrixReport(),
|
||||
pythonRemapRuntime: state?.pythonRemapRuntime ?? null,
|
||||
virtualHalSessionDiagnostics: createVirtualHalSessionDiagnosticsArtifact(),
|
||||
statusHistory: getStatusHistory(),
|
||||
mdiHistory: getMdiHistory(),
|
||||
@@ -4263,6 +4270,7 @@ M2
|
||||
getDroState: () => renderPlayback(playbackIndex)?.dro ?? null,
|
||||
getModalState: () => currentState()?.modal ?? null,
|
||||
getMachineStatusState: () => currentState()?.machineStatus ?? null,
|
||||
getPythonRemapRuntimeStatus: () => currentState()?.pythonRemapRuntime ?? null,
|
||||
getPlaybackFrame: () => renderPlayback(playbackIndex),
|
||||
isPlaybackRunning: () => Boolean(playbackTimer),
|
||||
resetPlayback: () => renderPlayback(0),
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { createLinuxCncInterpSdk } from "../../sdk/src/index.js";
|
||||
import {
|
||||
PYTHON_REMAP_STOP_LOOKAHEAD_FIXTURE,
|
||||
createLinuxCncInterpSdk,
|
||||
createLinuxCncPythonRemapRuntimePort,
|
||||
} from "../../sdk/src/index.js";
|
||||
import * as THREE from "./vendor/three/three.module.js";
|
||||
import {
|
||||
DEFAULT_SIMULATION_PROGRAM,
|
||||
@@ -190,6 +194,58 @@ export function createSimulationSummary({ programText, resultText, motion }) {
|
||||
};
|
||||
}
|
||||
|
||||
export async function createPythonRemapSimulationRuntimeStatus({
|
||||
runtimeMode = "contract-only",
|
||||
runtimeAdapter = null,
|
||||
} = {}) {
|
||||
const port = createLinuxCncPythonRemapRuntimePort({
|
||||
fixtureFamily: PYTHON_REMAP_STOP_LOOKAHEAD_FIXTURE.fixtureFamily,
|
||||
iniPath: PYTHON_REMAP_STOP_LOOKAHEAD_FIXTURE.iniPath,
|
||||
pythonPathPrepend: PYTHON_REMAP_STOP_LOOKAHEAD_FIXTURE.pythonPathPrepend,
|
||||
topLevelPath: PYTHON_REMAP_STOP_LOOKAHEAD_FIXTURE.topLevelPath,
|
||||
sourceFiles: PYTHON_REMAP_STOP_LOOKAHEAD_FIXTURE.modules,
|
||||
runtimeMode,
|
||||
runtimeAdapter,
|
||||
});
|
||||
const start = await port.start();
|
||||
const plan = await port.runLifecyclePlan();
|
||||
const diagnostics = port.exportDiagnostics();
|
||||
await port.close();
|
||||
|
||||
return {
|
||||
apiName: "real-browser-simulation-python-remap-runtime-status",
|
||||
statusVersion: 1,
|
||||
boundaryClass: "L4-PYTHON-REMAP",
|
||||
fixtureFamily: diagnostics.fixtureFamily,
|
||||
iniPath: diagnostics.iniPath,
|
||||
pythonPathPrepend: diagnostics.pythonPathPrepend,
|
||||
topLevelPath: diagnostics.topLevelPath,
|
||||
modules: diagnostics.modules,
|
||||
runtimeMode: diagnostics.runtimeMode,
|
||||
runtimeExecutionReady: diagnostics.runtimeExecutionReady,
|
||||
lifecycleTranscriptReady: diagnostics.lifecycleTranscriptReady,
|
||||
callableLookupReady: diagnostics.callableLookupReady,
|
||||
generatorLifecycleReady: diagnostics.generatorLifecycleReady,
|
||||
interpreterStateBindingReady: diagnostics.interpreterStateBindingReady,
|
||||
executionEnabled: diagnostics.executionEnabled,
|
||||
promotionAllowed: diagnostics.promotionAllowed,
|
||||
bulkPromotionAllowed: diagnostics.bulkPromotionAllowed,
|
||||
ngcOnlySubroutinePromoted: diagnostics.ngcOnlySubroutinePromoted,
|
||||
jsCncSemantics: diagnostics.jsCncSemantics,
|
||||
startStatus: start.status ?? "contract-only",
|
||||
planStatus: plan.status,
|
||||
phase: diagnostics.lifecycleTranscriptReady ? "ready" : "locked",
|
||||
ready: diagnostics.lifecycleTranscriptReady,
|
||||
rows: [
|
||||
{ id: "boundary", label: "Python Remap", value: "L4-PYTHON-REMAP" },
|
||||
{ id: "fixture", label: "Fixture", value: diagnostics.fixtureFamily },
|
||||
{ id: "runtime-mode", label: "Runtime mode", value: diagnostics.runtimeMode },
|
||||
{ id: "lifecycle", label: "Lifecycle", value: diagnostics.lifecycleTranscriptReady ? "ready" : "locked" },
|
||||
{ id: "promotion", label: "Promotion", value: diagnostics.promotionAllowed ? "allowed" : "locked" },
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
export function runLinuxCncProgram(interp, programText, options = {}) {
|
||||
if (options.iniPath) {
|
||||
return interp.runProgramWithIni(programText, options.iniPath);
|
||||
@@ -1284,6 +1340,9 @@ export function renderSimulationState(documentRef, state) {
|
||||
setText(documentRef, "[data-selected-program]", state.program?.label ?? "Custom program");
|
||||
setText(documentRef, "[data-program-source]", state.program?.sourceLabel ?? "Custom G-code text");
|
||||
setText(documentRef, "[data-canonical-output]", state.resultText);
|
||||
if (state.pythonRemapRuntime) {
|
||||
renderPythonRemapRuntimeStatus(documentRef, state.pythonRemapRuntime);
|
||||
}
|
||||
renderProgramSelector(documentRef, state.program?.id ?? "custom");
|
||||
renderRows(documentRef, state.summary.rows);
|
||||
renderModalState(documentRef, state.modal);
|
||||
@@ -1291,6 +1350,25 @@ export function renderSimulationState(documentRef, state) {
|
||||
renderSimulationPlaybackFrame(documentRef, state, state.motion.length - 1);
|
||||
}
|
||||
|
||||
export function renderPythonRemapRuntimeStatus(documentRef, status) {
|
||||
const statusMap = {
|
||||
boundary: status.boundaryClass,
|
||||
fixture: status.fixtureFamily,
|
||||
mode: status.runtimeMode,
|
||||
lifecycle: status.lifecycleTranscriptReady ? "ready" : "locked",
|
||||
callable: status.callableLookupReady ? "ready" : "locked",
|
||||
generator: status.generatorLifecycleReady ? "ready" : "locked",
|
||||
interpreter: status.interpreterStateBindingReady ? "ready" : "locked",
|
||||
execution: status.executionEnabled ? "enabled" : "disabled",
|
||||
promotion: status.promotionAllowed ? "allowed" : "locked",
|
||||
};
|
||||
documentRef.body.dataset.pythonRemapRuntimeReady = status.ready ? "true" : "false";
|
||||
documentRef.body.dataset.pythonRemapRuntimePhase = status.phase;
|
||||
for (const [name, value] of Object.entries(statusMap)) {
|
||||
setText(documentRef, `[data-python-remap-runtime="${name}"]`, value);
|
||||
}
|
||||
}
|
||||
|
||||
export async function runRealBrowserSimulation({
|
||||
documentRef = document,
|
||||
programId = DEFAULT_SIMULATION_PROGRAM_ID,
|
||||
@@ -1307,6 +1385,7 @@ export async function runRealBrowserSimulation({
|
||||
const summary = createSimulationSummary({ programText: resolvedProgramText, resultText, motion });
|
||||
const modal = createModalState(resultText);
|
||||
const machineStatus = createMachineStatusState(resultText);
|
||||
const pythonRemapRuntime = await createPythonRemapSimulationRuntimeStatus();
|
||||
const state = {
|
||||
apiName: "real-browser-simulation-state",
|
||||
stateVersion: 1,
|
||||
@@ -1325,6 +1404,7 @@ export async function runRealBrowserSimulation({
|
||||
summary,
|
||||
modal,
|
||||
machineStatus,
|
||||
pythonRemapRuntime,
|
||||
execution: {
|
||||
mode: iniPath ? "linuxcnc-wasm-with-ini" : "linuxcnc-wasm",
|
||||
iniPath,
|
||||
|
||||
@@ -11,10 +11,6 @@ function postError(id, type, error) {
|
||||
});
|
||||
}
|
||||
|
||||
function pythonRuntimeAvailable() {
|
||||
return typeof self.loadPyodide === "function" || Boolean(self.pyodide?.runPythonAsync);
|
||||
}
|
||||
|
||||
function getRuntimeProvider() {
|
||||
return self.linuxCncPythonRemapRuntimeProvider ?? null;
|
||||
}
|
||||
@@ -77,7 +73,7 @@ self.addEventListener("message", async (event) => {
|
||||
"exportDiagnostics",
|
||||
];
|
||||
const providerReady = requiredMethods.every((method) => typeof provider?.[method] === "function");
|
||||
const ready = providerReady || pythonRuntimeAvailable();
|
||||
const ready = providerReady;
|
||||
if (providerReady && provider.start) {
|
||||
await provider.start(message);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user