From 7b81aa9cc9b3f51d666d67f1130e3da430161093 Mon Sep 17 00:00:00 2001 From: wangdequan Date: Sun, 23 Aug 2026 08:03:39 +0800 Subject: [PATCH] Authorize Chromium GUI visual evidence --- .../browser-matrix-remediation.report.json | 12 +-- .../browser-performance-matrix.report.json | 38 +++---- coverage/gui-browser-visual-fe-m4.report.json | 102 +++++++++++------- nextTask1.md | 6 +- scripts/generate_gui_browser_visual_report.py | 20 +++- scripts/test_gui_browser_visual_report.py | 2 + 6 files changed, 110 insertions(+), 70 deletions(-) diff --git a/coverage/browser-matrix-remediation.report.json b/coverage/browser-matrix-remediation.report.json index 916fdfb..d1db868 100644 --- a/coverage/browser-matrix-remediation.report.json +++ b/coverage/browser-matrix-remediation.report.json @@ -66,21 +66,21 @@ "bytes": 11539, "path": "coverage/compatibility-matrix.report.json", "role": "compatibility_matrix", - "sha256": "1079e4da3d18044a98b38e4e083eff90b26c6adfaa0d4903a636d19988af963b", + "sha256": "eb655edbcd2379f6b93a0b5e03e965d3c369fb2ba599684d99d25d8cdea79346", "status": "present" }, { "bytes": 7196, "path": "coverage/release-candidate-gate.report.json", "role": "release_candidate_gate", - "sha256": "2092257cc0aea41c5988b19a0e7aef74ed6ccae09062213e1a98f44adc4314b1", + "sha256": "ff46025b4d03a4ab002d22a4f6101c213a702ff6b36dc688274304f79ef8a7a8", "status": "present" }, { "bytes": 15568, "path": "coverage/release-remediation-intake.report.json", "role": "remediation_intake", - "sha256": "b88b3978114cb7347f890c558ea0b6c948533b8a87d61bcee3806cd0912b0a6d", + "sha256": "86ba1971fec3cbef1431fb211c9258b5ad568b3267aa8bbbd6f61706f3286b77", "status": "present" } ], @@ -100,8 +100,8 @@ ], "exit_code": 0, "status": "passed", - "stderr_preview": "[354699:354699:0822/112700.686752:ERROR:mojo/public/cpp/bindings/lib/interface_endpoint_client.cc:748] Message 853159353 rejected by interface blink.mojom.Frame", - "stderr_sha256": "2c4d73f86043dd6c3ee198266456f336aa5749e713df89e05de2d6ab72fbf2cf", + "stderr_preview": "", + "stderr_sha256": "12ae32cb1ec02d01eda3581b127c1fee3b0dc53572ed6baf239721a03d82e126", "stdout_preview": "LinuxCNC WASM smoke", "stdout_sha256": "f1516af3b272ea95719b5ce833d3afcbdf192eb69962fa5b59443faf60fc9f26" }, @@ -167,7 +167,7 @@ "release_action": "STOP_RELEASE", "release_decision": "blocked_not_release_candidate", "remediation_status": "blocked_matrix_unverified", - "report_sha256": "2f47276d3ea7ce985796881fb0ae6c009c5762c7f3ba199c7b101f9f63f4310a", + "report_sha256": "87d6715003d80e6e546d47c607d6d3c2624807970589062377dded8f999c2e6d", "review_policy": { "current_environment_limit": "Safari binary and browser farm are unavailable; observed Chromium/Firefox probes do not establish a release minimum", "forbidden": [ diff --git a/coverage/browser-performance-matrix.report.json b/coverage/browser-performance-matrix.report.json index e4178f7..ae8ad48 100644 --- a/coverage/browser-performance-matrix.report.json +++ b/coverage/browser-performance-matrix.report.json @@ -51,41 +51,41 @@ "bytes": 225468, "path": "coverage/full-configuration-startup-matrix.report.json", "role": "full_configuration_matrix", - "sha256": "1a97f5fd66e86a0e6bbd22832040a7f8d839ba12677a5800b72d047a2bdde9f9", + "sha256": "eefde49a278a077e374b751d0d0ed59b1294ce399a757a665e3cc14f569f7656", "status": "present" }, { "bytes": 3170, "path": "coverage/recovery-offline-fault-matrix.report.json", "role": "recovery_offline_fault_matrix", - "sha256": "8ef9f92536fa04e7317fcc319a6f959c26494207f336132d3c454f0421c62f8c", + "sha256": "f8fa6f8f487b2c29c6581aa89e373d71c93af5a8b317055d7eb340f402974412", "status": "present" }, { - "bytes": 6340, + "bytes": 6180, "path": "coverage/browser-matrix-remediation.report.json", "role": "browser_matrix_remediation", - "sha256": "1ba374b8ebfcdabe5363c519011ae73a6535a5e5643149810ac0279a955896a5", + "sha256": "7e6a8f2dc51ad80a75504407d04f7be6727355dd9f7bcd1ff49cd47eb5cac284", "status": "present" }, { "bytes": 3301, "path": "coverage/frontend-m4.report.json", "role": "frontend_m4", - "sha256": "3fea18ba6ec7a76640bb2eafac6cabc13f53b6d438442d280f9bf5620b9fb26f", + "sha256": "213411ccef031c360b8db93c2ae2430019baa5b6ea541cd02896514172a11f6c", "status": "present" }, { "bytes": 7196, "path": "coverage/release-candidate-gate.report.json", "role": "release_candidate_gate", - "sha256": "2092257cc0aea41c5988b19a0e7aef74ed6ccae09062213e1a98f44adc4314b1", + "sha256": "ff46025b4d03a4ab002d22a4f6101c213a702ff6b36dc688274304f79ef8a7a8", "status": "present" } ], "next_transition": "execute K8-REL-17 release gate refresh after implementation evidence", "release_action": "STOP_RELEASE", - "report_sha256": "db1be56cb41198b185fbf543f71d0bc2f61bfd93b3794dcb5e13851496415258", + "report_sha256": "0fc082fa4149cd847e2fc48cc2fd3736f16fa0e211765fe04cc44eea175ab847", "runs": [ { "exit_code": 0, @@ -96,7 +96,7 @@ "file": "index.html" }, { - "bytes": 8105, + "bytes": 16777, "file": "app.mjs" }, { @@ -104,7 +104,7 @@ "file": "worker-client.mjs" }, { - "bytes": 3133, + "bytes": 2731, "file": "styles.css" }, { @@ -112,7 +112,7 @@ "file": "controls.mjs" }, { - "bytes": 4304, + "bytes": 5083, "file": "state-panel.mjs" }, { @@ -124,7 +124,7 @@ "file": "recovery-panel.mjs" }, { - "bytes": 1318, + "bytes": 1587, "file": "device-panel.mjs" }, { @@ -138,11 +138,11 @@ ], "schema": "browser-performance-sample.v1", "stable": true, - "total_bytes": 32908 + "total_bytes": 42226 }, "status": "passed", "stderr_sha256": "12ae32cb1ec02d01eda3581b127c1fee3b0dc53572ed6baf239721a03d82e126", - "stdout_sha256": "41b51533a83efdf78425ec49fce1f8bc2260bc88c87fb668c8e3d6614130cbd1" + "stdout_sha256": "c1147df2ce4b0af41c858bc063f517a38a3ef3df1ac8678d859c3539e01bbcf9" }, { "exit_code": 0, @@ -153,7 +153,7 @@ "file": "index.html" }, { - "bytes": 8105, + "bytes": 16777, "file": "app.mjs" }, { @@ -161,7 +161,7 @@ "file": "worker-client.mjs" }, { - "bytes": 3133, + "bytes": 2731, "file": "styles.css" }, { @@ -169,7 +169,7 @@ "file": "controls.mjs" }, { - "bytes": 4304, + "bytes": 5083, "file": "state-panel.mjs" }, { @@ -181,7 +181,7 @@ "file": "recovery-panel.mjs" }, { - "bytes": 1318, + "bytes": 1587, "file": "device-panel.mjs" }, { @@ -195,11 +195,11 @@ ], "schema": "browser-performance-sample.v1", "stable": true, - "total_bytes": 32908 + "total_bytes": 42226 }, "status": "passed", "stderr_sha256": "12ae32cb1ec02d01eda3581b127c1fee3b0dc53572ed6baf239721a03d82e126", - "stdout_sha256": "41b51533a83efdf78425ec49fce1f8bc2260bc88c87fb668c8e3d6614130cbd1" + "stdout_sha256": "c1147df2ce4b0af41c858bc063f517a38a3ef3df1ac8678d859c3539e01bbcf9" } ], "schema": "browser-performance-matrix.v1", diff --git a/coverage/gui-browser-visual-fe-m4.report.json b/coverage/gui-browser-visual-fe-m4.report.json index 5aedb19..7682e67 100644 --- a/coverage/gui-browser-visual-fe-m4.report.json +++ b/coverage/gui-browser-visual-fe-m4.report.json @@ -7,9 +7,21 @@ "browser": { "binary": "google-chrome", "minimum_matrix": "not established", - "scope": "Chromium visual smoke only" + "scope": "Chromium authorized visual slice", + "version": "Google Chrome 151.0.7922.169" }, "checks": { + "chromium_authorized_slice": { + "authorization": "explicit_user_authorized_chromium_unblock", + "browser_version": "Google Chrome 151.0.7922.169", + "scope": [ + "DOM", + "desktop_screenshot", + "mobile_screenshot", + "Three.js_canvas" + ], + "status": "verified" + }, "dom_controls": { "status": "verified" }, @@ -17,11 +29,11 @@ "status": "verified" }, "official_browser_matrix": { - "reason": "locked Chromium/Firefox/Safari minimums remain TBD; this is smoke evidence only", + "reason": "Firefox/Safari minimums remain TBD; Chromium authorization applies only to this slice", "status": "blocked" }, "opfs_recovery": { - "reason": "existing OPFS browser fault matrix remains blocked/unavailable", + "reason": "OPFS crash/restart matrix remains blocked/unavailable", "status": "blocked" }, "screenshot_nonempty": { @@ -36,13 +48,13 @@ "implementation_status": "verified", "outputs": [ { - "bytes": 90475, - "sha256": "64e67b74290c5f7c30565cd35f3fd5174bc0129a4440c6a6cd9d7f6838288cc3", + "bytes": 132137, + "sha256": "71aa049b571d48cb65d3b0498a75cafd8ec8f1ea57bf672c4445118ac1e07ba0", "viewport": "desktop" }, { - "bytes": 44029, - "sha256": "fa4580a13418ae1a62e09e6098ed4396e5c6f863df85d8f21de2f579e53bb3c2", + "bytes": 48632, + "sha256": "266194aecddeb10f18e11ea13c8780d1239753dc43c02946dd321e0cb00ec370", "viewport": "mobile" } ], @@ -56,35 +68,40 @@ "--disable-dev-shm-usage", "--virtual-time-budget=4000", "--window-size=1440,900", - "--screenshot=/tmp/linuxcnc-gui-visual-2igzjfyz/desktop.png", + "--screenshot=/tmp/linuxcnc-gui-visual-yjhbj010/desktop.png", "--dump-dom", "http://127.0.0.1:5174/" ], - "dom_sha256": "cf5e2dfcaf4b7d24b9de22bef91e2e3e1f6fead0de10625b23d9806cfe50575a", + "dom_sha256": "41512d21ba50815afd046499372587a78968daa5f08589600156c578e117733c", "markers": { - "Abort": true, - "Diagnostics": true, - "E-stop": true, - "Home": true, + "Active G-Codes:": true, + "Coolant": true, + "DRO": true, + "File": true, + "Help": true, + "Home Axis": true, "Load case": true, - "Manual jog": true, - "Operate": true, + "MDI [F5]": true, + "Machine": true, + "Manual Control [F3]": true, "Pause": true, - "Program": true, - "Recover": true, - "Restart": true, + "Preview": true, "Run": true, + "Simulation case": true, + "Spindle": true, "Step": true, - "Three.js / authoritative pose": true + "Three.js / authoritative pose": true, + "Tool Touch Off": true, + "View": true }, "returncode": 0, "screenshot": { - "bytes": 90475, - "path": "/tmp/linuxcnc-gui-visual-2igzjfyz/desktop.png", - "sha256": "64e67b74290c5f7c30565cd35f3fd5174bc0129a4440c6a6cd9d7f6838288cc3" + "bytes": 132137, + "path": "/tmp/linuxcnc-gui-visual-yjhbj010/desktop.png", + "sha256": "71aa049b571d48cb65d3b0498a75cafd8ec8f1ea57bf672c4445118ac1e07ba0" }, "status": "verified", - "stderr_sha256": "b5327507fc50e3cb0b7b4633d0c1ce43743dbd3188c920e28afe023035322464", + "stderr_sha256": "4c688f43737caa6998e38bac07e16b085f305cd1ea43052d482fc4d8ffc1157f", "window": "1440,900" }, "mobile": { @@ -96,40 +113,45 @@ "--disable-dev-shm-usage", "--virtual-time-budget=4000", "--window-size=390,844", - "--screenshot=/tmp/linuxcnc-gui-visual-2igzjfyz/mobile.png", + "--screenshot=/tmp/linuxcnc-gui-visual-yjhbj010/mobile.png", "--dump-dom", "http://127.0.0.1:5174/" ], - "dom_sha256": "66a6f651ce8df4a26b271e603adeb36731bd44e3464b77a74a81180b53804b6b", + "dom_sha256": "1dc0c46b1fe8f2bd9c34cc9c70e97e0de2cbbe3695360a27d49230bed8c5cc69", "markers": { - "Abort": true, - "Diagnostics": true, - "E-stop": true, - "Home": true, + "Active G-Codes:": true, + "Coolant": true, + "DRO": true, + "File": true, + "Help": true, + "Home Axis": true, "Load case": true, - "Manual jog": true, - "Operate": true, + "MDI [F5]": true, + "Machine": true, + "Manual Control [F3]": true, "Pause": true, - "Program": true, - "Recover": true, - "Restart": true, + "Preview": true, "Run": true, + "Simulation case": true, + "Spindle": true, "Step": true, - "Three.js / authoritative pose": true + "Three.js / authoritative pose": true, + "Tool Touch Off": true, + "View": true }, "returncode": 0, "screenshot": { - "bytes": 44029, - "path": "/tmp/linuxcnc-gui-visual-2igzjfyz/mobile.png", - "sha256": "fa4580a13418ae1a62e09e6098ed4396e5c6f863df85d8f21de2f579e53bb3c2" + "bytes": 48632, + "path": "/tmp/linuxcnc-gui-visual-yjhbj010/mobile.png", + "sha256": "266194aecddeb10f18e11ea13c8780d1239753dc43c02946dd321e0cb00ec370" }, "status": "verified", - "stderr_sha256": "dc18bae409847b94397f09f6c73409ee6e4b6c8830d97670947bc37450a11001", + "stderr_sha256": "c3b4dd1da17368589e678b93a124c94befc05dcf0471e8dcfe6730336c31afb2", "window": "390,844" } }, "release_action": "STOP_RELEASE", - "report_sha256": "cd2eb920ba82a97a11b4d7e4b2f56a0e1f0739c840da61f63d5beef392df24a4", + "report_sha256": "6386db199317ae95cd5ce03ccb0d525a056f3a9736eb3a28263869b00a33be05", "route": "http://127.0.0.1:5174/", "schema": "gui-browser-visual-fe-m4-report.v1", "status": "verified", diff --git a/nextTask1.md b/nextTask1.md index bd29971..b3ee76b 100644 --- a/nextTask1.md +++ b/nextTask1.md @@ -62,12 +62,14 @@ objective: >- non_goals: - 不复制桌面 GTK/Qt/Tk 窗口,不把宿主 Python/动态 loader/真实硬件变成 Web 能力 - 不修改 ABI、protocol、schema、context lock;manifest 归属缺口保留为可定位审计项 -completion_evidence: + completion_evidence: status: blocked report: coverage/gui-browser-visual-fe-m4.report.json - report_sha256: cd2eb920ba82a97a11b4d7e4b2f56a0e1f0739c840da61f63d5beef392df24a4 + report_sha256: 6386db199317ae95cd5ce03ccb0d525a056f3a9736eb3a28263869b00a33be05 implementation_status: verified chromium_visual: verified + chromium_authorized_slice: verified + chromium_version: Google Chrome 151.0.7922.169 browser_matrix: blocked opfs_recovery: blocked prior_completion_evidence: diff --git a/scripts/generate_gui_browser_visual_report.py b/scripts/generate_gui_browser_visual_report.py index ff45aff..88fa3d6 100644 --- a/scripts/generate_gui_browser_visual_report.py +++ b/scripts/generate_gui_browser_visual_report.py @@ -8,6 +8,7 @@ import json import os import subprocess import tempfile +import shutil from pathlib import Path from typing import Any @@ -21,11 +22,24 @@ def digest(data: bytes) -> str: return hashlib.sha256(data).hexdigest() +def browser_version() -> str | None: + binary = shutil.which("google-chrome") + if binary is None: + return None + result = subprocess.run([binary, "--version"], cwd=ROOT, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=False) + return result.stdout.decode("utf-8", errors="replace").strip() or None + + def probe(size: str, screenshot: Path) -> dict[str, Any]: command = ["google-chrome", "--headless=new", "--no-sandbox", "--disable-gpu", "--disable-dev-shm-usage", "--virtual-time-budget=4000", f"--window-size={size}", f"--screenshot={screenshot}", "--dump-dom", URL] result = subprocess.run(command, cwd=ROOT, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=False) dom = result.stdout.decode("utf-8", errors="replace") - markers = {marker: marker in dom for marker in ("Operate", "Program", "Diagnostics", "Load case", "Run", "Pause", "Step", "Restart", "Abort", "Home", "Recover", "E-stop", "Manual jog", "Three.js / authoritative pose")} + markers = {marker: marker in dom for marker in ( + "File", "Machine", "View", "Help", "Simulation case", "Load case", + "Manual Control [F3]", "MDI [F5]", "Preview", "DRO", "Run", "Pause", + "Step", "Home Axis", "Tool Touch Off", "Spindle", "Coolant", + "Active G-Codes:", "Three.js / authoritative pose", + )} return {"command": command, "window": size, "returncode": result.returncode, "status": "verified" if result.returncode == 0 and all(markers.values()) and screenshot.is_file() and screenshot.stat().st_size > 1000 else "blocked", "dom_sha256": digest(result.stdout), "stderr_sha256": digest(result.stderr), "screenshot": {"path": str(screenshot), "bytes": screenshot.stat().st_size if screenshot.is_file() else 0, "sha256": digest(screenshot.read_bytes()) if screenshot.is_file() else None}, "markers": markers} @@ -42,10 +56,10 @@ def generate() -> dict[str, Any]: "status": "verified" if desktop["status"] == "verified" and mobile["status"] == "verified" else "blocked", "implementation_status": "verified" if desktop["status"] == "verified" else "blocked", "route": URL, - "browser": {"binary": "google-chrome", "scope": "Chromium visual smoke only", "minimum_matrix": "not established"}, + "browser": {"binary": "google-chrome", "version": browser_version(), "scope": "Chromium authorized visual slice", "minimum_matrix": "not established"}, "probes": {"desktop": desktop, "mobile": mobile}, "outputs": outputs, - "checks": {"dom_controls": {"status": "verified" if desktop["status"] == "verified" else "blocked"}, "screenshot_nonempty": {"status": "verified" if all(row["bytes"] > 1000 for row in outputs) else "blocked"}, "mobile_layout": {"status": "verified" if mobile["status"] == "verified" else "blocked"}, "threejs": {"status": "verified", "evidence": "React production preview emits Three.js r185 canvas"}, "official_browser_matrix": {"status": "blocked", "reason": "locked Chromium/Firefox/Safari minimums remain TBD; this is smoke evidence only"}, "opfs_recovery": {"status": "blocked", "reason": "existing OPFS browser fault matrix remains blocked/unavailable"}}, + "checks": {"dom_controls": {"status": "verified" if desktop["status"] == "verified" else "blocked"}, "screenshot_nonempty": {"status": "verified" if all(row["bytes"] > 1000 for row in outputs) else "blocked"}, "mobile_layout": {"status": "verified" if mobile["status"] == "verified" else "blocked"}, "threejs": {"status": "verified", "evidence": "React production preview emits Three.js r185 canvas"}, "chromium_authorized_slice": {"status": "verified" if desktop["status"] == "verified" and mobile["status"] == "verified" else "blocked", "authorization": "explicit_user_authorized_chromium_unblock", "browser_version": browser_version(), "scope": ["DOM", "desktop_screenshot", "mobile_screenshot", "Three.js_canvas"]}, "official_browser_matrix": {"status": "blocked", "reason": "Firefox/Safari minimums remain TBD; Chromium authorization applies only to this slice"}, "opfs_recovery": {"status": "blocked", "reason": "OPFS crash/restart matrix remains blocked/unavailable"}}, "release_action": "STOP_RELEASE", "boundaries": ["Chromium screenshot/DOM smoke does not establish the three-browser release matrix", "visual evidence does not replace native/WASM/Worker golden parity", "OPFS/recovery blocker remains explicit"], } diff --git a/scripts/test_gui_browser_visual_report.py b/scripts/test_gui_browser_visual_report.py index fcc8776..d6ab88b 100644 --- a/scripts/test_gui_browser_visual_report.py +++ b/scripts/test_gui_browser_visual_report.py @@ -19,6 +19,8 @@ class GuiBrowserVisualReportTests(unittest.TestCase): self.assertEqual(report["schema"], "gui-browser-visual-fe-m4-report.v1") self.assertEqual(report["task_id"], "FE-M4-GUI-06") self.assertEqual(report["status"], "verified") + self.assertEqual(report["checks"]["chromium_authorized_slice"]["status"], "verified") + self.assertEqual(report["checks"]["chromium_authorized_slice"]["authorization"], "explicit_user_authorized_chromium_unblock") self.assertEqual(report["checks"]["official_browser_matrix"]["status"], "blocked") self.assertEqual(report["release_action"], "STOP_RELEASE")