feat(mcp): place_design creates a validated design on today's hosts (AK-02 2/3) - #953
Merged
Merged
Conversation
|
I hit an error while handling your request (Model unavailable on AI Gateway free tier: Free tier users do not have access to this model. Upgrade to paid credits at https://vercel.com/d?to=%2F%5Bteam%5D%2F%7E%2Fai%3Fmodal%3Dtop-up for unrestricted…). Please try again, rephrase, or reach out if it keeps failing. Error id: 045136d6-d42f-4d3c-a6d1-0051f452ef15 |
Aymericr
force-pushed
the
fidelity/ak-02b-place-design
branch
3 times, most recently
from
September 27, 2026 22:54
96c2bab to
87d84be
Compare
…_design (AK-02 1/3)
Core gains describeDesignSchema() and validateDesign(design, { parameters }).
The schema is generated from RecipeSchema with z.toJSONSchema (one named
recursive $def, Expr), because the node's recipe field is an opaque z.custom.
validateDesign is the authority over the rules JSON Schema cannot express: it
parses, sweeps the parameter ranges and measures per-part bounds and instances,
the triangles the renderer builds, draw groups per slot, datum contact and
balance, and connected components (floating parts). It accepts the design as
an object or a JSON string and never throws.
MCP serves the contract as pascal://schema/design and wraps validateDesign as
the read-only validate_design tool; the annotation inventory grows to 50 tools.
A nodes test pins the triangle and draw-group counts to buildProceduralGeometry.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…passes behind the wall The rules tell agents to keep wall-side geometry in front of the reference plane, but a design whose shapes reached behind it validated silently (the contact test even counted the penetration as touching). It now carries a behind_wall warning naming the parts and the depth. It stays a warning: the recipe and placement contracts accept such designs today (found by Bugbot). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…rors agents hit most The AK-02 eval showed agents looping on validate_design: 29–34 calls in the direct lane and every MCP-lane place_design refused with "Mounting requires one named, non-repeated reference surface", a message that does not say what to declare. Rule and sweep diagnostics now carry a hint built from the design itself: the reference and the declared surfaces plus a surface snippet for the mounting kind, the declared slots, parts or parameters for unknown references, and the y >= 0 and shape-budget repairs. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Aymericr
force-pushed
the
fidelity/ak-02b-place-design
branch
from
September 27, 2026 23:51
87d84be to
30de136
Compare
…te_design Four cases that fail on the current head: - trim 1 m behind the wall reference counts as touching it; - 64 draw groups pass without a draw-budget diagnostic; - a cone beside its base is weighed as a full cylinder, so balance fails; - triangle counts are not derived from a shared tessellation (no export). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ance, one tessellation source From the Codex review of AK-02 1/3; the failing cases are the previous commit. - Datum contact needs the shape to reach the plane within tolerance, so geometry wholly behind a wall (or above a ceiling) no longer counts as touching it. - A draw_budget warning fires above 16 draw calls (slot × motion group) per instance, and measurements report the budget. - Balance weighs a tapered cylinder as the frustum it is: π/12·(1 + t + t²). - PRIMITIVE_TESSELLATION and shapeTriangles(primitive, topScale) live in core's recipe module; the nodes renderer builds with those segments, so the counts cannot drift from the geometry across package versions. - The publishing evidence records the date and suite it was checked with. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…AK-02 2/3) Core gains planDesignPlacement(nodes, request): it validates the design with validateDesign, picks the host from the design's mounting (level, or a slab or zone of it, or a named design surface for floor designs; a straight wall face for wall-side designs; a ceiling for ceiling designs), builds the node with today's hosting fields (parentId, wallId/side, attachments) and runs the procedural relation checks directly, so they hold without the node registry. Refusals are typed (invalid_design, invalid_placement, node_exists, host_not_found, wrong_host, unknown_surface, does_not_fit); a wall misfit says where the reference fits. The MCP tool place_design wraps it create-only through applyPatch; the annotation inventory grows to 51 tools. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… about A slot or id the node schema rejects came back as the raw zod issue JSON; it is now one line per issue, e.g. "invalid_placement: node: Unknown slot paint". Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…rds (#938) With #938 merged, place_design runs assertPatchKeepsIdentity over its create (and the design-surface host's attachment update) before applyPatch, so an explicit id that exists is refused with the same node_exists code and message as apply_patch. The duplicate check planDesignPlacement carried until then is gone. Refusals become tool errors with a JSON { code, message, diagnostics? } body, as apply_patch returns them: an McpError keeps only its message, which dropped the codes and diagnostics. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Three cases that fail on the current head: - a design-surface placement adds two history entries, and one undo leaves the child in place without its attachment; - a 25 KiB inline design is placed instead of being refused under R7's 24 KiB; - reusing the surface host's id reports does_not_fit instead of node_exists. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…B, checks ids first From the Codex review of AK-02 2/3; the failing cases are the previous commit. - SceneBridge.applyPatch commits the whole patch as one history step (runAsSingleSceneHistoryStep), as apply_patch's description already promised, so a design and its surface host's attachment undo together. - planDesignPlacement refuses designs above 24 KiB of JSON with design_too_large (R7: larger designs wait for pinned definitions). - An explicit id that exists is refused with node_exists before the surface host's shadow graph is built, so reusing the host's own id no longer reads as does_not_fit. The apply_patch identity guard still runs over the final patch. The oversize fixture in the failing-case commit was too small (14.8 KiB); it now builds a valid ~60 KiB design. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Aymericr
force-pushed
the
fidelity/ak-02b-place-design
branch
from
September 28, 2026 04:17
30de136 to
96b80a3
Compare
This was referenced Sep 28, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Merge as one unit (coordinator ruling on the Codex R8 finding): #948, #953 and the private AK-02 3/3 PR (chat tools and scene programs) merge the same day, so there is no window where MCP has design tools that chat and programs lack. The owner's AD-6 exception covers today's surfaces.
Stacked on #948 (AK-02 1/3). Until #948 merges, this diff also shows its commit; the change here is commits dde17bf, 2036305 and 30de136 (rebased onto editor main with #938 merged, 5e7e128), plus the review fixes.
What
Agents can now create a design they validated on today's hosts, with typed refusals.
planDesignPlacement(nodes, request).validateDesign, the same authority asvalidate_design. The design can be an object or a JSON string.mounting, using today's hosting fields only:attachments[childId] = surfaceId);wallId/side, with position = along, height and offset of the reference);validateProceduralRelationsdirectly. The mount checks therefore hold without the node registry: before this, the trial saw ceiling and wall designs accepted as level children whenbuiltinPluginwas not loaded.{ node, parentId, hostUpdate? }or throwsDesignPlacementError. The codes areinvalid_design(with diagnostics),invalid_placement,host_not_found,wrong_host,unknown_surfaceanddoes_not_fit, plus the apply_patch guard codes. A wall misfit says where the reference fits, for example "fits along 0.317–3.683 m and at height 0.47–2.23 m on this wall".place_designwraps it and only creates.applyPatch.{ code, message, diagnostics? }; the message starts with the code.Codex review fixes (failing cases in the commit before 96b80a3):
SceneBridge.applyPatchcommits a whole patch as one history step, so a design-surface placement undoes in one step; designs above 24 KiB are refused withdesign_too_large(R7, as #947); an explicit existing id is refused withnode_existsbefore the surface host's shadow graph is built. The known limit about two undo steps no longer applies.Why
Owner decision AD-6: agent design tools ship now on today's surfaces. This is an explicit, owner-approved exception to charter R8, which otherwise waits for the P-04 tool kernel. It is kernel-shaped: one core function, and the MCP adapter adds only transport. Following the CHALLENGE correction, it uses v1 inline recipes and today's hosting fields; pin and
Mountarguments wait for AK-01/P-05 and the Mount decision.Create-only goes through #938's patch guards.
place_designrunsassertPatchKeepsIdentityover its create (and a surface host's attachment update) beforeapplyPatch, so an explicit existingidis refused with apply_patch's ownnode_existscode and message;planDesignPlacementno longer carries its own check (30de136). Refusals are tool errors with JSON{ code, message, diagnostics? }, like apply_patch's, because an McpError keeps only its message.Failing case before this PR: no tool placed a design.
tools/call place_designreturns "tool not found".apply_patch, an agent had to hand-write the node, and withoutbuiltinPlugina wall-side or ceiling design was accepted as a level child (trial.md, "mount relations are enforced only when the process has loaded builtinPlugin").Proof
bun test src/procedural-items/design-placement.test.ts(core)bun test src(core)bun test(mcp)bun test scripts/openai-tool-annotation-policy.test.ts,bun run skills:validatebun run check, corecheck-types, mcptsgo --noEmitThe tests use the trial fixtures:
invalid_placement: node: Unknown slot paint);validate_scenestays valid after placements.House effect: no change. This is an agent-facing tool, and the converter, viewer and bake never call it.
Eval (AK-02 3/3, cap-design-louver)
Latest run (2026-09-28, on the review-fix heads #948
eaf8c7cec/ #95396b80a3b6, prompt with "place exactly one vent", MCP lane withread_resourceand promptmcp-lane-v2; recordsbench/ai-chat/runs/eval-2026-09-28T04-35-16-586Zdirect,…T04-44-47-852Zmcp):validate_designcallspascal://schema/designfirst and placed within 27–87 s, but both placed louvers are 0.45–0.48 m deep instead of ~0.08 m; the third run never placedNet: the design tools work end to end on both lanes. Duplicate placement in chat and depth control via MCP are prompt and task findings for a follow-up, not tool defects.
R1–R9
validateProceduralRelations) beforeapplyPatch; no new reference kindsFor Wassim to review
design-placement.tsreusesvalidateProceduralRelationsandproceduralLocalPoseand mirrorsprepareProceduralPlacement. It also adds slab and zone resolution and design-surface attachments. Check that the wallpositionsemantics (reference along, height and offset) match how the move tool writes them.Known limits
place_item;check_collisionsreports them.🤖 Generated with Claude Code
Note
Medium Risk
Adds a new agent-driven scene mutation path and placement rules (wall/ceiling hosts, attachments) that must stay consistent with existing procedural relations; patch history grouping changes undo behavior for mixed batches.
Overview
Agents get a design validation and placement pipeline for procedural-item recipes: core
validateDesign/describeDesignSchema(schema, sweeps, measurements, coded diagnostics) andplanDesignPlacement, which validates the recipe, resolves hosts from mounting (floor/slab/zone/design surface, wall-side, ceiling), runsvalidateProceduralRelationswithout relying on the node registry, and returns create plans orDesignPlacementErrorcodes (including wall fit ranges and a 24 KiB inline cap).MCP exposes read-only
validate_design, create-onlyplace_design(viaapplyPatch+ patch identity guards), and resourcepascal://schema/design, with agent-guide/README updates. Trial HVAC/louver/stair-guard fixtures back core and MCP tests.Renderer alignment: shared
PRIMITIVE_TESSELLATION,shapeTriangles, andshapeBoundsso validation counts matchbuildProceduralGeometry.apply_patchis wrapped inrunAsSingleSceneHistoryStepso a create plus surface attachment update undo together. OpenAI tool annotation inventory bumps 49 → 51.Reviewed by Cursor Bugbot for commit 96b80a3. Bugbot is set up for automated code reviews on this repo. Configure here.