按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:
2026-06-18 17:20:29 +08:00
parent 014081f1f9
commit 1c94ea4527
29 changed files with 8500 additions and 121 deletions

View File

@@ -125,6 +125,20 @@ export const VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS = Object.freeze([
}),
]);
export const VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE = Object.freeze({
executed: 28,
passed: 28,
skipped: 131,
unexpectedFail: 0,
});
export const VIRTUAL_HAL_SIM_CONFIG_INVENTORY_ARTIFACT_HASHES = Object.freeze({
"wasm-port/build/wasm/sim-configs-inventory/boundary-summary.tsv":
"de6cf57b7c07182e3bcb32e22dbdf202b618cabc14620d6dff1ef815587950b9",
"wasm-port/build/wasm/sim-configs-inventory/ini-boundary-summary.tsv":
"b0afe27224e97a82fbecbbd75a7c86233c98fe957d9c1ba20f0656f8745a5eae",
});
export const VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES = Object.freeze([
Object.freeze({
id: "qtdragon-multi-joint-on-abort",
@@ -137,7 +151,7 @@ export const VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES = Object.freeze([
iniPath: "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini",
gcodePath: "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc",
currentNodeInventoryStatus: "PASS",
currentMatrixBrowserStatus: "delegated-to-woodpecker",
currentMatrixBrowserStatus: "explicit-browser-diagnostics",
dependencyClass: "hal-ui-multi-joint",
targetBrowserEvidence: "explicit-browser-diagnostics",
requiredVirtualHalReports: Object.freeze([
@@ -161,7 +175,7 @@ export const VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES = Object.freeze([
iniPath: "linuxcnc/configs/sim/qtdragon/qtdragon_xyz/qtdragon_inch.ini",
gcodePath: "linuxcnc/configs/sim/qtdragon/qtdragon_xyz/on_abort.ngc",
currentNodeInventoryStatus: "PASS",
currentMatrixBrowserStatus: "delegated-to-woodpecker",
currentMatrixBrowserStatus: "explicit-browser-diagnostics",
dependencyClass: "hal-ui-on-abort",
targetBrowserEvidence: "explicit-browser-diagnostics",
requiredVirtualHalReports: Object.freeze([
@@ -185,7 +199,7 @@ export const VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES = Object.freeze([
iniPath: "linuxcnc/configs/sim/qtdragon/qtdragon_xyz45/qtdragon_xyza.ini",
gcodePath: "linuxcnc/configs/sim/qtdragon/qtdragon_xyz45/on_abort.ngc",
currentNodeInventoryStatus: "PASS",
currentMatrixBrowserStatus: "delegated-to-woodpecker",
currentMatrixBrowserStatus: "explicit-browser-diagnostics",
dependencyClass: "hal-ui-rotary-axis",
targetBrowserEvidence: "explicit-browser-diagnostics",
requiredVirtualHalReports: Object.freeze([
@@ -209,7 +223,7 @@ export const VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES = Object.freeze([
iniPath: "linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_xyz/qtdragon_hd_vertical.ini",
gcodePath: "linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_xyz/on_abort.ngc",
currentNodeInventoryStatus: "PASS",
currentMatrixBrowserStatus: "delegated-to-woodpecker",
currentMatrixBrowserStatus: "explicit-browser-diagnostics",
dependencyClass: "hal-ui-on-abort",
targetBrowserEvidence: "explicit-browser-diagnostics",
requiredVirtualHalReports: Object.freeze([
@@ -233,7 +247,7 @@ export const VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES = Object.freeze([
iniPath: "linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_z_compensation/qtdragon_hd_z_compensation.ini",
gcodePath: "linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_z_compensation/on_abort.ngc",
currentNodeInventoryStatus: "PASS",
currentMatrixBrowserStatus: "delegated-to-woodpecker",
currentMatrixBrowserStatus: "explicit-browser-diagnostics",
dependencyClass: "hal-ui-z-compensation",
targetBrowserEvidence: "explicit-browser-diagnostics",
requiredVirtualHalReports: Object.freeze([
@@ -257,7 +271,7 @@ export const VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES = Object.freeze([
iniPath: "linuxcnc/configs/sim/qtvcp_screens/qtdragon/qtdragon_mpg.ini",
gcodePath: "linuxcnc/configs/sim/qtvcp_screens/qtdragon/on_abort.ngc",
currentNodeInventoryStatus: "PASS",
currentMatrixBrowserStatus: "delegated-to-woodpecker",
currentMatrixBrowserStatus: "explicit-browser-diagnostics",
dependencyClass: "hal-ui-on-abort",
targetBrowserEvidence: "explicit-browser-diagnostics",
requiredVirtualHalReports: Object.freeze([
@@ -282,7 +296,7 @@ export const VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES = Object.freeze([
iniPath: "linuxcnc/configs/sim/axis/vismach/puma/puma.ini",
gcodePath: "linuxcnc/configs/sim/axis/vismach/puma/puma_seam_weld.ngc",
currentNodeInventoryStatus: "PASS",
currentMatrixBrowserStatus: "represented-by-puma-cube",
currentMatrixBrowserStatus: "explicit-browser-diagnostics",
dependencyClass: "halui-vismach-remap",
targetBrowserEvidence: "explicit-browser-diagnostics",
requiredVirtualHalReports: Object.freeze([
@@ -306,7 +320,7 @@ export const VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES = Object.freeze([
iniPath: "linuxcnc/configs/sim/axis/rose_engine/rose_engine.ini",
gcodePath: "linuxcnc/configs/sim/axis/rose_engine/rcone_demo.ngc",
currentNodeInventoryStatus: "PASS",
currentMatrixBrowserStatus: "not-promoted",
currentMatrixBrowserStatus: "explicit-browser-diagnostics",
dependencyClass: "hal-process-only",
targetBrowserEvidence: "explicit-browser-diagnostics",
requiredVirtualHalReports: Object.freeze([
@@ -334,6 +348,14 @@ export const VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_FIXTURES = Object.freeze([
owningIniPath: "linuxcnc/configs/sim/axis/rose_engine/rose_engine.ini",
pairedMainProgram: "linuxcnc/configs/sim/axis/rose_engine/rcone_demo.ngc",
declarationSource: "NGCGUI_SUBFILE",
declarationEvidence: Object.freeze({
sourceFile: "linuxcnc/configs/sim/axis/rose_engine/rose_engine.ini",
section: "DISPLAY",
key: "NGCGUI_SUBFILE",
value: "rcone.ngc",
line: 34,
sourceLine: "NGCGUI_SUBFILE = rcone.ngc",
}),
currentNodeInventoryStatus: "PASS",
dependencyClass: "macro-load-non-main",
targetBrowserEvidence: "non-main-fixture-diagnostics",
@@ -353,6 +375,14 @@ export const VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_FIXTURES = Object.freeze([
owningIniPath: "linuxcnc/configs/sim/axis/external_offsets/eoffsets.ini",
pairedMainProgram: "linuxcnc/configs/sim/axis/external_offsets/eoffsets.ngc",
declarationSource: "NGCGUI_SUBFILE",
declarationEvidence: Object.freeze({
sourceFile: "linuxcnc/configs/sim/axis/external_offsets/eoffsets.ini",
section: "DISPLAY",
key: "NGCGUI_SUBFILE",
value: "queuebuster.ngc",
line: 40,
sourceLine: "NGCGUI_SUBFILE = queuebuster.ngc",
}),
currentNodeInventoryStatus: "NON_MAIN_CLASS",
dependencyClass: "macro-load-non-main-declared-only",
targetBrowserEvidence: "non-main-fixture-diagnostics",
@@ -370,6 +400,27 @@ export const VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_BLOCKED_FIXTURES = Object.freeze(
owningIniPath: "linuxcnc/configs/sim/gscreen/silverdragon/silverdragon.ini",
blockedKind: "PYTHON-UI-PROCESS",
dependencyClass: "macro-load-python-ui-boundary",
boundaryEvidence: Object.freeze({
sourceArtifacts: Object.freeze([
"wasm-port/build/wasm/sim-configs-inventory/boundary-summary.tsv",
"wasm-port/build/wasm/sim-configs-inventory/ini-boundary-summary.tsv",
]),
sourceArtifactHashes: VIRTUAL_HAL_SIM_CONFIG_INVENTORY_ARTIFACT_HASHES,
baselineSummary: VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE,
boundarySummary: Object.freeze({
path: "gscreen/silverdragon/macros/tool_sensor.ngc",
ini: "gscreen/silverdragon/silverdragon.ini",
recommendedBlocked: "UNAVAILABLE",
dependencies: "missing_vendored_ini:configs/sim/gscreen/silverdragon/silverdragon.ini",
}),
iniBoundarySummary: Object.freeze({
ini: "gscreen/silverdragon/silverdragon.ini",
vendored: 0,
reportAvailable: 0,
recommendedBlocked: "UNAVAILABLE",
dependencies: "missing_vendored_ini:configs/sim/gscreen/silverdragon/silverdragon.ini",
}),
}),
reason: "Owning SilverDragon UI machine file is not available in the vendored manifest; promotion would require Python UI process boundary proof outside virtual HAL.",
}),
Object.freeze({
@@ -378,10 +429,94 @@ export const VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_BLOCKED_FIXTURES = Object.freeze(
owningIniPath: "linuxcnc/configs/sim/gmoccapy/6_axis.ini",
blockedKind: "L4-PYTHON-REMAP",
dependencyClass: "macro-load-python-remap-boundary",
boundaryEvidence: Object.freeze({
sourceArtifacts: Object.freeze([
"wasm-port/build/wasm/sim-configs-inventory/boundary-summary.tsv",
"wasm-port/build/wasm/sim-configs-inventory/ini-boundary-summary.tsv",
]),
sourceArtifactHashes: VIRTUAL_HAL_SIM_CONFIG_INVENTORY_ARTIFACT_HASHES,
baselineSummary: VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE,
boundarySummary: Object.freeze({
path: "gmoccapy/macros/on_abort.ngc",
ini: "gmoccapy/6_axis.ini",
recommendedBlocked: "UNAVAILABLE",
dependencies: "missing_vendored_ini:configs/sim/gmoccapy/6_axis.ini",
}),
iniBoundarySummary: Object.freeze({
ini: "gmoccapy/6_axis.ini",
vendored: 0,
reportAvailable: 0,
recommendedBlocked: "UNAVAILABLE",
dependencies: "missing_vendored_ini:configs/sim/gmoccapy/6_axis.ini",
}),
}),
reason: "gmoccapy macro/load rows remain locked behind LinuxCNC-owned Python remap/prolog/epilog runtime proof.",
}),
]);
export const VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_AUDIT_CANDIDATES = Object.freeze([
Object.freeze({
id: "gscreen-industrial-lathe-wear-toolchange-audit",
fixturePath: "linuxcnc/configs/sim/gscreen/industrial_lathe_wear/toolchange.ngc",
owningIniPath: "linuxcnc/configs/sim/gscreen/industrial_lathe_wear/industrial_lathe_wear.ini",
dependencyClass: "macro-load-ui-family-audit",
auditStatus: "blocked-missing-owning-ini",
promotionAllowed: false,
boundaryEvidence: Object.freeze({
sourceArtifacts: Object.freeze([
"wasm-port/build/wasm/sim-configs-inventory/boundary-summary.tsv",
"wasm-port/build/wasm/sim-configs-inventory/ini-boundary-summary.tsv",
]),
sourceArtifactHashes: VIRTUAL_HAL_SIM_CONFIG_INVENTORY_ARTIFACT_HASHES,
baselineSummary: VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE,
boundarySummary: Object.freeze({
path: "gscreen/industrial_lathe_wear/toolchange.ngc",
ini: "gscreen/industrial_lathe_wear/industrial_lathe_wear.ini",
recommendedBlocked: "UNAVAILABLE",
dependencies: "missing_vendored_ini:configs/sim/gscreen/industrial_lathe_wear/industrial_lathe_wear.ini",
}),
iniBoundarySummary: Object.freeze({
ini: "gscreen/industrial_lathe_wear/industrial_lathe_wear.ini",
vendored: 0,
reportAvailable: 0,
recommendedBlocked: "UNAVAILABLE",
dependencies: "missing_vendored_ini:configs/sim/gscreen/industrial_lathe_wear/industrial_lathe_wear.ini",
}),
}),
reason: "Generated boundary evidence reports missing vendored owning INI for gscreen industrial_lathe_wear; keep as audit-only until machine files and UI/process declaration have LinuxCNC source evidence.",
}),
Object.freeze({
id: "qtvcp-industrial-lathe-wear-toolchange-audit",
fixturePath: "linuxcnc/configs/sim/qtvcp_screens/industrial_lathe_wear/toolchange.ngc",
owningIniPath: "linuxcnc/configs/sim/qtvcp_screens/industrial_lathe_wear/industrial_lathe_wear.ini",
dependencyClass: "macro-load-ui-family-audit",
auditStatus: "blocked-missing-owning-ini",
promotionAllowed: false,
boundaryEvidence: Object.freeze({
sourceArtifacts: Object.freeze([
"wasm-port/build/wasm/sim-configs-inventory/boundary-summary.tsv",
"wasm-port/build/wasm/sim-configs-inventory/ini-boundary-summary.tsv",
]),
sourceArtifactHashes: VIRTUAL_HAL_SIM_CONFIG_INVENTORY_ARTIFACT_HASHES,
baselineSummary: VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE,
boundarySummary: Object.freeze({
path: "qtvcp_screens/industrial_lathe_wear/toolchange.ngc",
ini: "qtvcp_screens/industrial_lathe_wear/industrial_lathe_wear.ini",
recommendedBlocked: "UNAVAILABLE",
dependencies: "missing_vendored_ini:configs/sim/qtvcp_screens/industrial_lathe_wear/industrial_lathe_wear.ini",
}),
iniBoundarySummary: Object.freeze({
ini: "qtvcp_screens/industrial_lathe_wear/industrial_lathe_wear.ini",
vendored: 0,
reportAvailable: 0,
recommendedBlocked: "UNAVAILABLE",
dependencies: "missing_vendored_ini:configs/sim/qtvcp_screens/industrial_lathe_wear/industrial_lathe_wear.ini",
}),
}),
reason: "Generated boundary evidence reports missing vendored owning INI for qtvcp_screens industrial_lathe_wear; keep as audit-only until machine files and UI/process declaration have LinuxCNC source evidence.",
}),
]);
export const VIRTUAL_HAL_COVERAGE_STATES = Object.freeze({
simulated: "simulated",
bridgeOnly: "bridge-only",
@@ -2683,6 +2818,10 @@ function normalizeLinuxCncSourcePath(path) {
return parts.join("/");
}
function normalizeSimConfigInventoryPath(path) {
return normalizeLinuxCncSourcePath(path).replace(/^configs\/sim\//, "");
}
function sourceManifestSetFromText(manifestText = "") {
return new Set(String(manifestText)
.split("\n")
@@ -2691,6 +2830,35 @@ function sourceManifestSetFromText(manifestText = "") {
.map(normalizeLinuxCncSourcePath));
}
function isGeneratedBoundaryEvidenceReady(boundaryEvidence = {}, fixturePath = "", owningIniPath = "") {
const boundarySummary = boundaryEvidence.boundarySummary ?? {};
const iniBoundarySummary = boundaryEvidence.iniBoundarySummary ?? {};
const baselineSummary = boundaryEvidence.baselineSummary ?? {};
const sourceArtifactHashes = boundaryEvidence.sourceArtifactHashes ?? {};
const sourceArtifacts = [...(boundaryEvidence.sourceArtifacts ?? [])];
const normalizedFixturePath = normalizeSimConfigInventoryPath(fixturePath);
const normalizedOwningIniPath = normalizeSimConfigInventoryPath(owningIniPath);
return sourceArtifacts.includes("wasm-port/build/wasm/sim-configs-inventory/boundary-summary.tsv") &&
sourceArtifacts.includes("wasm-port/build/wasm/sim-configs-inventory/ini-boundary-summary.tsv") &&
Object.entries(VIRTUAL_HAL_SIM_CONFIG_INVENTORY_ARTIFACT_HASHES)
.every(([artifactPath, expectedHash]) => sourceArtifactHashes[artifactPath] === expectedHash) &&
baselineSummary.executed === VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE.executed &&
baselineSummary.passed === VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE.passed &&
baselineSummary.skipped === VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE.skipped &&
baselineSummary.unexpectedFail === VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE.unexpectedFail &&
normalizeSimConfigInventoryPath(boundarySummary.path) === normalizedFixturePath &&
normalizeSimConfigInventoryPath(boundarySummary.ini) === normalizedOwningIniPath &&
boundarySummary.recommendedBlocked === "UNAVAILABLE" &&
typeof boundarySummary.dependencies === "string" &&
boundarySummary.dependencies.includes("missing_vendored_ini:") &&
normalizeSimConfigInventoryPath(iniBoundarySummary.ini) === normalizedOwningIniPath &&
iniBoundarySummary.vendored === 0 &&
iniBoundarySummary.reportAvailable === 0 &&
iniBoundarySummary.recommendedBlocked === "UNAVAILABLE" &&
typeof iniBoundarySummary.dependencies === "string" &&
iniBoundarySummary.dependencies.includes("missing_vendored_ini:");
}
export function createVirtualHalSimConfigSourceCoverageReport(options = {}) {
const targets = options.targets ?? VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS;
const manifestProvided = typeof options.manifestText === "string" || Array.isArray(options.manifestEntries);
@@ -2835,6 +3003,23 @@ export function createVirtualHalSimConfigPromotionCandidateReport(options = {})
const blockedCandidateIds = rows.filter((row) => !row.blockedKindExcluded).map((row) => row.id);
const missingManifestFiles = [...new Set(rows.flatMap((row) => row.missingManifestFiles))];
const missingRequiredReports = [...new Set(rows.flatMap((row) => row.missingRequiredReports))];
const familyRows = [...new Set(rows.map((row) => row.simConfigTarget ?? row.id))].map((familyId) => {
const familyCandidates = rows.filter((row) => (row.simConfigTarget ?? row.id) === familyId);
const completeCount = familyCandidates.filter((row) => row.complete).length;
const explicitBrowserDiagnosticsCount = familyCandidates
.filter((row) => row.targetBrowserEvidence === "explicit-browser-diagnostics").length;
const sourceFiles = [...new Set(familyCandidates.flatMap((row) => row.sourceFiles))];
return {
id: familyId,
candidateIds: familyCandidates.map((row) => row.id),
candidateCount: familyCandidates.length,
completeCount,
explicitBrowserDiagnosticsCount,
explicitBrowserDiagnosticsReady: explicitBrowserDiagnosticsCount === familyCandidates.length,
complete: completeCount === familyCandidates.length,
sourceFiles,
};
});
const complete = rows.length > 0 &&
missingCandidates.length === 0 &&
blockedCandidateIds.length === 0 &&
@@ -2858,9 +3043,11 @@ export function createVirtualHalSimConfigPromotionCandidateReport(options = {})
blockedCandidateIds,
missingManifestFiles,
missingRequiredReports,
familyRows,
rows,
summaryRows: [
{ id: "candidates", label: "Promotion candidates", value: `${rows.length}` },
{ id: "families", label: "Promotion families", value: `${familyRows.length}` },
{ id: "blocked-family", label: "Blocked-family exclusion", value: blockedCandidateIds.length === 0 ? "passed" : `blocked ${blockedCandidateIds.length}` },
{ id: "reports", label: "Virtual HAL reports", value: missingRequiredReports.length === 0 ? "complete" : `missing ${missingRequiredReports.length}` },
{ id: "manifest", label: "Manifest check", value: manifestProvided ? (missingManifestFiles.length === 0 ? "passed" : "failed") : "not provided" },
@@ -2872,6 +3059,7 @@ export function createVirtualHalSimConfigPromotionCandidateReport(options = {})
export function createVirtualHalSimConfigMacroLoadFixtureReport(options = {}) {
const fixtures = options.fixtures ?? VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_FIXTURES;
const blockedFixtures = options.blockedFixtures ?? VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_BLOCKED_FIXTURES;
const auditCandidates = options.auditCandidates ?? VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_AUDIT_CANDIDATES;
const manifestProvided = typeof options.manifestText === "string" || Array.isArray(options.manifestEntries);
const manifestSet = new Set([
...sourceManifestSetFromText(options.manifestText ?? ""),
@@ -2894,11 +3082,25 @@ export function createVirtualHalSimConfigMacroLoadFixtureReport(options = {}) {
const statusReady = allowedStatuses.has(fixture.currentNodeInventoryStatus);
const nonMainFixtureReady = fixture.nonMainFixture === true &&
fixture.targetBrowserEvidence === "non-main-fixture-diagnostics";
const declarationEvidence = fixture.declarationEvidence ?? null;
const requiresDeclarationEvidence = typeof fixture.declarationSource === "string" &&
fixture.declarationSource.length > 0;
const declarationEvidenceReady = !requiresDeclarationEvidence || (
declarationEvidence !== null &&
declarationEvidence.sourceFile === fixture.owningIniPath &&
declarationEvidence.key === fixture.declarationSource &&
declarationEvidence.value === fixture.fixturePath.split("/").at(-1) &&
Number.isInteger(declarationEvidence.line) &&
declarationEvidence.line > 0 &&
typeof declarationEvidence.sourceLine === "string" &&
declarationEvidence.sourceLine.includes(`${declarationEvidence.key} = ${declarationEvidence.value}`)
);
const complete = sourceFiles.length > 0 &&
missingManifestFiles.length === 0 &&
blockedKindExcluded &&
statusReady &&
nonMainFixtureReady;
nonMainFixtureReady &&
declarationEvidenceReady;
return {
id: fixture.id,
label: fixture.label,
@@ -2908,6 +3110,9 @@ export function createVirtualHalSimConfigMacroLoadFixtureReport(options = {}) {
owningIniPath: fixture.owningIniPath,
pairedMainProgram: fixture.pairedMainProgram,
declarationSource: fixture.declarationSource,
declarationEvidence,
declarationEvidenceReady,
requiresDeclarationEvidence,
currentNodeInventoryStatus: fixture.currentNodeInventoryStatus,
dependencyClass: fixture.dependencyClass,
targetBrowserEvidence: fixture.targetBrowserEvidence,
@@ -2924,6 +3129,9 @@ export function createVirtualHalSimConfigMacroLoadFixtureReport(options = {}) {
});
const missingFixtures = rows.filter((row) => !row.complete).map((row) => row.id);
const blockedFixtureIds = rows.filter((row) => !row.blockedKindExcluded).map((row) => row.id);
const declarationEvidenceViolations = rows
.filter((row) => row.requiresDeclarationEvidence === true && row.declarationEvidenceReady !== true)
.map((row) => row.id);
const standaloneMainViolations = rows
.filter((row) => row.nonMainFixture !== true || row.targetBrowserEvidence !== "non-main-fixture-diagnostics")
.map((row) => row.id);
@@ -2931,6 +3139,8 @@ export function createVirtualHalSimConfigMacroLoadFixtureReport(options = {}) {
const positiveFixturePaths = new Set(rows.map((row) => normalizeLinuxCncSourcePath(row.fixturePath)));
const blockedRows = blockedFixtures.map((fixture) => {
const excludedFromPositiveFixtures = !positiveFixturePaths.has(normalizeLinuxCncSourcePath(fixture.fixturePath));
const boundaryEvidence = fixture.boundaryEvidence ?? {};
const boundaryEvidenceReady = isGeneratedBoundaryEvidenceReady(boundaryEvidence, fixture.fixturePath, fixture.owningIniPath);
return {
id: fixture.id,
source: "linuxcnc-configs-sim-source-derived-virtual-hal-macro-load-blocked-fixture",
@@ -2939,19 +3149,61 @@ export function createVirtualHalSimConfigMacroLoadFixtureReport(options = {}) {
blockedKind: fixture.blockedKind,
dependencyClass: fixture.dependencyClass,
excludedFromPositiveFixtures,
boundaryEvidence,
boundaryEvidenceReady,
reason: fixture.reason,
complete: excludedFromPositiveFixtures,
complete: excludedFromPositiveFixtures && boundaryEvidenceReady,
};
});
const blockedFixturePromotionViolations = blockedRows
.filter((row) => row.excludedFromPositiveFixtures !== true)
.map((row) => row.id);
const blockedBoundaryEvidenceViolations = blockedRows
.filter((row) => row.boundaryEvidenceReady !== true)
.map((row) => row.id);
const auditRows = auditCandidates.map((candidate) => {
const excludedFromPositiveFixtures = !positiveFixturePaths.has(normalizeLinuxCncSourcePath(candidate.fixturePath));
const boundaryEvidence = candidate.boundaryEvidence ?? {};
const boundaryEvidenceReady = isGeneratedBoundaryEvidenceReady(boundaryEvidence, candidate.fixturePath, candidate.owningIniPath);
return {
id: candidate.id,
source: "linuxcnc-configs-sim-source-derived-virtual-hal-macro-load-audit-candidate",
fixturePath: candidate.fixturePath,
owningIniPath: candidate.owningIniPath,
dependencyClass: candidate.dependencyClass,
auditStatus: candidate.auditStatus,
promotionAllowed: candidate.promotionAllowed === true,
excludedFromPositiveFixtures,
boundaryEvidence,
boundaryEvidenceReady,
reason: candidate.reason,
complete: excludedFromPositiveFixtures && candidate.promotionAllowed !== true && boundaryEvidenceReady,
};
});
const missingAuditRows = auditRows
.filter((row) => !row.complete)
.map((row) => row.id);
const auditPromotionViolations = auditRows
.filter((row) => row.promotionAllowed !== true && row.excludedFromPositiveFixtures !== true)
.map((row) => row.id);
const auditBoundaryEvidenceViolations = auditRows
.filter((row) => row.boundaryEvidenceReady !== true)
.map((row) => row.id);
const auditPromotionAllowedViolations = auditRows
.filter((row) => row.promotionAllowed === true && row.boundaryEvidenceReady !== true)
.map((row) => row.id);
const complete = rows.length > 0 &&
missingFixtures.length === 0 &&
missingAuditRows.length === 0 &&
blockedFixtureIds.length === 0 &&
declarationEvidenceViolations.length === 0 &&
standaloneMainViolations.length === 0 &&
missingManifestFiles.length === 0 &&
blockedFixturePromotionViolations.length === 0;
blockedFixturePromotionViolations.length === 0 &&
blockedBoundaryEvidenceViolations.length === 0 &&
auditPromotionViolations.length === 0 &&
auditBoundaryEvidenceViolations.length === 0 &&
auditPromotionAllowedViolations.length === 0;
return {
apiName: "linuxcnc-wasm-virtual-hal-sim-config-macro-load-fixture-report",
reportVersion: 1,
@@ -2966,15 +3218,24 @@ export function createVirtualHalSimConfigMacroLoadFixtureReport(options = {}) {
fixturePaths: rows.map((row) => row.fixturePath),
missingFixtures,
blockedFixtureIds,
declarationEvidenceViolations,
standaloneMainViolations,
blockedFixturePromotionViolations,
blockedBoundaryEvidenceViolations,
missingAuditRows,
auditPromotionViolations,
auditBoundaryEvidenceViolations,
auditPromotionAllowedViolations,
missingManifestFiles,
rows,
blockedRows,
auditRows,
summaryRows: [
{ id: "fixtures", label: "Macro/load fixtures", value: `${rows.length}` },
{ id: "declarations", label: "Declaration evidence", value: declarationEvidenceViolations.length === 0 ? "passed" : `violations ${declarationEvidenceViolations.length}` },
{ id: "non-main", label: "Non-main fixture gate", value: standaloneMainViolations.length === 0 ? "passed" : `violations ${standaloneMainViolations.length}` },
{ id: "blocked-fixture-lock", label: "Blocked fixture lock", value: blockedFixturePromotionViolations.length === 0 ? "passed" : `violations ${blockedFixturePromotionViolations.length}` },
{ id: "blocked-fixture-lock", label: "Blocked fixture lock", value: blockedFixturePromotionViolations.length === 0 && blockedBoundaryEvidenceViolations.length === 0 ? "passed" : "violations" },
{ id: "ui-family-audit", label: "UI-family macro/load audit", value: missingAuditRows.length === 0 && auditPromotionViolations.length === 0 && auditBoundaryEvidenceViolations.length === 0 && auditPromotionAllowedViolations.length === 0 ? "passed" : "violations" },
{ id: "blocked-family", label: "Blocked-family exclusion", value: blockedFixtureIds.length === 0 ? "passed" : `blocked ${blockedFixtureIds.length}` },
{ id: "manifest", label: "Manifest check", value: manifestProvided ? (missingManifestFiles.length === 0 ? "passed" : "failed") : "not provided" },
{ id: "inventory-baseline", label: "Inventory baseline", value: "unchanged" },