Complete AXIS source inventory tasks
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -432,7 +432,7 @@ AxisShell
|
||||
|
||||
**目标**:AXIS source/UI/asset/case inventory 可重复生成。
|
||||
**必须通过**:AXIS-INV-01…04;全部源引用、行号、hash 有效;不存在未分类的外部依赖。
|
||||
**证据**:`coverage/axis-source-inventory.report.json`、`coverage/axis-asset-inventory.report.json`、`coverage/axis-case-inventory.report.json`。
|
||||
**证据**:`coverage/axis-source-inventory.report.json`(同一 self-hashed 报告包含 source/UI/asset/case inventory)。
|
||||
**失败即停止**:源码提交、资源字节、案例资源或 fixture 变化未重新生成报告。
|
||||
|
||||
### M1:像素和结构对标
|
||||
@@ -546,11 +546,11 @@ AxisShell
|
||||
|
||||
当前 React 已具备 AXIS 风格 shell、原始 bitmap toolbar、Manual/MDI 与 Preview/DRO 结构、Worker-backed program/MDI/jog/home/override/spindle/coolant/ESTOP/recover 入口和 Three.js 视角交互;这只证明实现切片,不等于本规范的 M1…M7 已验收。
|
||||
|
||||
M0 的第一步已经执行:[`coverage/axis-source-inventory.report.json`](../coverage/axis-source-inventory.report.json) 由 [`scripts/generate_axis_source_inventory.py`](../scripts/generate_axis_source_inventory.py) 生成,专属契约测试为 [`scripts/test_axis_source_inventory.py`](../scripts/test_axis_source_inventory.py),当前 `AXIS-INV-01=verified`,报告自哈希为 `b8456ef0fd5214fdea9ef7b05682e543173c898a83658d7b005b0922f8808be0`。该报告只冻结来源,不代表任何 Web 功能已通过行为或视觉验收。
|
||||
M0 的 `AXIS-INV-01…04` 已执行:[`coverage/axis-source-inventory.report.json`](../coverage/axis-source-inventory.report.json) 由 [`scripts/generate_axis_source_inventory.py`](../scripts/generate_axis_source_inventory.py) 生成,专属契约测试为 [`scripts/test_axis_source_inventory.py`](../scripts/test_axis_source_inventory.py),当前冻结 10 个源码入口、31 个 bitmap 资源和 115 个精确 AXIS INI 案例,报告自哈希为 `0ec92a467ca13700bd12a7f2889ada8aa11588ca50858dbe25f84a5c946b8176`。该报告只冻结来源,不代表任何 Web 功能已通过行为或视觉验收。
|
||||
|
||||
接续执行顺序固定为:
|
||||
|
||||
1. `AXIS-INV-01` 已完成;接着执行 `AXIS-INV-02…04`,补齐可复现 source/UI/asset/case inventory。
|
||||
1. `AXIS-INV-01…04` 已完成;报告保留 exact path、source hash、asset hash 和 DISPLAY 声明。
|
||||
2. `AXIS-CON-01…04`:补齐状态门控、命令、错误和 host boundary schema。
|
||||
3. `AXIS-UI-01…07`:为所有功能加入稳定 `data-axis-feature`、DOM geometry 和 accessibility evidence。
|
||||
4. `AXIS-CTRL-01…08`:逐状态运行 command replay,先关闭 ESTOP/OFF/ON/idle/paused/limit/queue-full。
|
||||
|
||||
@@ -35,6 +35,13 @@ TOOLBAR_ASSETS = (
|
||||
"tool_clear.gif",
|
||||
)
|
||||
IMAGE_ROOT = Path("linuxcnc/share/axis/images")
|
||||
CASE_ROOT = Path("linuxcnc/configs/sim/axis")
|
||||
SUPPORT_ASSETS = (
|
||||
"axis-16x16.png", "axis-24x24.png", "axis-32x32.png", "axis-48x48.png",
|
||||
"banner.gif", "spindle_ccw.gif", "spindle_cw.gif", "std_error.gif",
|
||||
"std_info.gif", "std_warning.gif",
|
||||
)
|
||||
DECLARATION_KEYS = ("DISPLAY", "PYVCP", "GLADEVCP", "NGCGUI", "EMBED_TAB_NAME", "EMBED_TAB_COMMAND", "HALFILE", "POSTGUI_HALFILE")
|
||||
|
||||
|
||||
def sha256(path: Path) -> str:
|
||||
@@ -88,10 +95,12 @@ def parse_axis_tcl() -> dict[str, Any]:
|
||||
|
||||
def asset_records() -> list[dict[str, Any]]:
|
||||
result: list[dict[str, Any]] = []
|
||||
for name in TOOLBAR_ASSETS:
|
||||
names = list(dict.fromkeys((*TOOLBAR_ASSETS, *SUPPORT_ASSETS)))
|
||||
for name in names:
|
||||
path = ROOT / IMAGE_ROOT / name
|
||||
result.append({
|
||||
"name": name,
|
||||
"role": "toolbar" if name in TOOLBAR_ASSETS else "support",
|
||||
"path": (IMAGE_ROOT / name).as_posix(),
|
||||
"bytes": path.stat().st_size if path.is_file() else None,
|
||||
"sha256": sha256(path) if path.is_file() else None,
|
||||
@@ -100,18 +109,50 @@ def asset_records() -> list[dict[str, Any]]:
|
||||
return result
|
||||
|
||||
|
||||
def case_records() -> list[dict[str, Any]]:
|
||||
records: list[dict[str, Any]] = []
|
||||
root = ROOT / CASE_ROOT
|
||||
for path in sorted(root.rglob("*.ini")):
|
||||
declarations: dict[str, str] = {}
|
||||
section = ""
|
||||
for raw in path.read_text(encoding="utf-8", errors="replace").splitlines():
|
||||
line = raw.split("#", 1)[0].strip()
|
||||
if not line:
|
||||
continue
|
||||
if line.startswith("[") and line.endswith("]"):
|
||||
section = line[1:-1].strip().upper()
|
||||
continue
|
||||
if "=" not in line or section != "DISPLAY":
|
||||
continue
|
||||
key, value = (part.strip() for part in line.split("=", 1))
|
||||
key = key.upper()
|
||||
if key in DECLARATION_KEYS:
|
||||
declarations[key] = value
|
||||
records.append({
|
||||
"path": path.relative_to(ROOT).as_posix(),
|
||||
"family": "axis",
|
||||
"source_sha256": sha256(path),
|
||||
"declarations": declarations,
|
||||
"status": "indexed",
|
||||
})
|
||||
return records
|
||||
|
||||
|
||||
def generate() -> dict[str, Any]:
|
||||
sources = source_records()
|
||||
assets = asset_records()
|
||||
cases = case_records()
|
||||
axis = parse_axis_tcl()
|
||||
report: dict[str, Any] = {
|
||||
"schema": "axis-source-inventory.v1",
|
||||
"task_id": "AXIS-INV-01",
|
||||
"context_id": CONTEXT_ID,
|
||||
"status": "verified" if all(row["status"] == "indexed" for row in sources + assets) else "blocked",
|
||||
"implementation_status": "source_frozen",
|
||||
"status": "verified" if all(row["status"] == "indexed" for row in sources + assets + cases) else "blocked",
|
||||
"implementation_status": "source_frozen_and_inventory",
|
||||
"completed_tasks": ["AXIS-INV-01", "AXIS-INV-02", "AXIS-INV-03", "AXIS-INV-04"],
|
||||
"source": sources,
|
||||
"assets": assets,
|
||||
"cases": cases,
|
||||
"axis_tcl": axis,
|
||||
"anchors": [
|
||||
{"id": "menus", "path": AXIS_TCL.as_posix(), "lines": "33-482"},
|
||||
@@ -124,7 +165,10 @@ def generate() -> dict[str, Any]:
|
||||
],
|
||||
"checks": {
|
||||
"source_paths": {"status": "verified" if all(row["status"] == "indexed" for row in sources) else "blocked"},
|
||||
"toolbar_assets": {"status": "verified" if all(row["status"] == "indexed" for row in assets) else "blocked", "expected": len(TOOLBAR_ASSETS), "indexed": sum(row["status"] == "indexed" for row in assets)},
|
||||
"toolbar_assets": {"status": "verified" if all(row["status"] == "indexed" for row in assets if row["role"] == "toolbar") else "blocked", "expected": len(TOOLBAR_ASSETS), "indexed": sum(row["status"] == "indexed" and row["role"] == "toolbar" for row in assets)},
|
||||
"support_assets": {"status": "verified" if all(row["status"] == "indexed" for row in assets if row["role"] == "support") else "blocked", "expected": len(SUPPORT_ASSETS), "indexed": sum(row["status"] == "indexed" and row["role"] == "support" for row in assets)},
|
||||
"case_paths": {"status": "verified" if cases and all(row["status"] == "indexed" for row in cases) else "blocked", "count": len(cases), "expected_baseline": 115},
|
||||
"case_display_declarations": {"status": "verified" if cases and all(row["declarations"].get("DISPLAY", "axis").lower() in {"axis", "profile_axis"} for row in cases) else "blocked", "allowed": ["axis", "profile_axis"]},
|
||||
"source_line_count": {"status": "verified" if axis["line_count"] == 2300 else "blocked", "expected": 2300, "actual": axis["line_count"]},
|
||||
"toolbar_names_declared": {"status": "verified" if all(name.removesuffix(".gif").removesuffix(".png") in axis["toolbar_load_image_names"] for name in TOOLBAR_ASSETS if name != "tool_axis_y2.png") else "blocked"},
|
||||
},
|
||||
|
||||
@@ -21,8 +21,13 @@ class AxisSourceInventoryTests(unittest.TestCase):
|
||||
self.assertEqual(report["schema"], "axis-source-inventory.v1")
|
||||
self.assertEqual(report["task_id"], "AXIS-INV-01")
|
||||
self.assertEqual(report["status"], "verified")
|
||||
self.assertEqual(len(report["assets"]), 21)
|
||||
self.assertEqual(len(report["assets"]), 31)
|
||||
self.assertEqual(report["completed_tasks"], ["AXIS-INV-01", "AXIS-INV-02", "AXIS-INV-03", "AXIS-INV-04"])
|
||||
self.assertEqual(report["checks"]["toolbar_assets"]["status"], "verified")
|
||||
self.assertEqual(report["checks"]["support_assets"]["status"], "verified")
|
||||
self.assertEqual(report["checks"]["case_paths"]["status"], "verified")
|
||||
self.assertEqual(report["checks"]["case_paths"]["count"], 115)
|
||||
self.assertEqual(report["checks"]["case_paths"]["expected_baseline"], 115)
|
||||
self.assertEqual(report["checks"]["source_line_count"]["actual"], 2300)
|
||||
self.assertGreaterEqual(report["axis_tcl"]["procedure_count"], 20)
|
||||
self.assertGreaterEqual(report["axis_tcl"]["binding_count"], 10)
|
||||
|
||||
Reference in New Issue
Block a user