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
+21 -36
View File
@@ -495,7 +495,7 @@ async def test_tool_groups_is_byte_identical_to_the_source_declared_grouping():
async def test_tool_group_sizes_are_unchanged():
"""Frozen snapshot of the surface (172 tools, 20 groups).
"""Frozen snapshot of the surface (204 tools, 23 groups).
Taken before @cad_tool landed at 131 tools; `batch` moved 2 -> 3 when
v1.5.0's `cad_batch` joined `entity_batch_create`/`entity_batch_modify`, and
@@ -517,35 +517,18 @@ async def test_tool_group_sizes_are_unchanged():
when `pid_tag_parse` (the ISA-5.1 tag grammar as a read-only tool)
joined; the `pid`
tag is ranked first in `_GROUP_TAG_PRIORITY` so those tools file under
`pid` rather than under their secondary `query` / `create` tags. `styles`
appeared (0 -> 9) when track E's SECTION 18 opened with the dimension,
text and multileader style tools, then 9 -> 10 when
`drawing_apply_standard` (ISO or ANSI styles, units and layers in one
call) joined; the `style` tag sits ahead of `layer` and `drawing` in
`_GROUP_TAG_PRIORITY` so they never file under their secondary
`query` / `create` / `modify` / `drawing` tags. `system`
moved 7 -> 8 when v1.6's `system_variable_describe` (the sysvar catalogue
as a read-only tool) opened SECTION 20. `drawing` moved 11 -> 13 when
v1.6's `drawing_properties_get` / `drawing_properties_set` (DWGPROPS on
both engines) joined SECTION 20 — tagged `drawing` and `settings`, and
`settings` is not a group tag, so they file under drawing.
`layouts` moved 12 -> 16 when v1.6's SECTION 19 opened with
`page_setup_list` / `page_setup_apply` / `plot_style_list` / `batch_plot`
— all tagged `layout`, which `_GROUP_TAG_PRIORITY` ranks above
`query`/`export`, so they file with the sheets they set up. `templates`
moved 2 -> 3 when v1.6's `drawing_template_list` joined SECTION 19
(tagged `template`, which ranks above `drawing`), then 3 -> 4 when
`drawing_template_save` joined. `drawing`
moved 13 -> 16 when v1.6's `document_list` / `document_activate` /
`document_close` (multi-document on both engines) opened SECTION 20;
`layers` moved 14 -> 18 with the four `layer_state_*` tools and `view`
4 -> 10 with `view_named_*` and `ucs_*` (UCS files under `view`, where
AutoCAD's own ribbon keeps it) when v1.6's SECTION 20 grew. `system`
moved 8 -> 14 with v1.6's live-only environment tools (`system_launch`,
`system_preferences_get/set`, `user_pick_point`, `user_select`,
`system_prompt_message`), which refuse headlessly with declared
capability keys. Every other number here has been unchanged since the
snapshot was taken.
`pid` rather than under their secondary `query` / `create` tags.
Three groups appeared with v1.6's track E — `styles` (10, SECTION 18),
`page_setup` (6, SECTION 19) and `environment` (22, SECTION 20) — each
tagged with its section name, ranked directly after `pid` in
`_GROUP_TAG_PRIORITY` so a style tool that also carries `dimension` or an
environment tool that also carries `layer` files under its section; the
`environment` group is exactly `PACK_TOOL_NAMES["settings"]`. (Until the
merge task tagged them, the four groups had filed those 28 tools under
`layouts` / `templates` / `drawing` / `layers` / `view` / `system` by
their secondary tags; those counts returned to their pre-track-E values
when the section tags landed.) Every other number here has been unchanged
since the snapshot was taken.
"""
sizes = {label: len(names) for label, names in (await server._tool_groups()).items()}
assert sizes == {
@@ -554,21 +537,23 @@ async def test_tool_group_sizes_are_unchanged():
"blocks": 9,
"corner_ops": 4,
"dimensions": 5,
"drawing": 16,
"drawing": 11,
"engineering": 10,
"entity_creation": 18,
"entity_modification": 16,
"entity_query": 9,
"layers": 18,
"layouts": 16,
"environment": 22,
"layers": 14,
"layouts": 12,
"page_setup": 6,
"pid": 9,
"premium": 12,
"solids": 5,
"styles": 10,
"system": 14,
"templates": 4,
"system": 7,
"templates": 2,
"transactions": 3,
"validation": 1,
"view": 10,
"view": 4,
}
assert sum(sizes.values()) == 204