解锁L4-TOOL-DB主机运行环境

结论:已识别RIP版LinuxCNC主机运行时,Tool DB native protocol probe可通过,inventory baseline保持28/28/131/0且promotion继续锁定。
This commit is contained in:
2026-06-19 06:28:38 +08:00
parent f101932bf1
commit d9ac3770a7
18 changed files with 3041 additions and 184 deletions

View File

@@ -24,6 +24,23 @@ import {
const __dirname = dirname(fileURLToPath(import.meta.url));
const root = resolve(__dirname, "../../..");
const sourceManifestText = readFileSync(resolve(root, "tools/source-manifest.txt"), "utf8");
function parseTsvRows(text) {
const [headerLine, ...dataLines] = text.trim().split(/\r?\n/);
const headers = headerLine.split("\t");
return dataLines
.filter((line) => line.trim().length > 0)
.map((line) => {
const values = line.split("\t");
return Object.fromEntries(headers.map((header, index) => [header, values[index] ?? ""]));
});
}
const promotionCandidateRows = parseTsvRows(
readFileSync(resolve(root, "build/wasm/sim-configs-inventory/promotion-candidates.tsv"), "utf8"),
);
const evidenceExpansionRows = parseTsvRows(
readFileSync(resolve(root, "build/wasm/sim-configs-inventory/evidence-expansion-candidates.tsv"), "utf8"),
);
const manifest = createProjectReleaseGateManifest();
const virtualHalSimConfigSourceCoverage = createVirtualHalSimConfigSourceCoverageReport();
const virtualHalMotionControllerMatrix = createVirtualHalMotionControllerMatrixReport({ manifestText: sourceManifestText });
@@ -92,6 +109,8 @@ const readyArtifactJson = JSON.stringify(createProjectReleaseReadinessReport({
virtualHalSimConfigSourceCoverage,
virtualHalSimConfigPromotionCandidates,
virtualHalSimConfigEvidenceExpansion,
promotionCandidateRows,
evidenceExpansionRows,
virtualHalSimConfigMacroLoadFixtures,
virtualHalMotionControllerMatrix: browserDiagnosticsArtifact.virtualHalMotionControllerMatrix,
}));
@@ -198,10 +217,38 @@ assert.equal(
readySummary.rows.find(({ id }) => id === "promotion-candidate-total")?.value,
"28",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "evidence-ready-candidate-rows")?.value,
"8",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "evidence-ready-candidate-preview")?.value,
"qtdragon-multi-joint-on-abort",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "evidence-ready-candidate-preview-gcode")?.value,
"linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "evidence-ready-candidate-promotion-allowed")?.value,
"0",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "evidence-ready-candidate-baseline-changing")?.value,
"no",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "evidence-expansion-candidates")?.value,
"13",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "promotion-candidate-artifact-rows")?.value,
"28",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "evidence-expansion-artifact-rows")?.value,
"13",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "evidence-expansion-next-evidence")?.value,
"browser-diagnostics-binding",
@@ -242,6 +289,42 @@ assert.equal(
readySummary.rows.find(({ id }) => id === "promotion-candidate-allowed")?.value,
"0",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "hard-block-runtime-locked-rows")?.value,
"19",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "hard-block-runtime-locked-preview")?.value,
"L4-TOOL-DB:axis/db_demo/base.ngc, L4-PYTHON-REMAP:axis/laser/raster_test.ngc, L4-PYTHON-REMAP:axis/laser/vector_test.ngc",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "hard-block-runtime-promotion-allowed")?.value,
"0",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "hard-block-runtime-family-count")?.value,
"3",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "hard-block-runtime-family-summary")?.value,
"L4-USER-M-PROCESS:1 locked=yes, L4-TOOL-DB:1 locked=yes, L4-PYTHON-REMAP:17 locked=yes",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "hard-block-runtime-detail-row-count")?.value,
"19",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "hard-block-runtime-detail-preview-1")?.value,
"L4-TOOL-DB:axis/db_demo/base.ngc; reason=design_tooldata_db_protocol_boundary; next=db_program_v2_1_handshake_getall_load_unload_or_put; promotion_allowed=0",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "hard-block-runtime-family-L4-TOOL-DB")?.value,
"1 locked rows; promotion_allowed=0; first=axis/db_demo/base.ngc; reason=design_tooldata_db_protocol_boundary; next=db_program_v2_1_handshake_getall_load_unload_or_put",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "hard-block-runtime-family-L4-TOOL-DB-paths")?.value,
"axis/db_demo/base.ngc",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "hard-block-runtime-lock")?.value,
"locked (3 families)",
@@ -270,7 +353,14 @@ assert.deepEqual(
["promotion-candidate-artifact", "wasm-port/build/wasm/sim-configs-inventory/promotion-candidates.tsv"],
["promotion-candidate-layers", "evidence-ready=8 inventory-ready=20"],
["promotion-candidate-total", "28"],
["evidence-ready-candidate-rows", "8"],
["evidence-ready-candidate-preview", "qtdragon-multi-joint-on-abort"],
["evidence-ready-candidate-preview-gcode", "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc"],
["evidence-ready-candidate-promotion-allowed", "0"],
["evidence-ready-candidate-baseline-changing", "no"],
["promotion-candidate-artifact-rows", "28"],
["evidence-expansion-candidates", "13"],
["evidence-expansion-artifact-rows", "13"],
["evidence-expansion-next-evidence", "browser-diagnostics-binding"],
["evidence-expansion-baseline-changing", "no"],
["evidence-expansion-preferred-candidate", "woodpecker-on-abort"],
@@ -281,6 +371,23 @@ assert.deepEqual(
["evidence-expansion-source-count-list", "3, 3, 3"],
["evidence-expansion-artifact", "wasm-port/build/wasm/sim-configs-inventory/evidence-expansion-candidates.tsv"],
["promotion-candidate-allowed", "0"],
["hard-block-runtime-locked-rows", "19"],
["hard-block-runtime-locked-preview", "L4-TOOL-DB:axis/db_demo/base.ngc, L4-PYTHON-REMAP:axis/laser/raster_test.ngc, L4-PYTHON-REMAP:axis/laser/vector_test.ngc"],
["hard-block-runtime-promotion-allowed", "0"],
["hard-block-runtime-family-count", "3"],
["hard-block-runtime-family-summary", "L4-USER-M-PROCESS:1 locked=yes, L4-TOOL-DB:1 locked=yes, L4-PYTHON-REMAP:17 locked=yes"],
["hard-block-runtime-detail-row-count", "19"],
["hard-block-runtime-detail-preview-1", "L4-TOOL-DB:axis/db_demo/base.ngc; reason=design_tooldata_db_protocol_boundary; next=db_program_v2_1_handshake_getall_load_unload_or_put; promotion_allowed=0"],
["hard-block-runtime-detail-preview-2", "L4-PYTHON-REMAP:axis/laser/raster_test.ngc; reason=design_linuxcnc_python_runtime_boundary; next=python_runtime_owner_and_fixture; promotion_allowed=0"],
["hard-block-runtime-detail-preview-3", "L4-PYTHON-REMAP:axis/laser/vector_test.ngc; reason=design_linuxcnc_python_runtime_boundary; next=python_runtime_owner_and_fixture; promotion_allowed=0"],
["hard-block-runtime-detail-preview-4", "L4-PYTHON-REMAP:axis/laser/vector_test2.ngc; reason=design_linuxcnc_python_runtime_boundary; next=python_runtime_owner_and_fixture; promotion_allowed=0"],
["hard-block-runtime-detail-preview-5", "L4-PYTHON-REMAP:axis/remap/cycle/nc_files/examples.ngc; reason=design_linuxcnc_python_runtime_boundary; next=python_runtime_owner_and_fixture; promotion_allowed=0"],
["hard-block-runtime-family-L4-USER-M-PROCESS", "1 locked rows; promotion_allowed=0; first=axis/vismach/millturn/example.ngc; reason=design_m128_m129_linuxcnc_state_boundary; next=kinstype_guard_and_ini_xyz_hal_pin_state"],
["hard-block-runtime-family-L4-TOOL-DB", "1 locked rows; promotion_allowed=0; first=axis/db_demo/base.ngc; reason=design_tooldata_db_protocol_boundary; next=db_program_v2_1_handshake_getall_load_unload_or_put"],
["hard-block-runtime-family-L4-PYTHON-REMAP", "17 locked rows; promotion_allowed=0; first=axis/laser/raster_test.ngc; reason=design_linuxcnc_python_runtime_boundary; next=python_runtime_owner_and_fixture"],
["hard-block-runtime-family-L4-USER-M-PROCESS-paths", "axis/vismach/millturn/example.ngc"],
["hard-block-runtime-family-L4-TOOL-DB-paths", "axis/db_demo/base.ngc"],
["hard-block-runtime-family-L4-PYTHON-REMAP-paths", "axis/laser/raster_test.ngc, axis/laser/vector_test.ngc, axis/laser/vector_test2.ngc, axis/remap/cycle/nc_files/examples.ngc, axis/remap/extend-builtins/nc_files/examples.ngc, axis/remap/getting-started/nc_files/examples.ngc, axis/remap/manual-toolchange-with-tool-length-switch/nc_files/tcdemo.ngc, axis/remap/rack-toolchange/nc_files/tcdemo.ngc, axis/remap/stop-lookahead/nc_files/examples.ngc, axis/vismach/5axis/table-rotary_spindle-rotary-nutating/demos/circular_pocket.ngc, axis/vismach/5axis/table-rotary_spindle-rotary-nutating/demos/incremental_repetition_back_and_forth.ngc, axis/vismach/5axis/table-rotary_spindle-rotary-nutating/demos/incremental_repetition.ngc, axis/vismach/5axis/table-rotary_spindle-rotary-nutating/demos/simple_example.ngc, axis/vismach/VMC_toolchange/toolchange.ngc, gmoccapy/non_trivial_kinematics/table-rotary-tilting/examples/boat-xyzac.ngc, gmoccapy/non_trivial_kinematics/table-rotary-tilting/examples/boat-xyzbc.ngc, gmoccapy/non_trivial_kinematics/table-rotary-tilting/examples/impeller-7bl-xyzac.ngc"],
...expectedPromotionFamilyRows,
["browser-diagnostics", "ready"],
["virtual-hal-promotion-candidate-summary", "ready"],

View File

@@ -397,7 +397,9 @@ assert.deepEqual(
["promotion-candidate-artifact", "wasm-port/build/wasm/sim-configs-inventory/promotion-candidates.tsv"],
["promotion-candidate-layers", "evidence-ready=8 inventory-ready=20"],
["promotion-candidate-total", "28"],
["promotion-candidate-artifact-rows", "28"],
["evidence-expansion-candidates", "13"],
["evidence-expansion-artifact-rows", "13"],
["evidence-expansion-next-evidence", "browser-diagnostics-binding"],
["evidence-expansion-baseline-changing", "no"],
["evidence-expansion-artifact", "wasm-port/build/wasm/sim-configs-inventory/evidence-expansion-candidates.tsv"],
@@ -496,7 +498,14 @@ assert.deepEqual(
["promotion-candidate-artifact", "wasm-port/build/wasm/sim-configs-inventory/promotion-candidates.tsv"],
["promotion-candidate-layers", "evidence-ready=8 inventory-ready=20"],
["promotion-candidate-total", "28"],
["evidence-ready-candidate-rows", "0"],
["evidence-ready-candidate-preview", "not provided"],
["evidence-ready-candidate-preview-gcode", "not provided"],
["evidence-ready-candidate-promotion-allowed", "0"],
["evidence-ready-candidate-baseline-changing", "no"],
["promotion-candidate-artifact-rows", "28"],
["evidence-expansion-candidates", "13"],
["evidence-expansion-artifact-rows", "13"],
["evidence-expansion-next-evidence", "browser-diagnostics-binding"],
["evidence-expansion-baseline-changing", "no"],
["evidence-expansion-preferred-candidate", "not provided"],
@@ -507,6 +516,18 @@ assert.deepEqual(
["evidence-expansion-source-count-list", "not provided"],
["evidence-expansion-artifact", "wasm-port/build/wasm/sim-configs-inventory/evidence-expansion-candidates.tsv"],
["promotion-candidate-allowed", "0"],
["hard-block-runtime-locked-rows", "0"],
["hard-block-runtime-locked-preview", "not provided"],
["hard-block-runtime-promotion-allowed", "0"],
["hard-block-runtime-family-count", "3"],
["hard-block-runtime-family-summary", "L4-USER-M-PROCESS:0 locked=yes, L4-TOOL-DB:0 locked=yes, L4-PYTHON-REMAP:0 locked=yes"],
["hard-block-runtime-detail-row-count", "0"],
["hard-block-runtime-family-L4-USER-M-PROCESS", "0 locked rows; promotion_allowed=0; first=not provided; reason=not provided; next=not provided"],
["hard-block-runtime-family-L4-TOOL-DB", "0 locked rows; promotion_allowed=0; first=not provided; reason=not provided; next=not provided"],
["hard-block-runtime-family-L4-PYTHON-REMAP", "0 locked rows; promotion_allowed=0; first=not provided; reason=not provided; next=not provided"],
["hard-block-runtime-family-L4-USER-M-PROCESS-paths", "not provided"],
["hard-block-runtime-family-L4-TOOL-DB-paths", "not provided"],
["hard-block-runtime-family-L4-PYTHON-REMAP-paths", "not provided"],
...expectedPromotionFamilyRows,
["browser-diagnostics", "not requested"],
["virtual-hal-promotion-candidate-summary", "not requested"],

View File

@@ -183,6 +183,24 @@ const sdkIndexText = readFileSync(resolve(root, "runtime/sdk/src/index.js"), "ut
const sdkReadmeText = readFileSync(resolve(root, "runtime/sdk/README.md"), "utf8");
const sourceManifestText = readFileSync(resolve(root, "tools/source-manifest.txt"), "utf8");
const trackerText = readFileSync(resolve(root, "../PROJECT_COMPLETION_TRACKER.md"), "utf8");
function parseTsvRows(text) {
const [headerLine, ...dataLines] = text.trim().split(/\r?\n/);
const headers = headerLine.split("\t");
return dataLines
.filter((line) => line.trim().length > 0)
.map((line) => {
const values = line.split("\t");
return Object.fromEntries(headers.map((header, index) => [header, values[index] ?? ""]));
});
}
const promotionCandidateArtifactRows = parseTsvRows(
readFileSync(resolve(root, "build/wasm/sim-configs-inventory/promotion-candidates.tsv"), "utf8"),
);
const evidenceExpansionArtifactRows = parseTsvRows(
readFileSync(resolve(root, "build/wasm/sim-configs-inventory/evidence-expansion-candidates.tsv"), "utf8"),
);
const expectedPromotionFamilySummary =
"qtdragon-on-abort: 6/6 ready; vismach-remap-sims: 1/1 ready; rose-engine-rcone-demo: 1/1 ready";
const expectedPromotionFamilyRows = [
@@ -204,7 +222,46 @@ const expectedPromotionCandidateArtifactSummary = {
totalCandidateCount: 28,
promotionAllowedCount: 0,
hardBlockRuntimeLock: "locked (3 families)",
hardBlockRuntimePromotionAllowedCount: 0,
inventoryBaseline: "executed=28 passed=28 skipped=131 unexpected_fail=0",
artifactRows: {
promotionCandidates: 28,
evidenceExpansion: 13,
},
hardBlockRuntimeFamilyRows: [],
hardBlockRuntimeFamilyDetailRows: [],
hardBlockRuntimeFamilySummaryRows: [
{
family: "L4-USER-M-PROCESS",
candidateCount: 0,
promotionAllowedCount: 0,
locked: true,
lockedPaths: [],
firstPath: null,
firstBlockReason: null,
nextProof: null,
},
{
family: "L4-TOOL-DB",
candidateCount: 0,
promotionAllowedCount: 0,
locked: true,
lockedPaths: [],
firstPath: null,
firstBlockReason: null,
nextProof: null,
},
{
family: "L4-PYTHON-REMAP",
candidateCount: 0,
promotionAllowedCount: 0,
locked: true,
lockedPaths: [],
firstPath: null,
firstBlockReason: null,
nextProof: null,
},
],
layers: [
{
id: "evidence-ready",
@@ -224,6 +281,7 @@ const expectedPromotionCandidateArtifactSummary = {
evidenceExpansion: {
id: "browser-diagnostics-expansion",
candidateCount: 13,
artifactRowCount: 13,
promotionAllowedCount: 0,
baselineChanging: false,
nextEvidence: "browser-diagnostics-binding",
@@ -1571,6 +1629,14 @@ assert.deepEqual(
releaseReadinessReady.promotionCandidateArtifactSummary,
expectedPromotionCandidateArtifactSummary,
);
assert.equal(
releaseReadinessReady.rows.find(({ id }) => id === "promotion-candidate-artifact-rows")?.value,
"28",
);
assert.equal(
releaseReadinessReady.rows.find(({ id }) => id === "evidence-expansion-artifact-rows")?.value,
"13",
);
assert.deepEqual(
releaseReadinessReady.virtualHalPromotionFamilyRows.map(({ id, value }) => [
`virtual-hal-promotion-family-${id}`,
@@ -1597,6 +1663,78 @@ assert.equal(
createProjectReleaseReadinessSummaryViewModel(releaseReadinessReady).rows.find(({ id }) => id === "promotion-candidate-layers")?.value,
"evidence-ready=8 inventory-ready=20",
);
const releaseReadinessWithCandidateArtifacts = createProjectReleaseReadinessReport({
observedOutputs: ["project_release_gate=ok"],
virtualHalSimConfigSourceCoverage: simConfigSourceCoverageReport,
virtualHalSimConfigPromotionCandidates: simConfigPromotionCandidateReport,
virtualHalSimConfigMacroLoadFixtures: simConfigMacroLoadFixtureReport,
virtualHalMotionControllerMatrix: manifestCheckedMotionControllerMatrixReport,
promotionCandidateRows: promotionCandidateArtifactRows,
evidenceExpansionRows: evidenceExpansionArtifactRows,
});
assert.equal(releaseReadinessWithCandidateArtifacts.promotionCandidateArtifactSummary.artifactRows.promotionCandidates, 28);
assert.equal(releaseReadinessWithCandidateArtifacts.promotionCandidateArtifactSummary.artifactRows.evidenceExpansion, 13);
assert.equal(
releaseReadinessWithCandidateArtifacts.promotionCandidateArtifactSummary.hardBlockRuntimeFamilyRows.length,
19,
);
assert.equal(
releaseReadinessWithCandidateArtifacts.promotionCandidateArtifactSummary.hardBlockRuntimePromotionAllowedCount,
0,
);
assert.equal(
releaseReadinessWithCandidateArtifacts.promotionCandidateArtifactSummary.hardBlockRuntimeFamilyRows
.some((row) => row.skipKind === "L4-TOOL-DB" && row.promotionAllowed === false),
true,
);
assert.deepEqual(
releaseReadinessWithCandidateArtifacts.promotionCandidateArtifactSummary.hardBlockRuntimeFamilySummaryRows
.map(({ family, candidateCount, promotionAllowedCount, locked }) => [
family,
candidateCount,
promotionAllowedCount,
locked,
]),
[
["L4-USER-M-PROCESS", 1, 0, true],
["L4-TOOL-DB", 1, 0, true],
["L4-PYTHON-REMAP", 17, 0, true],
],
);
assert.deepEqual(
releaseReadinessWithCandidateArtifacts.promotionCandidateArtifactSummary.hardBlockRuntimeFamilyDetailRows
.slice(0, 3)
.map(({ family, path, blockReason, nextProof, promotionAllowed }) => [
family,
path,
blockReason,
nextProof,
promotionAllowed,
]),
[
[
"L4-TOOL-DB",
"axis/db_demo/base.ngc",
"design_tooldata_db_protocol_boundary",
"db_program_v2_1_handshake_getall_load_unload_or_put",
false,
],
[
"L4-PYTHON-REMAP",
"axis/laser/raster_test.ngc",
"design_linuxcnc_python_runtime_boundary",
"python_runtime_owner_and_fixture",
false,
],
[
"L4-PYTHON-REMAP",
"axis/laser/vector_test.ngc",
"design_linuxcnc_python_runtime_boundary",
"python_runtime_owner_and_fixture",
false,
],
],
);
const releaseReadinessWithScreenshots = createProjectReleaseReadinessReport({
gateResults: Object.fromEntries(createProjectReleaseGateManifest().gateIds.map((id) => [id, true])),
virtualHalSimConfigSourceCoverage: simConfigSourceCoverageReport,
@@ -1735,11 +1873,21 @@ assert.deepEqual(releaseReadinessArtifactValidation, {
label: "Promotion candidate total",
value: "28",
},
{
id: "promotion-candidate-artifact-rows",
label: "Promotion candidate artifact rows",
value: "28",
},
{
id: "evidence-expansion-candidates",
label: "Evidence expansion candidates",
value: "13",
},
{
id: "evidence-expansion-artifact-rows",
label: "Evidence expansion artifact rows",
value: "13",
},
{
id: "evidence-expansion-next-evidence",
label: "Evidence expansion next evidence",
@@ -1899,6 +2047,22 @@ assert.equal(
).rows.find(({ id }) => id === "promotion-candidate-layers")?.value,
"evidence-ready=8 inventory-ready=20",
);
assert.equal(
createProjectReleaseReadinessArtifactUrlWorkflowSummaryViewModel(
await loadProjectReleaseReadinessArtifactUrlWorkflow({
artifactUrl: "/project-release-readiness.json",
diagnosticsUrl: "/browser-diagnostics.json",
fetchRef: async (url) => ({
ok: true,
status: 200,
text: async () => url === "/browser-diagnostics.json"
? JSON.stringify(browserDiagnosticsArtifact)
: JSON.stringify(releaseReadinessArtifact),
}),
}),
).rows.find(({ id }) => id === "evidence-ready-candidate-rows")?.value,
"8",
);
assert.equal(
createProjectReleaseReadinessArtifactUrlWorkflowSummaryViewModel(
await loadProjectReleaseReadinessArtifactUrlWorkflow({