fix(task-22): ucs_list decides "world" from the frame, not the empty name — an unnamed UCS is its own current row

An unnamed UCS (UCS Origin / 3P without saving, the common kind) has an
empty UCSNAME exactly like WCS does, so both engines answered
`current: world` while the drawing was not in WCS — verified live on
AutoCAD 2026 (`_.UCS _O 10,10,0` → UCSNAME="" WORLDUCS=0) and on the DXF
it writes ($UCSNAME='' $UCSORG=(0,20,0)). A silent wrong value.

- COM: a named match still wins; otherwise WORLDUCS (AutoCAD's own answer)
  decides, and WORLDUCS=0 appends a `name: None` row built from
  UCSORG/UCSXDIR/UCSYDIR.
- ezdxf: the same rule against $UCSORG/$UCSXDIR/$UCSYDIR via the new
  `engineering.environment.ucs.is_world_axes`; a stale $UCSNAME falls back
  to the frame instead of leaving no row current.
- Server `ucs_list` result: `current` is null for an unnamed UCS (never
  `world`), plus `current_unnamed: bool` so null is unambiguous.
- Tests: helper, headless (unnamed row, stale name, and the exact AutoCAD
  DXF over the wire), and COM fake reading WORLDUCS + the frame variables.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FKFStjEFzpGyLq5bMpWxTd
This commit is contained in:
Umut CAN
2026-09-17 15:10:00 +03:00
co-authored by Claude Opus 5
parent 4bf686e943
commit 64cec37cc7
6 changed files with 209 additions and 19 deletions
+9 -3
View File
@@ -7050,13 +7050,19 @@ async def view_named_list(ctx: Context = None) -> dict:
)
async def ucs_list(ctx: Context = None) -> dict:
"""The `world` row first, then every UCS table entry with origin and unit
axes, `current` on the active one. Tool coordinates stay WCS on both
engines whatever is current. No refusals. Pack: settings · lean: no."""
axes, `current` on the active one. `world` is current only when the frame
IS the WCS (WORLDUCS live, the `$UCS*` header headless) — an unnamed UCS
(`UCS Origin` / `3P` without saving) has an empty name too and is
reported as a trailing row with `name: null` and its origin/axes, so
`current` is `null` then and never `world`. Tool coordinates stay WCS on
both engines whatever is current. No refusals. Pack: settings · lean: no."""
rows = await _backend(ctx).ucs_list()
active = next((r for r in rows if r["current"]), None)
return {
"ucs": rows,
"count": len(rows),
"current": next((r["name"] for r in rows if r["current"]), None),
"current": active["name"] if active else None,
"current_unnamed": bool(active and active["name"] is None),
}