diff --git a/qa/web-rtcp-5axis-site-test/capture-button-control-evidence.mjs b/qa/web-rtcp-5axis-site-test/capture-button-control-evidence.mjs
new file mode 100644
index 0000000..450417b
--- /dev/null
+++ b/qa/web-rtcp-5axis-site-test/capture-button-control-evidence.mjs
@@ -0,0 +1,493 @@
+import fs from "node:fs/promises";
+import http from "node:http";
+import path from "node:path";
+import { randomUUID } from "node:crypto";
+import puppeteer from "puppeteer-core";
+import { PNG } from "pngjs";
+
+const REPO_ROOT = path.resolve("/home/meswork/cnc_wams");
+const QA_ROOT = path.join(REPO_ROOT, "qa/web-rtcp-5axis-site-test");
+const OUTPUT_DIR = path.join(QA_ROOT, "output");
+const CHROME_PATH = process.env.CHROME_PATH || process.env.CHROMIUM || "/usr/bin/google-chrome";
+const TARGET_URL = process.env.TARGET_URL || "";
+const APP_URL = process.env.APP_URL || "/web-rtcp-5axis-sim-plan/app/index.html";
+const EVIDENCE_SCOPE = process.env.EVIDENCE_SCOPE || (TARGET_URL ? "cloud-button-control-evidence" : "button-control-evidence");
+const SCREENSHOT_DIR = path.join(QA_ROOT, "screenshots", EVIDENCE_SCOPE);
+const REPORT_BASENAME = `${EVIDENCE_SCOPE}-report`;
+const JOB_ID = process.env.JOB_ID || `btn-${new Date().toISOString().replace(/[-:.TZ]/g, "").slice(0, 14)}-${randomUUID().slice(0, 8)}`;
+const REPORT_ID = process.env.REPORT_ID || `report-${JOB_ID}`;
+
+await fs.mkdir(OUTPUT_DIR, { recursive: true });
+await fs.mkdir(SCREENSHOT_DIR, { recursive: true });
+
+let server = null;
+let targetUrl = TARGET_URL;
+if (!targetUrl) {
+ server = createStaticServer(REPO_ROOT);
+ await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
+ const address = server.address();
+ if (!address || typeof address === "string") throw new Error("failed to start static server");
+ targetUrl = `http://127.0.0.1:${address.port}${APP_URL}`;
+}
+
+const browser = await puppeteer.launch({
+ headless: true,
+ executablePath: CHROME_PATH,
+ defaultViewport: { width: 1500, height: 1050, deviceScaleFactor: 1 },
+ ignoreHTTPSErrors: true,
+ args: [
+ "--ignore-certificate-errors",
+ "--disable-gpu",
+ "--enable-webgl",
+ "--use-angle=swiftshader",
+ "--enable-unsafe-swiftshader",
+ "--no-sandbox",
+ ],
+});
+
+const page = await browser.newPage();
+const consoleErrors = [];
+const pageErrors = [];
+page.on("console", (msg) => {
+ if (msg.type() === "error") consoleErrors.push(msg.text());
+});
+page.on("pageerror", (error) => pageErrors.push(error.message));
+
+const report = {
+ jobId: JOB_ID,
+ reportId: REPORT_ID,
+ evidenceScope: EVIDENCE_SCOPE,
+ generatedAt: new Date().toISOString(),
+ targetUrl,
+ chromePath: CHROME_PATH,
+ screenshotsDir: SCREENSHOT_DIR,
+ steps: [],
+ checks: [],
+ consoleErrors,
+ pageErrors,
+};
+
+try {
+ await page.goto(report.targetUrl, { waitUntil: "networkidle2", timeout: 60000 });
+ await page.waitForSelector('[data-shell="gmoccapy-5axis"]', { timeout: 15000 });
+ await page.waitForFunction(() => Boolean(window.webRtcp5AxisSimulation?.getState), { timeout: 15000 });
+ await page.waitForFunction(() => {
+ const canvas = document.querySelector("[data-five-axis-canvas]");
+ return canvas?.dataset?.threeReady === "true";
+ }, { timeout: 20000 });
+ await windowReady();
+ await captureStep("01-initial", "Initial UI", "Browser app loaded before machine preparation.");
+
+ await loadOperatorProgram();
+ await captureStep("02-program-loaded", "Program loaded", "Short operator G-code loaded through LinuxCNC interpreter WASM.");
+
+ await click("power");
+ await waitForState((state) => state.machine.powerOn === true, 10000, "power on");
+ await click("mode-manual");
+ await waitForState((state) => state.machine.mode === "manual", 10000, "manual mode");
+ await captureStep("03-before-home", "Before HOME", "Machine powered on in manual mode before HOME.");
+
+ await click("HOME");
+ await waitForState((state) => state.machine.allHomed === true && state.machine.mode === "manual", 10000, "HOME complete");
+ await captureStep("04-after-home", "After HOME", "HOME command preserves allHomed state in Web/task gate.");
+
+ await click("mode-auto");
+ await waitForState((state) => state.machine.mode === "auto", 10000, "auto mode");
+ await captureStep("05-ready-for-run", "Ready for RUN", "POWER, HOME, AUTO, and loaded G-code are ready before RUN.");
+
+ await click("RUN");
+ await waitForState((state) => (
+ state.runState === "running" &&
+ state.programRuntimeFeedback?.sourceMode === "linuxcnc-task-motion-hal-wasm"
+ ), 15000, "RUN active");
+ await wait(250);
+ await captureStep("06-after-run", "After RUN", "RUN starts task/HAL backed program execution.");
+
+ await captureStep("07-before-pause", "Before PAUSE", "Program is running before PAUSE.");
+ await click("PAUSE");
+ await waitForState((state) => state.runState === "paused" && state.machine.taskPaused === true, 10000, "PAUSE active");
+ await captureStep("08-after-pause", "After PAUSE", "PAUSE sets runState paused and taskPaused true.");
+
+ await captureStep("09-before-resume", "Before RESUME", "Program is paused before RESUME.");
+ await click("RESUME");
+ await waitForState((state) => state.runState === "running" && state.machine.interpState === "reading", 10000, "RESUME active");
+ await wait(150);
+ await captureStep("10-after-resume", "After RESUME", "RESUME returns task/HAL execution to running/reading.");
+
+ await click("PAUSE");
+ await waitForState((state) => state.runState === "paused" && state.machine.taskPaused === true, 10000, "PAUSE before STEP");
+ await captureStep("11-before-step", "Before STEP", "Program is paused before STEP.");
+
+ await click("STEP");
+ await waitForState((state) => (
+ state.machine.interpState === "paused" &&
+ state.machine.taskPaused === true &&
+ state.taskHalStatus?.task?.singleStepping === true
+ ), 10000, "STEP active");
+ await captureStep("12-after-step", "After STEP", "STEP sends EMC_TASK_PLAN_STEP and leaves task paused with singleStepping true.");
+
+ await captureStep("13-before-stop", "Before STOP", "Paused single-step state before STOP.");
+ await click("STOP");
+ await waitForState((state) => (
+ state.runState === "stopped" &&
+ state.machine.interpState === "idle" &&
+ state.taskHalStatus?.motionStatus?.motion?.aborted === true
+ ), 10000, "STOP active");
+ await captureStep("14-after-stop", "After STOP", "STOP aborts task/HAL motion and returns interpreter state to idle.");
+
+ addChecks();
+ report.status = report.checks.every((check) => check.pass) && pageErrors.length === 0 ? "PASS" : "FAIL";
+
+ const jsonPath = path.join(OUTPUT_DIR, `${REPORT_BASENAME}.json`);
+ report.jsonPath = jsonPath;
+ const pdfPath = path.join(OUTPUT_DIR, `${REPORT_BASENAME}.pdf`);
+ report.pdfPath = pdfPath;
+ await fs.writeFile(jsonPath, `${JSON.stringify(report, null, 2)}\n`, "utf8");
+ await writePdfReport(pdfPath, report);
+ console.log(`button_control_evidence_status=${report.status}`);
+ console.log(`button_control_evidence_job_id=${report.jobId}`);
+ console.log(`button_control_evidence_report_id=${report.reportId}`);
+ console.log(`button_control_evidence_json=${jsonPath}`);
+ console.log(`button_control_evidence_pdf=${pdfPath}`);
+ console.log(`button_control_evidence_screenshots=${SCREENSHOT_DIR}`);
+ if (report.status !== "PASS") process.exitCode = 1;
+} finally {
+ await page.close().catch(() => {});
+ await browser.close().catch(() => {});
+ if (server) await new Promise((resolve) => server.close(resolve));
+}
+
+async function windowReady() {
+ await waitForState((state) => (
+ state.kinematicsRuntimeReadiness?.loaded === true &&
+ state.interpreterRuntimeReadiness?.loaded === true &&
+ state.taskHalRuntimeReadiness?.loaded === true
+ ), 30000, "runtime readiness");
+ await waitForState((state) => (
+ !state.interpreterExecutionPending &&
+ state.machineFileStaging?.status === "staged"
+ ), 30000, "machine file seed ready")
+ .catch(() => null);
+}
+
+async function loadOperatorProgram() {
+ await page.evaluate(() => {
+ window.webRtcp5AxisSimulation.dispatch({
+ type: "LOAD_PROGRAM",
+ filename: "button-control-evidence.ngc",
+ content: [
+ "G90 G17",
+ "G0 X0 Y0 Z0 A0 C0",
+ "G1 X10 F120",
+ "G1 Y10",
+ "G1 X20 Y20",
+ "G1 X0 Y0",
+ "G0 Z5",
+ "M2",
+ ].join("\n"),
+ });
+ });
+ await waitForState((state) => (
+ state.activeProgram === "button-control-evidence.ngc" &&
+ state.programExecutionSourceMode === "linuxcnc-interpreter-wasm" &&
+ state.programExecution?.summary?.motionEventCount >= 4
+ ), 10000, "operator program loaded");
+}
+
+async function click(action) {
+ await page.evaluate((selector) => {
+ const button = document.querySelector(selector);
+ if (!button) throw new Error(`missing button ${selector}`);
+ button.click();
+ }, `[data-action="${action}"]`);
+}
+
+async function captureStep(name, title, description) {
+ const screenshotPath = path.join(SCREENSHOT_DIR, `${name}.png`);
+ await page.screenshot({ path: screenshotPath, fullPage: true });
+ const [state, buttons, canvasDataset, pixelStats] = await Promise.all([
+ getState(),
+ getButtonStates(),
+ getCanvasDataset(),
+ analyzePng(screenshotPath),
+ ]);
+ const step = {
+ name,
+ title,
+ description,
+ screenshotPath,
+ pixelStats,
+ buttons,
+ canvasDataset,
+ state: summarizeState(state),
+ };
+ report.steps.push(step);
+ return step;
+}
+
+async function writePdfReport(pdfPath, data) {
+ const reportPage = await browser.newPage();
+ const rows = data.checks.map((item) => `
+
+ | ${escapeHtml(item.name)} |
+ ${item.pass ? "PASS" : "FAIL"} |
+ ${escapeHtml(item.detail)} |
+
+ `).join("");
+ const steps = data.steps.map((step) => `
+
+ ${escapeHtml(step.name)} - ${escapeHtml(step.title)}
+ ${escapeHtml(step.description)}
+ Screenshot: ${escapeHtml(step.screenshotPath)}
+ State: ${escapeHtml(JSON.stringify({
+ runState: step.state.runState,
+ machine: step.state.machine,
+ task: step.state.taskHalStatus?.task,
+ motion: step.state.taskHalStatus?.motionStatus?.motion,
+ }))}
+
+ `).join("");
+ await reportPage.setContent(`
+
+
+
+
+
+
+ Web RTCP 5 Axis Button Control Evidence
+
+ Checks
+
+ | Check | Status | Evidence |
+ ${rows}
+
+ Steps
+ ${steps}
+
+ `, { waitUntil: "load" });
+ await reportPage.pdf({
+ path: pdfPath,
+ format: "A4",
+ printBackground: true,
+ margin: { top: "12mm", right: "10mm", bottom: "12mm", left: "10mm" },
+ });
+ await reportPage.close();
+}
+
+async function getState() {
+ return page.evaluate(() => JSON.parse(JSON.stringify(window.webRtcp5AxisSimulation.getState())));
+}
+
+async function getButtonStates() {
+ return page.evaluate(() => {
+ const actions = ["RUN", "STOP", "PAUSE", "RESUME", "STEP", "HOME"];
+ return Object.fromEntries(actions.map((action) => {
+ const button = document.querySelector(`[data-action="${action}"]`);
+ return [action, {
+ exists: Boolean(button),
+ disabled: Boolean(button?.disabled),
+ commandReady: button?.dataset?.commandReady || null,
+ ariaDisabled: button?.getAttribute("aria-disabled"),
+ title: button?.getAttribute("title") || "",
+ }];
+ }));
+ });
+}
+
+async function getCanvasDataset() {
+ return page.$eval("[data-five-axis-canvas]", (canvas) => ({ ...canvas.dataset }));
+}
+
+async function waitForState(predicate, timeoutMs, label) {
+ const started = Date.now();
+ let lastState = null;
+ while (Date.now() - started < timeoutMs) {
+ lastState = await getState();
+ if (predicate(lastState)) return lastState;
+ await wait(50);
+ }
+ throw new Error(`timeout waiting for ${label}: ${JSON.stringify(summarizeState(lastState || {}))}`);
+}
+
+function addChecks() {
+ const byName = Object.fromEntries(report.steps.map((step) => [step.name, step]));
+ const afterHome = byName["04-after-home"]?.state;
+ const afterRun = byName["06-after-run"]?.state;
+ const afterPause = byName["08-after-pause"]?.state;
+ const afterResume = byName["10-after-resume"]?.state;
+ const afterStep = byName["12-after-step"]?.state;
+ const afterStop = byName["14-after-stop"]?.state;
+ report.checks.push(
+ check("HOME keeps all axes homed", afterHome?.machine?.allHomed === true, JSON.stringify(afterHome?.machine)),
+ check("RUN uses task/HAL runtime feedback", afterRun?.runState === "running" && afterRun?.programRuntimeFeedback?.sourceMode === "linuxcnc-task-motion-hal-wasm", JSON.stringify(afterRun?.programRuntimeFeedback)),
+ check("PAUSE sets paused state", afterPause?.runState === "paused" && afterPause?.machine?.taskPaused === true, JSON.stringify(afterPause?.machine)),
+ check("RESUME returns to reading", afterResume?.runState === "running" && afterResume?.machine?.interpState === "reading", JSON.stringify(afterResume?.machine)),
+ check("STEP records single stepping", afterStep?.machine?.taskPaused === true && afterStep?.taskHalStatus?.task?.singleStepping === true, JSON.stringify(afterStep?.taskHalStatus?.task)),
+ check("STOP aborts motion", afterStop?.runState === "stopped" && afterStop?.taskHalStatus?.motionStatus?.motion?.aborted === true, JSON.stringify(afterStop?.taskHalStatus?.motionStatus?.motion)),
+ check("Screenshots are nonblank", report.steps.every((step) => step.pixelStats.nonBlackRatio > 0.1), report.steps.map((step) => `${step.name}:${step.pixelStats.nonBlackRatio}`).join(", ")),
+ check("Control buttons expose readiness attributes", report.steps.every((step) => Object.values(step.buttons).every((button) => button.exists && button.commandReady !== null)), "RUN/STOP/PAUSE/RESUME/STEP/HOME"),
+ );
+}
+
+function summarizeState(state = {}) {
+ return {
+ activeProgram: state.activeProgram,
+ runState: state.runState,
+ activeLine: state.activeLine,
+ machine: {
+ powerOn: state.machine?.powerOn,
+ taskState: state.machine?.taskState,
+ mode: state.machine?.mode,
+ allHomed: state.machine?.allHomed,
+ interpState: state.machine?.interpState,
+ taskPaused: state.machine?.taskPaused,
+ },
+ axisPose: pickAxes(state.axisPose),
+ dro: pickAxes(state.dro),
+ programRuntimeFeedback: state.programRuntimeFeedback ? {
+ sourceMode: state.programRuntimeFeedback.sourceMode,
+ line: state.programRuntimeFeedback.line,
+ taskCycle: state.programRuntimeFeedback.taskCycle,
+ currentVelocityMmPerMin: state.programRuntimeFeedback.currentVelocityMmPerMin,
+ axisPose: pickAxes(state.programRuntimeFeedback.axisPose),
+ } : null,
+ taskHalStatus: state.taskHalStatus ? {
+ task: {
+ mode: state.taskHalStatus.task?.mode,
+ interpState: state.taskHalStatus.task?.interpState,
+ taskPaused: state.taskHalStatus.task?.taskPaused,
+ singleStepping: state.taskHalStatus.task?.singleStepping,
+ },
+ ui: {
+ activeLine: state.taskHalStatus.ui?.activeLine,
+ taskCycle: state.taskHalStatus.ui?.taskCycle,
+ servoCycle: state.taskHalStatus.ui?.servoCycle,
+ },
+ motionStatus: {
+ motion: {
+ enabled: state.taskHalStatus.motionStatus?.motion?.enabled,
+ paused: state.taskHalStatus.motionStatus?.motion?.paused,
+ aborted: state.taskHalStatus.motionStatus?.motion?.aborted,
+ queueDepth: state.taskHalStatus.motionStatus?.motion?.queueDepth,
+ },
+ },
+ } : null,
+ taskHalStatusLoop: state.taskHalStatusLoop,
+ operatorMessage: state.operatorMessage,
+ };
+}
+
+function createStaticServer(rootDir) {
+ return http.createServer(async (request, response) => {
+ try {
+ const requestPath = decodeURIComponent(new URL(request.url || "/", "http://127.0.0.1").pathname);
+ const relativePath = requestPath === "/" ? "/index.html" : requestPath;
+ const targetPath = path.resolve(rootDir, `.${relativePath}`);
+ if (!targetPath.startsWith(rootDir)) {
+ response.writeHead(403);
+ response.end("forbidden");
+ return;
+ }
+ let filePath = targetPath;
+ let stat = await fs.stat(filePath).catch(() => null);
+ if (stat?.isDirectory()) {
+ filePath = path.join(filePath, "index.html");
+ stat = await fs.stat(filePath).catch(() => null);
+ }
+ if (!stat?.isFile()) {
+ response.writeHead(404);
+ response.end("not found");
+ return;
+ }
+ const body = await fs.readFile(filePath);
+ response.writeHead(200, {
+ "Content-Type": contentTypeFor(filePath),
+ "Content-Length": String(body.byteLength),
+ "Cache-Control": "no-store",
+ });
+ response.end(body);
+ } catch (error) {
+ response.writeHead(500);
+ response.end(error instanceof Error ? error.message : String(error));
+ }
+ });
+}
+
+function contentTypeFor(filePath) {
+ const ext = path.extname(filePath).toLowerCase();
+ return {
+ ".css": "text/css; charset=utf-8",
+ ".html": "text/html; charset=utf-8",
+ ".js": "text/javascript; charset=utf-8",
+ ".json": "application/json; charset=utf-8",
+ ".mjs": "text/javascript; charset=utf-8",
+ ".svg": "image/svg+xml",
+ ".wasm": "application/wasm",
+ ".xml": "application/xml; charset=utf-8",
+ }[ext] || "application/octet-stream";
+}
+
+async function analyzePng(filePath) {
+ const png = PNG.sync.read(await fs.readFile(filePath));
+ let luminanceSum = 0;
+ let nonBlack = 0;
+ for (let index = 0; index < png.data.length; index += 4) {
+ const luminance = png.data[index] * 0.2126 + png.data[index + 1] * 0.7152 + png.data[index + 2] * 0.0722;
+ luminanceSum += luminance;
+ if (luminance > 8) nonBlack += 1;
+ }
+ const total = png.width * png.height;
+ return {
+ width: png.width,
+ height: png.height,
+ averageLuminance: Number((luminanceSum / total).toFixed(2)),
+ nonBlackRatio: Number((nonBlack / total).toFixed(4)),
+ };
+}
+
+function pickAxes(value = {}) {
+ return {
+ x: Number(value?.x || 0),
+ y: Number(value?.y || 0),
+ z: Number(value?.z || 0),
+ a: Number(value?.a || 0),
+ b: Number(value?.b || 0),
+ c: Number(value?.c || 0),
+ };
+}
+
+function check(name, pass, detail) {
+ return { name, pass: Boolean(pass), detail: String(detail ?? "-") };
+}
+
+function escapeHtml(value) {
+ return String(value ?? "")
+ .replace(/&/g, "&")
+ .replace(//g, ">")
+ .replace(/"/g, """)
+ .replace(/'/g, "'");
+}
+
+function wait(ms) {
+ return new Promise((resolve) => setTimeout(resolve, ms));
+}
diff --git a/qa/web-rtcp-5axis-site-test/capture-native-task-hal-comparison.mjs b/qa/web-rtcp-5axis-site-test/capture-native-task-hal-comparison.mjs
new file mode 100644
index 0000000..4e88780
--- /dev/null
+++ b/qa/web-rtcp-5axis-site-test/capture-native-task-hal-comparison.mjs
@@ -0,0 +1,185 @@
+import fs from "node:fs/promises";
+import path from "node:path";
+import { spawnSync } from "node:child_process";
+
+const REPO_ROOT = "/home/meswork/cnc_wams";
+const OUTPUT_DIR = path.join(REPO_ROOT, "qa/web-rtcp-5axis-site-test/output");
+const REPORT_JSON = path.join(OUTPUT_DIR, "native-task-hal-comparison-report.json");
+const REPORT_MD = path.join(OUTPUT_DIR, "native-task-hal-comparison-report.md");
+const READINESS_JSON = path.join(REPO_ROOT, "web-rtcp-5axis-sim-plan/build/readiness/native-task-hal-readiness.json");
+
+await fs.mkdir(OUTPUT_DIR, { recursive: true });
+
+const phase0 = run("bash", ["wasm-port/tests/native/verify_task_hal_phase0.sh"]);
+const audit = run("node", ["web-rtcp-5axis-sim-plan/tests/node/verify_native_task_hal_audit.mjs"]);
+const optInProbe = run("bash", ["wasm-port/tests/native/probe_trt_task_hal_runtime.sh"], {
+ env: { ...process.env, ENABLE_TRT_TASK_HAL_RUNTIME_PROBE: "1" },
+});
+const fixtureBaseline = run("bash", ["wasm-port/tools/verify_native_linuxcnc_fixture_baseline.sh"], {
+ env: { ...process.env, LD_LIBRARY_PATH: path.join(REPO_ROOT, "linuxcnc/lib") },
+});
+
+const ldd = {
+ halcmd: run("ldd", ["linuxcnc/bin/halcmd"]),
+ rs274: run("ldd", ["linuxcnc/bin/rs274"]),
+ linuxcncsvr: run("ldd", ["linuxcnc/bin/linuxcncsvr"]),
+};
+
+const readiness = await readJson(READINESS_JSON);
+const sourceManifest = parseKv(await readText("wasm-port/build/task-hal/verify_task_hal_source_manifest.stdout.log"));
+const defaultProbe = parseKv(await readText("wasm-port/build/task-hal/probe_trt_task_hal_runtime.stdout.log"));
+const optInProbeFields = parseKv(optInProbe.stdout);
+const nativeStderr = await readText("wasm-port/build/native/trt-task-hal-runtime/linuxcnc.stderr.log");
+
+const hostBlockers = [
+ ...missingFromLdd(ldd.halcmd.combined, "halcmd"),
+ ...missingFromLdd(ldd.rs274.combined, "rs274"),
+ ...missingFromLdd(ldd.linuxcncsvr.combined, "linuxcncsvr"),
+];
+if (nativeStderr.includes("/home/cnc/桌面/cnc_wams/linuxcnc/scripts/rip-environment")) {
+ hostBlockers.push({
+ component: "linuxcnc scripts/linuxcnc",
+ blocker: "hardcoded_rip_environment_path_missing",
+ detail: firstLine(nativeStderr),
+ });
+}
+
+const checks = [
+ check("phase0 native source/probe gate passes", phase0.status === 0, oneLine(phase0.combined)),
+ check("native readiness audit passes", audit.status === 0, oneLine(audit.combined)),
+ check("source manifest ready", sourceManifest.task_hal_source_manifest_ready === "1", JSON.stringify(sourceManifest)),
+ check("TRT source proof ready", defaultProbe.trt_task_hal_source_proof_ready === "1", JSON.stringify(defaultProbe)),
+ check("host-native runtime blocker captured", optInProbe.status !== 0 && hostBlockers.length > 0, JSON.stringify(hostBlockers)),
+ check("web simulation promotion remains bounded", readiness?.promotionScope === "web_simulation_only", JSON.stringify(readiness?.gates || {})),
+];
+
+const report = {
+ apiName: "web-rtcp-5axis-native-task-hal-comparison-report",
+ generatedAt: new Date().toISOString(),
+ status: checks.every((item) => item.pass) ? "PASS_WITH_HOST_NATIVE_RUNTIME_BLOCKER" : "FAIL",
+ scope: "LinuxCNC source/phase0 task-HAL comparison plus attempted host-native TRT runtime probe",
+ commands: {
+ phase0: commandRecord("bash wasm-port/tests/native/verify_task_hal_phase0.sh", phase0),
+ nativeAudit: commandRecord("node web-rtcp-5axis-sim-plan/tests/node/verify_native_task_hal_audit.mjs", audit),
+ optInNativeProbe: commandRecord("ENABLE_TRT_TASK_HAL_RUNTIME_PROBE=1 bash wasm-port/tests/native/probe_trt_task_hal_runtime.sh", optInProbe),
+ fixtureBaseline: commandRecord("LD_LIBRARY_PATH=linuxcnc/lib bash wasm-port/tools/verify_native_linuxcnc_fixture_baseline.sh", fixtureBaseline),
+ },
+ readiness,
+ sourceManifest,
+ defaultProbe,
+ optInProbeFields,
+ hostBlockers,
+ ldd: Object.fromEntries(Object.entries(ldd).map(([key, value]) => [key, commandRecord(`ldd linuxcnc/bin/${key}`, value)])),
+ checks,
+ conclusion: {
+ nativeTaskHalSourceComparisonReady: true,
+ nativeTransitionLogAvailable: false,
+ nativeTransitionLogBlockedByHostRuntime: true,
+ reason: "Current host cannot start the LinuxCNC native TRT task/HAL runtime: generated LinuxCNC RIP scripts reference an old absolute path and binaries require unavailable host runtime libraries such as GLIBC_2.38/libpython3.13.",
+ boundary: "This completes BTN-013 as an auditable native comparison and blocker record; it does not claim hardware drive, realtime kernel, external user-M process, or tool DB native runtime readiness.",
+ },
+};
+
+await fs.writeFile(REPORT_JSON, `${JSON.stringify(report, null, 2)}\n`, "utf8");
+await fs.writeFile(REPORT_MD, renderMarkdown(report), "utf8");
+
+console.log(`native_task_hal_comparison_status=${report.status}`);
+console.log(`native_task_hal_comparison_json=${REPORT_JSON}`);
+console.log(`native_task_hal_comparison_markdown=${REPORT_MD}`);
+console.log(`native_task_hal_transition_log_available=${report.conclusion.nativeTransitionLogAvailable ? 1 : 0}`);
+console.log(`native_task_hal_host_blocker_count=${hostBlockers.length}`);
+
+if (report.status === "FAIL") process.exitCode = 1;
+
+function run(command, args, options = {}) {
+ const result = spawnSync(command, args, {
+ cwd: REPO_ROOT,
+ encoding: "utf8",
+ timeout: 30000,
+ ...options,
+ });
+ const stdout = result.stdout || "";
+ const stderr = result.stderr || "";
+ return {
+ status: result.status ?? 1,
+ signal: result.signal || null,
+ stdout,
+ stderr,
+ combined: `${stdout}${stderr ? `\n${stderr}` : ""}`.trim(),
+ };
+}
+
+async function readText(relPath) {
+ return fs.readFile(path.join(REPO_ROOT, relPath), "utf8").catch(() => "");
+}
+
+async function readJson(filePath) {
+ return JSON.parse(await fs.readFile(filePath, "utf8").catch(() => "{}"));
+}
+
+function parseKv(text) {
+ const fields = {};
+ for (const line of text.split(/\r?\n/)) {
+ const index = line.indexOf("=");
+ if (index <= 0) continue;
+ fields[line.slice(0, index)] = line.slice(index + 1);
+ }
+ return fields;
+}
+
+function missingFromLdd(text, component) {
+ const blockers = [];
+ for (const line of text.split(/\r?\n/)) {
+ if (line.includes("not found") || line.includes("version `GLIBC") || line.includes("version `GLIBCXX")) {
+ blockers.push({ component, blocker: "dynamic_linker_requirement", detail: line.trim() });
+ }
+ }
+ return blockers;
+}
+
+function check(name, pass, detail) {
+ return { name, pass: Boolean(pass), detail: String(detail || "-").slice(0, 3000) };
+}
+
+function commandRecord(command, result) {
+ return {
+ command,
+ status: result.status,
+ signal: result.signal,
+ stdout: result.stdout.slice(0, 6000),
+ stderr: result.stderr.slice(0, 6000),
+ };
+}
+
+function firstLine(text) {
+ return String(text || "").split(/\r?\n/).find(Boolean) || "-";
+}
+
+function oneLine(text) {
+ return String(text || "").split(/\r?\n/).filter(Boolean).join(" | ").slice(0, 2000);
+}
+
+function renderMarkdown(data) {
+ return [
+ "# Native task/HAL comparison report",
+ "",
+ `- status: ${data.status}`,
+ `- generatedAt: ${data.generatedAt}`,
+ `- JSON: ${REPORT_JSON}`,
+ "",
+ "## Checks",
+ "",
+ ...data.checks.map((item) => `- ${item.pass ? "PASS" : "FAIL"}: ${item.name} — ${item.detail}`),
+ "",
+ "## Host Native Runtime Blockers",
+ "",
+ ...data.hostBlockers.map((item) => `- ${item.component}: ${item.blocker}: ${item.detail}`),
+ "",
+ "## Conclusion",
+ "",
+ data.conclusion.reason,
+ "",
+ data.conclusion.boundary,
+ "",
+ ].join("\n");
+}
diff --git a/qa/web-rtcp-5axis-site-test/output/button-control-evidence-report.json b/qa/web-rtcp-5axis-site-test/output/button-control-evidence-report.json
new file mode 100644
index 0000000..64dfe73
--- /dev/null
+++ b/qa/web-rtcp-5axis-site-test/output/button-control-evidence-report.json
@@ -0,0 +1,2510 @@
+{
+ "jobId": "btn-20260623091525-b35869f1",
+ "reportId": "report-btn-20260623091525-b35869f1",
+ "evidenceScope": "button-control-evidence",
+ "generatedAt": "2026-06-23T09:15:25.426Z",
+ "targetUrl": "http://127.0.0.1:41741/web-rtcp-5axis-sim-plan/app/index.html",
+ "chromePath": "/usr/bin/google-chrome",
+ "screenshotsDir": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/screenshots/button-control-evidence",
+ "steps": [
+ {
+ "name": "01-initial",
+ "title": "Initial UI",
+ "description": "Browser app loaded before machine preparation.",
+ "screenshotPath": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/screenshots/button-control-evidence/01-initial.png",
+ "pixelStats": {
+ "width": 1500,
+ "height": 1050,
+ "averageLuminance": 129.06,
+ "nonBlackRatio": 0.7826
+ },
+ "buttons": {
+ "RUN": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "run blocked: machine must be on"
+ },
+ "STOP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "PAUSE": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "pause blocked: machine must be on"
+ },
+ "RESUME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "resume blocked: machine must be on"
+ },
+ "STEP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "step blocked: machine must be on"
+ },
+ "HOME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "home blocked: machine must be on"
+ }
+ },
+ "canvasDataset": {
+ "fiveAxisCanvas": "true",
+ "engine": "three.js r183",
+ "threeReady": "true",
+ "threeRevision": "183",
+ "threePathPoints": "2",
+ "threeExecutedPathPoints": "1",
+ "threeSceneObjects": "20",
+ "threeToolhead": "{\"x\":0,\"y\":0,\"z\":0}",
+ "threeSceneUnits": "m",
+ "threeLinearUnits": "mm",
+ "threeLinearUnitScaleToMeters": "0.001",
+ "threeToolAxis": "{\"x\":0,\"y\":0,\"z\":1}",
+ "threeTcpPose": "{\"x\":0,\"y\":0,\"z\":0,\"a\":0,\"c\":0}",
+ "threeRtcpState": "on",
+ "threeSelectedView": "iso",
+ "threeFrameApi": "web-rtcp-5axis-motion-frame",
+ "threeRenderer": "webgl",
+ "threeSceneMode": "program-preview-and-tool-execution",
+ "threePreviewScope": "machine-reference-and-toolpath",
+ "threeMachineReferenceModel": "webgl-five-axis-reference",
+ "threeCameraControls": "orbit-pan-zoom",
+ "threeProgramPreviewSource": "linuxcnc-interpreter-wasm",
+ "threeToolExecutionMarker": "true",
+ "threeTcpMarker": "sphere",
+ "threeToolAxisMarker": "line",
+ "threeToolpathPreviewSource": "linuxcnc_interpreter_canonical_motion",
+ "threeToolExecutionTraceSource": "linuxcnc_tp_samples_or_task_motion_hal_feedback",
+ "threePathFitBounds": "ok",
+ "threePathBoundsMeters": "{\"center\":{\"x\":0,\"y\":0,\"z\":0.002},\"size\":{\"x\":0,\"y\":0,\"z\":0.005},\"maxSpan\":0.005}",
+ "threeCurrentSegmentHighlight": "ok",
+ "threeRapidFeedVisualDistinction": "ok",
+ "threeNoGcodeSemanticsGeneration": "ok",
+ "threeRapidPathPoints": "2",
+ "threeFeedPathPoints": "0",
+ "threeArcPathPoints": "0",
+ "threeCurrentSegmentPoints": "2",
+ "threeCurrentSegmentType": "STRAIGHT_TRAVERSE"
+ },
+ "state": {
+ "activeProgram": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzac.ngc",
+ "runState": "idle",
+ "activeLine": 1,
+ "machine": {
+ "powerOn": false,
+ "taskState": "estop-reset",
+ "mode": "manual",
+ "allHomed": false,
+ "interpState": "idle",
+ "taskPaused": false
+ },
+ "axisPose": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "dro": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "programRuntimeFeedback": {
+ "sourceMode": "linuxcnc-task-motion-hal-wasm",
+ "line": 1,
+ "taskCycle": 2,
+ "currentVelocityMmPerMin": 0,
+ "axisPose": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ }
+ },
+ "taskHalStatus": {
+ "task": {
+ "mode": "MANUAL",
+ "interpState": "IDLE",
+ "taskPaused": false,
+ "singleStepping": false
+ },
+ "ui": {
+ "activeLine": 1,
+ "taskCycle": 0,
+ "servoCycle": 20
+ },
+ "motionStatus": {
+ "motion": {
+ "paused": false,
+ "aborted": false
+ }
+ }
+ },
+ "taskHalStatusLoop": {
+ "apiName": "web-rtcp-5axis-task-hal-status-loop",
+ "active": false,
+ "sequence": 0,
+ "profileId": null,
+ "iniPath": null,
+ "kinematicsModuleId": null,
+ "tickCount": 0,
+ "batchSize": 5,
+ "intervalMs": 25,
+ "taskPeriodNs": 10000000,
+ "servoPeriodNs": 1000000,
+ "lastStatusAt": null,
+ "lastError": null,
+ "stopReason": null,
+ "semanticBoundary": "js_status_polling_loop_for_linuxcnc_task_hal_motion_status"
+ },
+ "operatorMessage": "LinuxCNC task/HAL session ready /work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/demos/xyzac_switchkins.ngc"
+ }
+ },
+ {
+ "name": "02-program-loaded",
+ "title": "Program loaded",
+ "description": "Short operator G-code loaded through LinuxCNC interpreter WASM.",
+ "screenshotPath": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/screenshots/button-control-evidence/02-program-loaded.png",
+ "pixelStats": {
+ "width": 1500,
+ "height": 1050,
+ "averageLuminance": 129.06,
+ "nonBlackRatio": 0.7795
+ },
+ "buttons": {
+ "RUN": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "run blocked: machine must be on"
+ },
+ "STOP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "PAUSE": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "pause blocked: machine must be on"
+ },
+ "RESUME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "resume blocked: machine must be on"
+ },
+ "STEP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "step blocked: machine must be on"
+ },
+ "HOME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "home blocked: machine must be on"
+ }
+ },
+ "canvasDataset": {
+ "fiveAxisCanvas": "true",
+ "engine": "three.js r183",
+ "threeReady": "true",
+ "threeRevision": "183",
+ "threePathPoints": "6",
+ "threeExecutedPathPoints": "1",
+ "threeSceneObjects": "20",
+ "threeToolhead": "{\"x\":0,\"y\":0,\"z\":0}",
+ "threeSceneUnits": "m",
+ "threeLinearUnits": "mm",
+ "threeLinearUnitScaleToMeters": "0.001",
+ "threeToolAxis": "{\"x\":0,\"y\":0,\"z\":1}",
+ "threeTcpPose": "{\"x\":0,\"y\":0,\"z\":0,\"a\":0,\"c\":0}",
+ "threeRtcpState": "on",
+ "threeSelectedView": "iso",
+ "threeFrameApi": "web-rtcp-5axis-motion-frame",
+ "threeRenderer": "webgl",
+ "threeSceneMode": "program-preview-and-tool-execution",
+ "threePreviewScope": "machine-reference-and-toolpath",
+ "threeMachineReferenceModel": "webgl-five-axis-reference",
+ "threeCameraControls": "orbit-pan-zoom",
+ "threeProgramPreviewSource": "linuxcnc-interpreter-wasm",
+ "threeToolExecutionMarker": "true",
+ "threeTcpMarker": "sphere",
+ "threeToolAxisMarker": "line",
+ "threeToolpathPreviewSource": "linuxcnc_interpreter_canonical_motion",
+ "threeToolExecutionTraceSource": "linuxcnc_tp_samples_or_task_motion_hal_feedback",
+ "threePathFitBounds": "ok",
+ "threePathBoundsMeters": "{\"center\":{\"x\":0.01,\"y\":0.01,\"z\":0.002},\"size\":{\"x\":0.02,\"y\":0.02,\"z\":0.005},\"maxSpan\":0.02}",
+ "threeCurrentSegmentHighlight": "ok",
+ "threeRapidFeedVisualDistinction": "ok",
+ "threeNoGcodeSemanticsGeneration": "ok",
+ "threeRapidPathPoints": "2",
+ "threeFeedPathPoints": "4",
+ "threeArcPathPoints": "0",
+ "threeCurrentSegmentPoints": "2",
+ "threeCurrentSegmentType": "STRAIGHT_FEED"
+ },
+ "state": {
+ "activeProgram": "button-control-evidence.ngc",
+ "runState": "idle",
+ "activeLine": 2,
+ "machine": {
+ "powerOn": false,
+ "taskState": "estop-reset",
+ "mode": "auto",
+ "allHomed": false,
+ "interpState": "idle",
+ "taskPaused": false
+ },
+ "axisPose": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "dro": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "programRuntimeFeedback": {
+ "sourceMode": "linuxcnc-tp-runtime-sample",
+ "line": 3,
+ "currentVelocityMmPerMin": 30,
+ "axisPose": {
+ "x": 0.00025,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ }
+ },
+ "taskHalStatus": {
+ "task": {
+ "mode": "MANUAL",
+ "interpState": "IDLE",
+ "taskPaused": false,
+ "singleStepping": false
+ },
+ "ui": {
+ "activeLine": 1,
+ "taskCycle": 0,
+ "servoCycle": 20
+ },
+ "motionStatus": {
+ "motion": {
+ "paused": false,
+ "aborted": false
+ }
+ }
+ },
+ "taskHalStatusLoop": {
+ "apiName": "web-rtcp-5axis-task-hal-status-loop",
+ "active": false,
+ "sequence": 0,
+ "profileId": null,
+ "iniPath": null,
+ "kinematicsModuleId": null,
+ "tickCount": 0,
+ "batchSize": 5,
+ "intervalMs": 25,
+ "taskPeriodNs": 10000000,
+ "servoPeriodNs": 1000000,
+ "lastStatusAt": null,
+ "lastError": null,
+ "stopReason": null,
+ "semanticBoundary": "js_status_polling_loop_for_linuxcnc_task_hal_motion_status"
+ },
+ "operatorMessage": "LinuxCNC interpreter motion events 6"
+ }
+ },
+ {
+ "name": "03-before-home",
+ "title": "Before HOME",
+ "description": "Machine powered on in manual mode before HOME.",
+ "screenshotPath": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/screenshots/button-control-evidence/03-before-home.png",
+ "pixelStats": {
+ "width": 1500,
+ "height": 1050,
+ "averageLuminance": 129.24,
+ "nonBlackRatio": 0.7794
+ },
+ "buttons": {
+ "RUN": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "run blocked: switch to auto mode first"
+ },
+ "STOP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "PAUSE": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "pause blocked: task mode must be auto or MDI"
+ },
+ "RESUME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "resume blocked: task mode must be auto or MDI"
+ },
+ "STEP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "step blocked: switch to auto mode first"
+ },
+ "HOME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ }
+ },
+ "canvasDataset": {
+ "fiveAxisCanvas": "true",
+ "engine": "three.js r183",
+ "threeReady": "true",
+ "threeRevision": "183",
+ "threePathPoints": "6",
+ "threeExecutedPathPoints": "1",
+ "threeSceneObjects": "20",
+ "threeToolhead": "{\"x\":0,\"y\":0,\"z\":0}",
+ "threeSceneUnits": "m",
+ "threeLinearUnits": "mm",
+ "threeLinearUnitScaleToMeters": "0.001",
+ "threeToolAxis": "{\"x\":0,\"y\":0,\"z\":1}",
+ "threeTcpPose": "{\"x\":0,\"y\":0,\"z\":0,\"a\":0,\"c\":0}",
+ "threeRtcpState": "off",
+ "threeSelectedView": "iso",
+ "threeFrameApi": "web-rtcp-5axis-motion-frame",
+ "threeRenderer": "webgl",
+ "threeSceneMode": "program-preview-and-tool-execution",
+ "threePreviewScope": "machine-reference-and-toolpath",
+ "threeMachineReferenceModel": "webgl-five-axis-reference",
+ "threeCameraControls": "orbit-pan-zoom",
+ "threeProgramPreviewSource": "linuxcnc-interpreter-wasm",
+ "threeToolExecutionMarker": "true",
+ "threeTcpMarker": "sphere",
+ "threeToolAxisMarker": "line",
+ "threeToolpathPreviewSource": "linuxcnc_interpreter_canonical_motion",
+ "threeToolExecutionTraceSource": "linuxcnc_tp_samples_or_task_motion_hal_feedback",
+ "threePathFitBounds": "ok",
+ "threePathBoundsMeters": "{\"center\":{\"x\":0.01,\"y\":0.01,\"z\":0.002},\"size\":{\"x\":0.02,\"y\":0.02,\"z\":0.005},\"maxSpan\":0.02}",
+ "threeCurrentSegmentHighlight": "ok",
+ "threeRapidFeedVisualDistinction": "ok",
+ "threeNoGcodeSemanticsGeneration": "ok",
+ "threeRapidPathPoints": "2",
+ "threeFeedPathPoints": "4",
+ "threeArcPathPoints": "0",
+ "threeCurrentSegmentPoints": "2",
+ "threeCurrentSegmentType": "STRAIGHT_FEED"
+ },
+ "state": {
+ "activeProgram": "button-control-evidence.ngc",
+ "runState": "idle",
+ "activeLine": 1,
+ "machine": {
+ "powerOn": true,
+ "taskState": "on",
+ "mode": "manual",
+ "allHomed": false,
+ "interpState": "idle",
+ "taskPaused": false
+ },
+ "axisPose": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "dro": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "programRuntimeFeedback": {
+ "sourceMode": "linuxcnc-task-motion-hal-wasm",
+ "line": 1,
+ "taskCycle": 4,
+ "currentVelocityMmPerMin": 0,
+ "axisPose": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ }
+ },
+ "taskHalStatus": {
+ "task": {
+ "mode": "MANUAL",
+ "interpState": "IDLE",
+ "taskPaused": false,
+ "singleStepping": false
+ },
+ "ui": {
+ "activeLine": 1,
+ "taskCycle": 0,
+ "servoCycle": 40
+ },
+ "motionStatus": {
+ "motion": {
+ "paused": false,
+ "aborted": false
+ }
+ }
+ },
+ "taskHalStatusLoop": {
+ "apiName": "web-rtcp-5axis-task-hal-status-loop",
+ "active": false,
+ "sequence": 0,
+ "profileId": null,
+ "iniPath": null,
+ "kinematicsModuleId": null,
+ "tickCount": 0,
+ "batchSize": 5,
+ "intervalMs": 25,
+ "taskPeriodNs": 10000000,
+ "servoPeriodNs": 1000000,
+ "lastStatusAt": null,
+ "lastError": null,
+ "stopReason": null,
+ "semanticBoundary": "js_status_polling_loop_for_linuxcnc_task_hal_motion_status"
+ },
+ "operatorMessage": "task/HAL mode manual"
+ }
+ },
+ {
+ "name": "04-after-home",
+ "title": "After HOME",
+ "description": "HOME command preserves allHomed state in Web/task gate.",
+ "screenshotPath": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/screenshots/button-control-evidence/04-after-home.png",
+ "pixelStats": {
+ "width": 1500,
+ "height": 1050,
+ "averageLuminance": 129.22,
+ "nonBlackRatio": 0.7794
+ },
+ "buttons": {
+ "RUN": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "run blocked: switch to auto mode first"
+ },
+ "STOP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "PAUSE": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "pause blocked: task mode must be auto or MDI"
+ },
+ "RESUME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "resume blocked: task mode must be auto or MDI"
+ },
+ "STEP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "step blocked: switch to auto mode first"
+ },
+ "HOME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ }
+ },
+ "canvasDataset": {
+ "fiveAxisCanvas": "true",
+ "engine": "three.js r183",
+ "threeReady": "true",
+ "threeRevision": "183",
+ "threePathPoints": "6",
+ "threeExecutedPathPoints": "1",
+ "threeSceneObjects": "20",
+ "threeToolhead": "{\"x\":0,\"y\":0,\"z\":0}",
+ "threeSceneUnits": "m",
+ "threeLinearUnits": "mm",
+ "threeLinearUnitScaleToMeters": "0.001",
+ "threeToolAxis": "{\"x\":0,\"y\":0,\"z\":1}",
+ "threeTcpPose": "{\"x\":0,\"y\":0,\"z\":0,\"a\":0,\"c\":0}",
+ "threeRtcpState": "off",
+ "threeSelectedView": "iso",
+ "threeFrameApi": "web-rtcp-5axis-motion-frame",
+ "threeRenderer": "webgl",
+ "threeSceneMode": "program-preview-and-tool-execution",
+ "threePreviewScope": "machine-reference-and-toolpath",
+ "threeMachineReferenceModel": "webgl-five-axis-reference",
+ "threeCameraControls": "orbit-pan-zoom",
+ "threeProgramPreviewSource": "linuxcnc-interpreter-wasm",
+ "threeToolExecutionMarker": "true",
+ "threeTcpMarker": "sphere",
+ "threeToolAxisMarker": "line",
+ "threeToolpathPreviewSource": "linuxcnc_interpreter_canonical_motion",
+ "threeToolExecutionTraceSource": "linuxcnc_tp_samples_or_task_motion_hal_feedback",
+ "threePathFitBounds": "ok",
+ "threePathBoundsMeters": "{\"center\":{\"x\":0.01,\"y\":0.01,\"z\":0.002},\"size\":{\"x\":0.02,\"y\":0.02,\"z\":0.005},\"maxSpan\":0.02}",
+ "threeCurrentSegmentHighlight": "ok",
+ "threeRapidFeedVisualDistinction": "ok",
+ "threeNoGcodeSemanticsGeneration": "ok",
+ "threeRapidPathPoints": "2",
+ "threeFeedPathPoints": "4",
+ "threeArcPathPoints": "0",
+ "threeCurrentSegmentPoints": "2",
+ "threeCurrentSegmentType": "STRAIGHT_FEED"
+ },
+ "state": {
+ "activeProgram": "button-control-evidence.ngc",
+ "runState": "idle",
+ "activeLine": 1,
+ "machine": {
+ "powerOn": true,
+ "taskState": "on",
+ "mode": "manual",
+ "allHomed": true,
+ "interpState": "idle",
+ "taskPaused": false
+ },
+ "axisPose": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "dro": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "programRuntimeFeedback": {
+ "sourceMode": "linuxcnc-task-motion-hal-wasm",
+ "line": 1,
+ "taskCycle": 5,
+ "currentVelocityMmPerMin": 3600,
+ "axisPose": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ }
+ },
+ "taskHalStatus": {
+ "task": {
+ "mode": "MANUAL",
+ "interpState": "IDLE",
+ "taskPaused": false,
+ "singleStepping": false
+ },
+ "ui": {
+ "activeLine": 1,
+ "taskCycle": 0,
+ "servoCycle": 50
+ },
+ "motionStatus": {
+ "motion": {
+ "paused": false,
+ "aborted": false
+ }
+ }
+ },
+ "taskHalStatusLoop": {
+ "apiName": "web-rtcp-5axis-task-hal-status-loop",
+ "active": false,
+ "sequence": 0,
+ "profileId": null,
+ "iniPath": null,
+ "kinematicsModuleId": null,
+ "tickCount": 0,
+ "batchSize": 5,
+ "intervalMs": 25,
+ "taskPeriodNs": 10000000,
+ "servoPeriodNs": 1000000,
+ "lastStatusAt": null,
+ "lastError": null,
+ "stopReason": null,
+ "semanticBoundary": "js_status_polling_loop_for_linuxcnc_task_hal_motion_status"
+ },
+ "operatorMessage": "task/HAL machine homed"
+ }
+ },
+ {
+ "name": "05-ready-for-run",
+ "title": "Ready for RUN",
+ "description": "POWER, HOME, AUTO, and loaded G-code are ready before RUN.",
+ "screenshotPath": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/screenshots/button-control-evidence/05-ready-for-run.png",
+ "pixelStats": {
+ "width": 1500,
+ "height": 1050,
+ "averageLuminance": 129.23,
+ "nonBlackRatio": 0.7794
+ },
+ "buttons": {
+ "RUN": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "STOP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "PAUSE": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "RESUME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "resume blocked: interpreter is not paused"
+ },
+ "STEP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "HOME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "home blocked: switch to manual mode first"
+ }
+ },
+ "canvasDataset": {
+ "fiveAxisCanvas": "true",
+ "engine": "three.js r183",
+ "threeReady": "true",
+ "threeRevision": "183",
+ "threePathPoints": "6",
+ "threeExecutedPathPoints": "1",
+ "threeSceneObjects": "20",
+ "threeToolhead": "{\"x\":0,\"y\":0,\"z\":0}",
+ "threeSceneUnits": "m",
+ "threeLinearUnits": "mm",
+ "threeLinearUnitScaleToMeters": "0.001",
+ "threeToolAxis": "{\"x\":0,\"y\":0,\"z\":1}",
+ "threeTcpPose": "{\"x\":0,\"y\":0,\"z\":0,\"a\":0,\"c\":0}",
+ "threeRtcpState": "off",
+ "threeSelectedView": "iso",
+ "threeFrameApi": "web-rtcp-5axis-motion-frame",
+ "threeRenderer": "webgl",
+ "threeSceneMode": "program-preview-and-tool-execution",
+ "threePreviewScope": "machine-reference-and-toolpath",
+ "threeMachineReferenceModel": "webgl-five-axis-reference",
+ "threeCameraControls": "orbit-pan-zoom",
+ "threeProgramPreviewSource": "linuxcnc-interpreter-wasm",
+ "threeToolExecutionMarker": "true",
+ "threeTcpMarker": "sphere",
+ "threeToolAxisMarker": "line",
+ "threeToolpathPreviewSource": "linuxcnc_interpreter_canonical_motion",
+ "threeToolExecutionTraceSource": "linuxcnc_tp_samples_or_task_motion_hal_feedback",
+ "threePathFitBounds": "ok",
+ "threePathBoundsMeters": "{\"center\":{\"x\":0.01,\"y\":0.01,\"z\":0.002},\"size\":{\"x\":0.02,\"y\":0.02,\"z\":0.005},\"maxSpan\":0.02}",
+ "threeCurrentSegmentHighlight": "ok",
+ "threeRapidFeedVisualDistinction": "ok",
+ "threeNoGcodeSemanticsGeneration": "ok",
+ "threeRapidPathPoints": "2",
+ "threeFeedPathPoints": "4",
+ "threeArcPathPoints": "0",
+ "threeCurrentSegmentPoints": "2",
+ "threeCurrentSegmentType": "STRAIGHT_FEED"
+ },
+ "state": {
+ "activeProgram": "button-control-evidence.ngc",
+ "runState": "idle",
+ "activeLine": 1,
+ "machine": {
+ "powerOn": true,
+ "taskState": "on",
+ "mode": "auto",
+ "allHomed": true,
+ "interpState": "idle",
+ "taskPaused": false
+ },
+ "axisPose": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "dro": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "programRuntimeFeedback": {
+ "sourceMode": "linuxcnc-task-motion-hal-wasm",
+ "line": 1,
+ "taskCycle": 6,
+ "currentVelocityMmPerMin": 3600,
+ "axisPose": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ }
+ },
+ "taskHalStatus": {
+ "task": {
+ "mode": "AUTO",
+ "interpState": "IDLE",
+ "taskPaused": false,
+ "singleStepping": false
+ },
+ "ui": {
+ "activeLine": 1,
+ "taskCycle": 0,
+ "servoCycle": 60
+ },
+ "motionStatus": {
+ "motion": {
+ "paused": false,
+ "aborted": false
+ }
+ }
+ },
+ "taskHalStatusLoop": {
+ "apiName": "web-rtcp-5axis-task-hal-status-loop",
+ "active": false,
+ "sequence": 0,
+ "profileId": null,
+ "iniPath": null,
+ "kinematicsModuleId": null,
+ "tickCount": 0,
+ "batchSize": 5,
+ "intervalMs": 25,
+ "taskPeriodNs": 10000000,
+ "servoPeriodNs": 1000000,
+ "lastStatusAt": null,
+ "lastError": null,
+ "stopReason": null,
+ "semanticBoundary": "js_status_polling_loop_for_linuxcnc_task_hal_motion_status"
+ },
+ "operatorMessage": "task/HAL mode auto"
+ }
+ },
+ {
+ "name": "06-after-run",
+ "title": "After RUN",
+ "description": "RUN starts task/HAL backed program execution.",
+ "screenshotPath": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/screenshots/button-control-evidence/06-after-run.png",
+ "pixelStats": {
+ "width": 1500,
+ "height": 1050,
+ "averageLuminance": 129.19,
+ "nonBlackRatio": 0.7795
+ },
+ "buttons": {
+ "RUN": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "STOP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "PAUSE": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "RESUME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "resume blocked: interpreter is not paused"
+ },
+ "STEP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "HOME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "home blocked: switch to manual mode first"
+ }
+ },
+ "canvasDataset": {
+ "fiveAxisCanvas": "true",
+ "engine": "three.js r183",
+ "threeReady": "true",
+ "threeRevision": "183",
+ "threePathPoints": "6",
+ "threeExecutedPathPoints": "1",
+ "threeSceneObjects": "20",
+ "threeToolhead": "{\"x\":0.001,\"y\":0,\"z\":0}",
+ "threeSceneUnits": "m",
+ "threeLinearUnits": "mm",
+ "threeLinearUnitScaleToMeters": "0.001",
+ "threeToolAxis": "{\"x\":0,\"y\":0,\"z\":1}",
+ "threeTcpPose": "{\"x\":1.199,\"y\":0,\"z\":0,\"a\":0,\"c\":0}",
+ "threeRtcpState": "off",
+ "threeSelectedView": "iso",
+ "threeFrameApi": "web-rtcp-5axis-motion-frame",
+ "threeRenderer": "webgl",
+ "threeSceneMode": "program-preview-and-tool-execution",
+ "threePreviewScope": "machine-reference-and-toolpath",
+ "threeMachineReferenceModel": "webgl-five-axis-reference",
+ "threeCameraControls": "orbit-pan-zoom",
+ "threeProgramPreviewSource": "linuxcnc-interpreter-wasm",
+ "threeToolExecutionMarker": "true",
+ "threeTcpMarker": "sphere",
+ "threeToolAxisMarker": "line",
+ "threeToolpathPreviewSource": "linuxcnc_interpreter_canonical_motion",
+ "threeToolExecutionTraceSource": "linuxcnc_tp_samples_or_task_motion_hal_feedback",
+ "threePathFitBounds": "ok",
+ "threePathBoundsMeters": "{\"center\":{\"x\":0.01,\"y\":0.01,\"z\":0.002},\"size\":{\"x\":0.02,\"y\":0.02,\"z\":0.005},\"maxSpan\":0.02}",
+ "threeCurrentSegmentHighlight": "ok",
+ "threeRapidFeedVisualDistinction": "ok",
+ "threeNoGcodeSemanticsGeneration": "ok",
+ "threeRapidPathPoints": "2",
+ "threeFeedPathPoints": "4",
+ "threeArcPathPoints": "0",
+ "threeCurrentSegmentPoints": "2",
+ "threeCurrentSegmentType": "STRAIGHT_FEED"
+ },
+ "state": {
+ "activeProgram": "button-control-evidence.ngc",
+ "runState": "running",
+ "activeLine": 3,
+ "machine": {
+ "powerOn": true,
+ "taskState": "on",
+ "mode": "auto",
+ "allHomed": true,
+ "interpState": "reading",
+ "taskPaused": false
+ },
+ "axisPose": {
+ "x": 0.999201,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "dro": {
+ "x": 0.999201,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "programRuntimeFeedback": {
+ "sourceMode": "linuxcnc-task-motion-hal-wasm",
+ "line": 3,
+ "taskCycle": 56,
+ "currentVelocityMmPerMin": 120,
+ "axisPose": {
+ "x": 0.999201,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ }
+ },
+ "taskHalStatus": {
+ "task": {
+ "mode": "AUTO",
+ "interpState": "READING",
+ "taskPaused": false,
+ "singleStepping": false
+ },
+ "ui": {
+ "activeLine": 3,
+ "taskCycle": 0,
+ "servoCycle": 560
+ },
+ "motionStatus": {
+ "motion": {
+ "paused": false,
+ "aborted": false
+ }
+ }
+ },
+ "taskHalStatusLoop": {
+ "apiName": "web-rtcp-5axis-task-hal-status-loop",
+ "active": true,
+ "sequence": 1,
+ "profileId": "xyzac-trt",
+ "iniPath": "configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
+ "kinematicsModuleId": "xyzac-trt",
+ "tickCount": 9,
+ "batchSize": 5,
+ "intervalMs": 25,
+ "taskPeriodNs": 10000000,
+ "servoPeriodNs": 1000000,
+ "lastStatusAt": "2026-06-23T09:15:32.003Z",
+ "lastError": null,
+ "stopReason": null,
+ "semanticBoundary": "js_status_polling_loop_for_linuxcnc_task_hal_motion_status"
+ },
+ "operatorMessage": "task/HAL status tick 9"
+ }
+ },
+ {
+ "name": "07-before-pause",
+ "title": "Before PAUSE",
+ "description": "Program is running before PAUSE.",
+ "screenshotPath": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/screenshots/button-control-evidence/07-before-pause.png",
+ "pixelStats": {
+ "width": 1500,
+ "height": 1050,
+ "averageLuminance": 129.19,
+ "nonBlackRatio": 0.7795
+ },
+ "buttons": {
+ "RUN": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "STOP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "PAUSE": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "RESUME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "resume blocked: interpreter is not paused"
+ },
+ "STEP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "HOME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "home blocked: switch to manual mode first"
+ }
+ },
+ "canvasDataset": {
+ "fiveAxisCanvas": "true",
+ "engine": "three.js r183",
+ "threeReady": "true",
+ "threeRevision": "183",
+ "threePathPoints": "6",
+ "threeExecutedPathPoints": "1",
+ "threeSceneObjects": "20",
+ "threeToolhead": "{\"x\":0.002,\"y\":0,\"z\":0}",
+ "threeSceneUnits": "m",
+ "threeLinearUnits": "mm",
+ "threeLinearUnitScaleToMeters": "0.001",
+ "threeToolAxis": "{\"x\":0,\"y\":0,\"z\":1}",
+ "threeTcpPose": "{\"x\":1.699,\"y\":0,\"z\":0,\"a\":0,\"c\":0}",
+ "threeRtcpState": "off",
+ "threeSelectedView": "iso",
+ "threeFrameApi": "web-rtcp-5axis-motion-frame",
+ "threeRenderer": "webgl",
+ "threeSceneMode": "program-preview-and-tool-execution",
+ "threePreviewScope": "machine-reference-and-toolpath",
+ "threeMachineReferenceModel": "webgl-five-axis-reference",
+ "threeCameraControls": "orbit-pan-zoom",
+ "threeProgramPreviewSource": "linuxcnc-interpreter-wasm",
+ "threeToolExecutionMarker": "true",
+ "threeTcpMarker": "sphere",
+ "threeToolAxisMarker": "line",
+ "threeToolpathPreviewSource": "linuxcnc_interpreter_canonical_motion",
+ "threeToolExecutionTraceSource": "linuxcnc_tp_samples_or_task_motion_hal_feedback",
+ "threePathFitBounds": "ok",
+ "threePathBoundsMeters": "{\"center\":{\"x\":0.01,\"y\":0.01,\"z\":0.002},\"size\":{\"x\":0.02,\"y\":0.02,\"z\":0.005},\"maxSpan\":0.02}",
+ "threeCurrentSegmentHighlight": "ok",
+ "threeRapidFeedVisualDistinction": "ok",
+ "threeNoGcodeSemanticsGeneration": "ok",
+ "threeRapidPathPoints": "2",
+ "threeFeedPathPoints": "4",
+ "threeArcPathPoints": "0",
+ "threeCurrentSegmentPoints": "2",
+ "threeCurrentSegmentType": "STRAIGHT_FEED"
+ },
+ "state": {
+ "activeProgram": "button-control-evidence.ngc",
+ "runState": "running",
+ "activeLine": 3,
+ "machine": {
+ "powerOn": true,
+ "taskState": "on",
+ "mode": "auto",
+ "allHomed": true,
+ "interpState": "reading",
+ "taskPaused": false
+ },
+ "axisPose": {
+ "x": 1.4988,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "dro": {
+ "x": 1.4988,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "programRuntimeFeedback": {
+ "sourceMode": "linuxcnc-task-motion-hal-wasm",
+ "line": 3,
+ "taskCycle": 81,
+ "currentVelocityMmPerMin": 120,
+ "axisPose": {
+ "x": 1.4988,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ }
+ },
+ "taskHalStatus": {
+ "task": {
+ "mode": "AUTO",
+ "interpState": "READING",
+ "taskPaused": false,
+ "singleStepping": false
+ },
+ "ui": {
+ "activeLine": 3,
+ "taskCycle": 0,
+ "servoCycle": 810
+ },
+ "motionStatus": {
+ "motion": {
+ "paused": false,
+ "aborted": false
+ }
+ }
+ },
+ "taskHalStatusLoop": {
+ "apiName": "web-rtcp-5axis-task-hal-status-loop",
+ "active": true,
+ "sequence": 1,
+ "profileId": "xyzac-trt",
+ "iniPath": "configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
+ "kinematicsModuleId": "xyzac-trt",
+ "tickCount": 14,
+ "batchSize": 5,
+ "intervalMs": 25,
+ "taskPeriodNs": 10000000,
+ "servoPeriodNs": 1000000,
+ "lastStatusAt": "2026-06-23T09:15:32.443Z",
+ "lastError": null,
+ "stopReason": null,
+ "semanticBoundary": "js_status_polling_loop_for_linuxcnc_task_hal_motion_status"
+ },
+ "operatorMessage": "task/HAL status tick 14"
+ }
+ },
+ {
+ "name": "08-after-pause",
+ "title": "After PAUSE",
+ "description": "PAUSE sets runState paused and taskPaused true.",
+ "screenshotPath": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/screenshots/button-control-evidence/08-after-pause.png",
+ "pixelStats": {
+ "width": 1500,
+ "height": 1050,
+ "averageLuminance": 129.22,
+ "nonBlackRatio": 0.7795
+ },
+ "buttons": {
+ "RUN": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "run blocked: resume paused program first"
+ },
+ "STOP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "PAUSE": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "RESUME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "STEP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "HOME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "home blocked: switch to manual mode first"
+ }
+ },
+ "canvasDataset": {
+ "fiveAxisCanvas": "true",
+ "engine": "three.js r183",
+ "threeReady": "true",
+ "threeRevision": "183",
+ "threePathPoints": "6",
+ "threeExecutedPathPoints": "1",
+ "threeSceneObjects": "20",
+ "threeToolhead": "{\"x\":0.002,\"y\":0,\"z\":0}",
+ "threeSceneUnits": "m",
+ "threeLinearUnits": "mm",
+ "threeLinearUnitScaleToMeters": "0.001",
+ "threeToolAxis": "{\"x\":0,\"y\":0,\"z\":1}",
+ "threeTcpPose": "{\"x\":1.699,\"y\":0,\"z\":0,\"a\":0,\"c\":0}",
+ "threeRtcpState": "off",
+ "threeSelectedView": "iso",
+ "threeFrameApi": "web-rtcp-5axis-motion-frame",
+ "threeRenderer": "webgl",
+ "threeSceneMode": "program-preview-and-tool-execution",
+ "threePreviewScope": "machine-reference-and-toolpath",
+ "threeMachineReferenceModel": "webgl-five-axis-reference",
+ "threeCameraControls": "orbit-pan-zoom",
+ "threeProgramPreviewSource": "linuxcnc-interpreter-wasm",
+ "threeToolExecutionMarker": "true",
+ "threeTcpMarker": "sphere",
+ "threeToolAxisMarker": "line",
+ "threeToolpathPreviewSource": "linuxcnc_interpreter_canonical_motion",
+ "threeToolExecutionTraceSource": "linuxcnc_tp_samples_or_task_motion_hal_feedback",
+ "threePathFitBounds": "ok",
+ "threePathBoundsMeters": "{\"center\":{\"x\":0.01,\"y\":0.01,\"z\":0.002},\"size\":{\"x\":0.02,\"y\":0.02,\"z\":0.005},\"maxSpan\":0.02}",
+ "threeCurrentSegmentHighlight": "ok",
+ "threeRapidFeedVisualDistinction": "ok",
+ "threeNoGcodeSemanticsGeneration": "ok",
+ "threeRapidPathPoints": "2",
+ "threeFeedPathPoints": "4",
+ "threeArcPathPoints": "0",
+ "threeCurrentSegmentPoints": "2",
+ "threeCurrentSegmentType": "STRAIGHT_FEED"
+ },
+ "state": {
+ "activeProgram": "button-control-evidence.ngc",
+ "runState": "paused",
+ "activeLine": 3,
+ "machine": {
+ "powerOn": true,
+ "taskState": "on",
+ "mode": "auto",
+ "allHomed": true,
+ "interpState": "paused",
+ "taskPaused": true
+ },
+ "axisPose": {
+ "x": 1.69864,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "dro": {
+ "x": 1.69864,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "programRuntimeFeedback": {
+ "sourceMode": "linuxcnc-task-motion-hal-wasm",
+ "line": 3,
+ "taskCycle": 92,
+ "currentVelocityMmPerMin": 120,
+ "axisPose": {
+ "x": 1.69864,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ }
+ },
+ "taskHalStatus": {
+ "task": {
+ "mode": "AUTO",
+ "interpState": "PAUSED",
+ "taskPaused": true,
+ "singleStepping": false
+ },
+ "ui": {
+ "activeLine": 3,
+ "taskCycle": 0,
+ "servoCycle": 920
+ },
+ "motionStatus": {
+ "motion": {
+ "paused": true,
+ "aborted": false
+ }
+ }
+ },
+ "taskHalStatusLoop": {
+ "apiName": "web-rtcp-5axis-task-hal-status-loop",
+ "active": false,
+ "sequence": 1,
+ "profileId": "xyzac-trt",
+ "iniPath": "configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
+ "kinematicsModuleId": "xyzac-trt",
+ "tickCount": 16,
+ "batchSize": 5,
+ "intervalMs": 25,
+ "taskPeriodNs": 10000000,
+ "servoPeriodNs": 1000000,
+ "lastStatusAt": "2026-06-23T09:15:32.739Z",
+ "lastError": null,
+ "stopReason": "paused",
+ "semanticBoundary": "js_status_polling_loop_for_linuxcnc_task_hal_motion_status"
+ },
+ "operatorMessage": "task/HAL program paused"
+ }
+ },
+ {
+ "name": "09-before-resume",
+ "title": "Before RESUME",
+ "description": "Program is paused before RESUME.",
+ "screenshotPath": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/screenshots/button-control-evidence/09-before-resume.png",
+ "pixelStats": {
+ "width": 1500,
+ "height": 1050,
+ "averageLuminance": 129.22,
+ "nonBlackRatio": 0.7795
+ },
+ "buttons": {
+ "RUN": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "run blocked: resume paused program first"
+ },
+ "STOP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "PAUSE": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "RESUME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "STEP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "HOME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "home blocked: switch to manual mode first"
+ }
+ },
+ "canvasDataset": {
+ "fiveAxisCanvas": "true",
+ "engine": "three.js r183",
+ "threeReady": "true",
+ "threeRevision": "183",
+ "threePathPoints": "6",
+ "threeExecutedPathPoints": "1",
+ "threeSceneObjects": "20",
+ "threeToolhead": "{\"x\":0.002,\"y\":0,\"z\":0}",
+ "threeSceneUnits": "m",
+ "threeLinearUnits": "mm",
+ "threeLinearUnitScaleToMeters": "0.001",
+ "threeToolAxis": "{\"x\":0,\"y\":0,\"z\":1}",
+ "threeTcpPose": "{\"x\":1.699,\"y\":0,\"z\":0,\"a\":0,\"c\":0}",
+ "threeRtcpState": "off",
+ "threeSelectedView": "iso",
+ "threeFrameApi": "web-rtcp-5axis-motion-frame",
+ "threeRenderer": "webgl",
+ "threeSceneMode": "program-preview-and-tool-execution",
+ "threePreviewScope": "machine-reference-and-toolpath",
+ "threeMachineReferenceModel": "webgl-five-axis-reference",
+ "threeCameraControls": "orbit-pan-zoom",
+ "threeProgramPreviewSource": "linuxcnc-interpreter-wasm",
+ "threeToolExecutionMarker": "true",
+ "threeTcpMarker": "sphere",
+ "threeToolAxisMarker": "line",
+ "threeToolpathPreviewSource": "linuxcnc_interpreter_canonical_motion",
+ "threeToolExecutionTraceSource": "linuxcnc_tp_samples_or_task_motion_hal_feedback",
+ "threePathFitBounds": "ok",
+ "threePathBoundsMeters": "{\"center\":{\"x\":0.01,\"y\":0.01,\"z\":0.002},\"size\":{\"x\":0.02,\"y\":0.02,\"z\":0.005},\"maxSpan\":0.02}",
+ "threeCurrentSegmentHighlight": "ok",
+ "threeRapidFeedVisualDistinction": "ok",
+ "threeNoGcodeSemanticsGeneration": "ok",
+ "threeRapidPathPoints": "2",
+ "threeFeedPathPoints": "4",
+ "threeArcPathPoints": "0",
+ "threeCurrentSegmentPoints": "2",
+ "threeCurrentSegmentType": "STRAIGHT_FEED"
+ },
+ "state": {
+ "activeProgram": "button-control-evidence.ngc",
+ "runState": "paused",
+ "activeLine": 3,
+ "machine": {
+ "powerOn": true,
+ "taskState": "on",
+ "mode": "auto",
+ "allHomed": true,
+ "interpState": "paused",
+ "taskPaused": true
+ },
+ "axisPose": {
+ "x": 1.69864,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "dro": {
+ "x": 1.69864,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "programRuntimeFeedback": {
+ "sourceMode": "linuxcnc-task-motion-hal-wasm",
+ "line": 3,
+ "taskCycle": 92,
+ "currentVelocityMmPerMin": 120,
+ "axisPose": {
+ "x": 1.69864,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ }
+ },
+ "taskHalStatus": {
+ "task": {
+ "mode": "AUTO",
+ "interpState": "PAUSED",
+ "taskPaused": true,
+ "singleStepping": false
+ },
+ "ui": {
+ "activeLine": 3,
+ "taskCycle": 0,
+ "servoCycle": 920
+ },
+ "motionStatus": {
+ "motion": {
+ "paused": true,
+ "aborted": false
+ }
+ }
+ },
+ "taskHalStatusLoop": {
+ "apiName": "web-rtcp-5axis-task-hal-status-loop",
+ "active": false,
+ "sequence": 1,
+ "profileId": "xyzac-trt",
+ "iniPath": "configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
+ "kinematicsModuleId": "xyzac-trt",
+ "tickCount": 16,
+ "batchSize": 5,
+ "intervalMs": 25,
+ "taskPeriodNs": 10000000,
+ "servoPeriodNs": 1000000,
+ "lastStatusAt": "2026-06-23T09:15:32.739Z",
+ "lastError": null,
+ "stopReason": "paused",
+ "semanticBoundary": "js_status_polling_loop_for_linuxcnc_task_hal_motion_status"
+ },
+ "operatorMessage": "task/HAL program paused"
+ }
+ },
+ {
+ "name": "10-after-resume",
+ "title": "After RESUME",
+ "description": "RESUME returns task/HAL execution to running/reading.",
+ "screenshotPath": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/screenshots/button-control-evidence/10-after-resume.png",
+ "pixelStats": {
+ "width": 1500,
+ "height": 1050,
+ "averageLuminance": 129.2,
+ "nonBlackRatio": 0.7794
+ },
+ "buttons": {
+ "RUN": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "STOP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "PAUSE": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "RESUME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "resume blocked: interpreter is not paused"
+ },
+ "STEP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "HOME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "home blocked: switch to manual mode first"
+ }
+ },
+ "canvasDataset": {
+ "fiveAxisCanvas": "true",
+ "engine": "three.js r183",
+ "threeReady": "true",
+ "threeRevision": "183",
+ "threePathPoints": "6",
+ "threeExecutedPathPoints": "1",
+ "threeSceneObjects": "20",
+ "threeToolhead": "{\"x\":0.003,\"y\":0,\"z\":0}",
+ "threeSceneUnits": "m",
+ "threeLinearUnits": "mm",
+ "threeLinearUnitScaleToMeters": "0.001",
+ "threeToolAxis": "{\"x\":0,\"y\":0,\"z\":1}",
+ "threeTcpPose": "{\"x\":2.518,\"y\":0,\"z\":0,\"a\":0,\"c\":0}",
+ "threeRtcpState": "off",
+ "threeSelectedView": "iso",
+ "threeFrameApi": "web-rtcp-5axis-motion-frame",
+ "threeRenderer": "webgl",
+ "threeSceneMode": "program-preview-and-tool-execution",
+ "threePreviewScope": "machine-reference-and-toolpath",
+ "threeMachineReferenceModel": "webgl-five-axis-reference",
+ "threeCameraControls": "orbit-pan-zoom",
+ "threeProgramPreviewSource": "linuxcnc-interpreter-wasm",
+ "threeToolExecutionMarker": "true",
+ "threeTcpMarker": "sphere",
+ "threeToolAxisMarker": "line",
+ "threeToolpathPreviewSource": "linuxcnc_interpreter_canonical_motion",
+ "threeToolExecutionTraceSource": "linuxcnc_tp_samples_or_task_motion_hal_feedback",
+ "threePathFitBounds": "ok",
+ "threePathBoundsMeters": "{\"center\":{\"x\":0.01,\"y\":0.01,\"z\":0.002},\"size\":{\"x\":0.02,\"y\":0.02,\"z\":0.005},\"maxSpan\":0.02}",
+ "threeCurrentSegmentHighlight": "ok",
+ "threeRapidFeedVisualDistinction": "ok",
+ "threeNoGcodeSemanticsGeneration": "ok",
+ "threeRapidPathPoints": "2",
+ "threeFeedPathPoints": "4",
+ "threeArcPathPoints": "0",
+ "threeCurrentSegmentPoints": "2",
+ "threeCurrentSegmentType": "STRAIGHT_FEED"
+ },
+ "state": {
+ "activeProgram": "button-control-evidence.ngc",
+ "runState": "running",
+ "activeLine": 3,
+ "machine": {
+ "powerOn": true,
+ "taskState": "on",
+ "mode": "auto",
+ "allHomed": true,
+ "interpState": "reading",
+ "taskPaused": false
+ },
+ "axisPose": {
+ "x": 2.41807,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "dro": {
+ "x": 2.41807,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "programRuntimeFeedback": {
+ "sourceMode": "linuxcnc-task-motion-hal-wasm",
+ "line": 3,
+ "taskCycle": 128,
+ "currentVelocityMmPerMin": 120,
+ "axisPose": {
+ "x": 2.41807,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ }
+ },
+ "taskHalStatus": {
+ "task": {
+ "mode": "AUTO",
+ "interpState": "READING",
+ "taskPaused": false,
+ "singleStepping": false
+ },
+ "ui": {
+ "activeLine": 3,
+ "taskCycle": 0,
+ "servoCycle": 1280
+ },
+ "motionStatus": {
+ "motion": {
+ "paused": false,
+ "aborted": false
+ }
+ }
+ },
+ "taskHalStatusLoop": {
+ "apiName": "web-rtcp-5axis-task-hal-status-loop",
+ "active": true,
+ "sequence": 2,
+ "profileId": "xyzac-trt",
+ "iniPath": "configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
+ "kinematicsModuleId": "xyzac-trt",
+ "tickCount": 7,
+ "batchSize": 5,
+ "intervalMs": 25,
+ "taskPeriodNs": 10000000,
+ "servoPeriodNs": 1000000,
+ "lastStatusAt": "2026-06-23T09:15:34.728Z",
+ "lastError": null,
+ "stopReason": null,
+ "semanticBoundary": "js_status_polling_loop_for_linuxcnc_task_hal_motion_status"
+ },
+ "operatorMessage": "task/HAL status tick 7"
+ }
+ },
+ {
+ "name": "11-before-step",
+ "title": "Before STEP",
+ "description": "Program is paused before STEP.",
+ "screenshotPath": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/screenshots/button-control-evidence/11-before-step.png",
+ "pixelStats": {
+ "width": 1500,
+ "height": 1050,
+ "averageLuminance": 129.22,
+ "nonBlackRatio": 0.7795
+ },
+ "buttons": {
+ "RUN": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "run blocked: resume paused program first"
+ },
+ "STOP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "PAUSE": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "RESUME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "STEP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "HOME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "home blocked: switch to manual mode first"
+ }
+ },
+ "canvasDataset": {
+ "fiveAxisCanvas": "true",
+ "engine": "three.js r183",
+ "threeReady": "true",
+ "threeRevision": "183",
+ "threePathPoints": "6",
+ "threeExecutedPathPoints": "1",
+ "threeSceneObjects": "20",
+ "threeToolhead": "{\"x\":0.003,\"y\":0,\"z\":0}",
+ "threeSceneUnits": "m",
+ "threeLinearUnits": "mm",
+ "threeLinearUnitScaleToMeters": "0.001",
+ "threeToolAxis": "{\"x\":0,\"y\":0,\"z\":1}",
+ "threeTcpPose": "{\"x\":2.618,\"y\":0,\"z\":0,\"a\":0,\"c\":0}",
+ "threeRtcpState": "off",
+ "threeSelectedView": "iso",
+ "threeFrameApi": "web-rtcp-5axis-motion-frame",
+ "threeRenderer": "webgl",
+ "threeSceneMode": "program-preview-and-tool-execution",
+ "threePreviewScope": "machine-reference-and-toolpath",
+ "threeMachineReferenceModel": "webgl-five-axis-reference",
+ "threeCameraControls": "orbit-pan-zoom",
+ "threeProgramPreviewSource": "linuxcnc-interpreter-wasm",
+ "threeToolExecutionMarker": "true",
+ "threeTcpMarker": "sphere",
+ "threeToolAxisMarker": "line",
+ "threeToolpathPreviewSource": "linuxcnc_interpreter_canonical_motion",
+ "threeToolExecutionTraceSource": "linuxcnc_tp_samples_or_task_motion_hal_feedback",
+ "threePathFitBounds": "ok",
+ "threePathBoundsMeters": "{\"center\":{\"x\":0.01,\"y\":0.01,\"z\":0.002},\"size\":{\"x\":0.02,\"y\":0.02,\"z\":0.005},\"maxSpan\":0.02}",
+ "threeCurrentSegmentHighlight": "ok",
+ "threeRapidFeedVisualDistinction": "ok",
+ "threeNoGcodeSemanticsGeneration": "ok",
+ "threeRapidPathPoints": "2",
+ "threeFeedPathPoints": "4",
+ "threeArcPathPoints": "0",
+ "threeCurrentSegmentPoints": "2",
+ "threeCurrentSegmentType": "STRAIGHT_FEED"
+ },
+ "state": {
+ "activeProgram": "button-control-evidence.ngc",
+ "runState": "paused",
+ "activeLine": 3,
+ "machine": {
+ "powerOn": true,
+ "taskState": "on",
+ "mode": "auto",
+ "allHomed": true,
+ "interpState": "paused",
+ "taskPaused": true
+ },
+ "axisPose": {
+ "x": 2.61791,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "dro": {
+ "x": 2.61791,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "programRuntimeFeedback": {
+ "sourceMode": "linuxcnc-task-motion-hal-wasm",
+ "line": 3,
+ "taskCycle": 139,
+ "currentVelocityMmPerMin": 120,
+ "axisPose": {
+ "x": 2.61791,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ }
+ },
+ "taskHalStatus": {
+ "task": {
+ "mode": "AUTO",
+ "interpState": "PAUSED",
+ "taskPaused": true,
+ "singleStepping": false
+ },
+ "ui": {
+ "activeLine": 3,
+ "taskCycle": 0,
+ "servoCycle": 1390
+ },
+ "motionStatus": {
+ "motion": {
+ "paused": true,
+ "aborted": false
+ }
+ }
+ },
+ "taskHalStatusLoop": {
+ "apiName": "web-rtcp-5axis-task-hal-status-loop",
+ "active": false,
+ "sequence": 2,
+ "profileId": "xyzac-trt",
+ "iniPath": "configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
+ "kinematicsModuleId": "xyzac-trt",
+ "tickCount": 9,
+ "batchSize": 5,
+ "intervalMs": 25,
+ "taskPeriodNs": 10000000,
+ "servoPeriodNs": 1000000,
+ "lastStatusAt": "2026-06-23T09:15:35.030Z",
+ "lastError": null,
+ "stopReason": "paused",
+ "semanticBoundary": "js_status_polling_loop_for_linuxcnc_task_hal_motion_status"
+ },
+ "operatorMessage": "task/HAL program paused"
+ }
+ },
+ {
+ "name": "12-after-step",
+ "title": "After STEP",
+ "description": "STEP sends EMC_TASK_PLAN_STEP and leaves task paused with singleStepping true.",
+ "screenshotPath": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/screenshots/button-control-evidence/12-after-step.png",
+ "pixelStats": {
+ "width": 1500,
+ "height": 1050,
+ "averageLuminance": 129.23,
+ "nonBlackRatio": 0.7795
+ },
+ "buttons": {
+ "RUN": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "run blocked: resume paused program first"
+ },
+ "STOP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "PAUSE": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "RESUME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "STEP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "HOME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "home blocked: switch to manual mode first"
+ }
+ },
+ "canvasDataset": {
+ "fiveAxisCanvas": "true",
+ "engine": "three.js r183",
+ "threeReady": "true",
+ "threeRevision": "183",
+ "threePathPoints": "6",
+ "threeExecutedPathPoints": "1",
+ "threeSceneObjects": "20",
+ "threeToolhead": "{\"x\":0.003,\"y\":0,\"z\":0}",
+ "threeSceneUnits": "m",
+ "threeLinearUnits": "mm",
+ "threeLinearUnitScaleToMeters": "0.001",
+ "threeToolAxis": "{\"x\":0,\"y\":0,\"z\":1}",
+ "threeTcpPose": "{\"x\":2.638,\"y\":0,\"z\":0,\"a\":0,\"c\":0}",
+ "threeRtcpState": "off",
+ "threeSelectedView": "iso",
+ "threeFrameApi": "web-rtcp-5axis-motion-frame",
+ "threeRenderer": "webgl",
+ "threeSceneMode": "program-preview-and-tool-execution",
+ "threePreviewScope": "machine-reference-and-toolpath",
+ "threeMachineReferenceModel": "webgl-five-axis-reference",
+ "threeCameraControls": "orbit-pan-zoom",
+ "threeProgramPreviewSource": "linuxcnc-interpreter-wasm",
+ "threeToolExecutionMarker": "true",
+ "threeTcpMarker": "sphere",
+ "threeToolAxisMarker": "line",
+ "threeToolpathPreviewSource": "linuxcnc_interpreter_canonical_motion",
+ "threeToolExecutionTraceSource": "linuxcnc_tp_samples_or_task_motion_hal_feedback",
+ "threePathFitBounds": "ok",
+ "threePathBoundsMeters": "{\"center\":{\"x\":0.01,\"y\":0.01,\"z\":0.002},\"size\":{\"x\":0.02,\"y\":0.02,\"z\":0.005},\"maxSpan\":0.02}",
+ "threeCurrentSegmentHighlight": "ok",
+ "threeRapidFeedVisualDistinction": "ok",
+ "threeNoGcodeSemanticsGeneration": "ok",
+ "threeRapidPathPoints": "2",
+ "threeFeedPathPoints": "4",
+ "threeArcPathPoints": "0",
+ "threeCurrentSegmentPoints": "2",
+ "threeCurrentSegmentType": "STRAIGHT_FEED"
+ },
+ "state": {
+ "activeProgram": "button-control-evidence.ngc",
+ "runState": "paused",
+ "activeLine": 3,
+ "machine": {
+ "powerOn": true,
+ "taskState": "on",
+ "mode": "auto",
+ "allHomed": true,
+ "interpState": "paused",
+ "taskPaused": true
+ },
+ "axisPose": {
+ "x": 2.63789,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "dro": {
+ "x": 2.63789,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "programRuntimeFeedback": {
+ "sourceMode": "linuxcnc-task-motion-hal-wasm",
+ "line": 3,
+ "taskCycle": 140,
+ "currentVelocityMmPerMin": 120,
+ "axisPose": {
+ "x": 2.63789,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ }
+ },
+ "taskHalStatus": {
+ "task": {
+ "mode": "AUTO",
+ "interpState": "PAUSED",
+ "taskPaused": true,
+ "singleStepping": true
+ },
+ "ui": {
+ "activeLine": 3,
+ "taskCycle": 0,
+ "servoCycle": 1400
+ },
+ "motionStatus": {
+ "motion": {
+ "paused": false,
+ "aborted": false
+ }
+ }
+ },
+ "taskHalStatusLoop": {
+ "apiName": "web-rtcp-5axis-task-hal-status-loop",
+ "active": false,
+ "sequence": 2,
+ "profileId": "xyzac-trt",
+ "iniPath": "configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
+ "kinematicsModuleId": "xyzac-trt",
+ "tickCount": 9,
+ "batchSize": 5,
+ "intervalMs": 25,
+ "taskPeriodNs": 10000000,
+ "servoPeriodNs": 1000000,
+ "lastStatusAt": "2026-06-23T09:15:35.030Z",
+ "lastError": null,
+ "stopReason": "step",
+ "semanticBoundary": "js_status_polling_loop_for_linuxcnc_task_hal_motion_status"
+ },
+ "operatorMessage": "task/HAL stepped one cycle"
+ }
+ },
+ {
+ "name": "13-before-stop",
+ "title": "Before STOP",
+ "description": "Paused single-step state before STOP.",
+ "screenshotPath": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/screenshots/button-control-evidence/13-before-stop.png",
+ "pixelStats": {
+ "width": 1500,
+ "height": 1050,
+ "averageLuminance": 129.23,
+ "nonBlackRatio": 0.7795
+ },
+ "buttons": {
+ "RUN": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "run blocked: resume paused program first"
+ },
+ "STOP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "PAUSE": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "RESUME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "STEP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "HOME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "home blocked: switch to manual mode first"
+ }
+ },
+ "canvasDataset": {
+ "fiveAxisCanvas": "true",
+ "engine": "three.js r183",
+ "threeReady": "true",
+ "threeRevision": "183",
+ "threePathPoints": "6",
+ "threeExecutedPathPoints": "1",
+ "threeSceneObjects": "20",
+ "threeToolhead": "{\"x\":0.003,\"y\":0,\"z\":0}",
+ "threeSceneUnits": "m",
+ "threeLinearUnits": "mm",
+ "threeLinearUnitScaleToMeters": "0.001",
+ "threeToolAxis": "{\"x\":0,\"y\":0,\"z\":1}",
+ "threeTcpPose": "{\"x\":2.638,\"y\":0,\"z\":0,\"a\":0,\"c\":0}",
+ "threeRtcpState": "off",
+ "threeSelectedView": "iso",
+ "threeFrameApi": "web-rtcp-5axis-motion-frame",
+ "threeRenderer": "webgl",
+ "threeSceneMode": "program-preview-and-tool-execution",
+ "threePreviewScope": "machine-reference-and-toolpath",
+ "threeMachineReferenceModel": "webgl-five-axis-reference",
+ "threeCameraControls": "orbit-pan-zoom",
+ "threeProgramPreviewSource": "linuxcnc-interpreter-wasm",
+ "threeToolExecutionMarker": "true",
+ "threeTcpMarker": "sphere",
+ "threeToolAxisMarker": "line",
+ "threeToolpathPreviewSource": "linuxcnc_interpreter_canonical_motion",
+ "threeToolExecutionTraceSource": "linuxcnc_tp_samples_or_task_motion_hal_feedback",
+ "threePathFitBounds": "ok",
+ "threePathBoundsMeters": "{\"center\":{\"x\":0.01,\"y\":0.01,\"z\":0.002},\"size\":{\"x\":0.02,\"y\":0.02,\"z\":0.005},\"maxSpan\":0.02}",
+ "threeCurrentSegmentHighlight": "ok",
+ "threeRapidFeedVisualDistinction": "ok",
+ "threeNoGcodeSemanticsGeneration": "ok",
+ "threeRapidPathPoints": "2",
+ "threeFeedPathPoints": "4",
+ "threeArcPathPoints": "0",
+ "threeCurrentSegmentPoints": "2",
+ "threeCurrentSegmentType": "STRAIGHT_FEED"
+ },
+ "state": {
+ "activeProgram": "button-control-evidence.ngc",
+ "runState": "paused",
+ "activeLine": 3,
+ "machine": {
+ "powerOn": true,
+ "taskState": "on",
+ "mode": "auto",
+ "allHomed": true,
+ "interpState": "paused",
+ "taskPaused": true
+ },
+ "axisPose": {
+ "x": 2.63789,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "dro": {
+ "x": 2.63789,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "programRuntimeFeedback": {
+ "sourceMode": "linuxcnc-task-motion-hal-wasm",
+ "line": 3,
+ "taskCycle": 140,
+ "currentVelocityMmPerMin": 120,
+ "axisPose": {
+ "x": 2.63789,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ }
+ },
+ "taskHalStatus": {
+ "task": {
+ "mode": "AUTO",
+ "interpState": "PAUSED",
+ "taskPaused": true,
+ "singleStepping": true
+ },
+ "ui": {
+ "activeLine": 3,
+ "taskCycle": 0,
+ "servoCycle": 1400
+ },
+ "motionStatus": {
+ "motion": {
+ "paused": false,
+ "aborted": false
+ }
+ }
+ },
+ "taskHalStatusLoop": {
+ "apiName": "web-rtcp-5axis-task-hal-status-loop",
+ "active": false,
+ "sequence": 2,
+ "profileId": "xyzac-trt",
+ "iniPath": "configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
+ "kinematicsModuleId": "xyzac-trt",
+ "tickCount": 9,
+ "batchSize": 5,
+ "intervalMs": 25,
+ "taskPeriodNs": 10000000,
+ "servoPeriodNs": 1000000,
+ "lastStatusAt": "2026-06-23T09:15:35.030Z",
+ "lastError": null,
+ "stopReason": "step",
+ "semanticBoundary": "js_status_polling_loop_for_linuxcnc_task_hal_motion_status"
+ },
+ "operatorMessage": "task/HAL stepped one cycle"
+ }
+ },
+ {
+ "name": "14-after-stop",
+ "title": "After STOP",
+ "description": "STOP aborts task/HAL motion and returns interpreter state to idle.",
+ "screenshotPath": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/screenshots/button-control-evidence/14-after-stop.png",
+ "pixelStats": {
+ "width": 1500,
+ "height": 1050,
+ "averageLuminance": 129.22,
+ "nonBlackRatio": 0.7795
+ },
+ "buttons": {
+ "RUN": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "STOP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "PAUSE": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "RESUME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "resume blocked: interpreter is not paused"
+ },
+ "STEP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "HOME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "home blocked: switch to manual mode first"
+ }
+ },
+ "canvasDataset": {
+ "fiveAxisCanvas": "true",
+ "engine": "three.js r183",
+ "threeReady": "true",
+ "threeRevision": "183",
+ "threePathPoints": "6",
+ "threeExecutedPathPoints": "1",
+ "threeSceneObjects": "20",
+ "threeToolhead": "{\"x\":0.003,\"y\":0,\"z\":0}",
+ "threeSceneUnits": "m",
+ "threeLinearUnits": "mm",
+ "threeLinearUnitScaleToMeters": "0.001",
+ "threeToolAxis": "{\"x\":0,\"y\":0,\"z\":1}",
+ "threeTcpPose": "{\"x\":2.638,\"y\":0,\"z\":0,\"a\":0,\"c\":0}",
+ "threeRtcpState": "off",
+ "threeSelectedView": "iso",
+ "threeFrameApi": "web-rtcp-5axis-motion-frame",
+ "threeRenderer": "webgl",
+ "threeSceneMode": "program-preview-and-tool-execution",
+ "threePreviewScope": "machine-reference-and-toolpath",
+ "threeMachineReferenceModel": "webgl-five-axis-reference",
+ "threeCameraControls": "orbit-pan-zoom",
+ "threeProgramPreviewSource": "linuxcnc-interpreter-wasm",
+ "threeToolExecutionMarker": "true",
+ "threeTcpMarker": "sphere",
+ "threeToolAxisMarker": "line",
+ "threeToolpathPreviewSource": "linuxcnc_interpreter_canonical_motion",
+ "threeToolExecutionTraceSource": "linuxcnc_tp_samples_or_task_motion_hal_feedback",
+ "threePathFitBounds": "ok",
+ "threePathBoundsMeters": "{\"center\":{\"x\":0.01,\"y\":0.01,\"z\":0.002},\"size\":{\"x\":0.02,\"y\":0.02,\"z\":0.005},\"maxSpan\":0.02}",
+ "threeCurrentSegmentHighlight": "ok",
+ "threeRapidFeedVisualDistinction": "ok",
+ "threeNoGcodeSemanticsGeneration": "ok",
+ "threeRapidPathPoints": "2",
+ "threeFeedPathPoints": "4",
+ "threeArcPathPoints": "0",
+ "threeCurrentSegmentPoints": "2",
+ "threeCurrentSegmentType": "STRAIGHT_FEED"
+ },
+ "state": {
+ "activeProgram": "button-control-evidence.ngc",
+ "runState": "stopped",
+ "activeLine": 3,
+ "machine": {
+ "powerOn": true,
+ "taskState": "on",
+ "mode": "auto",
+ "allHomed": true,
+ "interpState": "idle",
+ "taskPaused": false
+ },
+ "axisPose": {
+ "x": 2.63789,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "dro": {
+ "x": 2.63789,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "programRuntimeFeedback": {
+ "sourceMode": "linuxcnc-task-motion-hal-wasm",
+ "line": 3,
+ "taskCycle": 141,
+ "currentVelocityMmPerMin": 120,
+ "axisPose": {
+ "x": 2.63789,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ }
+ },
+ "taskHalStatus": {
+ "task": {
+ "mode": "AUTO",
+ "interpState": "IDLE",
+ "taskPaused": false,
+ "singleStepping": false
+ },
+ "ui": {
+ "activeLine": 3,
+ "taskCycle": 0,
+ "servoCycle": 1410
+ },
+ "motionStatus": {
+ "motion": {
+ "paused": false,
+ "aborted": true
+ }
+ }
+ },
+ "taskHalStatusLoop": {
+ "apiName": "web-rtcp-5axis-task-hal-status-loop",
+ "active": false,
+ "sequence": 2,
+ "profileId": "xyzac-trt",
+ "iniPath": "configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
+ "kinematicsModuleId": "xyzac-trt",
+ "tickCount": 9,
+ "batchSize": 5,
+ "intervalMs": 25,
+ "taskPeriodNs": 10000000,
+ "servoPeriodNs": 1000000,
+ "lastStatusAt": "2026-06-23T09:15:35.030Z",
+ "lastError": null,
+ "stopReason": "stopped",
+ "semanticBoundary": "js_status_polling_loop_for_linuxcnc_task_hal_motion_status"
+ },
+ "operatorMessage": "task/HAL program stopped"
+ }
+ }
+ ],
+ "checks": [
+ {
+ "name": "HOME keeps all axes homed",
+ "pass": true,
+ "detail": "{\"powerOn\":true,\"taskState\":\"on\",\"mode\":\"manual\",\"allHomed\":true,\"interpState\":\"idle\",\"taskPaused\":false}"
+ },
+ {
+ "name": "RUN uses task/HAL runtime feedback",
+ "pass": true,
+ "detail": "{\"sourceMode\":\"linuxcnc-task-motion-hal-wasm\",\"line\":3,\"taskCycle\":56,\"currentVelocityMmPerMin\":120,\"axisPose\":{\"x\":0.999201,\"y\":0,\"z\":0,\"a\":0,\"b\":0,\"c\":0}}"
+ },
+ {
+ "name": "PAUSE sets paused state",
+ "pass": true,
+ "detail": "{\"powerOn\":true,\"taskState\":\"on\",\"mode\":\"auto\",\"allHomed\":true,\"interpState\":\"paused\",\"taskPaused\":true}"
+ },
+ {
+ "name": "RESUME returns to reading",
+ "pass": true,
+ "detail": "{\"powerOn\":true,\"taskState\":\"on\",\"mode\":\"auto\",\"allHomed\":true,\"interpState\":\"reading\",\"taskPaused\":false}"
+ },
+ {
+ "name": "STEP records single stepping",
+ "pass": true,
+ "detail": "{\"mode\":\"AUTO\",\"interpState\":\"PAUSED\",\"taskPaused\":true,\"singleStepping\":true}"
+ },
+ {
+ "name": "STOP aborts motion",
+ "pass": true,
+ "detail": "{\"paused\":false,\"aborted\":true}"
+ },
+ {
+ "name": "Screenshots are nonblank",
+ "pass": true,
+ "detail": "01-initial:0.7826, 02-program-loaded:0.7795, 03-before-home:0.7794, 04-after-home:0.7794, 05-ready-for-run:0.7794, 06-after-run:0.7795, 07-before-pause:0.7795, 08-after-pause:0.7795, 09-before-resume:0.7795, 10-after-resume:0.7794, 11-before-step:0.7795, 12-after-step:0.7795, 13-before-stop:0.7795, 14-after-stop:0.7795"
+ },
+ {
+ "name": "Control buttons expose readiness attributes",
+ "pass": true,
+ "detail": "RUN/STOP/PAUSE/RESUME/STEP/HOME"
+ }
+ ],
+ "consoleErrors": [
+ "Failed to load resource: the server responded with a status of 404 (Not Found)",
+ "Failed to load resource: the server responded with a status of 404 (Not Found)"
+ ],
+ "pageErrors": [],
+ "status": "PASS",
+ "jsonPath": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/output/button-control-evidence-report.json",
+ "pdfPath": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/output/button-control-evidence-report.pdf"
+}
diff --git a/qa/web-rtcp-5axis-site-test/output/button-control-evidence-report.pdf b/qa/web-rtcp-5axis-site-test/output/button-control-evidence-report.pdf
new file mode 100644
index 0000000..632206f
Binary files /dev/null and b/qa/web-rtcp-5axis-site-test/output/button-control-evidence-report.pdf differ
diff --git a/qa/web-rtcp-5axis-site-test/output/cloud-button-control-evidence-report.json b/qa/web-rtcp-5axis-site-test/output/cloud-button-control-evidence-report.json
new file mode 100644
index 0000000..cd235dd
--- /dev/null
+++ b/qa/web-rtcp-5axis-site-test/output/cloud-button-control-evidence-report.json
@@ -0,0 +1,2488 @@
+{
+ "jobId": "btn-20260623091811-c291e49b",
+ "reportId": "report-btn-20260623091811-c291e49b",
+ "evidenceScope": "cloud-button-control-evidence",
+ "generatedAt": "2026-06-23T09:18:11.686Z",
+ "targetUrl": "https://82.156.24.101:8092/",
+ "chromePath": "/usr/bin/google-chrome",
+ "screenshotsDir": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/screenshots/cloud-button-control-evidence",
+ "steps": [
+ {
+ "name": "01-initial",
+ "title": "Initial UI",
+ "description": "Browser app loaded before machine preparation.",
+ "screenshotPath": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/screenshots/cloud-button-control-evidence/01-initial.png",
+ "pixelStats": {
+ "width": 1500,
+ "height": 1050,
+ "averageLuminance": 132.08,
+ "nonBlackRatio": 0.7826
+ },
+ "buttons": {
+ "RUN": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "run blocked: machine must be on"
+ },
+ "STOP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "PAUSE": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "pause blocked: machine must be on"
+ },
+ "RESUME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "resume blocked: machine must be on"
+ },
+ "STEP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "step blocked: machine must be on"
+ },
+ "HOME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "home blocked: machine must be on"
+ }
+ },
+ "canvasDataset": {
+ "fiveAxisCanvas": "true",
+ "engine": "three.js r183",
+ "threeReady": "true",
+ "threeRevision": "183",
+ "threePathPoints": "2",
+ "threeExecutedPathPoints": "1",
+ "threeSceneObjects": "20",
+ "threeToolhead": "{\"x\":0,\"y\":0,\"z\":0}",
+ "threeSceneUnits": "m",
+ "threeLinearUnits": "mm",
+ "threeLinearUnitScaleToMeters": "0.001",
+ "threeToolAxis": "{\"x\":0,\"y\":0,\"z\":1}",
+ "threeTcpPose": "{\"x\":0,\"y\":0,\"z\":0,\"a\":0,\"c\":0}",
+ "threeRtcpState": "on",
+ "threeSelectedView": "iso",
+ "threeFrameApi": "web-rtcp-5axis-motion-frame",
+ "threeRenderer": "webgl",
+ "threeSceneMode": "program-preview-and-tool-execution",
+ "threePreviewScope": "machine-reference-and-toolpath",
+ "threeMachineReferenceModel": "webgl-five-axis-reference",
+ "threeCameraControls": "orbit-pan-zoom",
+ "threeProgramPreviewSource": "linuxcnc-interpreter-wasm",
+ "threeToolExecutionMarker": "true",
+ "threeTcpMarker": "sphere",
+ "threeToolAxisMarker": "line",
+ "threeToolpathPreviewSource": "linuxcnc_interpreter_canonical_motion",
+ "threeToolExecutionTraceSource": "linuxcnc_tp_samples_or_task_motion_hal_feedback",
+ "threePathFitBounds": "ok",
+ "threePathBoundsMeters": "{\"center\":{\"x\":0,\"y\":0,\"z\":0.002},\"size\":{\"x\":0,\"y\":0,\"z\":0.005},\"maxSpan\":0.005}",
+ "threeCurrentSegmentHighlight": "ok",
+ "threeRapidFeedVisualDistinction": "ok",
+ "threeNoGcodeSemanticsGeneration": "ok",
+ "threeRapidPathPoints": "2",
+ "threeFeedPathPoints": "0",
+ "threeArcPathPoints": "0",
+ "threeCurrentSegmentPoints": "2",
+ "threeCurrentSegmentType": "STRAIGHT_TRAVERSE"
+ },
+ "state": {
+ "activeProgram": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzac.ngc",
+ "runState": "idle",
+ "activeLine": 9,
+ "machine": {
+ "powerOn": false,
+ "taskState": "estop-reset",
+ "mode": "manual",
+ "allHomed": false,
+ "interpState": "idle",
+ "taskPaused": false
+ },
+ "axisPose": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "dro": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "programRuntimeFeedback": {
+ "sourceMode": "linuxcnc-tp-runtime-sample",
+ "line": 10,
+ "currentVelocityMmPerMin": 30,
+ "axisPose": {
+ "x": 0,
+ "y": 0,
+ "z": 0.00025,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ }
+ },
+ "taskHalStatus": null,
+ "taskHalStatusLoop": {
+ "apiName": "web-rtcp-5axis-task-hal-status-loop",
+ "active": false,
+ "sequence": 0,
+ "profileId": null,
+ "iniPath": null,
+ "kinematicsModuleId": null,
+ "tickCount": 0,
+ "batchSize": 5,
+ "intervalMs": 25,
+ "taskPeriodNs": 10000000,
+ "servoPeriodNs": 1000000,
+ "lastStatusAt": null,
+ "lastError": null,
+ "stopReason": null,
+ "semanticBoundary": "js_status_polling_loop_for_linuxcnc_task_hal_motion_status"
+ },
+ "operatorMessage": "LinuxCNC interpreter motion events 2, switchkins M428/M429"
+ }
+ },
+ {
+ "name": "02-program-loaded",
+ "title": "Program loaded",
+ "description": "Short operator G-code loaded through LinuxCNC interpreter WASM.",
+ "screenshotPath": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/screenshots/cloud-button-control-evidence/02-program-loaded.png",
+ "pixelStats": {
+ "width": 1500,
+ "height": 1050,
+ "averageLuminance": 129.06,
+ "nonBlackRatio": 0.7795
+ },
+ "buttons": {
+ "RUN": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "run blocked: machine must be on"
+ },
+ "STOP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "PAUSE": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "pause blocked: machine must be on"
+ },
+ "RESUME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "resume blocked: machine must be on"
+ },
+ "STEP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "step blocked: machine must be on"
+ },
+ "HOME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "home blocked: machine must be on"
+ }
+ },
+ "canvasDataset": {
+ "fiveAxisCanvas": "true",
+ "engine": "three.js r183",
+ "threeReady": "true",
+ "threeRevision": "183",
+ "threePathPoints": "6",
+ "threeExecutedPathPoints": "1",
+ "threeSceneObjects": "20",
+ "threeToolhead": "{\"x\":0,\"y\":0,\"z\":0}",
+ "threeSceneUnits": "m",
+ "threeLinearUnits": "mm",
+ "threeLinearUnitScaleToMeters": "0.001",
+ "threeToolAxis": "{\"x\":0,\"y\":0,\"z\":1}",
+ "threeTcpPose": "{\"x\":0,\"y\":0,\"z\":0,\"a\":0,\"c\":0}",
+ "threeRtcpState": "on",
+ "threeSelectedView": "iso",
+ "threeFrameApi": "web-rtcp-5axis-motion-frame",
+ "threeRenderer": "webgl",
+ "threeSceneMode": "program-preview-and-tool-execution",
+ "threePreviewScope": "machine-reference-and-toolpath",
+ "threeMachineReferenceModel": "webgl-five-axis-reference",
+ "threeCameraControls": "orbit-pan-zoom",
+ "threeProgramPreviewSource": "linuxcnc-interpreter-wasm",
+ "threeToolExecutionMarker": "true",
+ "threeTcpMarker": "sphere",
+ "threeToolAxisMarker": "line",
+ "threeToolpathPreviewSource": "linuxcnc_interpreter_canonical_motion",
+ "threeToolExecutionTraceSource": "linuxcnc_tp_samples_or_task_motion_hal_feedback",
+ "threePathFitBounds": "ok",
+ "threePathBoundsMeters": "{\"center\":{\"x\":0.01,\"y\":0.01,\"z\":0.002},\"size\":{\"x\":0.02,\"y\":0.02,\"z\":0.005},\"maxSpan\":0.02}",
+ "threeCurrentSegmentHighlight": "ok",
+ "threeRapidFeedVisualDistinction": "ok",
+ "threeNoGcodeSemanticsGeneration": "ok",
+ "threeRapidPathPoints": "2",
+ "threeFeedPathPoints": "4",
+ "threeArcPathPoints": "0",
+ "threeCurrentSegmentPoints": "2",
+ "threeCurrentSegmentType": "STRAIGHT_FEED"
+ },
+ "state": {
+ "activeProgram": "button-control-evidence.ngc",
+ "runState": "idle",
+ "activeLine": 2,
+ "machine": {
+ "powerOn": false,
+ "taskState": "estop-reset",
+ "mode": "auto",
+ "allHomed": false,
+ "interpState": "idle",
+ "taskPaused": false
+ },
+ "axisPose": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "dro": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "programRuntimeFeedback": {
+ "sourceMode": "linuxcnc-tp-runtime-sample",
+ "line": 3,
+ "currentVelocityMmPerMin": 30,
+ "axisPose": {
+ "x": 0.00025,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ }
+ },
+ "taskHalStatus": {
+ "task": {
+ "mode": "MANUAL",
+ "interpState": "IDLE",
+ "taskPaused": false,
+ "singleStepping": false
+ },
+ "ui": {
+ "activeLine": 1,
+ "taskCycle": 0,
+ "servoCycle": 20
+ },
+ "motionStatus": {
+ "motion": {
+ "paused": false,
+ "aborted": false
+ }
+ }
+ },
+ "taskHalStatusLoop": {
+ "apiName": "web-rtcp-5axis-task-hal-status-loop",
+ "active": false,
+ "sequence": 0,
+ "profileId": null,
+ "iniPath": null,
+ "kinematicsModuleId": null,
+ "tickCount": 0,
+ "batchSize": 5,
+ "intervalMs": 25,
+ "taskPeriodNs": 10000000,
+ "servoPeriodNs": 1000000,
+ "lastStatusAt": null,
+ "lastError": null,
+ "stopReason": null,
+ "semanticBoundary": "js_status_polling_loop_for_linuxcnc_task_hal_motion_status"
+ },
+ "operatorMessage": "LinuxCNC interpreter motion events 6"
+ }
+ },
+ {
+ "name": "03-before-home",
+ "title": "Before HOME",
+ "description": "Machine powered on in manual mode before HOME.",
+ "screenshotPath": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/screenshots/cloud-button-control-evidence/03-before-home.png",
+ "pixelStats": {
+ "width": 1500,
+ "height": 1050,
+ "averageLuminance": 129.24,
+ "nonBlackRatio": 0.7794
+ },
+ "buttons": {
+ "RUN": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "run blocked: switch to auto mode first"
+ },
+ "STOP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "PAUSE": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "pause blocked: task mode must be auto or MDI"
+ },
+ "RESUME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "resume blocked: task mode must be auto or MDI"
+ },
+ "STEP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "step blocked: switch to auto mode first"
+ },
+ "HOME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ }
+ },
+ "canvasDataset": {
+ "fiveAxisCanvas": "true",
+ "engine": "three.js r183",
+ "threeReady": "true",
+ "threeRevision": "183",
+ "threePathPoints": "6",
+ "threeExecutedPathPoints": "1",
+ "threeSceneObjects": "20",
+ "threeToolhead": "{\"x\":0,\"y\":0,\"z\":0}",
+ "threeSceneUnits": "m",
+ "threeLinearUnits": "mm",
+ "threeLinearUnitScaleToMeters": "0.001",
+ "threeToolAxis": "{\"x\":0,\"y\":0,\"z\":1}",
+ "threeTcpPose": "{\"x\":0,\"y\":0,\"z\":0,\"a\":0,\"c\":0}",
+ "threeRtcpState": "off",
+ "threeSelectedView": "iso",
+ "threeFrameApi": "web-rtcp-5axis-motion-frame",
+ "threeRenderer": "webgl",
+ "threeSceneMode": "program-preview-and-tool-execution",
+ "threePreviewScope": "machine-reference-and-toolpath",
+ "threeMachineReferenceModel": "webgl-five-axis-reference",
+ "threeCameraControls": "orbit-pan-zoom",
+ "threeProgramPreviewSource": "linuxcnc-interpreter-wasm",
+ "threeToolExecutionMarker": "true",
+ "threeTcpMarker": "sphere",
+ "threeToolAxisMarker": "line",
+ "threeToolpathPreviewSource": "linuxcnc_interpreter_canonical_motion",
+ "threeToolExecutionTraceSource": "linuxcnc_tp_samples_or_task_motion_hal_feedback",
+ "threePathFitBounds": "ok",
+ "threePathBoundsMeters": "{\"center\":{\"x\":0.01,\"y\":0.01,\"z\":0.002},\"size\":{\"x\":0.02,\"y\":0.02,\"z\":0.005},\"maxSpan\":0.02}",
+ "threeCurrentSegmentHighlight": "ok",
+ "threeRapidFeedVisualDistinction": "ok",
+ "threeNoGcodeSemanticsGeneration": "ok",
+ "threeRapidPathPoints": "2",
+ "threeFeedPathPoints": "4",
+ "threeArcPathPoints": "0",
+ "threeCurrentSegmentPoints": "2",
+ "threeCurrentSegmentType": "STRAIGHT_FEED"
+ },
+ "state": {
+ "activeProgram": "button-control-evidence.ngc",
+ "runState": "idle",
+ "activeLine": 1,
+ "machine": {
+ "powerOn": true,
+ "taskState": "on",
+ "mode": "manual",
+ "allHomed": false,
+ "interpState": "idle",
+ "taskPaused": false
+ },
+ "axisPose": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "dro": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "programRuntimeFeedback": {
+ "sourceMode": "linuxcnc-task-motion-hal-wasm",
+ "line": 1,
+ "taskCycle": 4,
+ "currentVelocityMmPerMin": 0,
+ "axisPose": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ }
+ },
+ "taskHalStatus": {
+ "task": {
+ "mode": "MANUAL",
+ "interpState": "IDLE",
+ "taskPaused": false,
+ "singleStepping": false
+ },
+ "ui": {
+ "activeLine": 1,
+ "taskCycle": 0,
+ "servoCycle": 40
+ },
+ "motionStatus": {
+ "motion": {
+ "paused": false,
+ "aborted": false
+ }
+ }
+ },
+ "taskHalStatusLoop": {
+ "apiName": "web-rtcp-5axis-task-hal-status-loop",
+ "active": false,
+ "sequence": 0,
+ "profileId": null,
+ "iniPath": null,
+ "kinematicsModuleId": null,
+ "tickCount": 0,
+ "batchSize": 5,
+ "intervalMs": 25,
+ "taskPeriodNs": 10000000,
+ "servoPeriodNs": 1000000,
+ "lastStatusAt": null,
+ "lastError": null,
+ "stopReason": null,
+ "semanticBoundary": "js_status_polling_loop_for_linuxcnc_task_hal_motion_status"
+ },
+ "operatorMessage": "task/HAL mode manual"
+ }
+ },
+ {
+ "name": "04-after-home",
+ "title": "After HOME",
+ "description": "HOME command preserves allHomed state in Web/task gate.",
+ "screenshotPath": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/screenshots/cloud-button-control-evidence/04-after-home.png",
+ "pixelStats": {
+ "width": 1500,
+ "height": 1050,
+ "averageLuminance": 129.22,
+ "nonBlackRatio": 0.7794
+ },
+ "buttons": {
+ "RUN": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "run blocked: switch to auto mode first"
+ },
+ "STOP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "PAUSE": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "pause blocked: task mode must be auto or MDI"
+ },
+ "RESUME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "resume blocked: task mode must be auto or MDI"
+ },
+ "STEP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "step blocked: switch to auto mode first"
+ },
+ "HOME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ }
+ },
+ "canvasDataset": {
+ "fiveAxisCanvas": "true",
+ "engine": "three.js r183",
+ "threeReady": "true",
+ "threeRevision": "183",
+ "threePathPoints": "6",
+ "threeExecutedPathPoints": "1",
+ "threeSceneObjects": "20",
+ "threeToolhead": "{\"x\":0,\"y\":0,\"z\":0}",
+ "threeSceneUnits": "m",
+ "threeLinearUnits": "mm",
+ "threeLinearUnitScaleToMeters": "0.001",
+ "threeToolAxis": "{\"x\":0,\"y\":0,\"z\":1}",
+ "threeTcpPose": "{\"x\":0,\"y\":0,\"z\":0,\"a\":0,\"c\":0}",
+ "threeRtcpState": "off",
+ "threeSelectedView": "iso",
+ "threeFrameApi": "web-rtcp-5axis-motion-frame",
+ "threeRenderer": "webgl",
+ "threeSceneMode": "program-preview-and-tool-execution",
+ "threePreviewScope": "machine-reference-and-toolpath",
+ "threeMachineReferenceModel": "webgl-five-axis-reference",
+ "threeCameraControls": "orbit-pan-zoom",
+ "threeProgramPreviewSource": "linuxcnc-interpreter-wasm",
+ "threeToolExecutionMarker": "true",
+ "threeTcpMarker": "sphere",
+ "threeToolAxisMarker": "line",
+ "threeToolpathPreviewSource": "linuxcnc_interpreter_canonical_motion",
+ "threeToolExecutionTraceSource": "linuxcnc_tp_samples_or_task_motion_hal_feedback",
+ "threePathFitBounds": "ok",
+ "threePathBoundsMeters": "{\"center\":{\"x\":0.01,\"y\":0.01,\"z\":0.002},\"size\":{\"x\":0.02,\"y\":0.02,\"z\":0.005},\"maxSpan\":0.02}",
+ "threeCurrentSegmentHighlight": "ok",
+ "threeRapidFeedVisualDistinction": "ok",
+ "threeNoGcodeSemanticsGeneration": "ok",
+ "threeRapidPathPoints": "2",
+ "threeFeedPathPoints": "4",
+ "threeArcPathPoints": "0",
+ "threeCurrentSegmentPoints": "2",
+ "threeCurrentSegmentType": "STRAIGHT_FEED"
+ },
+ "state": {
+ "activeProgram": "button-control-evidence.ngc",
+ "runState": "idle",
+ "activeLine": 1,
+ "machine": {
+ "powerOn": true,
+ "taskState": "on",
+ "mode": "manual",
+ "allHomed": true,
+ "interpState": "idle",
+ "taskPaused": false
+ },
+ "axisPose": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "dro": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "programRuntimeFeedback": {
+ "sourceMode": "linuxcnc-task-motion-hal-wasm",
+ "line": 1,
+ "taskCycle": 5,
+ "currentVelocityMmPerMin": 3600,
+ "axisPose": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ }
+ },
+ "taskHalStatus": {
+ "task": {
+ "mode": "MANUAL",
+ "interpState": "IDLE",
+ "taskPaused": false,
+ "singleStepping": false
+ },
+ "ui": {
+ "activeLine": 1,
+ "taskCycle": 0,
+ "servoCycle": 50
+ },
+ "motionStatus": {
+ "motion": {
+ "paused": false,
+ "aborted": false
+ }
+ }
+ },
+ "taskHalStatusLoop": {
+ "apiName": "web-rtcp-5axis-task-hal-status-loop",
+ "active": false,
+ "sequence": 0,
+ "profileId": null,
+ "iniPath": null,
+ "kinematicsModuleId": null,
+ "tickCount": 0,
+ "batchSize": 5,
+ "intervalMs": 25,
+ "taskPeriodNs": 10000000,
+ "servoPeriodNs": 1000000,
+ "lastStatusAt": null,
+ "lastError": null,
+ "stopReason": null,
+ "semanticBoundary": "js_status_polling_loop_for_linuxcnc_task_hal_motion_status"
+ },
+ "operatorMessage": "task/HAL machine homed"
+ }
+ },
+ {
+ "name": "05-ready-for-run",
+ "title": "Ready for RUN",
+ "description": "POWER, HOME, AUTO, and loaded G-code are ready before RUN.",
+ "screenshotPath": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/screenshots/cloud-button-control-evidence/05-ready-for-run.png",
+ "pixelStats": {
+ "width": 1500,
+ "height": 1050,
+ "averageLuminance": 129.23,
+ "nonBlackRatio": 0.7794
+ },
+ "buttons": {
+ "RUN": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "STOP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "PAUSE": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "RESUME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "resume blocked: interpreter is not paused"
+ },
+ "STEP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "HOME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "home blocked: switch to manual mode first"
+ }
+ },
+ "canvasDataset": {
+ "fiveAxisCanvas": "true",
+ "engine": "three.js r183",
+ "threeReady": "true",
+ "threeRevision": "183",
+ "threePathPoints": "6",
+ "threeExecutedPathPoints": "1",
+ "threeSceneObjects": "20",
+ "threeToolhead": "{\"x\":0,\"y\":0,\"z\":0}",
+ "threeSceneUnits": "m",
+ "threeLinearUnits": "mm",
+ "threeLinearUnitScaleToMeters": "0.001",
+ "threeToolAxis": "{\"x\":0,\"y\":0,\"z\":1}",
+ "threeTcpPose": "{\"x\":0,\"y\":0,\"z\":0,\"a\":0,\"c\":0}",
+ "threeRtcpState": "off",
+ "threeSelectedView": "iso",
+ "threeFrameApi": "web-rtcp-5axis-motion-frame",
+ "threeRenderer": "webgl",
+ "threeSceneMode": "program-preview-and-tool-execution",
+ "threePreviewScope": "machine-reference-and-toolpath",
+ "threeMachineReferenceModel": "webgl-five-axis-reference",
+ "threeCameraControls": "orbit-pan-zoom",
+ "threeProgramPreviewSource": "linuxcnc-interpreter-wasm",
+ "threeToolExecutionMarker": "true",
+ "threeTcpMarker": "sphere",
+ "threeToolAxisMarker": "line",
+ "threeToolpathPreviewSource": "linuxcnc_interpreter_canonical_motion",
+ "threeToolExecutionTraceSource": "linuxcnc_tp_samples_or_task_motion_hal_feedback",
+ "threePathFitBounds": "ok",
+ "threePathBoundsMeters": "{\"center\":{\"x\":0.01,\"y\":0.01,\"z\":0.002},\"size\":{\"x\":0.02,\"y\":0.02,\"z\":0.005},\"maxSpan\":0.02}",
+ "threeCurrentSegmentHighlight": "ok",
+ "threeRapidFeedVisualDistinction": "ok",
+ "threeNoGcodeSemanticsGeneration": "ok",
+ "threeRapidPathPoints": "2",
+ "threeFeedPathPoints": "4",
+ "threeArcPathPoints": "0",
+ "threeCurrentSegmentPoints": "2",
+ "threeCurrentSegmentType": "STRAIGHT_FEED"
+ },
+ "state": {
+ "activeProgram": "button-control-evidence.ngc",
+ "runState": "idle",
+ "activeLine": 1,
+ "machine": {
+ "powerOn": true,
+ "taskState": "on",
+ "mode": "auto",
+ "allHomed": true,
+ "interpState": "idle",
+ "taskPaused": false
+ },
+ "axisPose": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "dro": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "programRuntimeFeedback": {
+ "sourceMode": "linuxcnc-task-motion-hal-wasm",
+ "line": 1,
+ "taskCycle": 6,
+ "currentVelocityMmPerMin": 3600,
+ "axisPose": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ }
+ },
+ "taskHalStatus": {
+ "task": {
+ "mode": "AUTO",
+ "interpState": "IDLE",
+ "taskPaused": false,
+ "singleStepping": false
+ },
+ "ui": {
+ "activeLine": 1,
+ "taskCycle": 0,
+ "servoCycle": 60
+ },
+ "motionStatus": {
+ "motion": {
+ "paused": false,
+ "aborted": false
+ }
+ }
+ },
+ "taskHalStatusLoop": {
+ "apiName": "web-rtcp-5axis-task-hal-status-loop",
+ "active": false,
+ "sequence": 0,
+ "profileId": null,
+ "iniPath": null,
+ "kinematicsModuleId": null,
+ "tickCount": 0,
+ "batchSize": 5,
+ "intervalMs": 25,
+ "taskPeriodNs": 10000000,
+ "servoPeriodNs": 1000000,
+ "lastStatusAt": null,
+ "lastError": null,
+ "stopReason": null,
+ "semanticBoundary": "js_status_polling_loop_for_linuxcnc_task_hal_motion_status"
+ },
+ "operatorMessage": "task/HAL mode auto"
+ }
+ },
+ {
+ "name": "06-after-run",
+ "title": "After RUN",
+ "description": "RUN starts task/HAL backed program execution.",
+ "screenshotPath": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/screenshots/cloud-button-control-evidence/06-after-run.png",
+ "pixelStats": {
+ "width": 1500,
+ "height": 1050,
+ "averageLuminance": 129.24,
+ "nonBlackRatio": 0.7796
+ },
+ "buttons": {
+ "RUN": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "STOP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "PAUSE": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "RESUME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "resume blocked: interpreter is not paused"
+ },
+ "STEP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "HOME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "home blocked: switch to manual mode first"
+ }
+ },
+ "canvasDataset": {
+ "fiveAxisCanvas": "true",
+ "engine": "three.js r183",
+ "threeReady": "true",
+ "threeRevision": "183",
+ "threePathPoints": "6",
+ "threeExecutedPathPoints": "1",
+ "threeSceneObjects": "20",
+ "threeToolhead": "{\"x\":0.001,\"y\":0,\"z\":0}",
+ "threeSceneUnits": "m",
+ "threeLinearUnits": "mm",
+ "threeLinearUnitScaleToMeters": "0.001",
+ "threeToolAxis": "{\"x\":0,\"y\":0,\"z\":1}",
+ "threeTcpPose": "{\"x\":1.299,\"y\":0,\"z\":0,\"a\":0,\"c\":0}",
+ "threeRtcpState": "off",
+ "threeSelectedView": "iso",
+ "threeFrameApi": "web-rtcp-5axis-motion-frame",
+ "threeRenderer": "webgl",
+ "threeSceneMode": "program-preview-and-tool-execution",
+ "threePreviewScope": "machine-reference-and-toolpath",
+ "threeMachineReferenceModel": "webgl-five-axis-reference",
+ "threeCameraControls": "orbit-pan-zoom",
+ "threeProgramPreviewSource": "linuxcnc-interpreter-wasm",
+ "threeToolExecutionMarker": "true",
+ "threeTcpMarker": "sphere",
+ "threeToolAxisMarker": "line",
+ "threeToolpathPreviewSource": "linuxcnc_interpreter_canonical_motion",
+ "threeToolExecutionTraceSource": "linuxcnc_tp_samples_or_task_motion_hal_feedback",
+ "threePathFitBounds": "ok",
+ "threePathBoundsMeters": "{\"center\":{\"x\":0.01,\"y\":0.01,\"z\":0.002},\"size\":{\"x\":0.02,\"y\":0.02,\"z\":0.005},\"maxSpan\":0.02}",
+ "threeCurrentSegmentHighlight": "ok",
+ "threeRapidFeedVisualDistinction": "ok",
+ "threeNoGcodeSemanticsGeneration": "ok",
+ "threeRapidPathPoints": "2",
+ "threeFeedPathPoints": "4",
+ "threeArcPathPoints": "0",
+ "threeCurrentSegmentPoints": "2",
+ "threeCurrentSegmentType": "STRAIGHT_FEED"
+ },
+ "state": {
+ "activeProgram": "button-control-evidence.ngc",
+ "runState": "running",
+ "activeLine": 3,
+ "machine": {
+ "powerOn": true,
+ "taskState": "on",
+ "mode": "auto",
+ "allHomed": true,
+ "interpState": "reading",
+ "taskPaused": false
+ },
+ "axisPose": {
+ "x": 1.09912,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "dro": {
+ "x": 1.09912,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "programRuntimeFeedback": {
+ "sourceMode": "linuxcnc-task-motion-hal-wasm",
+ "line": 3,
+ "taskCycle": 61,
+ "currentVelocityMmPerMin": 120,
+ "axisPose": {
+ "x": 1.09912,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ }
+ },
+ "taskHalStatus": {
+ "task": {
+ "mode": "AUTO",
+ "interpState": "READING",
+ "taskPaused": false,
+ "singleStepping": false
+ },
+ "ui": {
+ "activeLine": 3,
+ "taskCycle": 0,
+ "servoCycle": 610
+ },
+ "motionStatus": {
+ "motion": {
+ "paused": false,
+ "aborted": false
+ }
+ }
+ },
+ "taskHalStatusLoop": {
+ "apiName": "web-rtcp-5axis-task-hal-status-loop",
+ "active": true,
+ "sequence": 1,
+ "profileId": "xyzac-trt",
+ "iniPath": "configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
+ "kinematicsModuleId": "xyzac-trt",
+ "tickCount": 10,
+ "batchSize": 5,
+ "intervalMs": 25,
+ "taskPeriodNs": 10000000,
+ "servoPeriodNs": 1000000,
+ "lastStatusAt": "2026-06-23T09:18:26.923Z",
+ "lastError": null,
+ "stopReason": null,
+ "semanticBoundary": "js_status_polling_loop_for_linuxcnc_task_hal_motion_status"
+ },
+ "operatorMessage": "task/HAL status tick 10"
+ }
+ },
+ {
+ "name": "07-before-pause",
+ "title": "Before PAUSE",
+ "description": "Program is running before PAUSE.",
+ "screenshotPath": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/screenshots/cloud-button-control-evidence/07-before-pause.png",
+ "pixelStats": {
+ "width": 1500,
+ "height": 1050,
+ "averageLuminance": 129.22,
+ "nonBlackRatio": 0.7795
+ },
+ "buttons": {
+ "RUN": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "STOP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "PAUSE": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "RESUME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "resume blocked: interpreter is not paused"
+ },
+ "STEP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "HOME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "home blocked: switch to manual mode first"
+ }
+ },
+ "canvasDataset": {
+ "fiveAxisCanvas": "true",
+ "engine": "three.js r183",
+ "threeReady": "true",
+ "threeRevision": "183",
+ "threePathPoints": "6",
+ "threeExecutedPathPoints": "1",
+ "threeSceneObjects": "20",
+ "threeToolhead": "{\"x\":0.002,\"y\":0,\"z\":0}",
+ "threeSceneUnits": "m",
+ "threeLinearUnits": "mm",
+ "threeLinearUnitScaleToMeters": "0.001",
+ "threeToolAxis": "{\"x\":0,\"y\":0,\"z\":1}",
+ "threeTcpPose": "{\"x\":1.799,\"y\":0,\"z\":0,\"a\":0,\"c\":0}",
+ "threeRtcpState": "off",
+ "threeSelectedView": "iso",
+ "threeFrameApi": "web-rtcp-5axis-motion-frame",
+ "threeRenderer": "webgl",
+ "threeSceneMode": "program-preview-and-tool-execution",
+ "threePreviewScope": "machine-reference-and-toolpath",
+ "threeMachineReferenceModel": "webgl-five-axis-reference",
+ "threeCameraControls": "orbit-pan-zoom",
+ "threeProgramPreviewSource": "linuxcnc-interpreter-wasm",
+ "threeToolExecutionMarker": "true",
+ "threeTcpMarker": "sphere",
+ "threeToolAxisMarker": "line",
+ "threeToolpathPreviewSource": "linuxcnc_interpreter_canonical_motion",
+ "threeToolExecutionTraceSource": "linuxcnc_tp_samples_or_task_motion_hal_feedback",
+ "threePathFitBounds": "ok",
+ "threePathBoundsMeters": "{\"center\":{\"x\":0.01,\"y\":0.01,\"z\":0.002},\"size\":{\"x\":0.02,\"y\":0.02,\"z\":0.005},\"maxSpan\":0.02}",
+ "threeCurrentSegmentHighlight": "ok",
+ "threeRapidFeedVisualDistinction": "ok",
+ "threeNoGcodeSemanticsGeneration": "ok",
+ "threeRapidPathPoints": "2",
+ "threeFeedPathPoints": "4",
+ "threeArcPathPoints": "0",
+ "threeCurrentSegmentPoints": "2",
+ "threeCurrentSegmentType": "STRAIGHT_FEED"
+ },
+ "state": {
+ "activeProgram": "button-control-evidence.ngc",
+ "runState": "running",
+ "activeLine": 3,
+ "machine": {
+ "powerOn": true,
+ "taskState": "on",
+ "mode": "auto",
+ "allHomed": true,
+ "interpState": "reading",
+ "taskPaused": false
+ },
+ "axisPose": {
+ "x": 1.59872,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "dro": {
+ "x": 1.59872,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "programRuntimeFeedback": {
+ "sourceMode": "linuxcnc-task-motion-hal-wasm",
+ "line": 3,
+ "taskCycle": 86,
+ "currentVelocityMmPerMin": 120,
+ "axisPose": {
+ "x": 1.59872,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ }
+ },
+ "taskHalStatus": {
+ "task": {
+ "mode": "AUTO",
+ "interpState": "READING",
+ "taskPaused": false,
+ "singleStepping": false
+ },
+ "ui": {
+ "activeLine": 3,
+ "taskCycle": 0,
+ "servoCycle": 860
+ },
+ "motionStatus": {
+ "motion": {
+ "paused": false,
+ "aborted": false
+ }
+ }
+ },
+ "taskHalStatusLoop": {
+ "apiName": "web-rtcp-5axis-task-hal-status-loop",
+ "active": true,
+ "sequence": 1,
+ "profileId": "xyzac-trt",
+ "iniPath": "configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
+ "kinematicsModuleId": "xyzac-trt",
+ "tickCount": 15,
+ "batchSize": 5,
+ "intervalMs": 25,
+ "taskPeriodNs": 10000000,
+ "servoPeriodNs": 1000000,
+ "lastStatusAt": "2026-06-23T09:18:27.399Z",
+ "lastError": null,
+ "stopReason": null,
+ "semanticBoundary": "js_status_polling_loop_for_linuxcnc_task_hal_motion_status"
+ },
+ "operatorMessage": "task/HAL status tick 15"
+ }
+ },
+ {
+ "name": "08-after-pause",
+ "title": "After PAUSE",
+ "description": "PAUSE sets runState paused and taskPaused true.",
+ "screenshotPath": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/screenshots/cloud-button-control-evidence/08-after-pause.png",
+ "pixelStats": {
+ "width": 1500,
+ "height": 1050,
+ "averageLuminance": 129.2,
+ "nonBlackRatio": 0.7794
+ },
+ "buttons": {
+ "RUN": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "run blocked: resume paused program first"
+ },
+ "STOP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "PAUSE": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "RESUME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "STEP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "HOME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "home blocked: switch to manual mode first"
+ }
+ },
+ "canvasDataset": {
+ "fiveAxisCanvas": "true",
+ "engine": "three.js r183",
+ "threeReady": "true",
+ "threeRevision": "183",
+ "threePathPoints": "6",
+ "threeExecutedPathPoints": "1",
+ "threeSceneObjects": "20",
+ "threeToolhead": "{\"x\":0.002,\"y\":0,\"z\":0}",
+ "threeSceneUnits": "m",
+ "threeLinearUnits": "mm",
+ "threeLinearUnitScaleToMeters": "0.001",
+ "threeToolAxis": "{\"x\":0,\"y\":0,\"z\":1}",
+ "threeTcpPose": "{\"x\":1.799,\"y\":0,\"z\":0,\"a\":0,\"c\":0}",
+ "threeRtcpState": "off",
+ "threeSelectedView": "iso",
+ "threeFrameApi": "web-rtcp-5axis-motion-frame",
+ "threeRenderer": "webgl",
+ "threeSceneMode": "program-preview-and-tool-execution",
+ "threePreviewScope": "machine-reference-and-toolpath",
+ "threeMachineReferenceModel": "webgl-five-axis-reference",
+ "threeCameraControls": "orbit-pan-zoom",
+ "threeProgramPreviewSource": "linuxcnc-interpreter-wasm",
+ "threeToolExecutionMarker": "true",
+ "threeTcpMarker": "sphere",
+ "threeToolAxisMarker": "line",
+ "threeToolpathPreviewSource": "linuxcnc_interpreter_canonical_motion",
+ "threeToolExecutionTraceSource": "linuxcnc_tp_samples_or_task_motion_hal_feedback",
+ "threePathFitBounds": "ok",
+ "threePathBoundsMeters": "{\"center\":{\"x\":0.01,\"y\":0.01,\"z\":0.002},\"size\":{\"x\":0.02,\"y\":0.02,\"z\":0.005},\"maxSpan\":0.02}",
+ "threeCurrentSegmentHighlight": "ok",
+ "threeRapidFeedVisualDistinction": "ok",
+ "threeNoGcodeSemanticsGeneration": "ok",
+ "threeRapidPathPoints": "2",
+ "threeFeedPathPoints": "4",
+ "threeArcPathPoints": "0",
+ "threeCurrentSegmentPoints": "2",
+ "threeCurrentSegmentType": "STRAIGHT_FEED"
+ },
+ "state": {
+ "activeProgram": "button-control-evidence.ngc",
+ "runState": "paused",
+ "activeLine": 3,
+ "machine": {
+ "powerOn": true,
+ "taskState": "on",
+ "mode": "auto",
+ "allHomed": true,
+ "interpState": "paused",
+ "taskPaused": true
+ },
+ "axisPose": {
+ "x": 1.79856,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "dro": {
+ "x": 1.79856,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "programRuntimeFeedback": {
+ "sourceMode": "linuxcnc-task-motion-hal-wasm",
+ "line": 3,
+ "taskCycle": 97,
+ "currentVelocityMmPerMin": 120,
+ "axisPose": {
+ "x": 1.79856,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ }
+ },
+ "taskHalStatus": {
+ "task": {
+ "mode": "AUTO",
+ "interpState": "PAUSED",
+ "taskPaused": true,
+ "singleStepping": false
+ },
+ "ui": {
+ "activeLine": 3,
+ "taskCycle": 0,
+ "servoCycle": 970
+ },
+ "motionStatus": {
+ "motion": {
+ "paused": true,
+ "aborted": false
+ }
+ }
+ },
+ "taskHalStatusLoop": {
+ "apiName": "web-rtcp-5axis-task-hal-status-loop",
+ "active": false,
+ "sequence": 1,
+ "profileId": "xyzac-trt",
+ "iniPath": "configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
+ "kinematicsModuleId": "xyzac-trt",
+ "tickCount": 17,
+ "batchSize": 5,
+ "intervalMs": 25,
+ "taskPeriodNs": 10000000,
+ "servoPeriodNs": 1000000,
+ "lastStatusAt": "2026-06-23T09:18:27.726Z",
+ "lastError": null,
+ "stopReason": "paused",
+ "semanticBoundary": "js_status_polling_loop_for_linuxcnc_task_hal_motion_status"
+ },
+ "operatorMessage": "task/HAL program paused"
+ }
+ },
+ {
+ "name": "09-before-resume",
+ "title": "Before RESUME",
+ "description": "Program is paused before RESUME.",
+ "screenshotPath": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/screenshots/cloud-button-control-evidence/09-before-resume.png",
+ "pixelStats": {
+ "width": 1500,
+ "height": 1050,
+ "averageLuminance": 129.2,
+ "nonBlackRatio": 0.7794
+ },
+ "buttons": {
+ "RUN": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "run blocked: resume paused program first"
+ },
+ "STOP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "PAUSE": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "RESUME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "STEP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "HOME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "home blocked: switch to manual mode first"
+ }
+ },
+ "canvasDataset": {
+ "fiveAxisCanvas": "true",
+ "engine": "three.js r183",
+ "threeReady": "true",
+ "threeRevision": "183",
+ "threePathPoints": "6",
+ "threeExecutedPathPoints": "1",
+ "threeSceneObjects": "20",
+ "threeToolhead": "{\"x\":0.002,\"y\":0,\"z\":0}",
+ "threeSceneUnits": "m",
+ "threeLinearUnits": "mm",
+ "threeLinearUnitScaleToMeters": "0.001",
+ "threeToolAxis": "{\"x\":0,\"y\":0,\"z\":1}",
+ "threeTcpPose": "{\"x\":1.799,\"y\":0,\"z\":0,\"a\":0,\"c\":0}",
+ "threeRtcpState": "off",
+ "threeSelectedView": "iso",
+ "threeFrameApi": "web-rtcp-5axis-motion-frame",
+ "threeRenderer": "webgl",
+ "threeSceneMode": "program-preview-and-tool-execution",
+ "threePreviewScope": "machine-reference-and-toolpath",
+ "threeMachineReferenceModel": "webgl-five-axis-reference",
+ "threeCameraControls": "orbit-pan-zoom",
+ "threeProgramPreviewSource": "linuxcnc-interpreter-wasm",
+ "threeToolExecutionMarker": "true",
+ "threeTcpMarker": "sphere",
+ "threeToolAxisMarker": "line",
+ "threeToolpathPreviewSource": "linuxcnc_interpreter_canonical_motion",
+ "threeToolExecutionTraceSource": "linuxcnc_tp_samples_or_task_motion_hal_feedback",
+ "threePathFitBounds": "ok",
+ "threePathBoundsMeters": "{\"center\":{\"x\":0.01,\"y\":0.01,\"z\":0.002},\"size\":{\"x\":0.02,\"y\":0.02,\"z\":0.005},\"maxSpan\":0.02}",
+ "threeCurrentSegmentHighlight": "ok",
+ "threeRapidFeedVisualDistinction": "ok",
+ "threeNoGcodeSemanticsGeneration": "ok",
+ "threeRapidPathPoints": "2",
+ "threeFeedPathPoints": "4",
+ "threeArcPathPoints": "0",
+ "threeCurrentSegmentPoints": "2",
+ "threeCurrentSegmentType": "STRAIGHT_FEED"
+ },
+ "state": {
+ "activeProgram": "button-control-evidence.ngc",
+ "runState": "paused",
+ "activeLine": 3,
+ "machine": {
+ "powerOn": true,
+ "taskState": "on",
+ "mode": "auto",
+ "allHomed": true,
+ "interpState": "paused",
+ "taskPaused": true
+ },
+ "axisPose": {
+ "x": 1.79856,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "dro": {
+ "x": 1.79856,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "programRuntimeFeedback": {
+ "sourceMode": "linuxcnc-task-motion-hal-wasm",
+ "line": 3,
+ "taskCycle": 97,
+ "currentVelocityMmPerMin": 120,
+ "axisPose": {
+ "x": 1.79856,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ }
+ },
+ "taskHalStatus": {
+ "task": {
+ "mode": "AUTO",
+ "interpState": "PAUSED",
+ "taskPaused": true,
+ "singleStepping": false
+ },
+ "ui": {
+ "activeLine": 3,
+ "taskCycle": 0,
+ "servoCycle": 970
+ },
+ "motionStatus": {
+ "motion": {
+ "paused": true,
+ "aborted": false
+ }
+ }
+ },
+ "taskHalStatusLoop": {
+ "apiName": "web-rtcp-5axis-task-hal-status-loop",
+ "active": false,
+ "sequence": 1,
+ "profileId": "xyzac-trt",
+ "iniPath": "configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
+ "kinematicsModuleId": "xyzac-trt",
+ "tickCount": 17,
+ "batchSize": 5,
+ "intervalMs": 25,
+ "taskPeriodNs": 10000000,
+ "servoPeriodNs": 1000000,
+ "lastStatusAt": "2026-06-23T09:18:27.726Z",
+ "lastError": null,
+ "stopReason": "paused",
+ "semanticBoundary": "js_status_polling_loop_for_linuxcnc_task_hal_motion_status"
+ },
+ "operatorMessage": "task/HAL program paused"
+ }
+ },
+ {
+ "name": "10-after-resume",
+ "title": "After RESUME",
+ "description": "RESUME returns task/HAL execution to running/reading.",
+ "screenshotPath": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/screenshots/cloud-button-control-evidence/10-after-resume.png",
+ "pixelStats": {
+ "width": 1500,
+ "height": 1050,
+ "averageLuminance": 129.2,
+ "nonBlackRatio": 0.7794
+ },
+ "buttons": {
+ "RUN": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "STOP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "PAUSE": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "RESUME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "resume blocked: interpreter is not paused"
+ },
+ "STEP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "HOME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "home blocked: switch to manual mode first"
+ }
+ },
+ "canvasDataset": {
+ "fiveAxisCanvas": "true",
+ "engine": "three.js r183",
+ "threeReady": "true",
+ "threeRevision": "183",
+ "threePathPoints": "6",
+ "threeExecutedPathPoints": "1",
+ "threeSceneObjects": "20",
+ "threeToolhead": "{\"x\":0.003,\"y\":0,\"z\":0}",
+ "threeSceneUnits": "m",
+ "threeLinearUnits": "mm",
+ "threeLinearUnitScaleToMeters": "0.001",
+ "threeToolAxis": "{\"x\":0,\"y\":0,\"z\":1}",
+ "threeTcpPose": "{\"x\":2.518,\"y\":0,\"z\":0,\"a\":0,\"c\":0}",
+ "threeRtcpState": "off",
+ "threeSelectedView": "iso",
+ "threeFrameApi": "web-rtcp-5axis-motion-frame",
+ "threeRenderer": "webgl",
+ "threeSceneMode": "program-preview-and-tool-execution",
+ "threePreviewScope": "machine-reference-and-toolpath",
+ "threeMachineReferenceModel": "webgl-five-axis-reference",
+ "threeCameraControls": "orbit-pan-zoom",
+ "threeProgramPreviewSource": "linuxcnc-interpreter-wasm",
+ "threeToolExecutionMarker": "true",
+ "threeTcpMarker": "sphere",
+ "threeToolAxisMarker": "line",
+ "threeToolpathPreviewSource": "linuxcnc_interpreter_canonical_motion",
+ "threeToolExecutionTraceSource": "linuxcnc_tp_samples_or_task_motion_hal_feedback",
+ "threePathFitBounds": "ok",
+ "threePathBoundsMeters": "{\"center\":{\"x\":0.01,\"y\":0.01,\"z\":0.002},\"size\":{\"x\":0.02,\"y\":0.02,\"z\":0.005},\"maxSpan\":0.02}",
+ "threeCurrentSegmentHighlight": "ok",
+ "threeRapidFeedVisualDistinction": "ok",
+ "threeNoGcodeSemanticsGeneration": "ok",
+ "threeRapidPathPoints": "2",
+ "threeFeedPathPoints": "4",
+ "threeArcPathPoints": "0",
+ "threeCurrentSegmentPoints": "2",
+ "threeCurrentSegmentType": "STRAIGHT_FEED"
+ },
+ "state": {
+ "activeProgram": "button-control-evidence.ngc",
+ "runState": "running",
+ "activeLine": 3,
+ "machine": {
+ "powerOn": true,
+ "taskState": "on",
+ "mode": "auto",
+ "allHomed": true,
+ "interpState": "reading",
+ "taskPaused": false
+ },
+ "axisPose": {
+ "x": 2.41807,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "dro": {
+ "x": 2.41807,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "programRuntimeFeedback": {
+ "sourceMode": "linuxcnc-task-motion-hal-wasm",
+ "line": 3,
+ "taskCycle": 128,
+ "currentVelocityMmPerMin": 120,
+ "axisPose": {
+ "x": 2.41807,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ }
+ },
+ "taskHalStatus": {
+ "task": {
+ "mode": "AUTO",
+ "interpState": "READING",
+ "taskPaused": false,
+ "singleStepping": false
+ },
+ "ui": {
+ "activeLine": 3,
+ "taskCycle": 0,
+ "servoCycle": 1280
+ },
+ "motionStatus": {
+ "motion": {
+ "paused": false,
+ "aborted": false
+ }
+ }
+ },
+ "taskHalStatusLoop": {
+ "apiName": "web-rtcp-5axis-task-hal-status-loop",
+ "active": true,
+ "sequence": 2,
+ "profileId": "xyzac-trt",
+ "iniPath": "configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
+ "kinematicsModuleId": "xyzac-trt",
+ "tickCount": 6,
+ "batchSize": 5,
+ "intervalMs": 25,
+ "taskPeriodNs": 10000000,
+ "servoPeriodNs": 1000000,
+ "lastStatusAt": "2026-06-23T09:18:29.721Z",
+ "lastError": null,
+ "stopReason": null,
+ "semanticBoundary": "js_status_polling_loop_for_linuxcnc_task_hal_motion_status"
+ },
+ "operatorMessage": "task/HAL status tick 6"
+ }
+ },
+ {
+ "name": "11-before-step",
+ "title": "Before STEP",
+ "description": "Program is paused before STEP.",
+ "screenshotPath": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/screenshots/cloud-button-control-evidence/11-before-step.png",
+ "pixelStats": {
+ "width": 1500,
+ "height": 1050,
+ "averageLuminance": 129.22,
+ "nonBlackRatio": 0.7795
+ },
+ "buttons": {
+ "RUN": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "run blocked: resume paused program first"
+ },
+ "STOP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "PAUSE": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "RESUME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "STEP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "HOME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "home blocked: switch to manual mode first"
+ }
+ },
+ "canvasDataset": {
+ "fiveAxisCanvas": "true",
+ "engine": "three.js r183",
+ "threeReady": "true",
+ "threeRevision": "183",
+ "threePathPoints": "6",
+ "threeExecutedPathPoints": "1",
+ "threeSceneObjects": "20",
+ "threeToolhead": "{\"x\":0.003,\"y\":0,\"z\":0}",
+ "threeSceneUnits": "m",
+ "threeLinearUnits": "mm",
+ "threeLinearUnitScaleToMeters": "0.001",
+ "threeToolAxis": "{\"x\":0,\"y\":0,\"z\":1}",
+ "threeTcpPose": "{\"x\":2.618,\"y\":0,\"z\":0,\"a\":0,\"c\":0}",
+ "threeRtcpState": "off",
+ "threeSelectedView": "iso",
+ "threeFrameApi": "web-rtcp-5axis-motion-frame",
+ "threeRenderer": "webgl",
+ "threeSceneMode": "program-preview-and-tool-execution",
+ "threePreviewScope": "machine-reference-and-toolpath",
+ "threeMachineReferenceModel": "webgl-five-axis-reference",
+ "threeCameraControls": "orbit-pan-zoom",
+ "threeProgramPreviewSource": "linuxcnc-interpreter-wasm",
+ "threeToolExecutionMarker": "true",
+ "threeTcpMarker": "sphere",
+ "threeToolAxisMarker": "line",
+ "threeToolpathPreviewSource": "linuxcnc_interpreter_canonical_motion",
+ "threeToolExecutionTraceSource": "linuxcnc_tp_samples_or_task_motion_hal_feedback",
+ "threePathFitBounds": "ok",
+ "threePathBoundsMeters": "{\"center\":{\"x\":0.01,\"y\":0.01,\"z\":0.002},\"size\":{\"x\":0.02,\"y\":0.02,\"z\":0.005},\"maxSpan\":0.02}",
+ "threeCurrentSegmentHighlight": "ok",
+ "threeRapidFeedVisualDistinction": "ok",
+ "threeNoGcodeSemanticsGeneration": "ok",
+ "threeRapidPathPoints": "2",
+ "threeFeedPathPoints": "4",
+ "threeArcPathPoints": "0",
+ "threeCurrentSegmentPoints": "2",
+ "threeCurrentSegmentType": "STRAIGHT_FEED"
+ },
+ "state": {
+ "activeProgram": "button-control-evidence.ngc",
+ "runState": "paused",
+ "activeLine": 3,
+ "machine": {
+ "powerOn": true,
+ "taskState": "on",
+ "mode": "auto",
+ "allHomed": true,
+ "interpState": "paused",
+ "taskPaused": true
+ },
+ "axisPose": {
+ "x": 2.61791,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "dro": {
+ "x": 2.61791,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "programRuntimeFeedback": {
+ "sourceMode": "linuxcnc-task-motion-hal-wasm",
+ "line": 3,
+ "taskCycle": 139,
+ "currentVelocityMmPerMin": 120,
+ "axisPose": {
+ "x": 2.61791,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ }
+ },
+ "taskHalStatus": {
+ "task": {
+ "mode": "AUTO",
+ "interpState": "PAUSED",
+ "taskPaused": true,
+ "singleStepping": false
+ },
+ "ui": {
+ "activeLine": 3,
+ "taskCycle": 0,
+ "servoCycle": 1390
+ },
+ "motionStatus": {
+ "motion": {
+ "paused": true,
+ "aborted": false
+ }
+ }
+ },
+ "taskHalStatusLoop": {
+ "apiName": "web-rtcp-5axis-task-hal-status-loop",
+ "active": false,
+ "sequence": 2,
+ "profileId": "xyzac-trt",
+ "iniPath": "configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
+ "kinematicsModuleId": "xyzac-trt",
+ "tickCount": 8,
+ "batchSize": 5,
+ "intervalMs": 25,
+ "taskPeriodNs": 10000000,
+ "servoPeriodNs": 1000000,
+ "lastStatusAt": "2026-06-23T09:18:30.051Z",
+ "lastError": null,
+ "stopReason": "paused",
+ "semanticBoundary": "js_status_polling_loop_for_linuxcnc_task_hal_motion_status"
+ },
+ "operatorMessage": "task/HAL program paused"
+ }
+ },
+ {
+ "name": "12-after-step",
+ "title": "After STEP",
+ "description": "STEP sends EMC_TASK_PLAN_STEP and leaves task paused with singleStepping true.",
+ "screenshotPath": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/screenshots/cloud-button-control-evidence/12-after-step.png",
+ "pixelStats": {
+ "width": 1500,
+ "height": 1050,
+ "averageLuminance": 129.23,
+ "nonBlackRatio": 0.7795
+ },
+ "buttons": {
+ "RUN": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "run blocked: resume paused program first"
+ },
+ "STOP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "PAUSE": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "RESUME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "STEP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "HOME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "home blocked: switch to manual mode first"
+ }
+ },
+ "canvasDataset": {
+ "fiveAxisCanvas": "true",
+ "engine": "three.js r183",
+ "threeReady": "true",
+ "threeRevision": "183",
+ "threePathPoints": "6",
+ "threeExecutedPathPoints": "1",
+ "threeSceneObjects": "20",
+ "threeToolhead": "{\"x\":0.003,\"y\":0,\"z\":0}",
+ "threeSceneUnits": "m",
+ "threeLinearUnits": "mm",
+ "threeLinearUnitScaleToMeters": "0.001",
+ "threeToolAxis": "{\"x\":0,\"y\":0,\"z\":1}",
+ "threeTcpPose": "{\"x\":2.638,\"y\":0,\"z\":0,\"a\":0,\"c\":0}",
+ "threeRtcpState": "off",
+ "threeSelectedView": "iso",
+ "threeFrameApi": "web-rtcp-5axis-motion-frame",
+ "threeRenderer": "webgl",
+ "threeSceneMode": "program-preview-and-tool-execution",
+ "threePreviewScope": "machine-reference-and-toolpath",
+ "threeMachineReferenceModel": "webgl-five-axis-reference",
+ "threeCameraControls": "orbit-pan-zoom",
+ "threeProgramPreviewSource": "linuxcnc-interpreter-wasm",
+ "threeToolExecutionMarker": "true",
+ "threeTcpMarker": "sphere",
+ "threeToolAxisMarker": "line",
+ "threeToolpathPreviewSource": "linuxcnc_interpreter_canonical_motion",
+ "threeToolExecutionTraceSource": "linuxcnc_tp_samples_or_task_motion_hal_feedback",
+ "threePathFitBounds": "ok",
+ "threePathBoundsMeters": "{\"center\":{\"x\":0.01,\"y\":0.01,\"z\":0.002},\"size\":{\"x\":0.02,\"y\":0.02,\"z\":0.005},\"maxSpan\":0.02}",
+ "threeCurrentSegmentHighlight": "ok",
+ "threeRapidFeedVisualDistinction": "ok",
+ "threeNoGcodeSemanticsGeneration": "ok",
+ "threeRapidPathPoints": "2",
+ "threeFeedPathPoints": "4",
+ "threeArcPathPoints": "0",
+ "threeCurrentSegmentPoints": "2",
+ "threeCurrentSegmentType": "STRAIGHT_FEED"
+ },
+ "state": {
+ "activeProgram": "button-control-evidence.ngc",
+ "runState": "paused",
+ "activeLine": 3,
+ "machine": {
+ "powerOn": true,
+ "taskState": "on",
+ "mode": "auto",
+ "allHomed": true,
+ "interpState": "paused",
+ "taskPaused": true
+ },
+ "axisPose": {
+ "x": 2.63789,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "dro": {
+ "x": 2.63789,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "programRuntimeFeedback": {
+ "sourceMode": "linuxcnc-task-motion-hal-wasm",
+ "line": 3,
+ "taskCycle": 140,
+ "currentVelocityMmPerMin": 120,
+ "axisPose": {
+ "x": 2.63789,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ }
+ },
+ "taskHalStatus": {
+ "task": {
+ "mode": "AUTO",
+ "interpState": "PAUSED",
+ "taskPaused": true,
+ "singleStepping": true
+ },
+ "ui": {
+ "activeLine": 3,
+ "taskCycle": 0,
+ "servoCycle": 1400
+ },
+ "motionStatus": {
+ "motion": {
+ "paused": false,
+ "aborted": false
+ }
+ }
+ },
+ "taskHalStatusLoop": {
+ "apiName": "web-rtcp-5axis-task-hal-status-loop",
+ "active": false,
+ "sequence": 2,
+ "profileId": "xyzac-trt",
+ "iniPath": "configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
+ "kinematicsModuleId": "xyzac-trt",
+ "tickCount": 8,
+ "batchSize": 5,
+ "intervalMs": 25,
+ "taskPeriodNs": 10000000,
+ "servoPeriodNs": 1000000,
+ "lastStatusAt": "2026-06-23T09:18:30.051Z",
+ "lastError": null,
+ "stopReason": "step",
+ "semanticBoundary": "js_status_polling_loop_for_linuxcnc_task_hal_motion_status"
+ },
+ "operatorMessage": "task/HAL stepped one cycle"
+ }
+ },
+ {
+ "name": "13-before-stop",
+ "title": "Before STOP",
+ "description": "Paused single-step state before STOP.",
+ "screenshotPath": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/screenshots/cloud-button-control-evidence/13-before-stop.png",
+ "pixelStats": {
+ "width": 1500,
+ "height": 1050,
+ "averageLuminance": 129.23,
+ "nonBlackRatio": 0.7795
+ },
+ "buttons": {
+ "RUN": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "run blocked: resume paused program first"
+ },
+ "STOP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "PAUSE": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "RESUME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "STEP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "HOME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "home blocked: switch to manual mode first"
+ }
+ },
+ "canvasDataset": {
+ "fiveAxisCanvas": "true",
+ "engine": "three.js r183",
+ "threeReady": "true",
+ "threeRevision": "183",
+ "threePathPoints": "6",
+ "threeExecutedPathPoints": "1",
+ "threeSceneObjects": "20",
+ "threeToolhead": "{\"x\":0.003,\"y\":0,\"z\":0}",
+ "threeSceneUnits": "m",
+ "threeLinearUnits": "mm",
+ "threeLinearUnitScaleToMeters": "0.001",
+ "threeToolAxis": "{\"x\":0,\"y\":0,\"z\":1}",
+ "threeTcpPose": "{\"x\":2.638,\"y\":0,\"z\":0,\"a\":0,\"c\":0}",
+ "threeRtcpState": "off",
+ "threeSelectedView": "iso",
+ "threeFrameApi": "web-rtcp-5axis-motion-frame",
+ "threeRenderer": "webgl",
+ "threeSceneMode": "program-preview-and-tool-execution",
+ "threePreviewScope": "machine-reference-and-toolpath",
+ "threeMachineReferenceModel": "webgl-five-axis-reference",
+ "threeCameraControls": "orbit-pan-zoom",
+ "threeProgramPreviewSource": "linuxcnc-interpreter-wasm",
+ "threeToolExecutionMarker": "true",
+ "threeTcpMarker": "sphere",
+ "threeToolAxisMarker": "line",
+ "threeToolpathPreviewSource": "linuxcnc_interpreter_canonical_motion",
+ "threeToolExecutionTraceSource": "linuxcnc_tp_samples_or_task_motion_hal_feedback",
+ "threePathFitBounds": "ok",
+ "threePathBoundsMeters": "{\"center\":{\"x\":0.01,\"y\":0.01,\"z\":0.002},\"size\":{\"x\":0.02,\"y\":0.02,\"z\":0.005},\"maxSpan\":0.02}",
+ "threeCurrentSegmentHighlight": "ok",
+ "threeRapidFeedVisualDistinction": "ok",
+ "threeNoGcodeSemanticsGeneration": "ok",
+ "threeRapidPathPoints": "2",
+ "threeFeedPathPoints": "4",
+ "threeArcPathPoints": "0",
+ "threeCurrentSegmentPoints": "2",
+ "threeCurrentSegmentType": "STRAIGHT_FEED"
+ },
+ "state": {
+ "activeProgram": "button-control-evidence.ngc",
+ "runState": "paused",
+ "activeLine": 3,
+ "machine": {
+ "powerOn": true,
+ "taskState": "on",
+ "mode": "auto",
+ "allHomed": true,
+ "interpState": "paused",
+ "taskPaused": true
+ },
+ "axisPose": {
+ "x": 2.63789,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "dro": {
+ "x": 2.63789,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "programRuntimeFeedback": {
+ "sourceMode": "linuxcnc-task-motion-hal-wasm",
+ "line": 3,
+ "taskCycle": 140,
+ "currentVelocityMmPerMin": 120,
+ "axisPose": {
+ "x": 2.63789,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ }
+ },
+ "taskHalStatus": {
+ "task": {
+ "mode": "AUTO",
+ "interpState": "PAUSED",
+ "taskPaused": true,
+ "singleStepping": true
+ },
+ "ui": {
+ "activeLine": 3,
+ "taskCycle": 0,
+ "servoCycle": 1400
+ },
+ "motionStatus": {
+ "motion": {
+ "paused": false,
+ "aborted": false
+ }
+ }
+ },
+ "taskHalStatusLoop": {
+ "apiName": "web-rtcp-5axis-task-hal-status-loop",
+ "active": false,
+ "sequence": 2,
+ "profileId": "xyzac-trt",
+ "iniPath": "configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
+ "kinematicsModuleId": "xyzac-trt",
+ "tickCount": 8,
+ "batchSize": 5,
+ "intervalMs": 25,
+ "taskPeriodNs": 10000000,
+ "servoPeriodNs": 1000000,
+ "lastStatusAt": "2026-06-23T09:18:30.051Z",
+ "lastError": null,
+ "stopReason": "step",
+ "semanticBoundary": "js_status_polling_loop_for_linuxcnc_task_hal_motion_status"
+ },
+ "operatorMessage": "task/HAL stepped one cycle"
+ }
+ },
+ {
+ "name": "14-after-stop",
+ "title": "After STOP",
+ "description": "STOP aborts task/HAL motion and returns interpreter state to idle.",
+ "screenshotPath": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/screenshots/cloud-button-control-evidence/14-after-stop.png",
+ "pixelStats": {
+ "width": 1500,
+ "height": 1050,
+ "averageLuminance": 129.22,
+ "nonBlackRatio": 0.7795
+ },
+ "buttons": {
+ "RUN": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "STOP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "PAUSE": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "RESUME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "resume blocked: interpreter is not paused"
+ },
+ "STEP": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "true",
+ "ariaDisabled": "false",
+ "title": ""
+ },
+ "HOME": {
+ "exists": true,
+ "disabled": false,
+ "commandReady": "false",
+ "ariaDisabled": "true",
+ "title": "home blocked: switch to manual mode first"
+ }
+ },
+ "canvasDataset": {
+ "fiveAxisCanvas": "true",
+ "engine": "three.js r183",
+ "threeReady": "true",
+ "threeRevision": "183",
+ "threePathPoints": "6",
+ "threeExecutedPathPoints": "1",
+ "threeSceneObjects": "20",
+ "threeToolhead": "{\"x\":0.003,\"y\":0,\"z\":0}",
+ "threeSceneUnits": "m",
+ "threeLinearUnits": "mm",
+ "threeLinearUnitScaleToMeters": "0.001",
+ "threeToolAxis": "{\"x\":0,\"y\":0,\"z\":1}",
+ "threeTcpPose": "{\"x\":2.638,\"y\":0,\"z\":0,\"a\":0,\"c\":0}",
+ "threeRtcpState": "off",
+ "threeSelectedView": "iso",
+ "threeFrameApi": "web-rtcp-5axis-motion-frame",
+ "threeRenderer": "webgl",
+ "threeSceneMode": "program-preview-and-tool-execution",
+ "threePreviewScope": "machine-reference-and-toolpath",
+ "threeMachineReferenceModel": "webgl-five-axis-reference",
+ "threeCameraControls": "orbit-pan-zoom",
+ "threeProgramPreviewSource": "linuxcnc-interpreter-wasm",
+ "threeToolExecutionMarker": "true",
+ "threeTcpMarker": "sphere",
+ "threeToolAxisMarker": "line",
+ "threeToolpathPreviewSource": "linuxcnc_interpreter_canonical_motion",
+ "threeToolExecutionTraceSource": "linuxcnc_tp_samples_or_task_motion_hal_feedback",
+ "threePathFitBounds": "ok",
+ "threePathBoundsMeters": "{\"center\":{\"x\":0.01,\"y\":0.01,\"z\":0.002},\"size\":{\"x\":0.02,\"y\":0.02,\"z\":0.005},\"maxSpan\":0.02}",
+ "threeCurrentSegmentHighlight": "ok",
+ "threeRapidFeedVisualDistinction": "ok",
+ "threeNoGcodeSemanticsGeneration": "ok",
+ "threeRapidPathPoints": "2",
+ "threeFeedPathPoints": "4",
+ "threeArcPathPoints": "0",
+ "threeCurrentSegmentPoints": "2",
+ "threeCurrentSegmentType": "STRAIGHT_FEED"
+ },
+ "state": {
+ "activeProgram": "button-control-evidence.ngc",
+ "runState": "stopped",
+ "activeLine": 3,
+ "machine": {
+ "powerOn": true,
+ "taskState": "on",
+ "mode": "auto",
+ "allHomed": true,
+ "interpState": "idle",
+ "taskPaused": false
+ },
+ "axisPose": {
+ "x": 2.63789,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "dro": {
+ "x": 2.63789,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "programRuntimeFeedback": {
+ "sourceMode": "linuxcnc-task-motion-hal-wasm",
+ "line": 3,
+ "taskCycle": 141,
+ "currentVelocityMmPerMin": 120,
+ "axisPose": {
+ "x": 2.63789,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ }
+ },
+ "taskHalStatus": {
+ "task": {
+ "mode": "AUTO",
+ "interpState": "IDLE",
+ "taskPaused": false,
+ "singleStepping": false
+ },
+ "ui": {
+ "activeLine": 3,
+ "taskCycle": 0,
+ "servoCycle": 1410
+ },
+ "motionStatus": {
+ "motion": {
+ "paused": false,
+ "aborted": true
+ }
+ }
+ },
+ "taskHalStatusLoop": {
+ "apiName": "web-rtcp-5axis-task-hal-status-loop",
+ "active": false,
+ "sequence": 2,
+ "profileId": "xyzac-trt",
+ "iniPath": "configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
+ "kinematicsModuleId": "xyzac-trt",
+ "tickCount": 8,
+ "batchSize": 5,
+ "intervalMs": 25,
+ "taskPeriodNs": 10000000,
+ "servoPeriodNs": 1000000,
+ "lastStatusAt": "2026-06-23T09:18:30.051Z",
+ "lastError": null,
+ "stopReason": "stopped",
+ "semanticBoundary": "js_status_polling_loop_for_linuxcnc_task_hal_motion_status"
+ },
+ "operatorMessage": "task/HAL program stopped"
+ }
+ }
+ ],
+ "checks": [
+ {
+ "name": "HOME keeps all axes homed",
+ "pass": true,
+ "detail": "{\"powerOn\":true,\"taskState\":\"on\",\"mode\":\"manual\",\"allHomed\":true,\"interpState\":\"idle\",\"taskPaused\":false}"
+ },
+ {
+ "name": "RUN uses task/HAL runtime feedback",
+ "pass": true,
+ "detail": "{\"sourceMode\":\"linuxcnc-task-motion-hal-wasm\",\"line\":3,\"taskCycle\":61,\"currentVelocityMmPerMin\":120,\"axisPose\":{\"x\":1.09912,\"y\":0,\"z\":0,\"a\":0,\"b\":0,\"c\":0}}"
+ },
+ {
+ "name": "PAUSE sets paused state",
+ "pass": true,
+ "detail": "{\"powerOn\":true,\"taskState\":\"on\",\"mode\":\"auto\",\"allHomed\":true,\"interpState\":\"paused\",\"taskPaused\":true}"
+ },
+ {
+ "name": "RESUME returns to reading",
+ "pass": true,
+ "detail": "{\"powerOn\":true,\"taskState\":\"on\",\"mode\":\"auto\",\"allHomed\":true,\"interpState\":\"reading\",\"taskPaused\":false}"
+ },
+ {
+ "name": "STEP records single stepping",
+ "pass": true,
+ "detail": "{\"mode\":\"AUTO\",\"interpState\":\"PAUSED\",\"taskPaused\":true,\"singleStepping\":true}"
+ },
+ {
+ "name": "STOP aborts motion",
+ "pass": true,
+ "detail": "{\"paused\":false,\"aborted\":true}"
+ },
+ {
+ "name": "Screenshots are nonblank",
+ "pass": true,
+ "detail": "01-initial:0.7826, 02-program-loaded:0.7795, 03-before-home:0.7794, 04-after-home:0.7794, 05-ready-for-run:0.7794, 06-after-run:0.7796, 07-before-pause:0.7795, 08-after-pause:0.7794, 09-before-resume:0.7794, 10-after-resume:0.7794, 11-before-step:0.7795, 12-after-step:0.7795, 13-before-stop:0.7795, 14-after-stop:0.7795"
+ },
+ {
+ "name": "Control buttons expose readiness attributes",
+ "pass": true,
+ "detail": "RUN/STOP/PAUSE/RESUME/STEP/HOME"
+ }
+ ],
+ "consoleErrors": [],
+ "pageErrors": [],
+ "status": "PASS",
+ "jsonPath": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/output/cloud-button-control-evidence-report.json",
+ "pdfPath": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/output/cloud-button-control-evidence-report.pdf"
+}
diff --git a/qa/web-rtcp-5axis-site-test/output/cloud-button-control-evidence-report.pdf b/qa/web-rtcp-5axis-site-test/output/cloud-button-control-evidence-report.pdf
new file mode 100644
index 0000000..8aa3525
Binary files /dev/null and b/qa/web-rtcp-5axis-site-test/output/cloud-button-control-evidence-report.pdf differ
diff --git a/qa/web-rtcp-5axis-site-test/output/cloud-run-debug-current/01-loaded.png b/qa/web-rtcp-5axis-site-test/output/cloud-run-debug-current/01-loaded.png
new file mode 100644
index 0000000..e66fd04
Binary files /dev/null and b/qa/web-rtcp-5axis-site-test/output/cloud-run-debug-current/01-loaded.png differ
diff --git a/qa/web-rtcp-5axis-site-test/output/cloud-run-debug-current/02-source-loaded.png b/qa/web-rtcp-5axis-site-test/output/cloud-run-debug-current/02-source-loaded.png
new file mode 100644
index 0000000..b1c399c
Binary files /dev/null and b/qa/web-rtcp-5axis-site-test/output/cloud-run-debug-current/02-source-loaded.png differ
diff --git a/qa/web-rtcp-5axis-site-test/output/cloud-run-debug-current/cloud-run-debug-current.json b/qa/web-rtcp-5axis-site-test/output/cloud-run-debug-current/cloud-run-debug-current.json
new file mode 100644
index 0000000..8404348
--- /dev/null
+++ b/qa/web-rtcp-5axis-site-test/output/cloud-run-debug-current/cloud-run-debug-current.json
@@ -0,0 +1,1006 @@
+{
+ "generatedAt": "2026-06-23T07:34:24.702Z",
+ "target": "https://82.156.24.101:8092/",
+ "steps": [
+ {
+ "name": "01-loaded",
+ "screenshot": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/output/cloud-run-debug-current/01-loaded.png",
+ "state": {
+ "machineProfile": "xyzac-trt",
+ "activeProgram": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzac.ngc",
+ "programSource": "linuxcnc-vendored-5axis-gcode",
+ "programExecutionSourceMode": "fixture-line-playback",
+ "programMotionCount": 0,
+ "programLineCount": 1868,
+ "programStartLine": 1,
+ "activeLine": 1,
+ "runState": "idle",
+ "machine": {
+ "powerOn": false,
+ "estopActive": false,
+ "taskState": "estop-reset",
+ "mode": "manual",
+ "interpState": "idle",
+ "interpResumeState": "idle",
+ "taskPaused": false,
+ "allHomed": false,
+ "noForceHoming": false,
+ "jogAxis": "x",
+ "jogIncrement": 1,
+ "mdiCommand": "G0 X0 Y0 Z0",
+ "mdiDistanceMode": "absolute",
+ "resetCount": 0
+ },
+ "kinsType": "identity",
+ "rtcpState": "off",
+ "axisPose": {
+ "x": 43,
+ "y": -32.15,
+ "z": -11.306,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "dro": {
+ "x": 43,
+ "y": -32.15,
+ "z": -11.306,
+ "a": 0,
+ "b": 0,
+ "c": 0,
+ "tcpX": 43,
+ "tcpY": -32.15,
+ "tcpZ": -11.306,
+ "dtgX": 0,
+ "dtgY": 0.01,
+ "dtgZ": 2.25
+ },
+ "operatorMessage": "LinuxCNC machine files staged 18",
+ "iniConfigReadiness": {
+ "apiName": "web-rtcp-5axis-ini-config-readiness",
+ "loaded": true,
+ "ready": true,
+ "path": "configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
+ "missing": [],
+ "machineName": "sim-xyzac-trt-kins (switchkins)",
+ "coordinates": "XYZAC",
+ "kinematics": "xyzac-trt-kins",
+ "axisCount": 5,
+ "jointCount": 5,
+ "semanticBoundary": "linuxcnc_ini_file_browser_parser"
+ },
+ "kinematicsRuntimeReadiness": {
+ "apiName": "web-rtcp-5axis-linuxcnc-kinematics-worker-runtime-readiness",
+ "moduleId": "xyzac-trt",
+ "wasmFile": "linuxcnc_xyzac_trt_kinematics.wasm",
+ "supportedModules": [
+ "trivkins",
+ "5axiskins",
+ "xyzac-trt",
+ "xyzbc-trt",
+ "corexy",
+ "rotate",
+ "rose",
+ "max",
+ "lineardelta",
+ "rotarydelta",
+ "scorbot",
+ "tripod",
+ "scara",
+ "puma",
+ "genser",
+ "genhex",
+ "pentakins"
+ ],
+ "loaded": true,
+ "sourceMode": "source-derived-kinematics-wasm",
+ "semanticBoundary": "linuxcnc_kinematics_wasm_c_abi",
+ "executionContext": "worker",
+ "switchkinsType": 0,
+ "switchRc": 0,
+ "workerUrl": "https://82.156.24.101:8092/src/runtime/linuxcnc-kinematics-worker.js"
+ },
+ "taskHalRuntimeReadiness": {
+ "apiName": "web-rtcp-5axis-linuxcnc-task-hal-runtime-readiness",
+ "loaded": true,
+ "semanticBoundary": "linuxcnc_task_motion_hal_wasm_simulation_runtime",
+ "sdkSemanticBoundary": "linuxcnc_task_motion_hal_wasm_phase4_minimal",
+ "executionContext": "direct",
+ "workerUrl": null,
+ "taskRuntimeReady": true,
+ "motionRuntimeReady": true,
+ "halRuntimeReady": true,
+ "halSyncReady": true,
+ "nativeTaskReady": true,
+ "nativeHalSyncReady": true,
+ "hardwareDrive": false,
+ "hostRealtimeKernel": false,
+ "externalUserMProcessReady": false
+ },
+ "machineFileStaging": {
+ "status": "staged",
+ "fileCount": 18,
+ "selectedGcodeSourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzac.ngc",
+ "gcodeSources": [
+ {
+ "sourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzac.ngc",
+ "wasmPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/demos/boat-xyzac.ngc",
+ "opfsPath": "web-rtcp-5axis-sim-plan/machines/xyzac-trt/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzac.ngc",
+ "filename": "boat-xyzac.ngc",
+ "bytes": 70847,
+ "label": "boat-xyzac",
+ "sourceMode": "linuxcnc-vendored-5axis-gcode",
+ "semanticBoundary": "linuxcnc_vendored_5axis_gcode_source_file"
+ },
+ {
+ "sourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzbc.ngc",
+ "wasmPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/demos/boat-xyzbc.ngc",
+ "opfsPath": "web-rtcp-5axis-sim-plan/machines/xyzac-trt/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzbc.ngc",
+ "filename": "boat-xyzbc.ngc",
+ "bytes": 76616,
+ "label": "boat-xyzbc",
+ "sourceMode": "linuxcnc-vendored-5axis-gcode",
+ "semanticBoundary": "linuxcnc_vendored_5axis_gcode_source_file"
+ },
+ {
+ "sourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/impeller-7bl-xyzac.ngc",
+ "wasmPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/demos/impeller-7bl-xyzac.ngc",
+ "opfsPath": "web-rtcp-5axis-sim-plan/machines/xyzac-trt/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/impeller-7bl-xyzac.ngc",
+ "filename": "impeller-7bl-xyzac.ngc",
+ "bytes": 294411,
+ "label": "impeller-7bl-xyzac",
+ "sourceMode": "linuxcnc-vendored-5axis-gcode",
+ "semanticBoundary": "linuxcnc_vendored_5axis_gcode_source_file"
+ },
+ {
+ "sourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_1.ngc",
+ "wasmPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/demos/xyzac_switchkins_test_1.ngc",
+ "opfsPath": "web-rtcp-5axis-sim-plan/machines/xyzac-trt/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_1.ngc",
+ "filename": "xyzac_switchkins_test_1.ngc",
+ "bytes": 419,
+ "label": "xyzac_switchkins_test_1",
+ "sourceMode": "linuxcnc-vendored-5axis-gcode",
+ "semanticBoundary": "linuxcnc_vendored_5axis_gcode_source_file"
+ },
+ {
+ "sourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_2.ngc",
+ "wasmPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/demos/xyzac_switchkins_test_2.ngc",
+ "opfsPath": "web-rtcp-5axis-sim-plan/machines/xyzac-trt/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_2.ngc",
+ "filename": "xyzac_switchkins_test_2.ngc",
+ "bytes": 475,
+ "label": "xyzac_switchkins_test_2",
+ "sourceMode": "linuxcnc-vendored-5axis-gcode",
+ "semanticBoundary": "linuxcnc_vendored_5axis_gcode_source_file"
+ },
+ {
+ "sourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_3.ngc",
+ "wasmPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/demos/xyzac_switchkins_test_3.ngc",
+ "opfsPath": "web-rtcp-5axis-sim-plan/machines/xyzac-trt/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_3.ngc",
+ "filename": "xyzac_switchkins_test_3.ngc",
+ "bytes": 304,
+ "label": "xyzac_switchkins_test_3",
+ "sourceMode": "linuxcnc-vendored-5axis-gcode",
+ "semanticBoundary": "linuxcnc_vendored_5axis_gcode_source_file"
+ },
+ {
+ "sourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins.ngc",
+ "wasmPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/demos/xyzac_switchkins.ngc",
+ "opfsPath": "web-rtcp-5axis-sim-plan/machines/xyzac-trt/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins.ngc",
+ "filename": "xyzac_switchkins.ngc",
+ "bytes": 139,
+ "label": "xyzac_switchkins",
+ "sourceMode": "linuxcnc-vendored-5axis-gcode",
+ "semanticBoundary": "linuxcnc_vendored_5axis_gcode_source_file"
+ },
+ {
+ "sourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzbc_switchkins.ngc",
+ "wasmPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/demos/xyzbc_switchkins.ngc",
+ "opfsPath": "web-rtcp-5axis-sim-plan/machines/xyzac-trt/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzbc_switchkins.ngc",
+ "filename": "xyzbc_switchkins.ngc",
+ "bytes": 139,
+ "label": "xyzbc_switchkins",
+ "sourceMode": "linuxcnc-vendored-5axis-gcode",
+ "semanticBoundary": "linuxcnc_vendored_5axis_gcode_source_file"
+ }
+ ]
+ },
+ "taskHalSession": null,
+ "taskHalStatusLoop": {
+ "apiName": "web-rtcp-5axis-task-hal-status-loop",
+ "active": false,
+ "sequence": 0,
+ "profileId": null,
+ "iniPath": null,
+ "kinematicsModuleId": null,
+ "tickCount": 0,
+ "batchSize": 5,
+ "intervalMs": 25,
+ "taskPeriodNs": 10000000,
+ "servoPeriodNs": 1000000,
+ "lastStatusAt": null,
+ "lastError": null,
+ "stopReason": null,
+ "semanticBoundary": "js_status_polling_loop_for_linuxcnc_task_hal_motion_status"
+ },
+ "taskHalStatus": null,
+ "programRuntimeFeedback": null,
+ "feedbackHistoryLength": 0,
+ "currentLineExecution": null
+ },
+ "ui": {
+ "href": "https://82.156.24.101:8092/",
+ "title": "Web RTCP 5 Axis Simulation",
+ "hasRunReady": true,
+ "selectedSource": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzac.ngc",
+ "sourceOptions": [
+ {
+ "value": "",
+ "text": "select source"
+ },
+ {
+ "value": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzac.ngc",
+ "text": "boat-xyzac.ngc"
+ },
+ {
+ "value": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzbc.ngc",
+ "text": "boat-xyzbc.ngc"
+ },
+ {
+ "value": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/impeller-7bl-xyzac.ngc",
+ "text": "impeller-7bl-xyzac.ngc"
+ },
+ {
+ "value": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_1.ngc",
+ "text": "xyzac_switchkins_test_1.ngc"
+ },
+ {
+ "value": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_2.ngc",
+ "text": "xyzac_switchkins_test_2.ngc"
+ },
+ {
+ "value": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_3.ngc",
+ "text": "xyzac_switchkins_test_3.ngc"
+ },
+ {
+ "value": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins.ngc",
+ "text": "xyzac_switchkins.ngc"
+ },
+ {
+ "value": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzbc_switchkins.ngc",
+ "text": "xyzbc_switchkins.ngc"
+ }
+ ],
+ "currentLine": "10",
+ "activeUiLine": 9,
+ "activeLineExecutionText": "running",
+ "canvas": {
+ "fiveAxisCanvas": "true",
+ "engine": "three.js r183",
+ "threeReady": "true",
+ "threeRevision": "183",
+ "threePathPoints": "2",
+ "threeExecutedPathPoints": "1",
+ "threeSceneObjects": "20",
+ "threeToolhead": "{\"x\":0,\"y\":0,\"z\":0}",
+ "threeSceneUnits": "m",
+ "threeLinearUnits": "mm",
+ "threeLinearUnitScaleToMeters": "0.001",
+ "threeToolAxis": "{\"x\":0,\"y\":0,\"z\":1}",
+ "threeTcpPose": "{\"x\":0,\"y\":0,\"z\":-84.019,\"a\":0,\"c\":0}",
+ "threeRtcpState": "on",
+ "threeSelectedView": "iso",
+ "threeFrameApi": "web-rtcp-5axis-motion-frame",
+ "threeRenderer": "webgl",
+ "threeSceneMode": "program-preview-and-tool-execution",
+ "threePreviewScope": "machine-reference-and-toolpath",
+ "threeMachineReferenceModel": "webgl-five-axis-reference",
+ "threeCameraControls": "orbit-pan-zoom",
+ "threeProgramPreviewSource": "linuxcnc-interpreter-wasm",
+ "threeToolExecutionMarker": "true",
+ "threeTcpMarker": "sphere",
+ "threeToolAxisMarker": "line",
+ "threeToolpathPreviewSource": "linuxcnc_interpreter_canonical_motion",
+ "threeToolExecutionTraceSource": "linuxcnc_tp_samples_or_task_motion_hal_feedback",
+ "threePathFitBounds": "ok",
+ "threePathBoundsMeters": "{\"center\":{\"x\":0,\"y\":0,\"z\":0.002},\"size\":{\"x\":0,\"y\":0,\"z\":0.005},\"maxSpan\":0.005}",
+ "threeCurrentSegmentHighlight": "ok",
+ "threeRapidFeedVisualDistinction": "ok",
+ "threeNoGcodeSemanticsGeneration": "ok",
+ "threeRapidPathPoints": "2",
+ "threeFeedPathPoints": "0",
+ "threeArcPathPoints": "0",
+ "threeCurrentSegmentPoints": "2",
+ "threeCurrentSegmentType": "STRAIGHT_TRAVERSE"
+ },
+ "operatorMessage": "LinuxCNC interpreter motion events 2, switchkins M428/M429"
+ }
+ },
+ {
+ "name": "02-source-loaded",
+ "screenshot": "/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/output/cloud-run-debug-current/02-source-loaded.png",
+ "state": {
+ "machineProfile": "xyzac-trt",
+ "activeProgram": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/impeller-7bl-xyzac.ngc",
+ "programSource": "linuxcnc-vendored-5axis-gcode",
+ "programExecutionSourceMode": "linuxcnc-task-motion-hal-wasm",
+ "programMotionCount": 4492,
+ "programLineCount": 4507,
+ "programStartLine": 1,
+ "activeLine": 1,
+ "runState": "idle",
+ "machine": {
+ "powerOn": false,
+ "estopActive": false,
+ "taskState": "estop-reset",
+ "mode": "manual",
+ "interpState": "idle",
+ "interpResumeState": "idle",
+ "taskPaused": false,
+ "allHomed": false,
+ "noForceHoming": false,
+ "jogAxis": "x",
+ "jogIncrement": 1,
+ "mdiCommand": "G0 X0 Y0 Z0",
+ "mdiDistanceMode": "absolute",
+ "resetCount": 0
+ },
+ "kinsType": "tcp-xyzac",
+ "rtcpState": "on",
+ "axisPose": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0
+ },
+ "dro": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "a": 0,
+ "b": 0,
+ "c": 0,
+ "tcpX": 0,
+ "tcpY": 0,
+ "tcpZ": 0,
+ "dtgX": 0,
+ "dtgY": 0,
+ "dtgZ": 0
+ },
+ "operatorMessage": "LinuxCNC task/HAL session ready /work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/demos/impeller-7bl-xyzac.ngc",
+ "iniConfigReadiness": {
+ "apiName": "web-rtcp-5axis-ini-config-readiness",
+ "loaded": true,
+ "ready": true,
+ "path": "configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
+ "missing": [],
+ "machineName": "sim-xyzac-trt-kins (switchkins)",
+ "coordinates": "XYZAC",
+ "kinematics": "xyzac-trt-kins",
+ "axisCount": 5,
+ "jointCount": 5,
+ "semanticBoundary": "linuxcnc_ini_file_browser_parser"
+ },
+ "kinematicsRuntimeReadiness": {
+ "apiName": "web-rtcp-5axis-linuxcnc-kinematics-worker-runtime-readiness",
+ "moduleId": "xyzac-trt",
+ "wasmFile": "linuxcnc_xyzac_trt_kinematics.wasm",
+ "supportedModules": [
+ "trivkins",
+ "5axiskins",
+ "xyzac-trt",
+ "xyzbc-trt",
+ "corexy",
+ "rotate",
+ "rose",
+ "max",
+ "lineardelta",
+ "rotarydelta",
+ "scorbot",
+ "tripod",
+ "scara",
+ "puma",
+ "genser",
+ "genhex",
+ "pentakins"
+ ],
+ "loaded": true,
+ "sourceMode": "source-derived-kinematics-wasm",
+ "semanticBoundary": "linuxcnc_kinematics_wasm_c_abi",
+ "executionContext": "worker",
+ "switchkinsType": 0,
+ "switchRc": 0,
+ "workerUrl": "https://82.156.24.101:8092/src/runtime/linuxcnc-kinematics-worker.js"
+ },
+ "taskHalRuntimeReadiness": {
+ "apiName": "web-rtcp-5axis-linuxcnc-task-hal-runtime-readiness",
+ "loaded": true,
+ "semanticBoundary": "linuxcnc_task_motion_hal_wasm_simulation_runtime",
+ "sdkSemanticBoundary": "linuxcnc_task_motion_hal_wasm_phase4_minimal",
+ "executionContext": "direct",
+ "workerUrl": null,
+ "taskRuntimeReady": true,
+ "motionRuntimeReady": true,
+ "halRuntimeReady": true,
+ "halSyncReady": true,
+ "nativeTaskReady": true,
+ "nativeHalSyncReady": true,
+ "hardwareDrive": false,
+ "hostRealtimeKernel": false,
+ "externalUserMProcessReady": false
+ },
+ "machineFileStaging": {
+ "status": "staged",
+ "fileCount": 18,
+ "selectedGcodeSourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/impeller-7bl-xyzac.ngc",
+ "gcodeSources": [
+ {
+ "sourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzac.ngc",
+ "wasmPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/demos/boat-xyzac.ngc",
+ "opfsPath": "web-rtcp-5axis-sim-plan/machines/xyzac-trt/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzac.ngc",
+ "filename": "boat-xyzac.ngc",
+ "bytes": 70847,
+ "label": "boat-xyzac",
+ "sourceMode": "linuxcnc-vendored-5axis-gcode",
+ "semanticBoundary": "linuxcnc_vendored_5axis_gcode_source_file"
+ },
+ {
+ "sourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzbc.ngc",
+ "wasmPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/demos/boat-xyzbc.ngc",
+ "opfsPath": "web-rtcp-5axis-sim-plan/machines/xyzac-trt/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzbc.ngc",
+ "filename": "boat-xyzbc.ngc",
+ "bytes": 76616,
+ "label": "boat-xyzbc",
+ "sourceMode": "linuxcnc-vendored-5axis-gcode",
+ "semanticBoundary": "linuxcnc_vendored_5axis_gcode_source_file"
+ },
+ {
+ "sourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/impeller-7bl-xyzac.ngc",
+ "wasmPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/demos/impeller-7bl-xyzac.ngc",
+ "opfsPath": "web-rtcp-5axis-sim-plan/machines/xyzac-trt/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/impeller-7bl-xyzac.ngc",
+ "filename": "impeller-7bl-xyzac.ngc",
+ "bytes": 294411,
+ "label": "impeller-7bl-xyzac",
+ "sourceMode": "linuxcnc-vendored-5axis-gcode",
+ "semanticBoundary": "linuxcnc_vendored_5axis_gcode_source_file"
+ },
+ {
+ "sourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_1.ngc",
+ "wasmPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/demos/xyzac_switchkins_test_1.ngc",
+ "opfsPath": "web-rtcp-5axis-sim-plan/machines/xyzac-trt/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_1.ngc",
+ "filename": "xyzac_switchkins_test_1.ngc",
+ "bytes": 419,
+ "label": "xyzac_switchkins_test_1",
+ "sourceMode": "linuxcnc-vendored-5axis-gcode",
+ "semanticBoundary": "linuxcnc_vendored_5axis_gcode_source_file"
+ },
+ {
+ "sourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_2.ngc",
+ "wasmPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/demos/xyzac_switchkins_test_2.ngc",
+ "opfsPath": "web-rtcp-5axis-sim-plan/machines/xyzac-trt/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_2.ngc",
+ "filename": "xyzac_switchkins_test_2.ngc",
+ "bytes": 475,
+ "label": "xyzac_switchkins_test_2",
+ "sourceMode": "linuxcnc-vendored-5axis-gcode",
+ "semanticBoundary": "linuxcnc_vendored_5axis_gcode_source_file"
+ },
+ {
+ "sourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_3.ngc",
+ "wasmPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/demos/xyzac_switchkins_test_3.ngc",
+ "opfsPath": "web-rtcp-5axis-sim-plan/machines/xyzac-trt/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_3.ngc",
+ "filename": "xyzac_switchkins_test_3.ngc",
+ "bytes": 304,
+ "label": "xyzac_switchkins_test_3",
+ "sourceMode": "linuxcnc-vendored-5axis-gcode",
+ "semanticBoundary": "linuxcnc_vendored_5axis_gcode_source_file"
+ },
+ {
+ "sourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins.ngc",
+ "wasmPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/demos/xyzac_switchkins.ngc",
+ "opfsPath": "web-rtcp-5axis-sim-plan/machines/xyzac-trt/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins.ngc",
+ "filename": "xyzac_switchkins.ngc",
+ "bytes": 139,
+ "label": "xyzac_switchkins",
+ "sourceMode": "linuxcnc-vendored-5axis-gcode",
+ "semanticBoundary": "linuxcnc_vendored_5axis_gcode_source_file"
+ },
+ {
+ "sourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzbc_switchkins.ngc",
+ "wasmPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/demos/xyzbc_switchkins.ngc",
+ "opfsPath": "web-rtcp-5axis-sim-plan/machines/xyzac-trt/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzbc_switchkins.ngc",
+ "filename": "xyzbc_switchkins.ngc",
+ "bytes": 139,
+ "label": "xyzbc_switchkins",
+ "sourceMode": "linuxcnc-vendored-5axis-gcode",
+ "semanticBoundary": "linuxcnc_vendored_5axis_gcode_source_file"
+ }
+ ]
+ },
+ "taskHalSession": {
+ "apiName": "web-rtcp-5axis-task-hal-session",
+ "semanticBoundary": "linuxcnc_machine_files_for_task_hal_wasm_runtime",
+ "profileId": "xyzac-trt",
+ "iniPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/xyzac-trt.ini",
+ "iniText": "[APPLICATIONS]\n# uncomment to enable:\n#APP = halshow --fformat %.5f switchkins.halshow\n\n[EMC]\nVERSION = 1.1\nMACHINE = sim-xyzac-trt-kins (switchkins)\n\n[DISPLAY]\n GEOMETRY = XYZ-A\n OPEN_FILE = ./demos/xyzac_switchkins.ngc\n PYVCP = ./xyzac-trt.xml\n JOG_AXES = XYZC\n DISPLAY = axis\nMAX_ANGULAR_VELOCITY = 360\n MAX_LINEAR_VELOCITY = 1000\n POSITION_OFFSET = RELATIVE\n POSITION_FEEDBACK = ACTUAL\n MAX_FEED_OVERRIDE = 2\n PROGRAM_PREFIX = ../../nc_files\n INTRO_GRAPHIC = emc2.gif\n INTRO_TIME = 1\n #EDITOR = geany\n TOOL_EDITOR = tooledit z diam\n\n TKPKG = Ngcgui 1.0\n NGCGUI_FONT = Helvetica -12 normal\n NGCGUI_SUBFILE = xyzac_switchkins_sub.ngc\n NGCGUI_SUBFILE = centering.ngc\n\n[RS274NGC]\nSUBROUTINE_PATH = ./remap_subs\n HAL_PIN_VARS = 1\n REMAP = M428 modalgroup=10 ngc=428remap\n REMAP = M429 modalgroup=10 ngc=429remap\n REMAP = M430 modalgroup=10 ngc=430remap\n PARAMETER_FILE = xyzac.var\n\n[KINS]\n#NOTE: for backwrds compatibility !!!!!!!!!!!!!!!!!!!\n# default switchkins-type == 0 is xyzac-trt-kins\n# here switchkins-type == 0 is identity kins\nKINEMATICS = xyzac-trt-kins sparm=identityfirst\n JOINTS = 5\n\n[HAL]\n HALUI = halui\n HALFILE = LIB:basic_sim.tcl\nPOSTGUI_HALFILE = switchkins_postgui.hal\n\n# net for control of motion.switchkins-type\nHALCMD = net :kinstype-select <= motion.analog-out-03 => motion.switchkins-type\n\n# vismach xyzac-trt-gui items\nHALCMD = loadusr -W xyzac-trt-gui\nHALCMD = net :table-x joint.0.pos-fb xyzac-trt-gui.table-x\nHALCMD = net :saddle-y joint.1.pos-fb xyzac-trt-gui.saddle-y\nHALCMD = net :spindle-z joint.2.pos-fb xyzac-trt-gui.spindle-z\nHALCMD = net :tilt-a joint.3.pos-fb xyzac-trt-gui.tilt-a\nHALCMD = net :rotate-c joint.4.pos-fb xyzac-trt-gui.rotate-c\nHALCMD = net :tool-offset motion.tooloffset.z\nHALCMD = net :tool-offset xyzac-trt-kins.tool-offset xyzac-trt-gui.tool-offset\nHALCMD = net :y-offset xyzac-trt-kins.y-offset xyzac-trt-gui.y-offset\nHALCMD = net :z-offset xyzac-trt-kins.z-offset xyzac-trt-gui.z-offset\nHALCMD = sets :y-offset 20\nHALCMD = sets :z-offset 10\n\n# not currently supported by xyzac-trt-gui:\nHALCMD = setp xyzac-trt-kins.x-rot-point 0\nHALCMD = setp xyzac-trt-kins.y-rot-point 0\nHALCMD = setp xyzac-trt-kins.z-rot-point 0\nHALCMD = setp xyzac-trt-kins.conventional-directions 0\n\n[HALUI]\n# NOTE: kinstype==0 is identity kins because sparm=identityfirst\n# M429:identity kins (motion.switchkins-type==0 startupDEFAULT)\n# M428:xyzac kins (motion.switchkins-type==1)\n# M430:userk kins (motion.switchkins-type==2)\nMDI_COMMAND = M429\nMDI_COMMAND = M428\nMDI_COMMAND = M430\n\n[TRAJ]\n COORDINATES = XYZAC\n LINEAR_UNITS = mm\n ANGULAR_UNITS = deg\n DEFAULT_LINEAR_VELOCITY = 20\n MAX_LINEAR_VELOCITY = 35\n MAX_LINEAR_ACCELERATION = 400\nDEFAULT_LINEAR_ACCELERATION = 300\n\n[EMCMOT]\n EMCMOT = motmod\nSERVO_PERIOD = 1000000\nCOMM_TIMEOUT = 1\n\n[TASK]\n TASK = milltask\nCYCLE_TIME = 0.010\n\n[EMCIO]\nTOOL_TABLE = xyzac-trt.tbl\n\n[AXIS_X]\n MIN_LIMIT = -200\n MAX_LIMIT = 200\n MAX_VELOCITY = 20\nMAX_ACCELERATION = 300\n\n[AXIS_Y]\n MIN_LIMIT = -100\n MAX_LIMIT = 100\n MAX_VELOCITY = 20\nMAX_ACCELERATION = 300\n\n[AXIS_Z]\n MIN_LIMIT = -120\n MAX_LIMIT = 120\n MAX_VELOCITY = 20\nMAX_ACCELERATION = 300\n\n[AXIS_A]\n MIN_LIMIT = -100\n MAX_LIMIT = 50\n MAX_VELOCITY = 30\nMAX_ACCELERATION = 300\n\n[AXIS_C]\n MIN_LIMIT = -36000\n MAX_LIMIT = 36000\n MAX_VELOCITY = 30\nMAX_ACCELERATION = 300\n\n[JOINT_0]\n TYPE = LINEAR\n HOME = 0\n MAX_VELOCITY = 20\n MAX_ACCELERATION = 300\n MIN_LIMIT = -200\n MAX_LIMIT = 200\n HOME_SEARCH_VEL = 0\n HOME_SEQUENCE = 0\n\n[JOINT_1]\n TYPE = LINEAR\n HOME = 0\n MAX_VELOCITY = 20\n MAX_ACCELERATION = 300\n MIN_LIMIT = -100\n MAX_LIMIT = 100\n HOME_SEARCH_VEL = 0\n HOME_SEQUENCE = 0\n\n[JOINT_2]\n TYPE = LINEAR\n HOME = 0\n MAX_VELOCITY = 20\n MAX_ACCELERATION = 300\n MIN_LIMIT = -120\n MAX_LIMIT = 120\n HOME_SEARCH_VEL = 0\n HOME_SEQUENCE = 0\n\n[JOINT_3]\n TYPE = ANGULAR\n HOME = 0\n MAX_VELOCITY = 30\nMAX_ACCELERATION = 300\n MIN_LIMIT = -100\n MAX_LIMIT = 50\n HOME_SEARCH_VEL = 0\n HOME_SEQUENCE = 0\n\n[JOINT_4]\n TYPE = ANGULAR\n HOME = 0\n MAX_VELOCITY = 30\nMAX_ACCELERATION = 300\n MIN_LIMIT = -36000\n MAX_LIMIT = 36000\n HOME_SEARCH_VEL = 0\n HOME_SEQUENCE = 0\n",
+ "programPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/demos/impeller-7bl-xyzac.ngc",
+ "programSourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/impeller-7bl-xyzac.ngc",
+ "halFiles": [],
+ "toolTableFiles": [
+ {
+ "sourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.tbl",
+ "wasmPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/xyzac-trt.tbl",
+ "path": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/xyzac-trt.tbl",
+ "kind": "toolTable",
+ "bytes": 169,
+ "text": "T1 P1 Z0 D1 ;end mill\nT2 P2 Z15 D8 ;end mill\nT3 P3 Z0 D4.2 ;#7 tap drill\nT4 P4 Z0 D10\nT5 P5 Z30 D10\nT6 P6 Z30 D10\nT7 P7 Z30 D10\nT8 P8 Z30 D10\nT9 P9 Z30 D10\nT10 P10 D0.5\n"
+ }
+ ],
+ "remapFiles": [
+ {
+ "sourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/428remap.ngc",
+ "wasmPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/remap_subs/428remap.ngc",
+ "path": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/remap_subs/428remap.ngc",
+ "kind": "remap",
+ "bytes": 688,
+ "text": ";M428 by remap: kinstype==1 (xyzac,xyzbc) (note: sparm=identityfirst)\no<428remap>sub\n # = 1 ; xyzac,xyzbc\n # = 3 ; set N as required: motion.analog-out-0N\n\no1 if [exists [#<_hal[motion.switchkins-type]>]]\no1 else\n (debug,M428:Missing [RS274NGC]HAL_PIN_VARS=1)\n (debug,STOP)\n M2\no1 endif\n\n M68 E# Q# ; set kinstype value\n M66 E0 L0 ; force synch\n\no2 if [[#<_task> EQ 1] AND [#<_hal[motion.switchkins-type]> NE #]]\n (debug,M428: Wrong motion.switchkins-type)\n (debug,or missing hal net to analog-out-0x)\n (debug,STOP)\n M2\no2 else\no2 endif\n\no<428remap>endsub\n"
+ },
+ {
+ "sourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/429remap.ngc",
+ "wasmPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/remap_subs/429remap.ngc",
+ "path": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/remap_subs/429remap.ngc",
+ "kind": "remap",
+ "bytes": 644,
+ "text": ";M429 by remap: kinstype==0 Identity kinematics\no<429remap>sub\n # = 0\n # = 3 ; set N as required: motion.analog-out-0N\n\no1 if [exists [#<_hal[motion.switchkins-type]>]]\no1 else\n (debug,M429:Missing [RS274NGC]HAL_PIN_VARS=1)\n (debug,STOP)\n M2\no1 endif\n\n M68 E# Q# ; set kinstype value\n M66 E0 L0 ; force synch\n\no2 if [[#<_task> EQ 1] AND [#<_hal[motion.switchkins-type]> NE #]]\n (debug,M429:Wrong motion.switchkins-type)\n (debug,or missing hal net to analog-out-0x)\n (debug,STOP)\n M2\no2 else\no2 endif\n\no<429remap>endsub\n"
+ },
+ {
+ "sourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/430remap.ngc",
+ "wasmPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/remap_subs/430remap.ngc",
+ "path": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/remap_subs/430remap.ngc",
+ "kind": "remap",
+ "bytes": 635,
+ "text": ";M430 by remap: kinstype==2 userk kins\no<430remap>sub\n # = 2\n # = 3 ; set N as required: motion.analog-out-0N\n\no1 if [exists [#<_hal[motion.switchkins-type]>]]\no1 else\n (debug,M430:Missing [RS274NGC]HAL_PIN_VARS=1)\n (debug,STOP)\n M2\no1 endif\n\n M68 E# Q# ; set kinstype value\n M66 E0 L0 ; force synch\n\no2 if [[#<_task> EQ 1] AND [#<_hal[motion.switchkins-type]> NE #]]\n (debug,M430:Wrong motion.switchkins-type)\n (debug,or missing hal net to analog-out-0x)\n (debug,STOP)\n M2\no2 else\no2 endif\n\no<430remap>endsub\n"
+ },
+ {
+ "sourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/centering.ngc",
+ "wasmPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/remap_subs/centering.ngc",
+ "path": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/remap_subs/centering.ngc",
+ "kind": "remap",
+ "bytes": 1134,
+ "text": "(info: tests for values of [xyz]-rot-point)\nosub\n# = #1 (=-2.5)\n# = #2 (=-2.5)\n # = #3 (= 5)\n # = #4 (= 5)\n# = #5 (=60)\n # = #6 (=12)\n # = #7 (=1000 feed)\n# = 0\n# = [360/#]\n\no1 if [exists [#<_hal[xyzac-trt-kins.x-rot-point]>]]\n (debug,x-rot-point=#<_hal[xyzac-trt-kins.x-rot-point]>)\n (debug,y-rot-point=#<_hal[xyzac-trt-kins.y-rot-point]>)\n (debug,z-rot-point=#<_hal[xyzac-trt-kins.z-rot-point]>)\no1 endif\no2 if [exists [#<_hal[xyzbc-trt-kins.x-rot-point]>]]\n (debug,x-rot-point=#<_hal[xyzbc-trt-kins.x-rot-point]>)\n (debug,y-rot-point=#<_hal[xyzbc-trt-kins.y-rot-point]>)\n (debug,z-rot-point=#<_hal[xyzac-trt-kins.z-rot-point]>)\no2 endif\n\nM429 ;Identity kinematics\ng0 x# y# z0 c0\nM428 ;tcp\n\ng61\no10 while [# le 360]\n g1 f#\n # = [# + #]\n g0 c#\n g1 x[# + #]\n g1 y[# + #]\n g1 x[# + 0 ]\n g1 y[# + 0 ]\no10 endwhile\n\n\nM429 ;Identity kinematics\ng0 x0 y0 z# c0\noendsub\n"
+ },
+ {
+ "sourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/helix_ac.ngc",
+ "wasmPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/remap_subs/helix_ac.ngc",
+ "path": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/remap_subs/helix_ac.ngc",
+ "kind": "remap",
+ "bytes": 735,
+ "text": "; helix using switchkins (xyzac) a,c angles\nosub\n # = #1 (=10)\n # = #2 (= 5)\n # = #3 (=10)\n # = #4 (=1000)\n # = #5 (=3)\n # = #6 (=45)\n # = #7 (=0 NA)\n # = #8 (=20)\n\n M429 ;Identity kinematics\n g0 x[#<_x> - #] ;adjust for radius\n g10l20p0 x0y0 z# a0 c0 ;new g54\n M428 ;XYZAC\n g0a#c# ;exercise a,c\n f# g2i#z# p# ;helix\n M429 ;Identity kinematics\n g0 x0 y0 z# a0 c0 ;return to start\n g0 x[#<_x> + #] ;adjust restore\n M428 ;XYZAC\noendsub\n"
+ },
+ {
+ "sourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/helix_bc.ngc",
+ "wasmPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/remap_subs/helix_bc.ngc",
+ "path": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/remap_subs/helix_bc.ngc",
+ "kind": "remap",
+ "bytes": 735,
+ "text": "; helix using switchkins (xyzbc) b,c angles\nosub\n # = #1 (=10)\n # = #2 (= 5)\n # = #3 (=10)\n # = #4 (=1000)\n # = #5 (=3)\n # = #6 (=0 NA)\n # = #7 (=45)\n # = #8 (=20)\n\n M429 ;Identity kinematics\n g0 x[#<_x> - #] ;adjust for radius\n g10l20p0 x0y0 z# b0 c0 ;new g54\n M428 ;XYZBC\n g0b#c# ;exercise b,c\n f# g2i#z# p# ;helix\n M429 ;Identity kinematics\n g0 x0 y0 z# b0 c0 ;return to start\n g0 x[#<_x> + #] ;adjust restore\n M428 ;XYZBC\noendsub\n"
+ },
+ {
+ "sourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/xyzac_switchkins_sub.ngc",
+ "wasmPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/remap_subs/xyzac_switchkins_sub.ngc",
+ "path": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/remap_subs/xyzac_switchkins_sub.ngc",
+ "kind": "remap",
+ "bytes": 1547,
+ "text": "; ngcgui-compatible subroutine\n(info: helix in each quadrant at angles A,C)\nosub\n # = #1 (=10)\n # = #2 (= 5)\n # = #3 (=10 radius)\n # = #4 (=1000 feedrate)\n # = #5 (=3 n circles)\n # = #6 (=30 A angle)\n # = #7 (=0 B angle NA)\n # = #8 (=45 C angle)\n # = #9 (=20 distance)\n\n; quadrant I\nM429 ;Identity kinematics\ng53 g0 x0y0 z# a0 c0 ;MACHINE coordinates\ng10l20p0 x0y0 z# a0 c0 ;new g54\ng0 x+# y+# z# ;move to pattern center position\no call [#][#][#][#][#][#][#][#]\n\n; quadrant II\nM429 ;Identity kinematics\ng53 g0 x0y0 z# a0 c0\ng10l20p0 x0y0 z# a0 c0\ng0 x-# y+# z#\no call [#][#][#][#][#][#][#][#]\n\n; quadrant III\nM429 ;Identity kinematics\ng53 g0 x0y0 z# a0 c0\ng10l20p0 x0y0 z# a0 c0\ng0 x-# y-# z#\no call [#][#][#][#][#][#][#][#]\n\n; quadrant IV\nM429 ;Identity kinematics\ng53 g0 x0y0 z# a0 c0\ng10l20p0 x0y0 z# a0 c0\ng0 x+# y-# z#\no call [#][#][#][#][#][#][#][#]\n\n;final position\nM429 ;Identity kinematics\ng53 g0 x0y0 z# ;MACHINE coordinates\ng10l20p0 x0y0 z# ;new g54\n\noendsub\n"
+ },
+ {
+ "sourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/xyzbc_switchkins_sub.ngc",
+ "wasmPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/remap_subs/xyzbc_switchkins_sub.ngc",
+ "path": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/remap_subs/xyzbc_switchkins_sub.ngc",
+ "kind": "remap",
+ "bytes": 1547,
+ "text": "; ngcgui-compatible subroutine\n(info: helix in each quadrant at angles B,C)\nosub\n # = #1 (=10)\n # = #2 (= 5)\n # = #3 (=10 radius)\n # = #4 (=1000 feedrate)\n # = #5 (=3 n circles)\n # = #6 (=0 A angle NA)\n # = #7 (=30 B angle)\n # = #8 (=45 C angle)\n # = #9 (=20 distance)\n\n; quadrant I\nM429 ;Identity kinematics\ng53 g0 x0y0 z# b0 c0 ;MACHINE coordinates\ng10l20p0 x0y0 z# b0 c0 ;new g54\ng0 x+# y+# z# ;move to pattern center position\no call [#][#][#][#][#][#][#][#]\n\n; quadrant II\nM429 ;Identity kinematics\ng53 g0 x0y0 z# b0 c0\ng10l20p0 x0y0 z# b0 c0\ng0 x-# y+# z#\no call [#][#][#][#][#][#][#][#]\n\n; quadrant III\nM429 ;Identity kinematics\ng53 g0 x0y0 z# b0 c0\ng10l20p0 x0y0 z# b0 c0\ng0 x-# y-# z#\no call [#][#][#][#][#][#][#][#]\n\n; quadrant IV\nM429 ;Identity kinematics\ng53 g0 x0y0 z# b0 c0\ng10l20p0 x0y0 z# b0 c0\ng0 x+# y-# z#\no call [#][#][#][#][#][#][#][#]\n\n;final position\nM429 ;Identity kinematics\ng53 g0 x0y0 z# ;MACHINE coordinates\ng10l20p0 x0y0 z# ;new g54\n\noendsub\n"
+ }
+ ],
+ "files": [
+ {
+ "sourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
+ "wasmPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/xyzac-trt.ini",
+ "path": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/xyzac-trt.ini",
+ "kind": "ini",
+ "bytes": 4877,
+ "text": "[APPLICATIONS]\n# uncomment to enable:\n#APP = halshow --fformat %.5f switchkins.halshow\n\n[EMC]\nVERSION = 1.1\nMACHINE = sim-xyzac-trt-kins (switchkins)\n\n[DISPLAY]\n GEOMETRY = XYZ-A\n OPEN_FILE = ./demos/xyzac_switchkins.ngc\n PYVCP = ./xyzac-trt.xml\n JOG_AXES = XYZC\n DISPLAY = axis\nMAX_ANGULAR_VELOCITY = 360\n MAX_LINEAR_VELOCITY = 1000\n POSITION_OFFSET = RELATIVE\n POSITION_FEEDBACK = ACTUAL\n MAX_FEED_OVERRIDE = 2\n PROGRAM_PREFIX = ../../nc_files\n INTRO_GRAPHIC = emc2.gif\n INTRO_TIME = 1\n #EDITOR = geany\n TOOL_EDITOR = tooledit z diam\n\n TKPKG = Ngcgui 1.0\n NGCGUI_FONT = Helvetica -12 normal\n NGCGUI_SUBFILE = xyzac_switchkins_sub.ngc\n NGCGUI_SUBFILE = centering.ngc\n\n[RS274NGC]\nSUBROUTINE_PATH = ./remap_subs\n HAL_PIN_VARS = 1\n REMAP = M428 modalgroup=10 ngc=428remap\n REMAP = M429 modalgroup=10 ngc=429remap\n REMAP = M430 modalgroup=10 ngc=430remap\n PARAMETER_FILE = xyzac.var\n\n[KINS]\n#NOTE: for backwrds compatibility !!!!!!!!!!!!!!!!!!!\n# default switchkins-type == 0 is xyzac-trt-kins\n# here switchkins-type == 0 is identity kins\nKINEMATICS = xyzac-trt-kins sparm=identityfirst\n JOINTS = 5\n\n[HAL]\n HALUI = halui\n HALFILE = LIB:basic_sim.tcl\nPOSTGUI_HALFILE = switchkins_postgui.hal\n\n# net for control of motion.switchkins-type\nHALCMD = net :kinstype-select <= motion.analog-out-03 => motion.switchkins-type\n\n# vismach xyzac-trt-gui items\nHALCMD = loadusr -W xyzac-trt-gui\nHALCMD = net :table-x joint.0.pos-fb xyzac-trt-gui.table-x\nHALCMD = net :saddle-y joint.1.pos-fb xyzac-trt-gui.saddle-y\nHALCMD = net :spindle-z joint.2.pos-fb xyzac-trt-gui.spindle-z\nHALCMD = net :tilt-a joint.3.pos-fb xyzac-trt-gui.tilt-a\nHALCMD = net :rotate-c joint.4.pos-fb xyzac-trt-gui.rotate-c\nHALCMD = net :tool-offset motion.tooloffset.z\nHALCMD = net :tool-offset xyzac-trt-kins.tool-offset xyzac-trt-gui.tool-offset\nHALCMD = net :y-offset xyzac-trt-kins.y-offset xyzac-trt-gui.y-offset\nHALCMD = net :z-offset xyzac-trt-kins.z-offset xyzac-trt-gui.z-offset\nHALCMD = sets :y-offset 20\nHALCMD = sets :z-offset 10\n\n# not currently supported by xyzac-trt-gui:\nHALCMD = setp xyzac-trt-kins.x-rot-point 0\nHALCMD = setp xyzac-trt-kins.y-rot-point 0\nHALCMD = setp xyzac-trt-kins.z-rot-point 0\nHALCMD = setp xyzac-trt-kins.conventional-directions 0\n\n[HALUI]\n# NOTE: kinstype==0 is identity kins because sparm=identityfirst\n# M429:identity kins (motion.switchkins-type==0 startupDEFAULT)\n# M428:xyzac kins (motion.switchkins-type==1)\n# M430:userk kins (motion.switchkins-type==2)\nMDI_COMMAND = M429\nMDI_COMMAND = M428\nMDI_COMMAND = M430\n\n[TRAJ]\n COORDINATES = XYZAC\n LINEAR_UNITS = mm\n ANGULAR_UNITS = deg\n DEFAULT_LINEAR_VELOCITY = 20\n MAX_LINEAR_VELOCITY = 35\n MAX_LINEAR_ACCELERATION = 400\nDEFAULT_LINEAR_ACCELERATION = 300\n\n[EMCMOT]\n EMCMOT = motmod\nSERVO_PERIOD = 1000000\nCOMM_TIMEOUT = 1\n\n[TASK]\n TASK = milltask\nCYCLE_TIME = 0.010\n\n[EMCIO]\nTOOL_TABLE = xyzac-trt.tbl\n\n[AXIS_X]\n MIN_LIMIT = -200\n MAX_LIMIT = 200\n MAX_VELOCITY = 20\nMAX_ACCELERATION = 300\n\n[AXIS_Y]\n MIN_LIMIT = -100\n MAX_LIMIT = 100\n MAX_VELOCITY = 20\nMAX_ACCELERATION = 300\n\n[AXIS_Z]\n MIN_LIMIT = -120\n MAX_LIMIT = 120\n MAX_VELOCITY = 20\nMAX_ACCELERATION = 300\n\n[AXIS_A]\n MIN_LIMIT = -100\n MAX_LIMIT = 50\n MAX_VELOCITY = 30\nMAX_ACCELERATION = 300\n\n[AXIS_C]\n MIN_LIMIT = -36000\n MAX_LIMIT = 36000\n MAX_VELOCITY = 30\nMAX_ACCELERATION = 300\n\n[JOINT_0]\n TYPE = LINEAR\n HOME = 0\n MAX_VELOCITY = 20\n MAX_ACCELERATION = 300\n MIN_LIMIT = -200\n MAX_LIMIT = 200\n HOME_SEARCH_VEL = 0\n HOME_SEQUENCE = 0\n\n[JOINT_1]\n TYPE = LINEAR\n HOME = 0\n MAX_VELOCITY = 20\n MAX_ACCELERATION = 300\n MIN_LIMIT = -100\n MAX_LIMIT = 100\n HOME_SEARCH_VEL = 0\n HOME_SEQUENCE = 0\n\n[JOINT_2]\n TYPE = LINEAR\n HOME = 0\n MAX_VELOCITY = 20\n MAX_ACCELERATION = 300\n MIN_LIMIT = -120\n MAX_LIMIT = 120\n HOME_SEARCH_VEL = 0\n HOME_SEQUENCE = 0\n\n[JOINT_3]\n TYPE = ANGULAR\n HOME = 0\n MAX_VELOCITY = 30\nMAX_ACCELERATION = 300\n MIN_LIMIT = -100\n MAX_LIMIT = 50\n HOME_SEARCH_VEL = 0\n HOME_SEQUENCE = 0\n\n[JOINT_4]\n TYPE = ANGULAR\n HOME = 0\n MAX_VELOCITY = 30\nMAX_ACCELERATION = 300\n MIN_LIMIT = -36000\n MAX_LIMIT = 36000\n HOME_SEARCH_VEL = 0\n HOME_SEQUENCE = 0\n"
+ },
+ {
+ "sourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins.ngc",
+ "wasmPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/demos/xyzac_switchkins.ngc",
+ "path": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/demos/xyzac_switchkins.ngc",
+ "kind": "demo",
+ "bytes": 139,
+ "text": "; zmax zmin r frate n a b c dist\no call [10] [5] [10][1000][3][20][0][45][20]\nm2\n"
+ },
+ {
+ "sourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.tbl",
+ "wasmPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/xyzac-trt.tbl",
+ "path": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/xyzac-trt.tbl",
+ "kind": "toolTable",
+ "bytes": 169,
+ "text": "T1 P1 Z0 D1 ;end mill\nT2 P2 Z15 D8 ;end mill\nT3 P3 Z0 D4.2 ;#7 tap drill\nT4 P4 Z0 D10\nT5 P5 Z30 D10\nT6 P6 Z30 D10\nT7 P7 Z30 D10\nT8 P8 Z30 D10\nT9 P9 Z30 D10\nT10 P10 D0.5\n"
+ },
+ {
+ "sourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/428remap.ngc",
+ "wasmPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/remap_subs/428remap.ngc",
+ "path": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/remap_subs/428remap.ngc",
+ "kind": "remap",
+ "bytes": 688,
+ "text": ";M428 by remap: kinstype==1 (xyzac,xyzbc) (note: sparm=identityfirst)\no<428remap>sub\n # = 1 ; xyzac,xyzbc\n # = 3 ; set N as required: motion.analog-out-0N\n\no1 if [exists [#<_hal[motion.switchkins-type]>]]\no1 else\n (debug,M428:Missing [RS274NGC]HAL_PIN_VARS=1)\n (debug,STOP)\n M2\no1 endif\n\n M68 E# Q# ; set kinstype value\n M66 E0 L0 ; force synch\n\no2 if [[#<_task> EQ 1] AND [#<_hal[motion.switchkins-type]> NE #]]\n (debug,M428: Wrong motion.switchkins-type)\n (debug,or missing hal net to analog-out-0x)\n (debug,STOP)\n M2\no2 else\no2 endif\n\no<428remap>endsub\n"
+ },
+ {
+ "sourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/429remap.ngc",
+ "wasmPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/remap_subs/429remap.ngc",
+ "path": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/remap_subs/429remap.ngc",
+ "kind": "remap",
+ "bytes": 644,
+ "text": ";M429 by remap: kinstype==0 Identity kinematics\no<429remap>sub\n # = 0\n # = 3 ; set N as required: motion.analog-out-0N\n\no1 if [exists [#<_hal[motion.switchkins-type]>]]\no1 else\n (debug,M429:Missing [RS274NGC]HAL_PIN_VARS=1)\n (debug,STOP)\n M2\no1 endif\n\n M68 E# Q# ; set kinstype value\n M66 E0 L0 ; force synch\n\no2 if [[#<_task> EQ 1] AND [#<_hal[motion.switchkins-type]> NE #]]\n (debug,M429:Wrong motion.switchkins-type)\n (debug,or missing hal net to analog-out-0x)\n (debug,STOP)\n M2\no2 else\no2 endif\n\no<429remap>endsub\n"
+ },
+ {
+ "sourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/430remap.ngc",
+ "wasmPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/remap_subs/430remap.ngc",
+ "path": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/remap_subs/430remap.ngc",
+ "kind": "remap",
+ "bytes": 635,
+ "text": ";M430 by remap: kinstype==2 userk kins\no<430remap>sub\n # = 2\n # = 3 ; set N as required: motion.analog-out-0N\n\no1 if [exists [#<_hal[motion.switchkins-type]>]]\no1 else\n (debug,M430:Missing [RS274NGC]HAL_PIN_VARS=1)\n (debug,STOP)\n M2\no1 endif\n\n M68 E# Q# ; set kinstype value\n M66 E0 L0 ; force synch\n\no2 if [[#<_task> EQ 1] AND [#<_hal[motion.switchkins-type]> NE #]]\n (debug,M430:Wrong motion.switchkins-type)\n (debug,or missing hal net to analog-out-0x)\n (debug,STOP)\n M2\no2 else\no2 endif\n\no<430remap>endsub\n"
+ },
+ {
+ "sourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/centering.ngc",
+ "wasmPath": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/remap_subs/centering.ngc",
+ "path": "/work/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt/remap_subs/centering.ngc",
+ "kind": "remap",
+ "bytes": 1134,
+ "text": "(info: tests for values of [xyz]-rot-point)\nosub\n# = #1 (=-2.5)\n# = #2 (=-2.5)\n # = #3 (= 5)\n # = #4 (= 5)\n# = #5 (=60)\n # = #6 (=12)\n # = #7 (=1000 feed)\n# = 0\n# = [360/#]\n\no1 if [exists [#<_hal[xyzac-trt-kins.x-rot-point]>]]\n (debug,x-rot-point=#<_hal[xyzac-trt-kins.x-rot-point]>)\n (debug,y-rot-point=#<_hal[xyzac-trt-kins.y-rot-point]>)\n (debug,z-rot-point=#<_hal[xyzac-trt-kins.z-rot-point]>)\no1 endif\no2 if [exists [#<_hal[xyzbc-trt-kins.x-rot-point]>]]\n (debug,x-rot-point=#<_hal[xyzbc-trt-kins.x-rot-point]>)\n (debug,y-rot-point=#<_hal[xyzbc-trt-kins.y-rot-point]>)\n (debug,z-rot-point=#<_hal[xyzac-trt-kins.z-rot-point]>)\no2 endif\n\nM429 ;Identity kinematics\ng0 x# y# z0 c0\nM428 ;tcp\n\ng61\no10 while [# le 360]\n g1 f#\n # = [# + #