虚拟HAL完全满足Web数控仿真

结论:ini-panel workflow overview 已提供固定 URL 表单和按钮,用户可直接输入 release artifact URL 与 browser diagnostics URL 并运行 release URL workflow;该流程验证的 virtual HAL evidence 仍完全来自 LinuxCNC source-derived reports,virtual HAL 继续满足 Web 数控系统仿真范围,不声明 Linux kernel hard-realtime ABI、外部硬件驱动 ABI 或 native HAL module ABI。
This commit is contained in:
2026-06-17 23:12:45 +08:00
parent 208992c42e
commit abf858641f
3 changed files with 200 additions and 0 deletions

View File

@@ -68,6 +68,39 @@
color: var(--text);
overflow-wrap: anywhere;
}
.url-workflow-form {
display: grid;
grid-template-columns: 1fr;
gap: 10px;
border-top: 1px solid var(--border);
padding-top: 12px;
}
.url-workflow-form label {
display: grid;
gap: 4px;
color: var(--muted);
font: 12px/1.4 "Segoe UI", "Noto Sans", sans-serif;
}
.url-workflow-form input {
width: 100%;
min-height: 32px;
border: 1px solid var(--border);
border-radius: 4px;
padding: 6px 8px;
color: var(--text);
font: 13px/1.4 "Segoe UI", "Noto Sans", sans-serif;
}
.url-workflow-form button {
justify-self: start;
min-height: 32px;
border: 1px solid #0f5f9d;
border-radius: 4px;
background: var(--accent);
color: #fff;
padding: 6px 12px;
font: 13px/1.4 "Segoe UI", "Noto Sans", sans-serif;
cursor: pointer;
}
</style>
</head>
<body>
@@ -79,6 +112,21 @@
<p data-handoff-workflow-status>Checking shell handoff workflow summary.</p>
<dl data-handoff-workflow-rows></dl>
</section>
<form class="url-workflow-form" data-release-artifact-url-workflow-form>
<label>
Release artifact URL
<input type="text" inputmode="url" data-release-artifact-url-input placeholder="../../tests/fixtures/project-release-readiness-ready.json">
</label>
<label>
Browser diagnostics URL
<input type="text" inputmode="url" data-browser-diagnostics-url-input placeholder="../../tests/fixtures/real-browser-simulation-diagnostics-ready.json">
</label>
<button type="submit" data-run-release-artifact-url-workflow>Run URL Workflow</button>
</form>
<section class="overview-status" aria-label="Release artifact URL workflow" data-workflow-overview-release-readiness-artifact-url-workflow>
<p data-workflow-overview-release-readiness-artifact-url-workflow-status>Waiting for release artifact URL workflow.</p>
<dl data-workflow-overview-release-readiness-artifact-url-workflow-rows></dl>
</section>
</section>
</main>
<script type="module">
@@ -149,6 +197,46 @@
const shellViewModel = createIniPanelShellViewModel();
const workflowRenderState = shellViewModel.shellSessionHandoffWorkflowRenderState;
renderIniPanelShellSessionHandoffWorkflowState(workflowRenderState, { documentRef: document });
const releaseArtifactUrlInput = document.querySelector("[data-release-artifact-url-input]");
const browserDiagnosticsUrlInput = document.querySelector("[data-browser-diagnostics-url-input]");
const releaseArtifactUrlWorkflowForm = document.querySelector("[data-release-artifact-url-workflow-form]");
async function runWorkflowOverviewReleaseReadinessArtifactUrlForm(options = {}) {
const artifactUrl = String(options.artifactUrl ?? releaseArtifactUrlInput?.value ?? "").trim();
const diagnosticsUrl = String(options.diagnosticsUrl ?? browserDiagnosticsUrlInput?.value ?? "").trim();
const workflow = await loadIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrl({
artifactUrl,
diagnosticsUrl,
fetchRef: options.fetchRef,
mount: options.mount ?? true,
});
const summary = createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowSummaryViewModel(workflow);
const renderState = createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState(summary);
const mountResult = mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState({
renderState,
documentRef: document,
});
document.body.dataset.releaseArtifactUrlWorkflowPhase = workflow.phase;
document.body.dataset.releaseArtifactUrlWorkflowReady = workflow.ready ? "true" : "false";
return {
workflow,
summary,
renderState,
mountResult,
};
}
releaseArtifactUrlWorkflowForm?.addEventListener("submit", (event) => {
event.preventDefault();
runWorkflowOverviewReleaseReadinessArtifactUrlForm().catch((error) => {
const status = document.querySelector("[data-workflow-overview-release-readiness-artifact-url-workflow-status]");
if (status) {
status.textContent = `Blocked: ${error?.message ?? "release artifact URL workflow failed"}`;
}
document.body.dataset.releaseArtifactUrlWorkflowPhase = "blocked";
document.body.dataset.releaseArtifactUrlWorkflowReady = "false";
});
});
window.linuxCncIniPanelWorkflowOverviewApi = {
getWorkflowOverviewRenderState: () => shellViewModel.shellSessionHandoffWorkflowRenderState,
@@ -207,6 +295,7 @@
loadWorkflowOverviewReleaseReadinessArtifactUrl: (options) => (
loadIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrl(options)
),
runWorkflowOverviewReleaseReadinessArtifactUrlForm,
getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowSummaryViewModel: (workflow) => (
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowSummaryViewModel(workflow)
),

View File

@@ -60,6 +60,7 @@
!workflowApi?.getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowDomReadiness ||
!workflowApi?.renderWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState ||
!workflowApi?.mountWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState ||
!workflowApi?.runWorkflowOverviewReleaseReadinessArtifactUrlForm ||
!workflowApi?.getWorkflowOverviewReleaseReadinessArtifactValidationSummaryViewModel ||
!workflowApi?.getWorkflowOverviewReleaseReadinessArtifactValidationActionPlan ||
!workflowApi?.getWorkflowOverviewReleaseReadinessArtifactValidationActionPlanRenderState ||
@@ -372,6 +373,20 @@
},
mount: true,
});
workflowDoc.querySelector("[data-release-artifact-url-input]").value = "../../tests/fixtures/project-release-readiness-ready.json";
workflowDoc.querySelector("[data-browser-diagnostics-url-input]").value = "../../tests/fixtures/real-browser-simulation-diagnostics-ready.json";
const releaseArtifactUrlFormResult = await workflowApi.runWorkflowOverviewReleaseReadinessArtifactUrlForm({
fetchRef: async (url) => {
if (String(url).endsWith("real-browser-simulation-diagnostics-ready.json")) {
return {
ok: true,
status: 200,
text: async () => diagnosticsArtifactJson,
};
}
return fetch(url);
},
});
const releaseArtifactUrlWorkflowSummary = workflowApi
.getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowSummaryViewModel(releaseArtifactUrlWorkflow);
const releaseArtifactUrlWorkflowActionPlan = workflowApi
@@ -519,6 +534,26 @@
"Ready: Artifact URL workflow complete",
"workflow overview release artifact URL workflow rendered status",
);
assertEqual(
releaseArtifactUrlFormResult.workflow.ready,
true,
"workflow overview fixed URL workflow form readiness",
);
assertEqual(
releaseArtifactUrlFormResult.mountResult.ready,
true,
"workflow overview fixed URL workflow form mount readiness",
);
assertEqual(
workflowDoc.body.dataset.releaseArtifactUrlWorkflowReady,
"true",
"workflow overview fixed URL workflow form body ready",
);
assertEqual(
workflowDoc.querySelector('[data-workflow-overview-release-readiness-artifact-url-workflow-value="browser-diagnostics"]').textContent,
"ready",
"workflow overview fixed URL workflow form browser diagnostics row",
);
assertEqual(
releaseArtifactJsonWorkflow.statusLine,
"Ready: Artifact JSON workflow complete",