[{"data":1,"prerenderedAt":2294},["ShallowReactive",2],{"algo-articles":3,"ai-articles":346},[4],{"id":5,"title":6,"author":7,"body":8,"date":318,"description":319,"extension":320,"keywords":321,"meta":336,"navigation":337,"path":338,"published":337,"seo":339,"stem":340,"tags":341,"__hash__":345},"algorithms\u002Falgorithms\u002Fexact-mesh-arrangements-and-booleans-in-real-time.md","Exact Mesh Arrangements and Booleans in Real-Time","Žiga Sajovic",{"type":9,"value":10,"toc":291},"minimark",[11,15,19,27,33,38,41,46,49,53,59,63,66,70,73,85,89,92,96,103,106,109,113,116,120,126,129,133,136,140,143,147,154,158,161,165,168,172,176,180,183,187,192,196,199,220,224,227,231,235,238,242,246,249,253,264,287],[12,13,14],"p",{},"Mesh arrangements decompose overlapping geometry into classified regions — splitting faces along intersection curves so every face belongs to exactly one region. Mesh booleans select which regions to keep: union, intersection, difference.",[16,17],"headline-numbers",{":items":18},"[{\"value\":\"7ms\",\"label\":\"Intersection curves\",\"detail\":\"2×1M polygons · 233× CGAL\"},{\"value\":\"28ms\",\"label\":\"Boolean union\",\"detail\":\"2×1M polygons · 6× MeshLib · 84× CGAL\"},{\"value\":\"173ms\",\"label\":\"Polygon arrangements\",\"detail\":\"2×1M polygons · 32× libigl\"}]",[12,20,21,22,26],{},"Real meshes are not ideal manifolds. They carry non-manifold flaps, inconsistent winding, coplanar faces, and accumulated pipeline artifacts. ",[23,24,25],"code",{},"trueform"," handles all of them.",[28,29],"data-table",{":headers":30,":highlight":31,":rows":32},"[\"Feature\",\"Handling\"]","0","[[\"Convex polygons\",\"Native — not limited to triangles\"],[\"Non-manifold edges\",\"Handled directly\"],[\"Inconsistent winding\",\"Bayesian classifiers per manifold edge-connected component\"],[\"Self-intersecting input\",\"Resolved via polygon arrangements\"],[\"Coplanar primitives\",\"Resolved via topological exactness — aligned\u002Fopposing boundary classification\"],[\"Hole cuts\",\"Hole patching into the face\"],[\"Contour crossings\",\"Resolved via indirect predicates\"]]",[34,35,37],"h2",{"id":36},"exactness","Exactness",[12,39,40],{},"Two kinds of exactness matter in mesh arrangements: geometric and topological.",[42,43,45],"h3",{"id":44},"geometric-exactness","Geometric exactness",[12,47,48],{},"Input coordinates are scaled to exact integer space. All predicates — orientation tests, intersection points, determinants — are computed with exact integer arithmetic through a precision chain. No floating-point operation participates in any geometric decision.",[28,50],{":headers":51,":highlight":31,":rows":52},"[\"\",\"Coordinates\",\"Intermediate\",\"Predicates\"]","[[\"int32 base (default)\",\"int32\",\"int64\",\"int128\"],[\"int64 base (extended)\",\"int64\",\"int128\",\"int256 (custom)\"]]",[12,54,55,58],{},[23,56,57],{},"orient3d_sign"," returns −1, 0, or +1 — exactly. Zero means coplanar, not \"close to coplanar.\"",[42,60,62],{"id":61},"topological-exactness","Topological exactness",[12,64,65],{},"An intersection point can land on a vertex, on an edge, or at the meeting point of two coplanar edges. Five distinct configurations:",[28,67],{":headers":68,":highlight":31,":rows":69},"[\"Type\",\"Configuration\",\"Resolution\"]","[[\"EF\",\"Edge pierces face\",\"Signed volume ratios\"],[\"EE\",\"Coplanar edge crossing\",\"2D orient2d on projected plane\"],[\"VE\",\"Vertex on edge\",\"orient2d + between test\"],[\"VF\",\"Vertex in face interior\",\"2D winding test\"],[\"VV\",\"Coincident vertices\",\"Exact coordinate match\"]]",[12,71,72],{},"Geometric exactness without topological exactness is typically paired with Simulation of Simplicity (SoS). SoS perturbs input so all configurations collapse to EF — deterministic but arbitrary. A square placed into a cube with edges on faces might produce no intersections, partial, or all, depending on perturbation order. These configurations are not edge cases to avoid — they define contour crossings in multi-mesh arrangements.",[12,74,75,77,78,80,81,84],{},[23,76,25],{}," classifies all five exactly — ",[23,79,57],{}," separates coplanar from non-coplanar, ",[23,82,83],{},"orient2d_sign"," resolves the coplanar cases. Each configuration is resolved to its canonical form.",[34,86,88],{"id":87},"arrangements","Arrangements",[12,90,91],{},"Arrangements resolve multiple mutually intersecting meshes simultaneously.",[42,93,95],{"id":94},"indirect-predicates","Indirect predicates",[12,97,98,99,102],{},"An intersection edge is defined by its originating face pair. An intersection point between two edges is defined by the union of their face pair IDs — a unique triplet of three faces. This identifies points topologically, avoiding geometric ambiguity. Coordinates are computed from the triplet via ",[23,100,101],{},"orient2d","-based interpolation in integer arithmetic, only when needed.",[104,105],"algo-arrangement-diagram",{},[12,107,108],{},"Indirect predicates allow the arrangement to be formulated in two stages: compute pairwise intersection contours between all mesh pairs, then intersect those contours within each face.",[42,110,112],{"id":111},"stage-1-pairwise-intersection-contours","Stage 1: pairwise intersection contours",[12,114,115],{},"An AABB tree narrows candidates to overlapping face pairs. For each pair, intersections are computed exactly. Each intersection produces an edge on both faces, tagged with its originating face pair.",[42,117,119],{"id":118},"stage-2-per-face-contour-intersections","Stage 2: per-face contour intersections",[12,121,122,123,125],{},"Each intersected face carries a small number of edges from different mesh pairs — typically 2–5. These are projected to the face plane and intersected with topological exactness: VV, VE, and EE configurations classified via ",[23,124,101],{},". The result is an intersection graph embedded in the face, defining how it will be split.",[12,127,128],{},"Each face has few edges — trivial to process. Each face is independent — all processed in parallel. Points are identified across faces via their triplets.",[34,130,132],{"id":131},"booleans","Booleans",[12,134,135],{},"A boolean is an arrangement with a classification step. After splitting faces along intersection curves, each resulting face must be labeled as inside or outside the other mesh. The boolean operation selects which labels to keep.",[42,137,139],{"id":138},"components","Components",[12,141,142],{},"Faces are grouped into manifold edge-connected components. Two faces belong to the same component if they share a manifold edge that is not an intersection edge. Non-manifold edges and intersection edges act as barriers — they prohibit crossing between components. Each component receives a single label.",[42,144,146],{"id":145},"wedge-classification","Wedge classification",[12,148,149,150,153],{},"For each intersection edge in a component, the two same-mesh faces sharing that edge form a wedge. A test point from the opposite-mesh neighbor is classified against this wedge using exact ",[23,151,152],{},"orient3d",":",[28,155],{":headers":156,":highlight":31,":rows":157},"[\"Result\",\"Meaning\",\"Vote\"]","[[\"on_negative_side\",\"Test point inside wedge\",\"inside\"],[\"on_positive_side\",\"Test point outside wedge\",\"outside\"],[\"on_boundary\",\"Coplanar — skip\",\"—\"]]",[12,159,160],{},"Coplanar face pairs are classified directly as aligned or opposing boundary based on normal direction.",[42,162,164],{"id":163},"bayesian-classification","Bayesian classification",[12,166,167],{},"Each intersection edge contributes an observation to its component — inside or outside. The per-component label is determined by a Beta-Bernoulli classifier over these observations: inside, outside, aligned boundary, or opposing boundary. Components with no intersection edges fall back to signed distance or ray-based containment tests.",[42,169,171],{"id":170},"operation-mapping","Operation mapping",[28,173],{":headers":174,":highlight":31,":rows":175},"[\"Operation\",\"Keep from A\",\"Keep from B\"]","[[\"Union\",\"outside + aligned boundary\",\"outside\"],[\"Intersection\",\"inside + aligned boundary\",\"inside\"],[\"Difference\",\"outside + opposing boundary\",\"inside\"]]",[34,177,179],{"id":178},"comparison-with-existing-sdks","Comparison with existing SDKs",[12,181,182],{},"Four libraries are commonly used for mesh booleans: CGAL, libigl, MeshLib, and trueform. This is how they compare.",[42,184,186],{"id":185},"capabilities","Capabilities",[28,188],{":headers":189,":highlight":190,":rows":191},"[\"Feature\",\"trueform\",\"MeshLib\",\"CGAL\",\"libigl\"]","1","[[\"Convex polygons\",\"✓\",\"Triangles\",\"✓\",\"Triangles\"],[\"Non-manifold edges\",\"✓\",\"Auto-deletes\",\"Requires manifold\",\"Requires manifold\"],[\"Inconsistent winding\",\"Bayesian\",\"✗\",\"✗\",\"✗\"],[\"Self-intersecting input\",\"✓\",\"Limited\",\"✓\",\"✓\"],[\"Coplanar primitives\",\"Exact\",\"SoS\",\"Kernel-dep.\",\"EPECK\"],[\"Hole cuts\",\"✓\",\"✗\",\"✓\",\"✓\"],[\"N-mesh arrangements\",\"✓\",\"✗\",\"✗\",\"✗\"],[\"Curve extraction\",\"Standalone\",\"✗\",\"Indirect\",\"Indirect\"]]",[42,193,195],{"id":194},"performance","Performance",[12,197,198],{},"Stanford Dragon at varying resolutions. Linear scaling is maintained through 2M+ polygons.",[12,200,201,207,208,207,212,207,216],{},[202,203,206],"span",{"className":204},[205],"tag-pill","Apple M4 Max"," ",[202,209,211],{"className":210},[205],"16 threads",[202,213,215],{"className":214},[205],"Clang -O3",[202,217,219],{"className":218},[205],"mimalloc",[42,221,223],{"id":222},"boolean-union","Boolean union",[12,225,226],{},"trueform uses exact predicates and canonical topology. MeshLib uses SoS with int32. CGAL uses EPIC kernel. libigl uses EPECK (GMP).",[28,228],{":headers":229,":highlight":190,":rows":230},"[\"Polygons\",\"trueform\",\"MeshLib\",\"CGAL\",\"libigl\"]","[[\"2 × 58K\",\"6.4 ms\",\"14.9 ms\",\"133 ms\",\"588 ms\"],[\"2 × 142K\",\"9.0 ms\",\"25.1 ms\",\"329 ms\",\"1225 ms\"],[\"2 × 244K\",\"12.4 ms\",\"54.4 ms\",\"573 ms\",\"1973 ms\"],[\"2 × 481K\",\"16.8 ms\",\"124.7 ms\",\"1082 ms\",\"3666 ms\"],[\"2 × 723K\",\"22.7 ms\",\"112.1 ms\",\"1746 ms\",\"5703 ms\"],[\"2 × 1.03M\",\"27.8 ms\",\"161.5 ms\",\"2339 ms\",\"7735 ms\"]]",[42,232,234],{"id":233},"polygon-arrangements","Polygon arrangements",[12,236,237],{},"Two copies concatenated into a single self-intersecting mesh. MeshLib not benchmarked — refuses nested contour crossings.",[28,239],{":headers":240,":highlight":190,":rows":241},"[\"Polygons\",\"trueform\",\"libigl\"]","[[\"117K\",\"12.7 ms\",\"642 ms\"],[\"284K\",\"27.0 ms\",\"1205 ms\"],[\"488K\",\"42.4 ms\",\"1785 ms\"],[\"962K\",\"78.1 ms\",\"2907 ms\"],[\"1.45M\",\"128.4 ms\",\"4382 ms\"],[\"2.05M\",\"173.2 ms\",\"5509 ms\"]]",[42,243,245],{"id":244},"intersection-curves","Intersection curves",[12,247,248],{},"Standalone extraction of crossing polylines. Most SDKs only provide curves as a side-effect of a full boolean operation.",[28,250],{":headers":251,":highlight":190,":rows":252},"[\"Polygons\",\"trueform\",\"CGAL\"]","[[\"2 × 58K\",\"2.3 ms\",\"86.9 ms\"],[\"2 × 142K\",\"3.4 ms\",\"230.7 ms\"],[\"2 × 244K\",\"4.1 ms\",\"416.7 ms\"],[\"2 × 481K\",\"5.4 ms\",\"777.1 ms\"],[\"2 × 723K\",\"7.0 ms\",\"1266.8 ms\"],[\"2 × 1.03M\",\"7.3 ms\",\"1695.6 ms\"]]",[12,254,255,256,263],{},"Interactive charts, full methodology, and source code: ",[257,258,262],"a",{"href":259,"rel":260},"https:\u002F\u002Ftrueform.polydera.com\u002Fcpp\u002Fbenchmarks",[261],"nofollow","trueform benchmarks",".",[12,265,266,271,272,271,277,271,282],{},[257,267,270],{"href":268,"rel":269},"https:\u002F\u002Ftrueform.polydera.com\u002Flive-examples\u002Fboolean",[261],"Try it live"," · ",[257,273,276],{"href":274,"rel":275},"https:\u002F\u002Ftrueform.polydera.com",[261],"Documentation",[257,278,281],{"href":279,"rel":280},"https:\u002F\u002Fgithub.com\u002Fpolydera\u002Ftrueform",[261],"GitHub",[257,283,286],{"href":284,"rel":285},"https:\u002F\u002Flunar.polydera.com",[261],"Open Lunar",[288,289],"cite-as",{"author":290,"title":6},"Sajovic, {\\v{Z}}iga",{"title":292,"searchDepth":293,"depth":293,"links":294},"",2,[295,300,305,311],{"id":36,"depth":293,"text":37,"children":296},[297,299],{"id":44,"depth":298,"text":45},3,{"id":61,"depth":298,"text":62},{"id":87,"depth":293,"text":88,"children":301},[302,303,304],{"id":94,"depth":298,"text":95},{"id":111,"depth":298,"text":112},{"id":118,"depth":298,"text":119},{"id":131,"depth":293,"text":132,"children":306},[307,308,309,310],{"id":138,"depth":298,"text":139},{"id":145,"depth":298,"text":146},{"id":163,"depth":298,"text":164},{"id":170,"depth":298,"text":171},{"id":178,"depth":293,"text":179,"children":312},[313,314,315,316,317],{"id":185,"depth":298,"text":186},{"id":194,"depth":298,"text":195},{"id":222,"depth":298,"text":223},{"id":233,"depth":298,"text":234},{"id":244,"depth":298,"text":245},"2026-04-20","Arrangements, booleans, and self-intersection resolution at interactive speeds on million-polygon meshes via exact arithmetic and canonical topology. 6× faster than MeshLib, 84× faster than CGAL.","md",[322,323,324,325,326,327,328,329,330,331,332,333,334,335],"fast mesh boolean","fastest mesh boolean","real-time mesh boolean","exact mesh boolean","mesh boolean library","CGAL alternative","mesh boolean comparison","mesh self-intersection","mesh arrangement algorithm","multi mesh arrangements","exact geometry processing","python mesh boolean","typescript mesh boolean","javascript mesh boolean",{},true,"\u002Falgorithms\u002Fexact-mesh-arrangements-and-booleans-in-real-time",{"title":6,"description":319},"algorithms\u002Fexact-mesh-arrangements-and-booleans-in-real-time",[342,343,344,131,87],"topology","exact-arithmetic","parallel","zol2epJQyW9u0dD0SL361wgQ89GaMaTgmBOBxcHz9G0",[347],{"id":348,"title":349,"author":7,"body":350,"date":318,"description":2274,"extension":320,"keywords":2275,"meta":2285,"navigation":337,"path":2286,"published":337,"seo":2287,"stem":2288,"tags":2289,"__hash__":2293},"ai\u002Fai\u002Fschema-driven-interfaces-for-humans-and-ais.md","Schema-Driven Interfaces for Humans and AIs",{"type":9,"value":351,"toc":2261},[352,355,362,366,369,373,376,379,383,386,390,393,396,399,932,939,943,989,992,996,999,1003,1010,1014,1020,1424,1434,1449,1453,1459,1462,1703,1710,2012,2015,2019,2024,2187,2190,2194,2203,2209,2213,2219,2234,2238,2242,2248,2251,2255,2257],[12,353,354],{},"Integrating AI into an application usually means building a second interface — an API wrapper, a set of MCP tools, a function-calling layer. This second interface reimplements validation, drifts out of sync with the UI, and burns thousands of tokens on static schemas before the model even begins to reason.",[12,356,357,361],{},[257,358,360],{"href":359},"\u002Flunar","Lunar"," — a geometry workbench with 45+ operations — treats each interface as a rendering of the same schema. This architecture reduces AI context overhead by over 95% at scale compared to traditional tool enumeration. The UI renders controls. MCP renders tool descriptions. Both feed one executor.",[34,363,365],{"id":364},"the-mcp-problem","The MCP problem",[12,367,368],{},"The standard approach to MCP integration is one tool per operation. This creates problems at scale.",[28,370],{":headers":371,":highlight":31,":rows":372},"[\"MCP server\",\"Tools exposed\",\"Schema tokens\"]","[[\"GitHub\",\"51+\",\"~25,000\"],[\"Playwright\",\"~25\",\"~15,000\"],[\"Filesystem\",\"14\",\"~5,000\"],[\"Typical 3-server setup\",\"~90\",\"~45,000\"],[\"Lunar\",\"3\",\"~1,200\"]]",[12,374,375],{},"Each tool schema consumes 400–800 tokens. A standard three-server setup burns ~45,000 tokens of context before the agent starts working. Cursor hard-caps at 40 MCP tools total — anything beyond is silently dropped.",[12,377,378],{},"The problems compound:",[28,380],{":headers":381,":highlight":31,":rows":382},"[\"Problem\",\"Effect\"]","[[\"Context pollution\",\"Tool schemas consume tokens that should go to reasoning\"],[\"Tool confusion\",\"Models misfire on similar-sounding tools (get_status, fetch_status, query_status)\"],[\"Resource support gap\",\"Under half of MCP clients support resources — tools-only is the practical reality\"],[\"Schema staleness\",\"Tool descriptions are static — adding an operation requires redeploying the MCP server\"],[\"Maintenance burden\",\"The AI interface is a separate codebase that must track the product\"]]",[12,384,385],{},"The workarounds — deferred loading, RAG-based tool selection, toolset flags — address symptoms. The root cause is architectural: operations are coupled to their interface.",[34,387,389],{"id":388},"operations-as-schemas-interfaces-as-renderers","Operations as schemas, interfaces as renderers",[12,391,392],{},"Most applications define operations inside their interface. The UI handler IS the boolean operation. The API endpoint IS the boolean operation. The MCP tool IS the boolean operation. Three implementations of the same thing.",[12,394,395],{},"Lunar defines operations independently — as typed schemas. Interfaces are renderers: they read the schema, present it in their format, gather inputs, and pass them to a shared executor. The operation doesn't know what rendered it.",[397,398],"ai-interface-diagram",{},[400,401,405],"pre",{"className":402,"code":403,"language":404,"meta":292,"style":292},"language-typescript shiki shiki-themes dark-plus","operators.register({\n  id: 'tf.boolean',\n  label: 'Boolean',\n  description: 'Perform a boolean operation (union, intersection, or difference) on two meshes.',\n  category: 'cut',\n  tags: ['boolean', 'csg', 'union', 'intersection', 'difference', 'subtract', 'combine'],\n  docsUrl: 'https:\u002F\u002Ftrueform.polydera.com\u002Fts\u002Fmodules\u002Fcut#boolean-operations',\n  inputs: [\n    { name: 'meshA', label: 'Mesh A', type: 'mesh', description: 'First mesh' },\n    { name: 'meshB', label: 'Mesh B', type: 'mesh', description: 'Second mesh' },\n    { name: 'operation', label: 'Operation', type: 'string',\n      description: 'Boolean operation type',\n      enum: ['union', 'intersection', 'difference'], default: 'union' },\n    { name: 'returnCurves', label: 'Return Curves', type: 'boolean',\n      description: 'Include intersection curves', optional: true, default: false }\n  ],\n  outputs: [\n    { name: 'mesh', label: 'Result', type: 'mesh',\n      description: 'Boolean result mesh', primary: true },\n    { name: 'labels', label: 'Labels', type: 'ndarray',\n      description: 'Per-face region labels' },\n    { name: 'curves', label: 'Curves', type: 'curves',\n      description: 'Intersection curves',\n      condition: { input: 'returnCurves', value: true } }\n  ],\n  async: async ({ meshA, meshB, operation, returnCurves }) => { \u002F* dispatch *\u002F }\n})\n","typescript",[23,406,407,425,437,447,458,469,515,526,535,574,606,632,643,672,698,725,731,739,763,780,806,816,841,851,875,880,926],{"__ignoreMap":292},[202,408,411,415,418,422],{"class":409,"line":410},"line",1,[202,412,414],{"class":413},"s3F5K","operators",[202,416,263],{"class":417},"sTNBD",[202,419,421],{"class":420},"sCudf","register",[202,423,424],{"class":417},"({\n",[202,426,427,430,434],{"class":409,"line":293},[202,428,429],{"class":413},"  id:",[202,431,433],{"class":432},"sKc5r"," 'tf.boolean'",[202,435,436],{"class":417},",\n",[202,438,439,442,445],{"class":409,"line":298},[202,440,441],{"class":413},"  label:",[202,443,444],{"class":432}," 'Boolean'",[202,446,436],{"class":417},[202,448,450,453,456],{"class":409,"line":449},4,[202,451,452],{"class":413},"  description:",[202,454,455],{"class":432}," 'Perform a boolean operation (union, intersection, or difference) on two meshes.'",[202,457,436],{"class":417},[202,459,461,464,467],{"class":409,"line":460},5,[202,462,463],{"class":413},"  category:",[202,465,466],{"class":432}," 'cut'",[202,468,436],{"class":417},[202,470,472,475,478,481,484,487,489,492,494,497,499,502,504,507,509,512],{"class":409,"line":471},6,[202,473,474],{"class":413},"  tags:",[202,476,477],{"class":417}," [",[202,479,480],{"class":432},"'boolean'",[202,482,483],{"class":417},", ",[202,485,486],{"class":432},"'csg'",[202,488,483],{"class":417},[202,490,491],{"class":432},"'union'",[202,493,483],{"class":417},[202,495,496],{"class":432},"'intersection'",[202,498,483],{"class":417},[202,500,501],{"class":432},"'difference'",[202,503,483],{"class":417},[202,505,506],{"class":432},"'subtract'",[202,508,483],{"class":417},[202,510,511],{"class":432},"'combine'",[202,513,514],{"class":417},"],\n",[202,516,518,521,524],{"class":409,"line":517},7,[202,519,520],{"class":413},"  docsUrl:",[202,522,523],{"class":432}," 'https:\u002F\u002Ftrueform.polydera.com\u002Fts\u002Fmodules\u002Fcut#boolean-operations'",[202,525,436],{"class":417},[202,527,529,532],{"class":409,"line":528},8,[202,530,531],{"class":413},"  inputs:",[202,533,534],{"class":417}," [\n",[202,536,538,541,544,547,549,552,555,557,560,563,565,568,571],{"class":409,"line":537},9,[202,539,540],{"class":417},"    { ",[202,542,543],{"class":413},"name:",[202,545,546],{"class":432}," 'meshA'",[202,548,483],{"class":417},[202,550,551],{"class":413},"label:",[202,553,554],{"class":432}," 'Mesh A'",[202,556,483],{"class":417},[202,558,559],{"class":413},"type:",[202,561,562],{"class":432}," 'mesh'",[202,564,483],{"class":417},[202,566,567],{"class":413},"description:",[202,569,570],{"class":432}," 'First mesh'",[202,572,573],{"class":417}," },\n",[202,575,577,579,581,584,586,588,591,593,595,597,599,601,604],{"class":409,"line":576},10,[202,578,540],{"class":417},[202,580,543],{"class":413},[202,582,583],{"class":432}," 'meshB'",[202,585,483],{"class":417},[202,587,551],{"class":413},[202,589,590],{"class":432}," 'Mesh B'",[202,592,483],{"class":417},[202,594,559],{"class":413},[202,596,562],{"class":432},[202,598,483],{"class":417},[202,600,567],{"class":413},[202,602,603],{"class":432}," 'Second mesh'",[202,605,573],{"class":417},[202,607,609,611,613,616,618,620,623,625,627,630],{"class":409,"line":608},11,[202,610,540],{"class":417},[202,612,543],{"class":413},[202,614,615],{"class":432}," 'operation'",[202,617,483],{"class":417},[202,619,551],{"class":413},[202,621,622],{"class":432}," 'Operation'",[202,624,483],{"class":417},[202,626,559],{"class":413},[202,628,629],{"class":432}," 'string'",[202,631,436],{"class":417},[202,633,635,638,641],{"class":409,"line":634},12,[202,636,637],{"class":413},"      description:",[202,639,640],{"class":432}," 'Boolean operation type'",[202,642,436],{"class":417},[202,644,646,649,651,653,655,657,659,661,664,667,670],{"class":409,"line":645},13,[202,647,648],{"class":413},"      enum:",[202,650,477],{"class":417},[202,652,491],{"class":432},[202,654,483],{"class":417},[202,656,496],{"class":432},[202,658,483],{"class":417},[202,660,501],{"class":432},[202,662,663],{"class":417},"], ",[202,665,666],{"class":413},"default:",[202,668,669],{"class":432}," 'union'",[202,671,573],{"class":417},[202,673,675,677,679,682,684,686,689,691,693,696],{"class":409,"line":674},14,[202,676,540],{"class":417},[202,678,543],{"class":413},[202,680,681],{"class":432}," 'returnCurves'",[202,683,483],{"class":417},[202,685,551],{"class":413},[202,687,688],{"class":432}," 'Return Curves'",[202,690,483],{"class":417},[202,692,559],{"class":413},[202,694,695],{"class":432}," 'boolean'",[202,697,436],{"class":417},[202,699,701,703,706,708,711,715,717,719,722],{"class":409,"line":700},15,[202,702,637],{"class":413},[202,704,705],{"class":432}," 'Include intersection curves'",[202,707,483],{"class":417},[202,709,710],{"class":413},"optional:",[202,712,714],{"class":713},"scz_3"," true",[202,716,483],{"class":417},[202,718,666],{"class":413},[202,720,721],{"class":713}," false",[202,723,724],{"class":417}," }\n",[202,726,728],{"class":409,"line":727},16,[202,729,730],{"class":417},"  ],\n",[202,732,734,737],{"class":409,"line":733},17,[202,735,736],{"class":413},"  outputs:",[202,738,534],{"class":417},[202,740,742,744,746,748,750,752,755,757,759,761],{"class":409,"line":741},18,[202,743,540],{"class":417},[202,745,543],{"class":413},[202,747,562],{"class":432},[202,749,483],{"class":417},[202,751,551],{"class":413},[202,753,754],{"class":432}," 'Result'",[202,756,483],{"class":417},[202,758,559],{"class":413},[202,760,562],{"class":432},[202,762,436],{"class":417},[202,764,766,768,771,773,776,778],{"class":409,"line":765},19,[202,767,637],{"class":413},[202,769,770],{"class":432}," 'Boolean result mesh'",[202,772,483],{"class":417},[202,774,775],{"class":413},"primary:",[202,777,714],{"class":713},[202,779,573],{"class":417},[202,781,783,785,787,790,792,794,797,799,801,804],{"class":409,"line":782},20,[202,784,540],{"class":417},[202,786,543],{"class":413},[202,788,789],{"class":432}," 'labels'",[202,791,483],{"class":417},[202,793,551],{"class":413},[202,795,796],{"class":432}," 'Labels'",[202,798,483],{"class":417},[202,800,559],{"class":413},[202,802,803],{"class":432}," 'ndarray'",[202,805,436],{"class":417},[202,807,809,811,814],{"class":409,"line":808},21,[202,810,637],{"class":413},[202,812,813],{"class":432}," 'Per-face region labels'",[202,815,573],{"class":417},[202,817,819,821,823,826,828,830,833,835,837,839],{"class":409,"line":818},22,[202,820,540],{"class":417},[202,822,543],{"class":413},[202,824,825],{"class":432}," 'curves'",[202,827,483],{"class":417},[202,829,551],{"class":413},[202,831,832],{"class":432}," 'Curves'",[202,834,483],{"class":417},[202,836,559],{"class":413},[202,838,825],{"class":432},[202,840,436],{"class":417},[202,842,844,846,849],{"class":409,"line":843},23,[202,845,637],{"class":413},[202,847,848],{"class":432}," 'Intersection curves'",[202,850,436],{"class":417},[202,852,854,857,860,863,865,867,870,872],{"class":409,"line":853},24,[202,855,856],{"class":413},"      condition:",[202,858,859],{"class":417}," { ",[202,861,862],{"class":413},"input:",[202,864,681],{"class":432},[202,866,483],{"class":417},[202,868,869],{"class":413},"value:",[202,871,714],{"class":713},[202,873,874],{"class":417}," } }\n",[202,876,878],{"class":409,"line":877},25,[202,879,730],{"class":417},[202,881,883,886,888,891,894,897,899,902,904,907,909,912,915,918,920,924],{"class":409,"line":882},26,[202,884,885],{"class":420},"  async",[202,887,153],{"class":413},[202,889,890],{"class":713}," async",[202,892,893],{"class":417}," ({ ",[202,895,896],{"class":413},"meshA",[202,898,483],{"class":417},[202,900,901],{"class":413},"meshB",[202,903,483],{"class":417},[202,905,906],{"class":413},"operation",[202,908,483],{"class":417},[202,910,911],{"class":413},"returnCurves",[202,913,914],{"class":417}," }) ",[202,916,917],{"class":713},"=>",[202,919,859],{"class":417},[202,921,923],{"class":922},"sOLPB","\u002F* dispatch *\u002F",[202,925,724],{"class":417},[202,927,929],{"class":409,"line":928},27,[202,930,931],{"class":417},"})\n",[12,933,934,935,938],{},"This definition carries everything a renderer needs: typed inputs with labels, constraints, and defaults. Outputs with conditions. Tags for search. A docs URL for linking. The ",[23,936,937],{},"async"," function is used by the executor to dispatch the task to the engine. Each interface reads the same definition and renders it in its own format — the operation itself is written once.",[34,940,942],{"id":941},"the-human-interface","The human interface",[12,944,945,946,949,950,953,954,957,958,961,962,965,966,953,969,972,973,976,977,980,981,984,985,988],{},"The schema drives every element of the UI. ",[23,947,948],{},"type"," maps to widget: ",[23,951,952],{},"number"," with ",[23,955,956],{},"min","\u002F",[23,959,960],{},"max"," → slider, ",[23,963,964],{},"boolean"," → toggle, ",[23,967,968],{},"string",[23,970,971],{},"enum"," → dropdown. ",[23,974,975],{},"category"," places the operator in the sidebar. ",[23,978,979],{},"tags"," feed Cmd+K search — typing \"csg\" finds Boolean. ",[23,982,983],{},"label"," titles each control. ",[23,986,987],{},"docsUrl"," links the help icon to documentation. Operand inputs come from scene selection — the user selects nodes, the panel fills in operand slots by type.",[12,990,991],{},"No UI code per operation. Adding an operator to the registry adds it to the sidebar, makes it searchable, generates its control panel, and connects its help link. The panel renderer reads the schema and builds the interface.",[34,993,995],{"id":994},"the-model-interface","The model interface",[12,997,998],{},"An AI model receives three tools:",[28,1000],{":headers":1001,":highlight":31,":rows":1002},"[\"Tool\",\"Purpose\",\"Analogy\"]","[[\"discover()\",\"Browse operator catalog, get schemas on demand\",\"Human browses categories, opens Cmd+K\"],[\"world_state()\",\"Read scene — same data that drives UI panels, stats, bounding boxes\",\"Human looks at the viewport\"],[\"run({ operations })\",\"Execute one or more operations in batch\",\"Human clicks Run\"]]",[12,1004,1005,1006,1009],{},"Three tools, ~1,200 tokens of schema. The model discovers 45+ operations dynamically through ",[23,1007,1008],{},"discover()"," — they are not loaded at connection time.",[42,1011,1013],{"id":1012},"compact-catalog","Compact catalog",[12,1015,1016,1017,1019],{},"The first ",[23,1018,1008],{}," call returns a compact listing:",[400,1021,1025],{"className":1022,"code":1023,"language":1024,"meta":292,"style":292},"language-json shiki shiki-themes dark-plus","{\n  \"cut\": [\n    { \"id\": \"tf.boolean\",    \"l\": \"Boolean\", \"n\": 2, \"p\": [\"operation\"] },\n    { \"id\": \"tf.meshArrangements\", \"l\": \"Mesh Arrangements\", \"n\": \"N\" },\n    ...\n  ],\n  \"geometry\": [\n    { \"id\": \"tf.sphereMesh\", \"l\": \"Sphere\", \"p\": [\"radius\", \"stacks\"] },\n    { \"id\": \"tf.boxMesh\",    \"l\": \"Box\",    \"p\": [\"width\", \"height\", \"depth\"] },\n    ...\n  ],\n  \"scene\": [\n    { \"id\": \"scene.add_mesh\",   \"l\": \"Add Mesh\",   \"p\": [\"label\", \"points\", \"faces\"] },\n    { \"id\": \"scene.add_curves\", \"l\": \"Add Curves\",  \"p\": [\"label\", \"points\", \"paths\", \"offsets\"] },\n    { \"id\": \"scene.screenshot\", \"l\": \"Screenshot\" },\n    ...\n  ],\n  \"camera\": [\n    { \"id\": \"camera.describe\",  \"l\": \"Describe Camera\" },\n    { \"id\": \"camera.fit_to_nodes\", \"l\": \"Fit to Nodes\", \"p\": [\"nodeIds\"] },\n    ...\n  ],\n  ...\n}\n","json",[23,1026,1027,1032,1040,1089,1120,1126,1130,1137,1173,1214,1218,1222,1229,1271,1316,1338,1342,1346,1353,1375,1406,1410,1414,1419],{"__ignoreMap":292},[202,1028,1029],{"class":409,"line":410},[202,1030,1031],{"class":417},"{\n",[202,1033,1034,1037],{"class":409,"line":293},[202,1035,1036],{"class":413},"  \"cut\"",[202,1038,1039],{"class":417},": [\n",[202,1041,1042,1044,1047,1050,1053,1056,1059,1061,1064,1066,1069,1071,1075,1077,1080,1083,1086],{"class":409,"line":298},[202,1043,540],{"class":417},[202,1045,1046],{"class":413},"\"id\"",[202,1048,1049],{"class":417},": ",[202,1051,1052],{"class":432},"\"tf.boolean\"",[202,1054,1055],{"class":417},",    ",[202,1057,1058],{"class":413},"\"l\"",[202,1060,1049],{"class":417},[202,1062,1063],{"class":432},"\"Boolean\"",[202,1065,483],{"class":417},[202,1067,1068],{"class":413},"\"n\"",[202,1070,1049],{"class":417},[202,1072,1074],{"class":1073},"sDGX8","2",[202,1076,483],{"class":417},[202,1078,1079],{"class":413},"\"p\"",[202,1081,1082],{"class":417},": [",[202,1084,1085],{"class":432},"\"operation\"",[202,1087,1088],{"class":417},"] },\n",[202,1090,1091,1093,1095,1097,1100,1102,1104,1106,1109,1111,1113,1115,1118],{"class":409,"line":449},[202,1092,540],{"class":417},[202,1094,1046],{"class":413},[202,1096,1049],{"class":417},[202,1098,1099],{"class":432},"\"tf.meshArrangements\"",[202,1101,483],{"class":417},[202,1103,1058],{"class":413},[202,1105,1049],{"class":417},[202,1107,1108],{"class":432},"\"Mesh Arrangements\"",[202,1110,483],{"class":417},[202,1112,1068],{"class":413},[202,1114,1049],{"class":417},[202,1116,1117],{"class":432},"\"N\"",[202,1119,573],{"class":417},[202,1121,1122],{"class":409,"line":460},[202,1123,1125],{"class":1124},"sHkYM","    ...\n",[202,1127,1128],{"class":409,"line":471},[202,1129,730],{"class":417},[202,1131,1132,1135],{"class":409,"line":517},[202,1133,1134],{"class":413},"  \"geometry\"",[202,1136,1039],{"class":417},[202,1138,1139,1141,1143,1145,1148,1150,1152,1154,1157,1159,1161,1163,1166,1168,1171],{"class":409,"line":528},[202,1140,540],{"class":417},[202,1142,1046],{"class":413},[202,1144,1049],{"class":417},[202,1146,1147],{"class":432},"\"tf.sphereMesh\"",[202,1149,483],{"class":417},[202,1151,1058],{"class":413},[202,1153,1049],{"class":417},[202,1155,1156],{"class":432},"\"Sphere\"",[202,1158,483],{"class":417},[202,1160,1079],{"class":413},[202,1162,1082],{"class":417},[202,1164,1165],{"class":432},"\"radius\"",[202,1167,483],{"class":417},[202,1169,1170],{"class":432},"\"stacks\"",[202,1172,1088],{"class":417},[202,1174,1175,1177,1179,1181,1184,1186,1188,1190,1193,1195,1197,1199,1202,1204,1207,1209,1212],{"class":409,"line":537},[202,1176,540],{"class":417},[202,1178,1046],{"class":413},[202,1180,1049],{"class":417},[202,1182,1183],{"class":432},"\"tf.boxMesh\"",[202,1185,1055],{"class":417},[202,1187,1058],{"class":413},[202,1189,1049],{"class":417},[202,1191,1192],{"class":432},"\"Box\"",[202,1194,1055],{"class":417},[202,1196,1079],{"class":413},[202,1198,1082],{"class":417},[202,1200,1201],{"class":432},"\"width\"",[202,1203,483],{"class":417},[202,1205,1206],{"class":432},"\"height\"",[202,1208,483],{"class":417},[202,1210,1211],{"class":432},"\"depth\"",[202,1213,1088],{"class":417},[202,1215,1216],{"class":409,"line":576},[202,1217,1125],{"class":1124},[202,1219,1220],{"class":409,"line":608},[202,1221,730],{"class":417},[202,1223,1224,1227],{"class":409,"line":634},[202,1225,1226],{"class":413},"  \"scene\"",[202,1228,1039],{"class":417},[202,1230,1231,1233,1235,1237,1240,1243,1245,1247,1250,1252,1254,1256,1259,1261,1264,1266,1269],{"class":409,"line":645},[202,1232,540],{"class":417},[202,1234,1046],{"class":413},[202,1236,1049],{"class":417},[202,1238,1239],{"class":432},"\"scene.add_mesh\"",[202,1241,1242],{"class":417},",   ",[202,1244,1058],{"class":413},[202,1246,1049],{"class":417},[202,1248,1249],{"class":432},"\"Add Mesh\"",[202,1251,1242],{"class":417},[202,1253,1079],{"class":413},[202,1255,1082],{"class":417},[202,1257,1258],{"class":432},"\"label\"",[202,1260,483],{"class":417},[202,1262,1263],{"class":432},"\"points\"",[202,1265,483],{"class":417},[202,1267,1268],{"class":432},"\"faces\"",[202,1270,1088],{"class":417},[202,1272,1273,1275,1277,1279,1282,1284,1286,1288,1291,1294,1296,1298,1300,1302,1304,1306,1309,1311,1314],{"class":409,"line":674},[202,1274,540],{"class":417},[202,1276,1046],{"class":413},[202,1278,1049],{"class":417},[202,1280,1281],{"class":432},"\"scene.add_curves\"",[202,1283,483],{"class":417},[202,1285,1058],{"class":413},[202,1287,1049],{"class":417},[202,1289,1290],{"class":432},"\"Add Curves\"",[202,1292,1293],{"class":417},",  ",[202,1295,1079],{"class":413},[202,1297,1082],{"class":417},[202,1299,1258],{"class":432},[202,1301,483],{"class":417},[202,1303,1263],{"class":432},[202,1305,483],{"class":417},[202,1307,1308],{"class":432},"\"paths\"",[202,1310,483],{"class":417},[202,1312,1313],{"class":432},"\"offsets\"",[202,1315,1088],{"class":417},[202,1317,1318,1320,1322,1324,1327,1329,1331,1333,1336],{"class":409,"line":700},[202,1319,540],{"class":417},[202,1321,1046],{"class":413},[202,1323,1049],{"class":417},[202,1325,1326],{"class":432},"\"scene.screenshot\"",[202,1328,483],{"class":417},[202,1330,1058],{"class":413},[202,1332,1049],{"class":417},[202,1334,1335],{"class":432},"\"Screenshot\"",[202,1337,573],{"class":417},[202,1339,1340],{"class":409,"line":727},[202,1341,1125],{"class":1124},[202,1343,1344],{"class":409,"line":733},[202,1345,730],{"class":417},[202,1347,1348,1351],{"class":409,"line":741},[202,1349,1350],{"class":413},"  \"camera\"",[202,1352,1039],{"class":417},[202,1354,1355,1357,1359,1361,1364,1366,1368,1370,1373],{"class":409,"line":765},[202,1356,540],{"class":417},[202,1358,1046],{"class":413},[202,1360,1049],{"class":417},[202,1362,1363],{"class":432},"\"camera.describe\"",[202,1365,1293],{"class":417},[202,1367,1058],{"class":413},[202,1369,1049],{"class":417},[202,1371,1372],{"class":432},"\"Describe Camera\"",[202,1374,573],{"class":417},[202,1376,1377,1379,1381,1383,1386,1388,1390,1392,1395,1397,1399,1401,1404],{"class":409,"line":782},[202,1378,540],{"class":417},[202,1380,1046],{"class":413},[202,1382,1049],{"class":417},[202,1384,1385],{"class":432},"\"camera.fit_to_nodes\"",[202,1387,483],{"class":417},[202,1389,1058],{"class":413},[202,1391,1049],{"class":417},[202,1393,1394],{"class":432},"\"Fit to Nodes\"",[202,1396,483],{"class":417},[202,1398,1079],{"class":413},[202,1400,1082],{"class":417},[202,1402,1403],{"class":432},"\"nodeIds\"",[202,1405,1088],{"class":417},[202,1407,1408],{"class":409,"line":808},[202,1409,1125],{"class":1124},[202,1411,1412],{"class":409,"line":818},[202,1413,730],{"class":417},[202,1415,1416],{"class":409,"line":843},[202,1417,1418],{"class":1124},"  ...\n",[202,1420,1421],{"class":409,"line":853},[202,1422,1423],{"class":417},"}\n",[12,1425,1426,1427,1430,1431,1433],{},"Organized by category. ",[23,1428,1429],{},"n"," = how many operands to pass. ",[23,1432,12],{}," = parameter names. The model sees the full catalog in one response without consuming context for 45+ full schemas.",[12,1435,1436,1437,1440,1441,1444,1445,1448],{},"When it needs to use an operator, it calls ",[23,1438,1439],{},"discover({ operatorIds: [...] })"," for full schemas — types, constraints, defaults, and an ",[23,1442,1443],{},"_example"," showing the exact ",[23,1446,1447],{},"run()"," call. On-demand, not upfront.",[42,1450,1452],{"id":1451},"world-state","World state",[12,1454,1455,1458],{},[23,1456,1457],{},"world_state()"," is how the model observes the scene — the equivalent of the human looking at the viewport and the properties panel.",[12,1460,1461],{},"Called without arguments, it returns a compact overview:",[400,1463,1465],{"className":1022,"code":1464,"language":1024,"meta":292,"style":292},"{\n  \"summary\": \"2 meshes, 550319 faces, 1 selected\",\n  \"nodes\": [\n    { \"id\": \"Stanford Dragon-1\", \"label\": \"Stanford Dragon\",\n      \"type\": \"mesh\", \"visible\": true, \"center\": [-1.14, 1.39, 0.26],\n      \"children\": [\"shape-index-1\"] },\n    { \"id\": \"shape-index-1\", \"label\": \"Shape Index\",\n      \"type\": \"ndarray\", \"visible\": true, \"parentId\": \"Stanford Dragon-1\" },\n    { \"id\": \"Stanford Bunny-1\", \"label\": \"Stanford Bunny\",\n      \"type\": \"mesh\", \"visible\": true, \"center\": [12.24, 1.26, 0.00],\n      \"children\": [\"shape-index-2\", \"boundary-edges-1\"] },\n    ...\n  ]\n}\n",[23,1466,1467,1471,1483,1490,1512,1554,1566,1587,1615,1637,1674,1690,1694,1699],{"__ignoreMap":292},[202,1468,1469],{"class":409,"line":410},[202,1470,1031],{"class":417},[202,1472,1473,1476,1478,1481],{"class":409,"line":293},[202,1474,1475],{"class":413},"  \"summary\"",[202,1477,1049],{"class":417},[202,1479,1480],{"class":432},"\"2 meshes, 550319 faces, 1 selected\"",[202,1482,436],{"class":417},[202,1484,1485,1488],{"class":409,"line":298},[202,1486,1487],{"class":413},"  \"nodes\"",[202,1489,1039],{"class":417},[202,1491,1492,1494,1496,1498,1501,1503,1505,1507,1510],{"class":409,"line":449},[202,1493,540],{"class":417},[202,1495,1046],{"class":413},[202,1497,1049],{"class":417},[202,1499,1500],{"class":432},"\"Stanford Dragon-1\"",[202,1502,483],{"class":417},[202,1504,1258],{"class":413},[202,1506,1049],{"class":417},[202,1508,1509],{"class":432},"\"Stanford Dragon\"",[202,1511,436],{"class":417},[202,1513,1514,1517,1519,1522,1524,1527,1529,1532,1534,1537,1539,1542,1544,1547,1549,1552],{"class":409,"line":460},[202,1515,1516],{"class":413},"      \"type\"",[202,1518,1049],{"class":417},[202,1520,1521],{"class":432},"\"mesh\"",[202,1523,483],{"class":417},[202,1525,1526],{"class":413},"\"visible\"",[202,1528,1049],{"class":417},[202,1530,1531],{"class":713},"true",[202,1533,483],{"class":417},[202,1535,1536],{"class":413},"\"center\"",[202,1538,1082],{"class":417},[202,1540,1541],{"class":1073},"-1.14",[202,1543,483],{"class":417},[202,1545,1546],{"class":1073},"1.39",[202,1548,483],{"class":417},[202,1550,1551],{"class":1073},"0.26",[202,1553,514],{"class":417},[202,1555,1556,1559,1561,1564],{"class":409,"line":471},[202,1557,1558],{"class":413},"      \"children\"",[202,1560,1082],{"class":417},[202,1562,1563],{"class":432},"\"shape-index-1\"",[202,1565,1088],{"class":417},[202,1567,1568,1570,1572,1574,1576,1578,1580,1582,1585],{"class":409,"line":517},[202,1569,540],{"class":417},[202,1571,1046],{"class":413},[202,1573,1049],{"class":417},[202,1575,1563],{"class":432},[202,1577,483],{"class":417},[202,1579,1258],{"class":413},[202,1581,1049],{"class":417},[202,1583,1584],{"class":432},"\"Shape Index\"",[202,1586,436],{"class":417},[202,1588,1589,1591,1593,1596,1598,1600,1602,1604,1606,1609,1611,1613],{"class":409,"line":528},[202,1590,1516],{"class":413},[202,1592,1049],{"class":417},[202,1594,1595],{"class":432},"\"ndarray\"",[202,1597,483],{"class":417},[202,1599,1526],{"class":413},[202,1601,1049],{"class":417},[202,1603,1531],{"class":713},[202,1605,483],{"class":417},[202,1607,1608],{"class":413},"\"parentId\"",[202,1610,1049],{"class":417},[202,1612,1500],{"class":432},[202,1614,573],{"class":417},[202,1616,1617,1619,1621,1623,1626,1628,1630,1632,1635],{"class":409,"line":537},[202,1618,540],{"class":417},[202,1620,1046],{"class":413},[202,1622,1049],{"class":417},[202,1624,1625],{"class":432},"\"Stanford Bunny-1\"",[202,1627,483],{"class":417},[202,1629,1258],{"class":413},[202,1631,1049],{"class":417},[202,1633,1634],{"class":432},"\"Stanford Bunny\"",[202,1636,436],{"class":417},[202,1638,1639,1641,1643,1645,1647,1649,1651,1653,1655,1657,1659,1662,1664,1667,1669,1672],{"class":409,"line":576},[202,1640,1516],{"class":413},[202,1642,1049],{"class":417},[202,1644,1521],{"class":432},[202,1646,483],{"class":417},[202,1648,1526],{"class":413},[202,1650,1049],{"class":417},[202,1652,1531],{"class":713},[202,1654,483],{"class":417},[202,1656,1536],{"class":413},[202,1658,1082],{"class":417},[202,1660,1661],{"class":1073},"12.24",[202,1663,483],{"class":417},[202,1665,1666],{"class":1073},"1.26",[202,1668,483],{"class":417},[202,1670,1671],{"class":1073},"0.00",[202,1673,514],{"class":417},[202,1675,1676,1678,1680,1683,1685,1688],{"class":409,"line":608},[202,1677,1558],{"class":413},[202,1679,1082],{"class":417},[202,1681,1682],{"class":432},"\"shape-index-2\"",[202,1684,483],{"class":417},[202,1686,1687],{"class":432},"\"boundary-edges-1\"",[202,1689,1088],{"class":417},[202,1691,1692],{"class":409,"line":634},[202,1693,1125],{"class":1124},[202,1695,1696],{"class":409,"line":645},[202,1697,1698],{"class":417},"  ]\n",[202,1700,1701],{"class":409,"line":674},[202,1702,1423],{"class":417},[12,1704,1705,1706,1709],{},"Called with ",[23,1707,1708],{},"nodeIds",", it returns full detail — the same data that drives the properties inspector:",[400,1711,1713],{"className":1022,"code":1712,"language":1024,"meta":292,"style":292},"{\n  \"nodes\": [\n    { \"id\": \"Stanford Dragon-1\", \"type\": \"mesh\",\n      \"children\": [\"shape-index-1\"],\n      \"properties\": {\n        \"faces\": 480868, \"vertices\": 240428,\n        \"aabb\": { \"min\": [-9.06, -4.20, -3.28], \"max\": [6.78, 6.98, 3.80] },\n        \"obb\": { \"center\": [-1.81, 0.46, -0.25], \"axes\": [...], \"extent\": [16.14, 12.54, 6.88] }\n      }\n    },\n    { \"id\": \"shape-index-1\", \"type\": \"ndarray\", \"parentId\": \"Stanford Dragon-1\",\n      \"properties\": {\n        \"shape\": [240428], \"dtype\": \"float32\",\n        \"min\": -0.999, \"max\": 0.997, \"mean\": 0.171, \"std\": 0.482\n      }\n    }\n  ]\n}\n",[23,1714,1715,1719,1725,1746,1756,1764,1786,1834,1891,1896,1901,1929,1935,1956,1995,1999,2004,2008],{"__ignoreMap":292},[202,1716,1717],{"class":409,"line":410},[202,1718,1031],{"class":417},[202,1720,1721,1723],{"class":409,"line":293},[202,1722,1487],{"class":413},[202,1724,1039],{"class":417},[202,1726,1727,1729,1731,1733,1735,1737,1740,1742,1744],{"class":409,"line":298},[202,1728,540],{"class":417},[202,1730,1046],{"class":413},[202,1732,1049],{"class":417},[202,1734,1500],{"class":432},[202,1736,483],{"class":417},[202,1738,1739],{"class":413},"\"type\"",[202,1741,1049],{"class":417},[202,1743,1521],{"class":432},[202,1745,436],{"class":417},[202,1747,1748,1750,1752,1754],{"class":409,"line":449},[202,1749,1558],{"class":413},[202,1751,1082],{"class":417},[202,1753,1563],{"class":432},[202,1755,514],{"class":417},[202,1757,1758,1761],{"class":409,"line":460},[202,1759,1760],{"class":413},"      \"properties\"",[202,1762,1763],{"class":417},": {\n",[202,1765,1766,1769,1771,1774,1776,1779,1781,1784],{"class":409,"line":471},[202,1767,1768],{"class":413},"        \"faces\"",[202,1770,1049],{"class":417},[202,1772,1773],{"class":1073},"480868",[202,1775,483],{"class":417},[202,1777,1778],{"class":413},"\"vertices\"",[202,1780,1049],{"class":417},[202,1782,1783],{"class":1073},"240428",[202,1785,436],{"class":417},[202,1787,1788,1791,1794,1797,1799,1802,1804,1807,1809,1812,1814,1817,1819,1822,1824,1827,1829,1832],{"class":409,"line":517},[202,1789,1790],{"class":413},"        \"aabb\"",[202,1792,1793],{"class":417},": { ",[202,1795,1796],{"class":413},"\"min\"",[202,1798,1082],{"class":417},[202,1800,1801],{"class":1073},"-9.06",[202,1803,483],{"class":417},[202,1805,1806],{"class":1073},"-4.20",[202,1808,483],{"class":417},[202,1810,1811],{"class":1073},"-3.28",[202,1813,663],{"class":417},[202,1815,1816],{"class":413},"\"max\"",[202,1818,1082],{"class":417},[202,1820,1821],{"class":1073},"6.78",[202,1823,483],{"class":417},[202,1825,1826],{"class":1073},"6.98",[202,1828,483],{"class":417},[202,1830,1831],{"class":1073},"3.80",[202,1833,1088],{"class":417},[202,1835,1836,1839,1841,1843,1845,1848,1850,1853,1855,1858,1860,1863,1865,1868,1870,1873,1875,1878,1880,1883,1885,1888],{"class":409,"line":528},[202,1837,1838],{"class":413},"        \"obb\"",[202,1840,1793],{"class":417},[202,1842,1536],{"class":413},[202,1844,1082],{"class":417},[202,1846,1847],{"class":1073},"-1.81",[202,1849,483],{"class":417},[202,1851,1852],{"class":1073},"0.46",[202,1854,483],{"class":417},[202,1856,1857],{"class":1073},"-0.25",[202,1859,663],{"class":417},[202,1861,1862],{"class":413},"\"axes\"",[202,1864,1082],{"class":417},[202,1866,1867],{"class":1124},"...",[202,1869,663],{"class":417},[202,1871,1872],{"class":413},"\"extent\"",[202,1874,1082],{"class":417},[202,1876,1877],{"class":1073},"16.14",[202,1879,483],{"class":417},[202,1881,1882],{"class":1073},"12.54",[202,1884,483],{"class":417},[202,1886,1887],{"class":1073},"6.88",[202,1889,1890],{"class":417},"] }\n",[202,1892,1893],{"class":409,"line":537},[202,1894,1895],{"class":417},"      }\n",[202,1897,1898],{"class":409,"line":576},[202,1899,1900],{"class":417},"    },\n",[202,1902,1903,1905,1907,1909,1911,1913,1915,1917,1919,1921,1923,1925,1927],{"class":409,"line":608},[202,1904,540],{"class":417},[202,1906,1046],{"class":413},[202,1908,1049],{"class":417},[202,1910,1563],{"class":432},[202,1912,483],{"class":417},[202,1914,1739],{"class":413},[202,1916,1049],{"class":417},[202,1918,1595],{"class":432},[202,1920,483],{"class":417},[202,1922,1608],{"class":413},[202,1924,1049],{"class":417},[202,1926,1500],{"class":432},[202,1928,436],{"class":417},[202,1930,1931,1933],{"class":409,"line":634},[202,1932,1760],{"class":413},[202,1934,1763],{"class":417},[202,1936,1937,1940,1942,1944,1946,1949,1951,1954],{"class":409,"line":645},[202,1938,1939],{"class":413},"        \"shape\"",[202,1941,1082],{"class":417},[202,1943,1783],{"class":1073},[202,1945,663],{"class":417},[202,1947,1948],{"class":413},"\"dtype\"",[202,1950,1049],{"class":417},[202,1952,1953],{"class":432},"\"float32\"",[202,1955,436],{"class":417},[202,1957,1958,1961,1963,1966,1968,1970,1972,1975,1977,1980,1982,1985,1987,1990,1992],{"class":409,"line":674},[202,1959,1960],{"class":413},"        \"min\"",[202,1962,1049],{"class":417},[202,1964,1965],{"class":1073},"-0.999",[202,1967,483],{"class":417},[202,1969,1816],{"class":413},[202,1971,1049],{"class":417},[202,1973,1974],{"class":1073},"0.997",[202,1976,483],{"class":417},[202,1978,1979],{"class":413},"\"mean\"",[202,1981,1049],{"class":417},[202,1983,1984],{"class":1073},"0.171",[202,1986,483],{"class":417},[202,1988,1989],{"class":413},"\"std\"",[202,1991,1049],{"class":417},[202,1993,1994],{"class":1073},"0.482\n",[202,1996,1997],{"class":409,"line":700},[202,1998,1895],{"class":417},[202,2000,2001],{"class":409,"line":727},[202,2002,2003],{"class":417},"    }\n",[202,2005,2006],{"class":409,"line":733},[202,2007,1698],{"class":417},[202,2009,2010],{"class":409,"line":741},[202,2011,1423],{"class":417},[12,2013,2014],{},"Derived data — curvature fields, boundary edges, distance maps — lives as children of the mesh that produced it. The model sees the same scene graph the human sees: nodes, parent-child relationships, spatial properties. Two levels of detail — compact for orientation, detailed for spatial reasoning.",[42,2016,2018],{"id":2017},"running-operations","Running operations",[12,2020,2021,2023],{},[23,2022,1447],{}," accepts an array of operations. Create a sphere, position it, boolean it — one tool call:",[400,2025,2027],{"className":1022,"code":2026,"language":1024,"meta":292,"style":292},"{\n  \"operations\": [\n    {\n      \"operatorId\": \"tf.sphereMesh\",\n      \"params\": { \"radius\": 3 }\n    },\n    {\n      \"operatorId\": \"scene.set_position\",\n      \"nodeIds\": [\"sphere-1\"],\n      \"params\": { \"xyz\": [2, 4, 0] }\n    },\n    {\n      \"operatorId\": \"tf.boolean\",\n      \"nodeIds\": [\"dragon-1\", \"sphere-1\"],\n      \"params\": { \"operation\": \"difference\" }\n    }\n  ]\n}\n",[23,2028,2029,2033,2040,2045,2056,2072,2076,2080,2091,2103,2127,2131,2135,2145,2160,2175,2179,2183],{"__ignoreMap":292},[202,2030,2031],{"class":409,"line":410},[202,2032,1031],{"class":417},[202,2034,2035,2038],{"class":409,"line":293},[202,2036,2037],{"class":413},"  \"operations\"",[202,2039,1039],{"class":417},[202,2041,2042],{"class":409,"line":298},[202,2043,2044],{"class":417},"    {\n",[202,2046,2047,2050,2052,2054],{"class":409,"line":449},[202,2048,2049],{"class":413},"      \"operatorId\"",[202,2051,1049],{"class":417},[202,2053,1147],{"class":432},[202,2055,436],{"class":417},[202,2057,2058,2061,2063,2065,2067,2070],{"class":409,"line":460},[202,2059,2060],{"class":413},"      \"params\"",[202,2062,1793],{"class":417},[202,2064,1165],{"class":413},[202,2066,1049],{"class":417},[202,2068,2069],{"class":1073},"3",[202,2071,724],{"class":417},[202,2073,2074],{"class":409,"line":471},[202,2075,1900],{"class":417},[202,2077,2078],{"class":409,"line":517},[202,2079,2044],{"class":417},[202,2081,2082,2084,2086,2089],{"class":409,"line":528},[202,2083,2049],{"class":413},[202,2085,1049],{"class":417},[202,2087,2088],{"class":432},"\"scene.set_position\"",[202,2090,436],{"class":417},[202,2092,2093,2096,2098,2101],{"class":409,"line":537},[202,2094,2095],{"class":413},"      \"nodeIds\"",[202,2097,1082],{"class":417},[202,2099,2100],{"class":432},"\"sphere-1\"",[202,2102,514],{"class":417},[202,2104,2105,2107,2109,2112,2114,2116,2118,2121,2123,2125],{"class":409,"line":576},[202,2106,2060],{"class":413},[202,2108,1793],{"class":417},[202,2110,2111],{"class":413},"\"xyz\"",[202,2113,1082],{"class":417},[202,2115,1074],{"class":1073},[202,2117,483],{"class":417},[202,2119,2120],{"class":1073},"4",[202,2122,483],{"class":417},[202,2124,31],{"class":1073},[202,2126,1890],{"class":417},[202,2128,2129],{"class":409,"line":608},[202,2130,1900],{"class":417},[202,2132,2133],{"class":409,"line":634},[202,2134,2044],{"class":417},[202,2136,2137,2139,2141,2143],{"class":409,"line":645},[202,2138,2049],{"class":413},[202,2140,1049],{"class":417},[202,2142,1052],{"class":432},[202,2144,436],{"class":417},[202,2146,2147,2149,2151,2154,2156,2158],{"class":409,"line":674},[202,2148,2095],{"class":413},[202,2150,1082],{"class":417},[202,2152,2153],{"class":432},"\"dragon-1\"",[202,2155,483],{"class":417},[202,2157,2100],{"class":432},[202,2159,514],{"class":417},[202,2161,2162,2164,2166,2168,2170,2173],{"class":409,"line":700},[202,2163,2060],{"class":413},[202,2165,1793],{"class":417},[202,2167,1085],{"class":413},[202,2169,1049],{"class":417},[202,2171,2172],{"class":432},"\"difference\"",[202,2174,724],{"class":417},[202,2176,2177],{"class":409,"line":727},[202,2178,2003],{"class":417},[202,2180,2181],{"class":409,"line":733},[202,2182,1698],{"class":417},[202,2184,2185],{"class":409,"line":741},[202,2186,1423],{"class":417},[12,2188,2189],{},"Operations execute sequentially — each can reference nodes created by the previous. Fewer round-trips, fewer tokens, faster workflows.",[42,2191,2193],{"id":2192},"dynamic-catalog","Dynamic catalog",[12,2195,2196,2197,2199,2200,2202],{},"Because ",[23,2198,1008],{}," is a tool call — not a static schema — the catalog updates as the application evolves. Add an operation to the registry, and the next ",[23,2201,1008],{}," call includes it. No MCP server redeployment. No schema versioning. No stale descriptions.",[12,2204,2205,2206,2208],{},"The same applies to ",[23,2207,1457],{}," — scene state is read via a tool call, not MCP resources. This avoids the resource support gap: tools work across all clients.",[34,2210,2212],{"id":2211},"one-executor-one-application","One executor, one application",[12,2214,2215,2216,2218],{},"The human interface gathers inputs from UI widgets and scene selection. The model interface gathers inputs from the ",[23,2217,1447],{}," request. Both produce the same shape — a params dict and a list of nodeIds — and from there, the path is identical. One executor resolves operands, validates against the schema, runs the operation, places outputs into the scene. If validation fails, the same error propagates back through whichever interface initiated it. One validation path, written once.",[12,2220,2221,2222,2225,2226,2229,2230,2233],{},"All actions — geometry, scene manipulation, camera control, data injection — are operations in the same registry. ",[23,2223,2224],{},"camera.describe"," returns the viewport's coordinate mapping. ",[23,2227,2228],{},"scene.screenshot"," captures what the human sees. ",[23,2231,2232],{},"scene.add_mesh"," injects raw vertex arrays into the scene. All discovered and executed the same way. There is one application. The model doesn't get a separate API. It gets the application.",[34,2235,2237],{"id":2236},"maintainability","Maintainability",[28,2239],{":headers":2240,":highlight":1074,":rows":2241},"[\"Action\",\"Traditional MCP\",\"Schema-driven\"]","[[\"Add an operation\",\"Register tool + write handler + update docs\",\"One register() call\"],[\"Change a parameter\",\"Update tool schema + handler + UI + validation\",\"Change the schema\"],[\"Add a constraint\",\"Update validation in UI + API + wrapper\",\"Add min\u002Fmax to the input\"],[\"Remove an operation\",\"Remove tool + handler + update docs + deprecation\",\"Remove the register() call\"],[\"Test\",\"Test UI + test API + test wrapper\",\"Test the operator\"]]",[12,2243,2244,2245,2247],{},"No wrapper code. The schema is the documentation — ",[23,2246,1008],{}," serves it directly.",[12,2249,2250],{},"If MCP is replaced by a different protocol, the application doesn't change — you implement a new renderer for the schema. The logic, the validation, the execution path all stay. The interface layer is disposable by design.",[2252,2253],"article-cta",{":buttons":2254},"[{\"label\":\"Open Lunar\",\"to\":\"https:\u002F\u002Flunar.polydera.com\",\"icon\":\"i-lucide-moon\"}]",[288,2256],{"author":290,"title":349},[2258,2259,2260],"style",{},"html pre.shiki code .s3F5K, html code.shiki .s3F5K{--shiki-default:#9CDCFE}html pre.shiki code .sTNBD, html code.shiki .sTNBD{--shiki-default:#D4D4D4}html pre.shiki code .sCudf, html code.shiki .sCudf{--shiki-default:#DCDCAA}html pre.shiki code .sKc5r, html code.shiki .sKc5r{--shiki-default:#CE9178}html pre.shiki code .scz_3, html code.shiki .scz_3{--shiki-default:#569CD6}html pre.shiki code .sOLPB, html code.shiki .sOLPB{--shiki-default:#6A9955}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sDGX8, html code.shiki .sDGX8{--shiki-default:#B5CEA8}html pre.shiki code .sHkYM, html code.shiki .sHkYM{--shiki-default:#F44747}",{"title":292,"searchDepth":293,"depth":293,"links":2262},[2263,2264,2265,2266,2272,2273],{"id":364,"depth":293,"text":365},{"id":388,"depth":293,"text":389},{"id":941,"depth":293,"text":942},{"id":994,"depth":293,"text":995,"children":2267},[2268,2269,2270,2271],{"id":1012,"depth":298,"text":1013},{"id":1451,"depth":298,"text":1452},{"id":2017,"depth":298,"text":2018},{"id":2192,"depth":298,"text":2193},{"id":2211,"depth":293,"text":2212},{"id":2236,"depth":293,"text":2237},"When operations are defined as typed schemas, each interface is just a rendering of the same source — UI controls for humans, tool descriptions for models. Adding a new interface is implementing a new renderer. Through dynamic discovery, this architecture eliminates maintenance drift and reduces AI context overhead by over 95% at scale.",[2276,2277,2278,2279,2280,2281,2282,2283,2284],"MCP context window","schema-driven MCP","AI geometry processing","MCP server design","AI integration architecture","AI CAD","AI 3D modeling","AI geometry","MCP dynamic tool discovery",{},"\u002Fai\u002Fschema-driven-interfaces-for-humans-and-ais",{"title":349,"description":2274},"ai\u002Fschema-driven-interfaces-for-humans-and-ais",[2290,2291,414,2292],"architecture","mcp","lunar","x2yts-kJaPZbiDOsX6KBLVw86xZ4SqFrCgwdGFoV0nE",1776780745031]