diff --git a/PROJECT_COMPLETION_TRACKER.md b/PROJECT_COMPLETION_TRACKER.md index 1308b4c..470e13d 100644 --- a/PROJECT_COMPLETION_TRACKER.md +++ b/PROJECT_COMPLETION_TRACKER.md @@ -9,7 +9,7 @@ turn-by-turn continuation notes and next-batch execution records. ## Current Status - Active continuation file: `text14.txt` -- Latest completed batch: project release readiness artifact embedded gate evidence validation +- Latest completed batch: project release readiness artifact validation summary view-model API - Latest relevant commit: use `git log -1 --oneline` after each committed batch - Working tree at tracker creation: clean - Required policy: LinuxCNC remains the only CNC semantic source @@ -43,7 +43,7 @@ The project is complete for the current scope when all of the following are true | Native nc_files baseline | Stable | Last recorded Layer 1: `total 107`, `pass 101`, `expected_fail 6`, `unexpected_fail 0`. | | Native sim configs baseline | Stable | Last recorded Layer 2: `total 159`, `pass 151`, `expected_fail 8`, `unexpected_fail 0`. | | OPFS/session persistence | Stable for current scope | Browser smoke passes, SDK re-exports OPFS/session helpers including `readMachineSessionReadiness()` and `createMachineSessionPersistenceSummary()`, the UI exposes `getMachineSessionPersistenceSummary()`, and `docs/opfs-session-persistence.md` defines the project-level release gate. | -| SDK/API surface | Stable for current scope | SDK re-exports core, OPFS/session readiness/load helpers, sim-config staging, project release gate manifest/result matrix/action-plan/readiness summary view-model, project release readiness report/artifact validation plus URL loading workflow, INI panel entry/launcher/control-page/shell/workflow overview helpers, the session readiness workflow report, and the shell API surface inventory with a Node surface smoke. | +| SDK/API surface | Stable for current scope | SDK re-exports core, OPFS/session readiness/load helpers, sim-config staging, project release gate manifest/result matrix/action-plan/readiness summary view-model, project release readiness report/artifact validation summary plus URL loading workflow, INI panel entry/launcher/control-page/shell/workflow overview helpers, the session readiness workflow report, and the shell API surface inventory with a Node surface smoke. | | Browser/UI workflow | Stable for current scope | Workflow overview embedding mount DOM closure is complete, and INI panel session workflows plus read-only control/shell handoff expose, render, fetch, validate, and report OPFS/session readiness, OPFS/session persistence summary, release readiness artifact validation/rendering, and API surface inventory before loading or reading WASM session state. | | Workflow overview embedding | Stable for current scope | Report/display/render, DOM contract/readiness/renderer, mount result/display/render, mount DOM contract/readiness/renderer/wrapper exist. | | Host/runtime boundary proof | Stable blocked state | Host smoke passes; runtime families remain blocked and `docs/host-runtime-boundary-handoff.md` records host readiness, promotion blockers, dispatch, and evidence gates. | diff --git a/text14.txt b/text14.txt index 2915432..1597d28 100644 --- a/text14.txt +++ b/text14.txt @@ -3308,6 +3308,63 @@ ui_node_smokes=ok 继续只做实质能力推进。优先选择可执行 gate、SDK/API surface、或真实 browser workflow; 不要做只整理断言或局部常量化的批次。 +四十七、2026-06-16 继续执行记录:project release readiness artifact validation summary view-model API + +本轮继续按“每批必须产出可调用 API、可验证 workflow、可执行 gate、或真实 UI/browser 能力”推进, +把 release readiness artifact validation 进一步封装为 dashboard/browser shell 可直接消费的 summary +view-model。外部调用方现在可以读取稳定 statusLine 和 rows,而不需要自己解释 validation missing、 +gateManifestReady、gateResultMatrixReady 或 gateActionPlanReady 字段。 + +完成内容: + +- `runtime/sdk/src/project-release-readiness.js` 新增: + - `createProjectReleaseReadinessArtifactValidationSummaryViewModel()`; +- 新 summary view-model 返回: + - `apiName: project-release-readiness-artifact-validation-summary-view-model`; + - `viewModelVersion: 1`; + - `phase/ready`; + - `title/statusText/detailText/statusLine`; + - rows:`artifact`、`gate-count`、`gate-manifest`、`gate-result-matrix`、`gate-action-plan`、`missing`; +- 支持 ready artifact 和 stale/missing artifact 两类显示状态; +- `runtime/sdk/src/index.js` re-export 新 summary API; +- `verify_project_release_gate_manifest.mjs` 覆盖 ready artifact summary 和 stale artifact summary; +- `verify_sdk_surface.mjs` 覆盖 SDK export 和 ready statusLine; +- `runtime/sdk/README.md`、`docs/project-release-handoff.md`、`verify_project_release_handoff_docs.mjs` + 记录 artifact validation summary API; +- `PROJECT_COMPLETION_TRACKER.md` 同步 latest completed batch 和 SDK/API surface 状态; +- 未新增控制按钮; +- 未在 SDK 中执行 shell command; +- 未解析 G-code; +- 未解释 canonical events; +- 未新增 JS CNC 语义; +- 未运行 opt-in runtime probes; +- 未 promotion blocked runtime family; +- 未改变 LinuxCNC interpreter、tool、parameter、planner、kinematics、remap 或 LinuxCNC-owned + runtime semantics。 + +验证已通过(先行 targeted): + +```bash +wasm-port/tests/sdk/node/verify_project_release_gate_manifest.sh +wasm-port/tests/sdk/node/verify_sdk_surface.sh +wasm-port/tests/docs/node/verify_project_release_handoff_docs.sh +wasm-port/tests/host/verify_project_release_readiness_artifact.sh wasm-port/tests/fixtures/project-release-readiness-ready.json +``` + +关键输出: + +```text +project_release_gate_manifest_node_smoke=ok +sdk_surface_node_smoke=ok +project_release_handoff_docs_node_smoke=ok +project_release_readiness_artifact_node_smoke=ok +``` + +下一步工作计划: + +继续只做实质能力推进。优先选择可执行 gate、SDK/API surface、或真实 browser workflow; +不要做只整理断言或局部常量化的批次。 + 四十六、2026-06-16 继续执行记录:project release readiness artifact embedded gate evidence validation 本轮继续按“每批必须产出可调用 API、可验证 workflow、可执行 gate、或真实 UI/browser 能力”推进, diff --git a/wasm-port/docs/project-release-handoff.md b/wasm-port/docs/project-release-handoff.md index 056dc6a..637b857 100644 --- a/wasm-port/docs/project-release-handoff.md +++ b/wasm-port/docs/project-release-handoff.md @@ -54,6 +54,8 @@ continuation records are in `../text14.txt`. `createProjectReleaseReadinessArtifactValidation()`. Artifact validation requires the embedded gate manifest, result matrix, and action plan to be ready, so stale release JSON cannot pass the executable artifact gate. + `createProjectReleaseReadinessArtifactValidationSummaryViewModel()` turns the + validation into stable dashboard rows without reinterpreting artifact fields. Browser shells can also pass the JSON to `linuxCncIniPanelWorkflowOverviewApi.validateWorkflowOverviewReleaseReadinessArtifactJson()` through the workflow overview iframe and receive stable validation rows. They diff --git a/wasm-port/runtime/sdk/README.md b/wasm-port/runtime/sdk/README.md index e4a0345..ea7f8d5 100644 --- a/wasm-port/runtime/sdk/README.md +++ b/wasm-port/runtime/sdk/README.md @@ -55,6 +55,7 @@ import { createProjectReleaseGateManifest, createProjectReleaseGateResultMatrix, createProjectReleaseReadinessArtifactValidation, + createProjectReleaseReadinessArtifactValidationSummaryViewModel, createProjectReleaseReadinessReport, createProjectReleaseReadinessSummaryViewModel, createSessionSnapshot, @@ -226,6 +227,9 @@ host test assertions. The validation result includes `expectedGateCount` and current manifest, plus `gateManifestReady`, `gateResultMatrixReady`, and `gateActionPlanReady` so stale artifacts that omit the embedded gate evidence chain fail the same executable gate. +`createProjectReleaseReadinessArtifactValidationSummaryViewModel()` turns that +validation result into stable status text and display rows for dashboards or +browser shells without reinterpreting the artifact fields. ## OPFS/session persistence exports diff --git a/wasm-port/runtime/sdk/src/index.js b/wasm-port/runtime/sdk/src/index.js index 1ef7954..e39f05b 100644 --- a/wasm-port/runtime/sdk/src/index.js +++ b/wasm-port/runtime/sdk/src/index.js @@ -5,6 +5,7 @@ export { createProjectReleaseGateManifest, createProjectReleaseGateResultMatrix, createProjectReleaseReadinessArtifactValidation, + createProjectReleaseReadinessArtifactValidationSummaryViewModel, createProjectReleaseReadinessReport, createProjectReleaseReadinessSummaryViewModel, parseProjectReleaseReadinessArtifactJson, diff --git a/wasm-port/runtime/sdk/src/project-release-readiness.js b/wasm-port/runtime/sdk/src/project-release-readiness.js index 3ece050..1eb3a52 100644 --- a/wasm-port/runtime/sdk/src/project-release-readiness.js +++ b/wasm-port/runtime/sdk/src/project-release-readiness.js @@ -324,6 +324,59 @@ export function createProjectReleaseReadinessSummaryViewModel( }; } +export function createProjectReleaseReadinessArtifactValidationSummaryViewModel( + validation = createProjectReleaseReadinessArtifactValidation(), +) { + const missing = arrayOrEmpty(validation?.missing); + const ready = validation?.ready === true; + const statusText = ready ? "Ready" : "Blocked"; + const detailText = ready + ? "Artifact evidence complete" + : (missing.length > 0 ? missing.join(", ") : "artifact evidence missing"); + return { + apiName: "project-release-readiness-artifact-validation-summary-view-model", + viewModelVersion: 1, + phase: ready ? "ready" : "blocked", + ready, + title: "Project release artifact validation", + statusText, + detailText, + statusLine: `${statusText}: ${detailText}`, + rows: [ + { + id: "artifact", + label: "Readiness artifact", + value: validation?.artifactApiName ?? "missing", + }, + { + id: "gate-count", + label: "Gate count", + value: `${validation?.gateCount ?? 0}/${validation?.expectedGateCount ?? 0}`, + }, + { + id: "gate-manifest", + label: "Gate manifest", + value: validation?.gateManifestReady === true ? "ready" : "missing", + }, + { + id: "gate-result-matrix", + label: "Gate result matrix", + value: validation?.gateResultMatrixReady === true ? "ready" : "missing", + }, + { + id: "gate-action-plan", + label: "Gate action plan", + value: validation?.gateActionPlanReady === true ? "ready" : "missing", + }, + { + id: "missing", + label: "Missing artifact evidence", + value: missing.length > 0 ? missing.join(", ") : "none", + }, + ], + }; +} + export function parseProjectReleaseReadinessArtifactJson(text) { return JSON.parse(String(text)); } diff --git a/wasm-port/tests/docs/node/verify_project_release_handoff_docs.mjs b/wasm-port/tests/docs/node/verify_project_release_handoff_docs.mjs index fd8255a..694492d 100644 --- a/wasm-port/tests/docs/node/verify_project_release_handoff_docs.mjs +++ b/wasm-port/tests/docs/node/verify_project_release_handoff_docs.mjs @@ -38,6 +38,7 @@ for (const phrase of [ "createProjectReleaseReadinessSummaryViewModel()", "parseProjectReleaseReadinessArtifactJson()", "createProjectReleaseReadinessArtifactValidation()", + "createProjectReleaseReadinessArtifactValidationSummaryViewModel()", "embedded gate manifest, result matrix, and action plan", "validateWorkflowOverviewReleaseReadinessArtifactJson()", "loadWorkflowOverviewReleaseReadinessArtifactUrl()", @@ -108,6 +109,7 @@ for (const phrase of [ "createProjectReleaseReadinessSummaryViewModel()", "parseProjectReleaseReadinessArtifactJson()", "createProjectReleaseReadinessArtifactValidation()", + "createProjectReleaseReadinessArtifactValidationSummaryViewModel()", "gateManifestReady", "gateResultMatrixReady", "gateActionPlanReady", diff --git a/wasm-port/tests/sdk/node/verify_project_release_gate_manifest.mjs b/wasm-port/tests/sdk/node/verify_project_release_gate_manifest.mjs index 494cb55..fdf94d7 100644 --- a/wasm-port/tests/sdk/node/verify_project_release_gate_manifest.mjs +++ b/wasm-port/tests/sdk/node/verify_project_release_gate_manifest.mjs @@ -4,6 +4,8 @@ import { createProjectReleaseGateActionPlan, createProjectReleaseGateManifest, createProjectReleaseGateResultMatrix, + createProjectReleaseReadinessArtifactValidation, + createProjectReleaseReadinessArtifactValidationSummaryViewModel, createProjectReleaseReadinessReport, createProjectReleaseReadinessSummaryViewModel, } from "../../../runtime/sdk/src/index.js"; @@ -171,4 +173,31 @@ assert.equal( "promoted: L4-TOOL-DB", ); +const artifactValidationSummary = createProjectReleaseReadinessArtifactValidationSummaryViewModel( + createProjectReleaseReadinessArtifactValidation(report), +); +assert.equal( + artifactValidationSummary.apiName, + "project-release-readiness-artifact-validation-summary-view-model", +); +assert.equal(artifactValidationSummary.phase, "ready"); +assert.equal(artifactValidationSummary.statusLine, "Ready: Artifact evidence complete"); +assert.deepEqual( + artifactValidationSummary.rows.map(({ id, value }) => [id, value]), + [ + ["artifact", "project-release-readiness-report"], + ["gate-count", "10/10"], + ["gate-manifest", "ready"], + ["gate-result-matrix", "ready"], + ["gate-action-plan", "ready"], + ["missing", "none"], + ], +); +const staleArtifactValidationSummary = createProjectReleaseReadinessArtifactValidationSummaryViewModel( + createProjectReleaseReadinessArtifactValidation({}), +); +assert.equal(staleArtifactValidationSummary.phase, "blocked"); +assert.match(staleArtifactValidationSummary.statusLine, /^Blocked: apiName, reportVersion/); +assert.equal(staleArtifactValidationSummary.rows.find(({ id }) => id === "gate-action-plan")?.value, "missing"); + console.log("project_release_gate_manifest_node_smoke=ok"); diff --git a/wasm-port/tests/sdk/node/verify_sdk_surface.mjs b/wasm-port/tests/sdk/node/verify_sdk_surface.mjs index 4332a03..0ef0fc1 100644 --- a/wasm-port/tests/sdk/node/verify_sdk_surface.mjs +++ b/wasm-port/tests/sdk/node/verify_sdk_surface.mjs @@ -36,6 +36,7 @@ import { createProjectReleaseGateManifest, createProjectReleaseGateResultMatrix, createProjectReleaseReadinessArtifactValidation, + createProjectReleaseReadinessArtifactValidationSummaryViewModel, createProjectReleaseReadinessReport, createProjectReleaseReadinessSummaryViewModel, parseProjectReleaseReadinessArtifactJson, @@ -91,6 +92,10 @@ const requiredExports = [ ["createProjectReleaseGateManifest", createProjectReleaseGateManifest], ["createProjectReleaseGateResultMatrix", createProjectReleaseGateResultMatrix], ["createProjectReleaseReadinessArtifactValidation", createProjectReleaseReadinessArtifactValidation], + [ + "createProjectReleaseReadinessArtifactValidationSummaryViewModel", + createProjectReleaseReadinessArtifactValidationSummaryViewModel, + ], ["createProjectReleaseReadinessReport", createProjectReleaseReadinessReport], ["createProjectReleaseReadinessSummaryViewModel", createProjectReleaseReadinessSummaryViewModel], ["parseProjectReleaseReadinessArtifactJson", parseProjectReleaseReadinessArtifactJson], @@ -255,7 +260,8 @@ const releaseReadinessArtifact = parseProjectReleaseReadinessArtifactJson(JSON.s }, }))); assert.equal(releaseReadinessArtifact.apiName, "project-release-readiness-report"); -assert.deepEqual(createProjectReleaseReadinessArtifactValidation(releaseReadinessArtifact), { +const releaseReadinessArtifactValidation = createProjectReleaseReadinessArtifactValidation(releaseReadinessArtifact); +assert.deepEqual(releaseReadinessArtifactValidation, { apiName: "project-release-readiness-artifact-validation", validationVersion: 1, phase: "ready", @@ -307,6 +313,12 @@ assert.deepEqual(createProjectReleaseReadinessArtifactValidation(releaseReadines }, ], }); +assert.equal( + createProjectReleaseReadinessArtifactValidationSummaryViewModel( + releaseReadinessArtifactValidation, + ).statusLine, + "Ready: Artifact evidence complete", +); assert.deepEqual( createProjectReleaseReadinessArtifactValidation({}).missing, [