feat(server): settings pack — 22 environment tools behind TOOL_PACKS, lean grows to 55, three groups, golden set +10

Task 24 (merge sanity) on main after the five track E groups merged.

- TOOL_PACK_NAMES = ("core", "pid", "settings"); PACK_TOOL_NAMES["settings"]
  is exactly the 22 SECTION 20 tools. Styles and page setup stay in core.
- LEAN_TOOL_NAMES += page_setup_apply, batch_plot (53 -> 55).
- _GROUP_TAG_PRIORITY / _GROUP_TAG_LABELS: "style" moved up next to "pid",
  "pagesetup" -> page_setup and "environment" -> environment added; the 28
  SECTION 19/20 decorators gain their section tag, so _tool_groups() reports
  styles 10 / page_setup 6 / environment 22 (23 groups, 204 tools) and
  pack == group == section for the settings pack.
- SECTION headers, backends/base.py composition, contracts/__init__.py
  exports and the layer_states feature entry were already correct after the
  merge (read and confirmed, nothing edited).
- Pack text: config.py, .env.example, README config row; README <sub> line
  204 tools in 23 groups; release snapshot 3259 collected tests (measured).
- docs/tool-inventory.json regenerated; registry snapshot re-derived.
- tests: test_tool_packs.py replaced (11 tests), test_capability_contract.py
  +3 (composition, the agreed capability flags, layer_states honesty),
  golden set +10 tuning cases (81 = 66 tuning + 15 holdout); all ten route
  in the top 3 without alias edits.

Deviation from the plan text: TRACK_E_KEYS carries five keys, not six. The
plan's "mleaderstyle" (ezdxf True / com False) contradicts spec §8.1, which
retracted that key because the ActiveX route exists (§4.2); measured on the
tree: capability_keys() == {boundary_trace, chspace, interactive_prompt,
live_application, preferences, revcloud, wipeout}, and
ComBackend.mleaderstyle_create is a native implementation
(backends/com_backend.py:6752, is_capability_default -> False). The test now
also asserts the key is absent.

No new ActiveX call was written in this task, so no live probe was needed.

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-22 11:35:00 +03:00
co-authored by Claude Opus 5
parent 90c1194f7f
commit 70afd57831
9 changed files with 356 additions and 126 deletions
+50
View File
@@ -32,6 +32,9 @@ import pytest
from backends.base import AutoCADBackend, UnsupportedCapabilityError
from backends.capability import capability_keys, is_capability_default
from backends.com_backend import ComBackend
from backends.contracts.environment import EnvironmentContract
from backends.contracts.pagesetup import PageSetupContract
from backends.contracts.styles import StylesContract
from backends.ezdxf_backend import EzdxfBackend
# Marked per-test rather than module-wide: half of these are plain registry
@@ -116,3 +119,50 @@ async def test_an_implementing_backend_is_unaffected(backend):
result = await backend.entity_change_space([], "nope")
assert result["ok"] is False
assert "error" in result, "the real implementation still does its own validation"
# ── track E: composition and the five agreed keys ───────────────────────────
#: spec §8.1 — the flag each engine must report. `mleaderstyle` is deliberately
#: absent: the spec retracted it (the ActiveX route through the
#: ``ACAD_MLEADERSTYLE`` dictionary exists, §4.2), and both engines implement
#: ``mleaderstyle_create`` natively — `capability_keys()` never registers it.
TRACK_E_KEYS = {
"dwgprops": {"ezdxf": False, "com": True},
"dwt_write": {"ezdxf": False, "com": True},
"live_application": {"ezdxf": False, "com": True},
"preferences": {"ezdxf": False, "com": True},
"interactive_prompt": {"ezdxf": False, "com": True},
}
def _feature_keys_full(backend) -> dict:
return backend.capabilities().to_dict()["features"]
def test_track_e_contracts_are_composed_into_the_backend():
for contract in (StylesContract, PageSetupContract, EnvironmentContract):
assert issubclass(AutoCADBackend, contract), f"{contract.__name__} not in AutoCADBackend"
assert issubclass(EzdxfBackend, contract) and issubclass(ComBackend, contract)
def test_track_e_capability_keys_carry_the_agreed_flags():
assert "mleaderstyle" not in capability_keys(), "spec §8.1: no such engine boundary"
ezdxf_features = _feature_keys_full(EzdxfBackend())
com_features = _feature_keys_full(ComBackend())
for key, flags in TRACK_E_KEYS.items():
assert key in ezdxf_features, f"{key} undeclared on ezdxf"
assert key in com_features, f"{key} undeclared on com"
assert ezdxf_features[key]["supported"] is flags["ezdxf"], key
assert com_features[key]["supported"] is flags["com"], key
def test_layer_states_are_declared_as_ours_not_autocads():
"""Spec §7.2 / §8.3: the states live in the file and travel with it, and do
not appear in AutoCAD's Layer States Manager. Said in the map, not only in
a docstring."""
for backend in (EzdxfBackend(), ComBackend()):
feature = _feature_keys_full(backend)["layer_states"]
assert feature["supported"] is True
assert feature["mode"] == "xrecord"
assert "layer_states_manager" in (feature["reason"] or ""), backend.name