按text22收束promotion证据
结论:完成 evidence-ready / inventory-ready 双层 promotion candidate 管理,release/SDK gate 已纳入 virtual HAL promotion summary,baseline 保持 28/28/131/0,Python remap、tool DB、external user-M hard block 继续 locked。
This commit is contained in:
@@ -4,6 +4,7 @@ import { basename, dirname, posix, resolve } from "node:path";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
import {
|
||||
VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES,
|
||||
analyzeIniRuntimeBoundaries,
|
||||
createLinuxCncInterpSdk,
|
||||
planSimConfigStaging,
|
||||
@@ -100,6 +101,7 @@ const runtimeBoundaryNativeAlignmentSummaryPath = resolve(buildDir, "runtime-bou
|
||||
const runtimeProbeGateAlignmentPath = resolve(buildDir, "runtime-probe-gate-alignment.tsv");
|
||||
const nativeRuntimeProbeExecutionPlanPath = resolve(buildDir, "native-runtime-probe-execution-plan.tsv");
|
||||
const nativeRuntimeProbePassEvidenceContractPath = resolve(buildDir, "native-runtime-probe-pass-evidence-contract.tsv");
|
||||
const promotionCandidatesPath = resolve(buildDir, "promotion-candidates.tsv");
|
||||
const blockedRuntimePromotionLockPath = resolve(buildDir, "blocked-runtime-promotion-lock.tsv");
|
||||
const runtimeBoundaryPromotionReadinessPath = resolve(buildDir, "runtime-boundary-promotion-readiness.tsv");
|
||||
const runtimeBoundaryPromotionBlockersPath = resolve(buildDir, "runtime-boundary-promotion-blockers.tsv");
|
||||
@@ -155,6 +157,7 @@ const generatedSimConfigInventoryArtifactPaths = [
|
||||
runtimeProbeGateAlignmentPath,
|
||||
nativeRuntimeProbeExecutionPlanPath,
|
||||
nativeRuntimeProbePassEvidenceContractPath,
|
||||
promotionCandidatesPath,
|
||||
blockedRuntimePromotionLockPath,
|
||||
runtimeBoundaryPromotionReadinessPath,
|
||||
runtimeBoundaryPromotionBlockersPath,
|
||||
@@ -6087,7 +6090,7 @@ function verifyBoundaryPhaseCompletionSummaryRows(rows) {
|
||||
const rowByCriterion = new Map(parsedRows.map((row) => [row.criterion, row]));
|
||||
assert.equal(
|
||||
rowByCriterion.get("wasm_inventory_artifact_documentation_coverage")?.count,
|
||||
"54",
|
||||
"55",
|
||||
"WASM artifact documentation completion count must match generated artifact baseline",
|
||||
);
|
||||
assert.equal(
|
||||
@@ -8609,7 +8612,7 @@ function verifyGeneratedArtifactDocumentationCoverage({
|
||||
);
|
||||
assert.equal(
|
||||
artifactNames.length,
|
||||
54,
|
||||
55,
|
||||
"generated sim-config inventory artifact list count drift",
|
||||
);
|
||||
assert.deepEqual(
|
||||
@@ -8628,6 +8631,7 @@ function verifyGeneratedArtifactDocumentationCoverage({
|
||||
"native-runtime-probe-summary.tsv",
|
||||
"next-boundary-recommendations.tsv",
|
||||
"next-boundary-worklist.tsv",
|
||||
"promotion-candidates.tsv",
|
||||
"python-remap-boundary-summary.tsv",
|
||||
"python-remap-family-summary.tsv",
|
||||
"python-remap-native-runtime-alignment.tsv",
|
||||
@@ -8703,7 +8707,7 @@ function verifyGeneratedArtifactDocumentationCoverage({
|
||||
"generated sim-config inventory artifacts must be listed in browser smoke",
|
||||
);
|
||||
assert.ok(
|
||||
browserSmokeText.includes("wasmArtifactNames.length !== 54"),
|
||||
browserSmokeText.includes("wasmArtifactNames.length !== 55"),
|
||||
"browser smoke must keep generated WASM artifact fixed-count guard",
|
||||
);
|
||||
assert.ok(
|
||||
@@ -11946,6 +11950,198 @@ function verifyHardBlockedInventorySkips(rows, pathMatrixByPath) {
|
||||
}
|
||||
}
|
||||
|
||||
function sourcePathToInventoryPath(sourcePath) {
|
||||
const prefix = "linuxcnc/configs/sim/";
|
||||
return sourcePath.startsWith(prefix) ? sourcePath.slice(prefix.length) : "";
|
||||
}
|
||||
|
||||
function promotionCandidateRows({
|
||||
summaryRows,
|
||||
boundaryRows,
|
||||
nextBoundaryRecords,
|
||||
trackedMatrixByPath,
|
||||
nativeByPath,
|
||||
}) {
|
||||
const summaryByPath = new Map(summaryRows.map((row) => {
|
||||
const [
|
||||
path,
|
||||
inventoryStatus,
|
||||
reason,
|
||||
className,
|
||||
nativeStatus,
|
||||
nativeExpectedFailure,
|
||||
] = row.split("\t");
|
||||
return [path, {
|
||||
path,
|
||||
inventoryStatus,
|
||||
reason,
|
||||
className,
|
||||
nativeStatus,
|
||||
nativeExpectedFailure,
|
||||
}];
|
||||
}));
|
||||
const boundaryByPath = new Map(boundaryRows.map((row) => [row.path, row]));
|
||||
const nextBoundaryByBlocked = new Map(nextBoundaryRecords.map((row) => [row.blocked, row]));
|
||||
|
||||
const evidenceReadyRows = VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES.map((candidate) => {
|
||||
const inventoryPath = sourcePathToInventoryPath(candidate.gcodePath);
|
||||
const summary = summaryByPath.get(inventoryPath);
|
||||
const matrix = trackedMatrixByPath.get(inventoryPath);
|
||||
const native = nativeByPath.get(inventoryPath);
|
||||
const boundary = boundaryByPath.get(inventoryPath);
|
||||
const virtualHalEvidenceReady = candidate.currentNodeInventoryStatus === "PASS" &&
|
||||
candidate.currentMatrixBrowserStatus === "explicit-browser-diagnostics" &&
|
||||
candidate.targetBrowserEvidence === "explicit-browser-diagnostics" &&
|
||||
candidate.blockedKind === "-" &&
|
||||
summary?.inventoryStatus === "PASS";
|
||||
return [
|
||||
"evidence-ready",
|
||||
candidate.id,
|
||||
inventoryPath,
|
||||
sourcePathToInventoryPath(candidate.iniPath),
|
||||
summary?.inventoryStatus ?? "-",
|
||||
summary?.reason ?? "-",
|
||||
matrix?.layer4Node ?? "-",
|
||||
matrix?.layer4Browser ?? "-",
|
||||
summary?.className ?? native?.class ?? "-",
|
||||
summary?.nativeStatus ?? native?.status ?? "-",
|
||||
summary?.nativeExpectedFailure ?? native?.expected_failure ?? "-",
|
||||
matrix?.blocked ?? candidate.blockedKind ?? "-",
|
||||
candidate.dependencyClass,
|
||||
flagValue(virtualHalEvidenceReady),
|
||||
"0",
|
||||
virtualHalEvidenceReady ? "browser_release_evidence_ready_inventory_baseline_unchanged" : "virtual_hal_evidence_incomplete",
|
||||
"wasm-port/tests/sdk/node/verify_sdk_surface.sh && wasm-port/tests/sdk/node/verify_project_release_gate_manifest.sh",
|
||||
].map(tsvValue).join("\t");
|
||||
});
|
||||
|
||||
const inventoryReadyRows = [...summaryByPath.values()]
|
||||
.filter((row) => row.className === "main" && row.inventoryStatus === "SKIP")
|
||||
.sort((left, right) => left.path.localeCompare(right.path))
|
||||
.map((row) => {
|
||||
const boundary = boundaryByPath.get(row.path);
|
||||
const matrix = trackedMatrixByPath.get(row.path);
|
||||
const boundaryWork = nextBoundaryByBlocked.get(row.reason);
|
||||
const promotionAllowed = row.reason === "-" &&
|
||||
boundary?.recommended_blocked === "-" &&
|
||||
row.nativeStatus === "PASS";
|
||||
const blockReason = promotionAllowed
|
||||
? "-"
|
||||
: (boundaryWork?.next_action ?? `blocked_by_${row.reason}`);
|
||||
const recommendedNextCommand = promotionAllowed
|
||||
? "SKIP_INTERP_BUILD=1 wasm-port/tests/wasm/node/verify_sim_configs_inventory_wasm.sh"
|
||||
: (boundaryWork?.required_native_proof ?? "no_direct_baseline_promotion_candidate");
|
||||
return [
|
||||
"inventory-ready",
|
||||
row.path,
|
||||
row.path,
|
||||
boundary?.ini ?? "-",
|
||||
row.inventoryStatus,
|
||||
row.reason,
|
||||
matrix?.layer4Node ?? "-",
|
||||
matrix?.layer4Browser ?? "-",
|
||||
row.className,
|
||||
row.nativeStatus,
|
||||
row.nativeExpectedFailure,
|
||||
matrix?.blocked ?? row.reason,
|
||||
boundary?.dependencies ?? "-",
|
||||
"0",
|
||||
flagValue(promotionAllowed),
|
||||
blockReason,
|
||||
recommendedNextCommand,
|
||||
].map(tsvValue).join("\t");
|
||||
});
|
||||
|
||||
return [...evidenceReadyRows, ...inventoryReadyRows];
|
||||
}
|
||||
|
||||
function verifyPromotionCandidateRows(rows, summaryRows, boundaryRows) {
|
||||
const expectedHeaders = [
|
||||
"candidate_kind",
|
||||
"candidate_id",
|
||||
"path",
|
||||
"ini",
|
||||
"current_status",
|
||||
"skip_kind",
|
||||
"matrix_layer4_node",
|
||||
"matrix_layer4_browser",
|
||||
"class",
|
||||
"native_status",
|
||||
"native_expected_failure",
|
||||
"blocked_kind",
|
||||
"dependency_class",
|
||||
"virtual_hal_evidence_ready",
|
||||
"promotion_allowed",
|
||||
"block_reason",
|
||||
"recommended_next_command",
|
||||
];
|
||||
const parsedRows = parseTsv(
|
||||
`${expectedHeaders.join("\t")}\n${rows.join("\n")}\n`,
|
||||
expectedHeaders,
|
||||
);
|
||||
const expectedSkippedMain = summaryRows
|
||||
.map((row) => {
|
||||
const [path, inventoryStatus, reason, className] = row.split("\t");
|
||||
return { path, inventoryStatus, reason, className };
|
||||
})
|
||||
.filter((row) => row.inventoryStatus === "SKIP" && row.className === "main")
|
||||
.map((row) => row.path)
|
||||
.sort();
|
||||
const evidenceReadyPaths = VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES
|
||||
.map((candidate) => sourcePathToInventoryPath(candidate.gcodePath))
|
||||
.sort();
|
||||
const boundaryByPath = new Map(boundaryRows.map((row) => [row.path, row]));
|
||||
const parsedEvidenceReady = parsedRows.filter((row) => row.candidate_kind === "evidence-ready");
|
||||
const parsedInventoryReady = parsedRows.filter((row) => row.candidate_kind === "inventory-ready");
|
||||
|
||||
assert.deepEqual(
|
||||
parsedEvidenceReady.map((row) => row.path).sort(),
|
||||
evidenceReadyPaths,
|
||||
"promotion-candidates must cover virtual HAL evidence-ready rows",
|
||||
);
|
||||
assert.deepEqual(
|
||||
parsedInventoryReady.map((row) => row.path).sort(),
|
||||
expectedSkippedMain,
|
||||
"promotion-candidates must cover every skipped main inventory candidate row",
|
||||
);
|
||||
assert.equal(
|
||||
parsedInventoryReady.filter((row) => row.promotion_allowed === "1").length,
|
||||
0,
|
||||
"current baseline has no direct skipped-main inventory promotion candidate",
|
||||
);
|
||||
for (const row of parsedEvidenceReady) {
|
||||
assert.equal(row.current_status, "PASS", `${row.path}: evidence-ready row must be a current inventory PASS`);
|
||||
assert.equal(row.skip_kind, "-", `${row.path}: evidence-ready row must not have a skip kind`);
|
||||
assert.equal(row.blocked_kind, "-", `${row.path}: evidence-ready row must not be hard-blocked`);
|
||||
assert.equal(row.virtual_hal_evidence_ready, "1", `${row.path}: evidence-ready row lacks virtual HAL evidence`);
|
||||
assert.equal(row.promotion_allowed, "0", `${row.path}: evidence-ready row must not claim inventory promotion`);
|
||||
assert.equal(row.matrix_layer4_node, "INV", `${row.path}: evidence-ready row should remain Node INV`);
|
||||
assert.equal(row.matrix_layer4_browser, "-", `${row.path}: evidence-ready row should record explicit diagnostics outside matrix browser REP`);
|
||||
assert.equal(row.block_reason, "browser_release_evidence_ready_inventory_baseline_unchanged");
|
||||
assert.ok(
|
||||
row.recommended_next_command.includes("verify_sdk_surface.sh"),
|
||||
`${row.path}: evidence-ready row lacks virtual HAL gate command`,
|
||||
);
|
||||
}
|
||||
for (const row of parsedInventoryReady) {
|
||||
assert.equal(row.current_status, "SKIP", `${row.path}: promotion candidate status drift`);
|
||||
assert.equal(row.class, "main", `${row.path}: promotion candidate must be main class`);
|
||||
assert.equal(row.blocked_kind, row.skip_kind, `${row.path}: skipped inventory blocked kind drift`);
|
||||
assert.equal(row.virtual_hal_evidence_ready, "0", `${row.path}: skipped inventory row must not claim virtual HAL evidence ready`);
|
||||
assert.ok(
|
||||
["L4-PYTHON-REMAP", "L4-TOOL-DB", "L4-USER-M-PROCESS", "UPSTREAM-DEMO"].includes(row.skip_kind),
|
||||
`${row.path}: direct promotion candidate must remain hard-blocked or upstream-demo`,
|
||||
);
|
||||
const boundary = boundaryByPath.get(row.path);
|
||||
assert.ok(boundary, `${row.path}: promotion candidate lacks boundary evidence`);
|
||||
if (row.skip_kind.startsWith("L4-")) {
|
||||
assert.notEqual(row.recommended_next_command, "-", `${row.path}: blocked row lacks next proof command`);
|
||||
assert.notEqual(row.block_reason, "-", `${row.path}: blocked row lacks block reason`);
|
||||
}
|
||||
}
|
||||
return parsedRows;
|
||||
}
|
||||
|
||||
for (const record of nativeRecords) {
|
||||
const skipReason = blockedKind(record, pathMatrixByPath);
|
||||
if (skipReason) {
|
||||
@@ -12425,6 +12621,44 @@ writeFileSync(
|
||||
].join("\n")}\n`,
|
||||
);
|
||||
|
||||
const promotionCandidateRowsGenerated = promotionCandidateRows({
|
||||
summaryRows,
|
||||
boundaryRows: boundarySummaryRecords,
|
||||
nextBoundaryRecords,
|
||||
trackedMatrixByPath,
|
||||
nativeByPath: new Map(nativeRecords.map((record) => [record.path, record])),
|
||||
});
|
||||
verifyPromotionCandidateRows(
|
||||
promotionCandidateRowsGenerated,
|
||||
summaryRows,
|
||||
boundarySummaryRecords,
|
||||
);
|
||||
writeFileSync(
|
||||
promotionCandidatesPath,
|
||||
`${[
|
||||
[
|
||||
"candidate_kind",
|
||||
"candidate_id",
|
||||
"path",
|
||||
"ini",
|
||||
"current_status",
|
||||
"skip_kind",
|
||||
"matrix_layer4_node",
|
||||
"matrix_layer4_browser",
|
||||
"class",
|
||||
"native_status",
|
||||
"native_expected_failure",
|
||||
"blocked_kind",
|
||||
"dependency_class",
|
||||
"virtual_hal_evidence_ready",
|
||||
"promotion_allowed",
|
||||
"block_reason",
|
||||
"recommended_next_command",
|
||||
].join("\t"),
|
||||
...promotionCandidateRowsGenerated,
|
||||
].join("\n")}\n`,
|
||||
);
|
||||
|
||||
writeFileSync(
|
||||
boundarySummaryPath,
|
||||
`${[
|
||||
|
||||
Reference in New Issue
Block a user