Skip to content

Agents and scripts: the standard part commands describe their exact parameters and reply (#11003) - #11004

Open
austin62jake wants to merge 2 commits into
tangency-labs:mainfrom
austin62jake:schema-parts-11003
Open

austin62jake wants to merge 2 commits into
tangency-labs:mainfrom
austin62jake:schema-parts-11003

Conversation

@austin62jake

@austin62jake austin62jake commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Change

Agents and scripts drive SolidCraft through named commands. The MCP tool describe_command and the command engine.describe give a command's exact parameters and reply, but only for commands with schemas. The standard part commands (parts.library, parts.insert, parts.fastener and parts.resize), which insert fasteners, dowel pins and bearings, now have them. With the parameter check at warn or strict, the check now warns about or refuses a misspelt or wrong-typed parameter, instead of ignoring it. Fixes #11003, part of #2829.

The conversion follows docs/book/src/dev/schemas.md, and takes the commands off schema/unconverted.txt. The contracts and reply types are in a new schema/parts.rs.

Command Contract Reply
parts.library family? PartsLibrary: {families}, or one family's {family, name, standard, system, sizes, lengths}
parts.insert, parts.fastener family, size, length?, at?, point?, direction?, name? InsertedPart {component, occurrence, name}, with joint, occurrences and joints when seated in holes
parts.resize component, size?, length? ResizedPart {component, name, size, length}

parts.insert and parts.fastener run the same handler and share one contract.

Each key reads as the handler reads it, with its message:

  • family and size: "family is required (parts.library)", "size is required".
  • length: above 0 and at most 2000 mm, or "length must be 0…2000 mm".
  • at (HolePicks): one point, or a list of up to 1000. A list is told apart the way the handler tells it, by a first item that is a list, or by being empty. The messages are "at must be [x,y,z] or a list of them" and "at takes at most 1000 holes".
  • component: an id or a name, or "component must be an id or a name".

The handlers build their replies from these types instead of json! literals; the JSON is the same. A size's dimensions differ by family, so sizes stays a list of objects, each with its size.

One difference in strict: the insert's messages name it parts.insert (Insert Fastener) under either id. Strict names the id called (parts.insert or parts.fastener); the message after the name is the same.

With no family or component at all, strict says "family is required" or "component is required", as for every contract's missing key, where the handlers add "(parts.library)" or ask for an id or a name.

What warn and strict now catch:

  • the insert reads a point, direction or name that isn't the right kind as absent;
  • the library reads a family that isn't text as absent;
  • the resize reads a size that isn't text as absent.

A call that works today works the same.

Changes a default: no

Tests

In crates/engine/src/schema/parts_tests.rs:

  • schemas_and_the_key_check_agree: the keys of the three contracts.

  • strict_keeps_todays_errors: an unknown family for the library; a component that is true or unknown for the resize.

  • the_insert_keeps_its_messages_in_strict: ten calls that fail today get the same message in strict under both ids, compared after the command's name:

    • family as a number, unknown, or with no size;
    • size as a number;
    • length 0, text or 3000;
    • at as text, with a 2-number point, or 1001 points.

    It also checks a resize's length of 0 on an inserted part.

  • part_commands_reply_with_their_schemas, in Warn, with no warnings for each good call:

    • the whole library, the socket head cap screw family (with lengths) and the bearings (without);
    • a hex nut at a point, turned by a {x, y, z} direction and named, with no joint;
    • a screw seated in two holes with parts.fastener, with two occurrences and two joints;
    • that screw resized to M8 × 25.

    Then a misspelt key on each command gets param_warnings, and the reply still matches.

The tests already in cmd/parts.rs pass unchanged.

Validation

On Windows 10, with --profile ci:

  • cargo test -p solidcraft-engine -p solidcraft-mcp --lib --tests --features solidcraft-engine/param-audit: every binary passed. The engine library had 3160 passed and 8 ignored; mcp had 96 passed.

  • cargo test -p solidcraft-ui-egui --lib agent_chat: 247 passed.

  • cargo clippy -p solidcraft-engine -p solidcraft-mcp --all-targets -- -D warnings: clean.

  • cargo fmt --all -- --check, cargo xtask lists, cargo xtask layers, cargo xtask skills: OK.

  • Parameter audit, from the runs above with SOLIDCRAFT_PARAM_AUDIT: 4205 call signatures. The calls to these commands that work today and that strict would refuse are:

    • tests::hostile_arguments_never_panic, which sends parts.library unknown keys on purpose;
    • this PR's own test's three deliberate misspellings.

    The calls that already fail get the same message in strict, apart from the command's name in the insert's messages and a missing family or component, as noted above.

Integration status

Checked against main at 147b4049c. Rebased onto main after the SMLib kernel merge (#11351), for the conflicts in schema/mod.rs and schema/unconverted.txt. The merge added a range check for point and direction to the insert. The contract's Point3 already takes only points under 1e9 mm.

The numbers in Validation are from before the rebase; this PR's CI run checks the rebased branch with SMLib. In that run, "Native Linux tests" fails only licences::tests::the_licences_are_built_in, which main itself fails since #11351 (main's run 41553615059 on 147b4049c). This PR doesn't touch the licence list.

🤖 Generated with Claude Code

@austin62jake
austin62jake marked this pull request as ready for review November 2, 2026 08:20
@bherbruck bherbruck added ready to merge reviewed, every ask addressed; merge once CI is green approved-for-ci Reviewed: run the full PR CI (build, tests, goldens, Clippy) and removed approved-for-ci Reviewed: run the full PR CI (build, tests, goldens, Clippy) labels Nov 2, 2026
@bherbruck
bherbruck enabled auto-merge November 2, 2026 18:24
@bherbruck bherbruck added approved-for-ci Reviewed: run the full PR CI (build, tests, goldens, Clippy) and removed approved-for-ci Reviewed: run the full PR CI (build, tests, goldens, Clippy) labels Nov 2, 2026
@bherbruck
bherbruck added this pull request to the merge queue Nov 2, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Nov 2, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
parts.library, parts.insert, parts.fastener and parts.resize get typed
contracts and reply types in schema/parts.rs and leave unconverted.txt.
Each key reads as the handler reads it, with its message; the replies
are built from PartsLibrary, InsertedPart and ResizedPart, with the same
JSON as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@austin62jake austin62jake changed the title Typed schemas for the standard part commands (#11003) Agents and scripts: the standard part commands describe their exact parameters and reply (#11003) Nov 3, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved-for-ci Reviewed: run the full PR CI (build, tests, goldens, Clippy) ready to merge reviewed, every ask addressed; merge once CI is green

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Typed schemas for the standard part commands (part of #2829)

3 participants