Add audited, versioned MCP save workflow (#1452)

- `--export ... --target-version`, and explicit target_format /
  target_version on automation and protocol saves; a conversion that
  would drop unsupported records is refused unless allow_lossy is set.
- `audit` read op: dangling layers/blocks, duplicate handles, non-finite
  bounds, serialization, lossy records and the source DXF handle graph.
- `save_verified`: writes the requested version from the same snapshot a
  normal save writes, reopens it, checks the version and the entity
  manifest, audits the ASCII DXF handle graph and returns a SHA-256.
- ZOOM EXTENTS includes SDF text glyphs.
- Live MCP acceptance script and an optional reference-console audit
  runner under docs/automation.

Squashed from the PR with review fixes: merged with the DWT save path,
the save snapshot, the tool lists added since, and vendor-neutral
harness names; the dated verification record is left out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Luis MartinezandClaude Opus 5.5 authored and Hakan Seven committed 2026-09-24 16:49:11 +03:00
1 parent 0f99b77004
commit dddf60d79e
16 files changed
+1102 -22

No files matched your search

+15 -1
View File
@@ -5,6 +5,7 @@ from pathlib import Path
import subprocess
import sys
import time
import uuid
MODERN = "2026-07-28"
@@ -91,6 +92,19 @@ def main() -> None:
assert "io.modelcontextprotocol/tasks" in discovery["capabilities"]["extensions"]
sessions = client.tool("ocs_sessions", {"launch_if_none": True})["result"]
session = sessions[0]["session_id"]
while sessions[0].get("modal"):
client.tool(
"ocs_execute",
{
"ocs_session_id": session,
"request": {
"op": "action",
"request_id": f"eval-close-modal-{uuid.uuid4().hex}",
"name": "close_modal",
},
},
)
sessions = client.tool("ocs_sessions", {"launch_if_none": False})["result"]
active = next(
document for document in sessions[0]["documents"]
if document["id"] == sessions[0]["document_id"]
@@ -98,7 +112,7 @@ def main() -> None:
if active.get("start"):
client.tool(
"ocs_execute",
{"ocs_session_id": session, "request": {"op": "new", "request_id": "eval-new"}},
{"ocs_session_id": session, "request": {"op": "new", "request_id": f"eval-new-{uuid.uuid4().hex}"}},
)
base = 1_000_000 + int(time.time()) % 100_000