Files
Umut CANandClaude Opus 5 2be5e4180d docs(pid): track A shipped — CLAUDE.md, README, changelog with the live COM smoke record
scripts/smoke_pid_com.py runs the whole track against the live AutoCAD in
a new document. ComBackend.connect() is lazy by design, so the script reads
reachability from system_status()["connected"] rather than from connect()
as the plan sketched, and closes its document without saving unless --keep
is passed. On this machine (AutoCAD 2026, "25.1s (LMS Tech)") it exits 0:
5 nodes, 4 edges, 0 dangling, confidence_min 1.0, 0 critique issues,
2 XDATA chunks — identical to the headless engine on the same spec. The
first attempt exited 2 on a stale win32com gen_py cache (a package folder
holding only __pycache__); an environment fault, no backend change needed.

A/B against v1.5.1 published as ab-v1.5.1-vs-v1.6.0-dev.json: 26/29 ->
29/29, three miss -> pass, zero regressed. check_doc_numbers.py now names
the report and the two row labels in one place (AB_REPORT, AB_*_LABEL),
and README.md / benchmarks/README.md carry the new rows; the v1.5.0 and
v1.4.0 tables stay as history.

README: P&ID row, the showcase and catalogue images, the token table
re-measured (161 / 44,930 by default, 152 / 41,420 with TOOL_PACKS=core,
lean 50 / 14,007), every stale count reconciled (154 -> 166 registered,
149 -> 161 advertised, corpus 158/672 -> 162/731 by the same count, 19 ->
20 groups, 6 -> 8 resources, six-task matrix with pid_roundtrip), a
"Known limitations of the P&ID track" subsection, and the snapshot line at
this machine's 2423 collected tests (CI has not run on this tree; noted in
the changelog with the pre-existing 1369 vs 1363 drift).

CLAUDE.md: section 17, sections 5 and 7 counts, TOOL_PACKS, the two 1.6
contracts and the reader rules. Spec status -> implemented. The plan and
spec markdown were reformatted by ruff (fenced Python only) because
`ruff format --check .` was already red on them at HEAD and the gate
requires the whole tree clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FKFStjEFzpGyLq5bMpWxTd
2026-09-16 13:34:06 +03:00

87 lines
3.2 KiB
Python

"""Exercise the P&ID track once against the live AutoCAD on this machine.
Creates a NEW document (never touches the operator's open drawing), then runs
the whole track through the same code the tools call:
apply_layer_set("pid") -> run_spec(EXAMPLE_SPEC)
= block_define -> pid_symbol_insert -> ACADMCP_PID xdata
-> pid_line_draw -> pid_graph -> six pid_* critique focuses
-> entity_get_xdata on the pump
and prints the graph stats as JSON. Exit codes:
0 every line landed on a port (``dangling == 0``)
1 the sheet drew but the reader found a dangling end
2 no live CAD application reachable (pywin32 missing, or the ProgID
cannot be created) -- the COM paths then remain fake-tested only
The backend's ``connect()`` is lazy on purpose (the server must start before
AutoCAD is open), so reachability is read from ``system_status()`` rather than
from ``connect()``. Note that the backend's ``Dispatch`` fallback *launches*
the ProgID when nothing is running; a cold AutoCAD start can take longer than
``COM_CALL_TIMEOUT`` (60 s), so open AutoCAD first when the first call times
out.
AUTOCAD_MCP_BACKEND=com uv run --frozen python scripts/smoke_pid_com.py
uv run --frozen python scripts/smoke_pid_com.py --keep # leave the document open
"""
from __future__ import annotations
import asyncio
import json
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT))
XDATA_APP = "ACADMCP_PID"
async def main(keep_document: bool = False) -> int:
try:
from backends.com_backend import ComBackend
except ImportError as exc:
print(f"pywin32 not available: {exc}")
return 2
backend = ComBackend()
try:
await backend.connect()
except Exception as exc:
print(f"no live AutoCAD reachable: {exc}")
return 2
try:
status = await backend.system_status()
if not status.get("connected"):
print(f"no live AutoCAD reachable: {status.get('error', status)}")
return 2
from engineering.layers import apply_layer_set
from engineering.pid.spec import EXAMPLE_SPEC, run_spec
await backend.drawing_new()
await apply_layer_set(backend, "pid")
result = await run_spec(backend, EXAMPLE_SPEC)
got = await backend.entity_get_xdata(result["handles"]["P-101"], XDATA_APP)
report = {
"autocad": status.get("autocad_version") or status.get("cad_progid"),
"active_document": (await backend.system_status()).get("active_document"),
"handles": result["handles"],
"graph_stats": result["graph"]["stats"],
"crossings_total": result["crossings_total"],
"critique_issues": len(result["critique"]),
"critique": result["critique"],
"xdata_chunks": len(got["xdata"].get(XDATA_APP, [])),
}
print(json.dumps(report, indent=2))
if not keep_document:
await backend.drawing_close(save=False)
return 0 if result["graph"]["stats"]["dangling"] == 0 else 1
finally:
await backend.disconnect()
if __name__ == "__main__":
raise SystemExit(asyncio.run(main(keep_document="--keep" in sys.argv[1:])))