@developerz.ai/ts23d 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (567) hide show
  1. package/.claude/agents/bug-hunter.md +21 -0
  2. package/.claude/agents/docs-author.md +13 -0
  3. package/.claude/agents/dx-auditor.md +14 -0
  4. package/.claude/agents/primitive-author.md +22 -0
  5. package/.claude/agents/recipe-author.md +36 -0
  6. package/.claude/agents/visual-reviewer.md +23 -0
  7. package/.claude/commands/feature.md +28 -0
  8. package/.claude/commands/new-recipe.md +19 -0
  9. package/.claude/commands/release.md +14 -0
  10. package/.claude/commands/verify.md +9 -0
  11. package/.claude/skills/author-recipe/SKILL.md +93 -0
  12. package/CHANGELOG.md +90 -0
  13. package/CLAUDE.md +85 -0
  14. package/LICENSE +21 -0
  15. package/README.md +385 -2
  16. package/dist/chunk-6b05mnmx.js +19 -0
  17. package/dist/chunk-6b05mnmx.js.map +11 -0
  18. package/dist/chunk-7rtfjh9f.js +45 -0
  19. package/dist/chunk-7rtfjh9f.js.map +10 -0
  20. package/dist/chunk-8j4c28jt.js +4085 -0
  21. package/dist/chunk-8j4c28jt.js.map +46 -0
  22. package/dist/chunk-d1fv6hrm.js +2532 -0
  23. package/dist/chunk-d1fv6hrm.js.map +43 -0
  24. package/dist/chunk-dbq4qf52.js +902 -0
  25. package/dist/chunk-dbq4qf52.js.map +25 -0
  26. package/dist/chunk-drna2rny.js +836 -0
  27. package/dist/chunk-drna2rny.js.map +17 -0
  28. package/dist/chunk-dxvypr7y.js +89 -0
  29. package/dist/chunk-dxvypr7y.js.map +11 -0
  30. package/dist/chunk-f6yme003.js +1589 -0
  31. package/dist/chunk-f6yme003.js.map +30 -0
  32. package/dist/chunk-hg7pf34j.js +465 -0
  33. package/dist/chunk-hg7pf34j.js.map +19 -0
  34. package/dist/chunk-jq4e17tj.js +1031 -0
  35. package/dist/chunk-jq4e17tj.js.map +21 -0
  36. package/dist/chunk-y63c6zcv.js +2668 -0
  37. package/dist/chunk-y63c6zcv.js.map +53 -0
  38. package/dist/cli/args.d.ts +30 -0
  39. package/dist/cli/bin.d.ts +2 -0
  40. package/dist/cli/bin.js +348 -0
  41. package/dist/cli/bin.js.map +15 -0
  42. package/dist/cli/load.d.ts +2 -0
  43. package/dist/cli/manifest.d.ts +53 -0
  44. package/dist/cli/render-cmds.d.ts +12 -0
  45. package/dist/cli/run.d.ts +1 -0
  46. package/dist/cli/texture-cache.d.ts +4 -0
  47. package/dist/core/asset.d.ts +10 -0
  48. package/dist/core/definition.d.ts +155 -0
  49. package/dist/core/errors.d.ts +17 -0
  50. package/dist/core/family.d.ts +23 -0
  51. package/dist/core/index.d.ts +9 -0
  52. package/dist/core/index.js +69 -0
  53. package/dist/core/index.js.map +9 -0
  54. package/dist/core/mesh.d.ts +35 -0
  55. package/dist/core/part.d.ts +114 -0
  56. package/dist/core/png.d.ts +1 -0
  57. package/dist/core/rng.d.ts +12 -0
  58. package/dist/core/transform.d.ts +20 -0
  59. package/dist/core/vec.d.ts +11 -0
  60. package/dist/core/world.d.ts +16 -0
  61. package/dist/export/bin-writer.d.ts +16 -0
  62. package/dist/export/container.d.ts +3 -0
  63. package/dist/export/credits.d.ts +4 -0
  64. package/dist/export/glb-options.d.ts +48 -0
  65. package/dist/export/glb.d.ts +8 -0
  66. package/dist/export/hierarchy.d.ts +23 -0
  67. package/dist/export/index.d.ts +5 -0
  68. package/dist/export/index.js +40 -0
  69. package/dist/export/index.js.map +9 -0
  70. package/dist/export/lights.d.ts +8 -0
  71. package/dist/export/lod-coverage.d.ts +12 -0
  72. package/dist/export/materials.d.ts +23 -0
  73. package/dist/export/merge-pivots.d.ts +6 -0
  74. package/dist/export/metadata.d.ts +21 -0
  75. package/dist/export/motion.d.ts +9 -0
  76. package/dist/export/optimize-parts.d.ts +26 -0
  77. package/dist/export/primitive.d.ts +3 -0
  78. package/dist/export/tangents.d.ts +2 -0
  79. package/dist/export/textures.d.ts +22 -0
  80. package/dist/export/version.d.ts +2 -0
  81. package/dist/grammar/index.d.ts +2 -0
  82. package/dist/grammar/index.js +16 -0
  83. package/dist/grammar/index.js.map +9 -0
  84. package/dist/grammar/split.d.ts +21 -0
  85. package/dist/grammar/whyte.d.ts +5 -0
  86. package/dist/index.d.ts +11 -0
  87. package/dist/index.js +457 -0
  88. package/dist/index.js.map +9 -0
  89. package/dist/kinds/building.d.ts +44 -0
  90. package/dist/kinds/faces.d.ts +27 -0
  91. package/dist/kinds/head-armour.d.ts +5 -0
  92. package/dist/kinds/head-beard.d.ts +6 -0
  93. package/dist/kinds/head-bust.d.ts +5 -0
  94. package/dist/kinds/head-extras.d.ts +15 -0
  95. package/dist/kinds/head-face.d.ts +8 -0
  96. package/dist/kinds/head-garb.d.ts +4 -0
  97. package/dist/kinds/head-geom.d.ts +7 -0
  98. package/dist/kinds/head-hair.d.ts +4 -0
  99. package/dist/kinds/head-layout.d.ts +29 -0
  100. package/dist/kinds/head-mesh.d.ts +31 -0
  101. package/dist/kinds/head-mouth.d.ts +4 -0
  102. package/dist/kinds/head-params.d.ts +116 -0
  103. package/dist/kinds/head-presets.d.ts +19 -0
  104. package/dist/kinds/head-rim.d.ts +10 -0
  105. package/dist/kinds/head-tone.d.ts +10 -0
  106. package/dist/kinds/head-torso.d.ts +35 -0
  107. package/dist/kinds/head.d.ts +39 -0
  108. package/dist/kinds/hull-lines.d.ts +65 -0
  109. package/dist/kinds/hull-skin.d.ts +6 -0
  110. package/dist/kinds/hull.d.ts +14 -0
  111. package/dist/kinds/index.d.ts +16 -0
  112. package/dist/kinds/index.js +78 -0
  113. package/dist/kinds/index.js.map +9 -0
  114. package/dist/kinds/mass.d.ts +15 -0
  115. package/dist/kinds/openings.d.ts +30 -0
  116. package/dist/kinds/planned.d.ts +6 -0
  117. package/dist/kinds/roof-chimney.d.ts +16 -0
  118. package/dist/kinds/roof-shape.d.ts +64 -0
  119. package/dist/kinds/roof.d.ts +31 -0
  120. package/dist/kinds/vegetation-fronds.d.ts +15 -0
  121. package/dist/kinds/vegetation-impostor.d.ts +9 -0
  122. package/dist/kinds/vegetation-leaves.d.ts +15 -0
  123. package/dist/kinds/vegetation-mesh.d.ts +21 -0
  124. package/dist/kinds/vegetation-params.d.ts +90 -0
  125. package/dist/kinds/vegetation-presets.d.ts +20 -0
  126. package/dist/kinds/vegetation-skeleton.d.ts +20 -0
  127. package/dist/kinds/vegetation.d.ts +42 -0
  128. package/dist/kinds/vehicle.d.ts +42 -0
  129. package/dist/material/cc0.d.ts +4 -0
  130. package/dist/material/define.d.ts +34 -0
  131. package/dist/material/generator.d.ts +4 -0
  132. package/dist/material/index.d.ts +9 -0
  133. package/dist/material/index.js +70 -0
  134. package/dist/material/index.js.map +9 -0
  135. package/dist/material/library.d.ts +7 -0
  136. package/dist/material/material-def.d.ts +30 -0
  137. package/dist/material/paint/bond.d.ts +3 -0
  138. package/dist/material/paint/canvas.d.ts +39 -0
  139. package/dist/material/paint/cell.d.ts +4 -0
  140. package/dist/material/paint/cells-round.d.ts +5 -0
  141. package/dist/material/paint/cells.d.ts +7 -0
  142. package/dist/material/paint/compose.d.ts +5 -0
  143. package/dist/material/paint/concrete.d.ts +3 -0
  144. package/dist/material/paint/courses.d.ts +31 -0
  145. package/dist/material/paint/decode-png.d.ts +6 -0
  146. package/dist/material/paint/default-sheet.d.ts +4 -0
  147. package/dist/material/paint/fabric.d.ts +4 -0
  148. package/dist/material/paint/foliage-broad.d.ts +5 -0
  149. package/dist/material/paint/foliage-common.d.ts +35 -0
  150. package/dist/material/paint/foliage-compound.d.ts +4 -0
  151. package/dist/material/paint/foliage-conifer.d.ts +5 -0
  152. package/dist/material/paint/foliage-raster.d.ts +26 -0
  153. package/dist/material/paint/foliage.d.ts +3 -0
  154. package/dist/material/paint/image-strip.d.ts +4 -0
  155. package/dist/material/paint/kit.d.ts +5 -0
  156. package/dist/material/paint/masks.d.ts +3 -0
  157. package/dist/material/paint/metal.d.ts +3 -0
  158. package/dist/material/paint/noise.d.ts +9 -0
  159. package/dist/material/paint/normal.d.ts +8 -0
  160. package/dist/material/paint/orm.d.ts +8 -0
  161. package/dist/material/paint/planks.d.ts +3 -0
  162. package/dist/material/paint/plates.d.ts +3 -0
  163. package/dist/material/paint/shapes.d.ts +8 -0
  164. package/dist/material/paint/slate.d.ts +3 -0
  165. package/dist/material/paint/stamp.d.ts +3 -0
  166. package/dist/material/paint/strip.d.ts +3 -0
  167. package/dist/material/paint/surface.d.ts +5 -0
  168. package/dist/material/paint/types.d.ts +65 -0
  169. package/dist/material/paint/validate.d.ts +3 -0
  170. package/dist/material/palette.d.ts +14 -0
  171. package/dist/material/shader-godot.d.ts +2 -0
  172. package/dist/material/shader-three.d.ts +2 -0
  173. package/dist/material/shader.d.ts +46 -0
  174. package/dist/material/slots.d.ts +5 -0
  175. package/dist/material/texture-source.d.ts +34 -0
  176. package/dist/material/trim-sheet.d.ts +38 -0
  177. package/dist/neural/generator.d.ts +25 -0
  178. package/dist/neural/images.d.ts +17 -0
  179. package/dist/neural/index.d.ts +2 -0
  180. package/dist/neural/index.js +14 -0
  181. package/dist/neural/index.js.map +9 -0
  182. package/dist/passes/bake-ao.d.ts +17 -0
  183. package/dist/passes/grime.d.ts +15 -0
  184. package/dist/passes/index.d.ts +6 -0
  185. package/dist/passes/index.js +22 -0
  186. package/dist/passes/index.js.map +9 -0
  187. package/dist/passes/livery.d.ts +19 -0
  188. package/dist/passes/optimize-cache.d.ts +15 -0
  189. package/dist/passes/optimize-weld.d.ts +15 -0
  190. package/dist/passes/optimize.d.ts +28 -0
  191. package/dist/passes/ray-grid.d.ts +23 -0
  192. package/dist/passes/weighted-normals.d.ts +8 -0
  193. package/dist/primitives/beam.d.ts +17 -0
  194. package/dist/primitives/bevel-box.d.ts +13 -0
  195. package/dist/primitives/box.d.ts +16 -0
  196. package/dist/primitives/cell.d.ts +20 -0
  197. package/dist/primitives/check.d.ts +12 -0
  198. package/dist/primitives/closed.d.ts +11 -0
  199. package/dist/primitives/erosion.d.ts +22 -0
  200. package/dist/primitives/font-5x7.d.ts +3 -0
  201. package/dist/primitives/heightfield.d.ts +16 -0
  202. package/dist/primitives/index.d.ts +23 -0
  203. package/dist/primitives/index.js +81 -0
  204. package/dist/primitives/index.js.map +9 -0
  205. package/dist/primitives/lathe-facets.d.ts +8 -0
  206. package/dist/primitives/lathe.d.ts +26 -0
  207. package/dist/primitives/lattice.d.ts +30 -0
  208. package/dist/primitives/loft.d.ts +15 -0
  209. package/dist/primitives/mc-table.d.ts +2 -0
  210. package/dist/primitives/member.d.ts +19 -0
  211. package/dist/primitives/noise.d.ts +34 -0
  212. package/dist/primitives/planar.d.ts +10 -0
  213. package/dist/primitives/prism.d.ts +13 -0
  214. package/dist/primitives/sculpt-edit.d.ts +56 -0
  215. package/dist/primitives/sculpt-tree.d.ts +23 -0
  216. package/dist/primitives/sculpt.d.ts +27 -0
  217. package/dist/primitives/sdf-grid.d.ts +17 -0
  218. package/dist/primitives/sdf-ops.d.ts +37 -0
  219. package/dist/primitives/sdf.d.ts +21 -0
  220. package/dist/primitives/strip-uv.d.ts +11 -0
  221. package/dist/primitives/surface-nets.d.ts +7 -0
  222. package/dist/primitives/sweep.d.ts +19 -0
  223. package/dist/primitives/terrain-color.d.ts +30 -0
  224. package/dist/primitives/terrain-grid.d.ts +36 -0
  225. package/dist/primitives/text-layout.d.ts +22 -0
  226. package/dist/primitives/text.d.ts +27 -0
  227. package/dist/primitives/tiled.d.ts +22 -0
  228. package/dist/primitives/transport.d.ts +17 -0
  229. package/dist/primitives/triangulate.d.ts +2 -0
  230. package/dist/primitives/value-noise.d.ts +10 -0
  231. package/dist/qa/checks.d.ts +11 -0
  232. package/dist/qa/clash.d.ts +2 -0
  233. package/dist/qa/floating.d.ts +5 -0
  234. package/dist/qa/gates.d.ts +12 -0
  235. package/dist/qa/geometry.d.ts +21 -0
  236. package/dist/qa/index.d.ts +12 -0
  237. package/dist/qa/index.js +78 -0
  238. package/dist/qa/index.js.map +9 -0
  239. package/dist/qa/inside.d.ts +12 -0
  240. package/dist/qa/inspect.d.ts +18 -0
  241. package/dist/qa/lods.d.ts +12 -0
  242. package/dist/qa/measures.d.ts +4 -0
  243. package/dist/qa/occlusion.d.ts +3 -0
  244. package/dist/qa/sanity.d.ts +7 -0
  245. package/dist/qa/types.d.ts +12 -0
  246. package/dist/render/beauty.d.ts +40 -0
  247. package/dist/render/camera.d.ts +33 -0
  248. package/dist/render/depth-map.d.ts +38 -0
  249. package/dist/render/font.d.ts +1 -0
  250. package/dist/render/ground.d.ts +13 -0
  251. package/dist/render/index.d.ts +10 -0
  252. package/dist/render/index.js +47 -0
  253. package/dist/render/index.js.map +9 -0
  254. package/dist/render/lighting.d.ts +27 -0
  255. package/dist/render/lod-strip.d.ts +5 -0
  256. package/dist/render/metrics.d.ts +37 -0
  257. package/dist/render/options.d.ts +28 -0
  258. package/dist/render/photo-match.d.ts +19 -0
  259. package/dist/render/raster.d.ts +25 -0
  260. package/dist/render/resolve.d.ts +11 -0
  261. package/dist/render/review-prompt.d.ts +2 -0
  262. package/dist/render/review-warnings.d.ts +34 -0
  263. package/dist/render/review.d.ts +24 -0
  264. package/dist/render/scene.d.ts +18 -0
  265. package/dist/render/shade.d.ts +22 -0
  266. package/dist/render/sheet.d.ts +15 -0
  267. package/dist/render/texture.d.ts +15 -0
  268. package/dist/render/thumbnail.d.ts +8 -0
  269. package/dist/render/vis-buffer.d.ts +18 -0
  270. package/dist/testing/assert.d.ts +21 -0
  271. package/dist/testing/compiled.d.ts +15 -0
  272. package/dist/testing/hash.d.ts +1 -0
  273. package/dist/testing/index.d.ts +4 -0
  274. package/dist/testing/index.js +134 -0
  275. package/dist/testing/index.js.map +13 -0
  276. package/dist/testing/snapshot.d.ts +13 -0
  277. package/docs/README.md +56 -0
  278. package/docs/architecture/README.md +68 -0
  279. package/docs/architecture/adding-a-kind.md +44 -0
  280. package/docs/architecture/adding-a-primitive.md +49 -0
  281. package/docs/architecture/errors.md +47 -0
  282. package/docs/architecture/glb-production.md +214 -0
  283. package/docs/architecture/gltf-capabilities.md +117 -0
  284. package/docs/architecture/materials.md +151 -0
  285. package/docs/decisions/001-recipe-compiler-over-ai-meshes.md +27 -0
  286. package/docs/decisions/002-typescript-not-json.md +22 -0
  287. package/docs/decisions/003-shared-trim-sheet.md +21 -0
  288. package/docs/decisions/004-z-up-metres.md +21 -0
  289. package/docs/decisions/005-zero-runtime-deps.md +21 -0
  290. package/docs/decisions/006-single-package-subpath-exports.md +20 -0
  291. package/docs/decisions/007-cpu-contact-sheets.md +21 -0
  292. package/docs/decisions/008-surface-materials.md +21 -0
  293. package/docs/decisions/009-gltf-front-axis.md +21 -0
  294. package/docs/decisions/README.md +15 -0
  295. package/docs/idea/01-vision.md +117 -0
  296. package/docs/idea/02-dsl.md +343 -0
  297. package/docs/idea/03-ir.md +97 -0
  298. package/docs/idea/04-materials.md +114 -0
  299. package/docs/idea/05-agent-loop.md +141 -0
  300. package/docs/idea/06-qa.md +101 -0
  301. package/docs/idea/07-what-fits.md +45 -0
  302. package/docs/idea/08-neural-adapters.md +78 -0
  303. package/docs/idea/09-kinds.md +105 -0
  304. package/docs/idea/10-sculpting.md +166 -0
  305. package/docs/idea/11-materials-authoring.md +132 -0
  306. package/docs/idea/12-blender-bridge.md +136 -0
  307. package/docs/idea/13-asset-pipeline-research.md +89 -0
  308. package/docs/landscape.md +49 -0
  309. package/docs/plans/roadmap.md +139 -0
  310. package/examples/build-with-bun.ts +41 -0
  311. package/llms.txt +47 -0
  312. package/package.json +100 -4
  313. package/recipes/README.md +38 -0
  314. package/recipes/asteroid/README.md +46 -0
  315. package/recipes/asteroid/asteroid.ts +336 -0
  316. package/recipes/boulders/README.md +28 -0
  317. package/recipes/boulders/boulders.ts +117 -0
  318. package/recipes/boxcar/README.md +53 -0
  319. package/recipes/boxcar/boxcar.ts +1000 -0
  320. package/recipes/cargo_container_scifi/README.md +52 -0
  321. package/recipes/cargo_container_scifi/cargo_container_scifi.ts +461 -0
  322. package/recipes/dropship/README.md +84 -0
  323. package/recipes/dropship/dropship.ts +1144 -0
  324. package/recipes/eiffel_tower/README.md +110 -0
  325. package/recipes/eiffel_tower/eiffel_tower.ts +781 -0
  326. package/recipes/goblin_head/README.md +75 -0
  327. package/recipes/goblin_head/goblin_head.ts +38 -0
  328. package/recipes/human_head/README.md +68 -0
  329. package/recipes/human_head/human_head.ts +38 -0
  330. package/recipes/loco_440/README.md +32 -0
  331. package/recipes/loco_440/loco_440.ts +1404 -0
  332. package/recipes/material_swatches/README.md +21 -0
  333. package/recipes/material_swatches/material_swatches.ts +189 -0
  334. package/recipes/mountain_range/README.md +45 -0
  335. package/recipes/mountain_range/mountain_range.ts +128 -0
  336. package/recipes/oak/README.md +30 -0
  337. package/recipes/oak/oak.ts +19 -0
  338. package/recipes/orc_head/README.md +78 -0
  339. package/recipes/orc_head/orc_head.ts +41 -0
  340. package/recipes/palm/README.md +30 -0
  341. package/recipes/palm/palm.ts +19 -0
  342. package/recipes/pine/README.md +29 -0
  343. package/recipes/pine/pine.ts +19 -0
  344. package/recipes/signal_gantry/README.md +36 -0
  345. package/recipes/signal_gantry/signal_gantry.ts +522 -0
  346. package/recipes/station_halt/README.md +39 -0
  347. package/recipes/station_halt/station_halt.ts +722 -0
  348. package/recipes/t34/README.md +44 -0
  349. package/recipes/t34/t34.ts +1068 -0
  350. package/recipes/tiger_1/README.md +75 -0
  351. package/recipes/tiger_1/tiger_1.ts +1370 -0
  352. package/recipes/water_tower/README.md +40 -0
  353. package/recipes/water_tower/water_tower.ts +542 -0
  354. package/src/cli/args.ts +125 -0
  355. package/src/cli/bin.ts +7 -0
  356. package/src/cli/load.ts +17 -0
  357. package/src/cli/manifest.ts +95 -0
  358. package/src/cli/render-cmds.ts +66 -0
  359. package/src/cli/run.ts +192 -0
  360. package/src/cli/texture-cache.ts +24 -0
  361. package/src/core/asset.ts +129 -0
  362. package/src/core/definition.ts +156 -0
  363. package/src/core/errors.ts +50 -0
  364. package/src/core/family.ts +50 -0
  365. package/src/core/index.ts +66 -0
  366. package/src/core/mesh.ts +114 -0
  367. package/src/core/part.ts +130 -0
  368. package/src/core/png.ts +49 -0
  369. package/src/core/rng.ts +49 -0
  370. package/src/core/transform.ts +90 -0
  371. package/src/core/vec.ts +26 -0
  372. package/src/core/world.ts +80 -0
  373. package/src/export/bin-writer.ts +79 -0
  374. package/src/export/container.ts +35 -0
  375. package/src/export/credits.ts +25 -0
  376. package/src/export/glb-options.ts +53 -0
  377. package/src/export/glb.ts +187 -0
  378. package/src/export/hierarchy.ts +122 -0
  379. package/src/export/index.ts +34 -0
  380. package/src/export/lights.ts +49 -0
  381. package/src/export/lod-coverage.ts +71 -0
  382. package/src/export/materials.ts +126 -0
  383. package/src/export/merge-pivots.ts +146 -0
  384. package/src/export/metadata.ts +62 -0
  385. package/src/export/motion.ts +70 -0
  386. package/src/export/optimize-parts.ts +80 -0
  387. package/src/export/primitive.ts +35 -0
  388. package/src/export/tangents.ts +75 -0
  389. package/src/export/textures.ts +88 -0
  390. package/src/export/version.ts +6 -0
  391. package/src/grammar/index.ts +4 -0
  392. package/src/grammar/split.ts +87 -0
  393. package/src/grammar/whyte.ts +20 -0
  394. package/src/index.ts +14 -0
  395. package/src/kinds/building.ts +153 -0
  396. package/src/kinds/faces.ts +138 -0
  397. package/src/kinds/head-armour.ts +181 -0
  398. package/src/kinds/head-beard.ts +133 -0
  399. package/src/kinds/head-bust.ts +184 -0
  400. package/src/kinds/head-extras.ts +150 -0
  401. package/src/kinds/head-face.ts +242 -0
  402. package/src/kinds/head-garb.ts +181 -0
  403. package/src/kinds/head-geom.ts +31 -0
  404. package/src/kinds/head-hair.ts +193 -0
  405. package/src/kinds/head-layout.ts +63 -0
  406. package/src/kinds/head-mesh.ts +195 -0
  407. package/src/kinds/head-mouth.ts +111 -0
  408. package/src/kinds/head-params.ts +162 -0
  409. package/src/kinds/head-presets.ts +155 -0
  410. package/src/kinds/head-rim.ts +128 -0
  411. package/src/kinds/head-tone.ts +52 -0
  412. package/src/kinds/head-torso.ts +230 -0
  413. package/src/kinds/head.ts +176 -0
  414. package/src/kinds/hull-lines.ts +160 -0
  415. package/src/kinds/hull-skin.ts +83 -0
  416. package/src/kinds/hull.ts +209 -0
  417. package/src/kinds/index.ts +63 -0
  418. package/src/kinds/mass.ts +110 -0
  419. package/src/kinds/openings.ts +141 -0
  420. package/src/kinds/planned.ts +12 -0
  421. package/src/kinds/roof-chimney.ts +100 -0
  422. package/src/kinds/roof-shape.ts +230 -0
  423. package/src/kinds/roof.ts +250 -0
  424. package/src/kinds/vegetation-fronds.ts +126 -0
  425. package/src/kinds/vegetation-impostor.ts +118 -0
  426. package/src/kinds/vegetation-leaves.ts +168 -0
  427. package/src/kinds/vegetation-mesh.ts +174 -0
  428. package/src/kinds/vegetation-params.ts +147 -0
  429. package/src/kinds/vegetation-presets.ts +184 -0
  430. package/src/kinds/vegetation-skeleton.ts +168 -0
  431. package/src/kinds/vegetation.ts +199 -0
  432. package/src/kinds/vehicle.ts +144 -0
  433. package/src/material/cc0.ts +41 -0
  434. package/src/material/define.ts +130 -0
  435. package/src/material/generator.ts +63 -0
  436. package/src/material/index.ts +60 -0
  437. package/src/material/library.ts +196 -0
  438. package/src/material/material-def.ts +84 -0
  439. package/src/material/paint/bond.ts +60 -0
  440. package/src/material/paint/canvas.ts +101 -0
  441. package/src/material/paint/cell.ts +39 -0
  442. package/src/material/paint/cells-round.ts +119 -0
  443. package/src/material/paint/cells.ts +111 -0
  444. package/src/material/paint/compose.ts +53 -0
  445. package/src/material/paint/concrete.ts +62 -0
  446. package/src/material/paint/courses.ts +85 -0
  447. package/src/material/paint/decode-png.ts +106 -0
  448. package/src/material/paint/default-sheet.ts +73 -0
  449. package/src/material/paint/fabric.ts +63 -0
  450. package/src/material/paint/foliage-broad.ts +126 -0
  451. package/src/material/paint/foliage-common.ts +93 -0
  452. package/src/material/paint/foliage-compound.ts +135 -0
  453. package/src/material/paint/foliage-conifer.ts +143 -0
  454. package/src/material/paint/foliage-raster.ts +196 -0
  455. package/src/material/paint/foliage.ts +23 -0
  456. package/src/material/paint/image-strip.ts +88 -0
  457. package/src/material/paint/kit.ts +37 -0
  458. package/src/material/paint/masks.ts +46 -0
  459. package/src/material/paint/metal.ts +109 -0
  460. package/src/material/paint/noise.ts +52 -0
  461. package/src/material/paint/normal.ts +52 -0
  462. package/src/material/paint/orm.ts +108 -0
  463. package/src/material/paint/planks.ts +101 -0
  464. package/src/material/paint/plates.ts +72 -0
  465. package/src/material/paint/shapes.ts +28 -0
  466. package/src/material/paint/slate.ts +52 -0
  467. package/src/material/paint/stamp.ts +40 -0
  468. package/src/material/paint/strip.ts +48 -0
  469. package/src/material/paint/surface.ts +60 -0
  470. package/src/material/paint/types.ts +94 -0
  471. package/src/material/paint/validate.ts +74 -0
  472. package/src/material/palette.ts +46 -0
  473. package/src/material/shader-godot.ts +77 -0
  474. package/src/material/shader-three.ts +103 -0
  475. package/src/material/shader.ts +100 -0
  476. package/src/material/slots.ts +18 -0
  477. package/src/material/texture-source.ts +86 -0
  478. package/src/material/trim-sheet.ts +166 -0
  479. package/src/neural/generator.ts +37 -0
  480. package/src/neural/images.ts +27 -0
  481. package/src/neural/index.ts +10 -0
  482. package/src/passes/bake-ao.ts +183 -0
  483. package/src/passes/grime.ts +37 -0
  484. package/src/passes/index.ts +8 -0
  485. package/src/passes/livery.ts +66 -0
  486. package/src/passes/optimize-cache.ts +175 -0
  487. package/src/passes/optimize-weld.ts +147 -0
  488. package/src/passes/optimize.ts +85 -0
  489. package/src/passes/ray-grid.ts +237 -0
  490. package/src/passes/weighted-normals.ts +125 -0
  491. package/src/primitives/beam.ts +60 -0
  492. package/src/primitives/bevel-box.ts +140 -0
  493. package/src/primitives/box.ts +90 -0
  494. package/src/primitives/cell.ts +115 -0
  495. package/src/primitives/check.ts +49 -0
  496. package/src/primitives/closed.ts +74 -0
  497. package/src/primitives/erosion.ts +183 -0
  498. package/src/primitives/font-5x7.ts +117 -0
  499. package/src/primitives/heightfield.ts +101 -0
  500. package/src/primitives/index.ts +56 -0
  501. package/src/primitives/lathe-facets.ts +45 -0
  502. package/src/primitives/lathe.ts +174 -0
  503. package/src/primitives/lattice.ts +131 -0
  504. package/src/primitives/loft.ts +174 -0
  505. package/src/primitives/mc-table.ts +41 -0
  506. package/src/primitives/member.ts +130 -0
  507. package/src/primitives/noise.ts +157 -0
  508. package/src/primitives/planar.ts +55 -0
  509. package/src/primitives/prism.ts +85 -0
  510. package/src/primitives/sculpt-edit.ts +212 -0
  511. package/src/primitives/sculpt-tree.ts +226 -0
  512. package/src/primitives/sculpt.ts +80 -0
  513. package/src/primitives/sdf-grid.ts +131 -0
  514. package/src/primitives/sdf-ops.ts +145 -0
  515. package/src/primitives/sdf.ts +83 -0
  516. package/src/primitives/strip-uv.ts +26 -0
  517. package/src/primitives/surface-nets.ts +161 -0
  518. package/src/primitives/sweep.ts +162 -0
  519. package/src/primitives/terrain-color.ts +85 -0
  520. package/src/primitives/terrain-grid.ts +137 -0
  521. package/src/primitives/text-layout.ts +85 -0
  522. package/src/primitives/text.ts +197 -0
  523. package/src/primitives/tiled.ts +93 -0
  524. package/src/primitives/transport.ts +85 -0
  525. package/src/primitives/triangulate.ts +42 -0
  526. package/src/primitives/value-noise.ts +62 -0
  527. package/src/qa/checks.ts +110 -0
  528. package/src/qa/clash.ts +177 -0
  529. package/src/qa/floating.ts +63 -0
  530. package/src/qa/gates.ts +126 -0
  531. package/src/qa/geometry.ts +187 -0
  532. package/src/qa/index.ts +28 -0
  533. package/src/qa/inside.ts +114 -0
  534. package/src/qa/inspect.ts +107 -0
  535. package/src/qa/lods.ts +97 -0
  536. package/src/qa/measures.ts +67 -0
  537. package/src/qa/occlusion.ts +166 -0
  538. package/src/qa/sanity.ts +137 -0
  539. package/src/qa/types.ts +17 -0
  540. package/src/render/beauty.ts +115 -0
  541. package/src/render/camera.ts +142 -0
  542. package/src/render/depth-map.ts +191 -0
  543. package/src/render/font.ts +76 -0
  544. package/src/render/ground.ts +87 -0
  545. package/src/render/index.ts +34 -0
  546. package/src/render/lighting.ts +121 -0
  547. package/src/render/lod-strip.ts +34 -0
  548. package/src/render/metrics.ts +147 -0
  549. package/src/render/options.ts +81 -0
  550. package/src/render/photo-match.ts +28 -0
  551. package/src/render/raster.ts +143 -0
  552. package/src/render/resolve.ts +109 -0
  553. package/src/render/review-prompt.ts +59 -0
  554. package/src/render/review-warnings.ts +92 -0
  555. package/src/render/review.ts +103 -0
  556. package/src/render/scene.ts +119 -0
  557. package/src/render/shade.ts +204 -0
  558. package/src/render/sheet.ts +88 -0
  559. package/src/render/texture.ts +97 -0
  560. package/src/render/thumbnail.ts +75 -0
  561. package/src/render/vis-buffer.ts +119 -0
  562. package/src/testing/assert.ts +115 -0
  563. package/src/testing/compiled.ts +31 -0
  564. package/src/testing/hash.ts +14 -0
  565. package/src/testing/index.ts +14 -0
  566. package/src/testing/snapshot.ts +37 -0
  567. package/src/types/gltf-validator.d.ts +13 -0
@@ -0,0 +1,134 @@
1
+ import {
2
+ Ts23dError2,
3
+ compile2
4
+ } from "../chunk-hg7pf34j.js";
5
+ import {
6
+ glob2,
7
+ clashes2,
8
+ measure2,
9
+ DEFAULT_GATES2,
10
+ runQa2,
11
+ DEFAULT_LOD_GATES2,
12
+ runLodQa2
13
+ } from "../chunk-jq4e17tj.js";
14
+ import"../chunk-y63c6zcv.js";
15
+ import"../chunk-drna2rny.js";
16
+ import {
17
+ exportGlb2
18
+ } from "../chunk-dbq4qf52.js";
19
+
20
+ // src/testing/compiled.ts
21
+ var ALL_LODS = [0, 1, 2];
22
+ var compileLods = (asset, o = {}) => (o.lods ?? ALL_LODS).map((lod) => compile2(asset, { lod, ...o.seed !== undefined ? { seed: o.seed } : {} }));
23
+ var describeFinding = (f, lod) => `${lod !== undefined ? `LOD${lod} ` : ""}${f.gate}${f.part ? ` [${f.part}]` : ""}: ${f.message}`;
24
+ function failOn(what, found) {
25
+ if (found.length === 0)
26
+ return;
27
+ const lines = found.map(({ finding, lod }) => ` - ${describeFinding(finding, lod)}`);
28
+ throw new Ts23dError2("T3D_QA_FAILED", {
29
+ cause: `${what}: ${found.length} finding(s)
30
+ ${lines.join(`
31
+ `)}`,
32
+ fix: found[0]?.finding.fix ?? "read the findings above"
33
+ });
34
+ }
35
+
36
+ // src/testing/assert.ts
37
+ function assertQaPass(asset, o = {}) {
38
+ const lods = compileLods(asset, o);
39
+ const found = lods.flatMap((a) => runQa2(a, o.gates ?? DEFAULT_GATES2).map((finding) => ({ finding, lod: a.lod })));
40
+ const chain = lods.length > 1 ? runLodQa2(lods, o.lodGates ?? DEFAULT_LOD_GATES2) : [];
41
+ failOn(`${asset.name} QA`, [...found, ...chain.map((finding) => ({ finding }))]);
42
+ }
43
+ function assertBudget(asset, caps = asset.budget.triangles, o = {}) {
44
+ failOn(`${asset.name} budget`, compileLods(asset, o).flatMap((a) => {
45
+ const tris = a.parts.reduce((s, p) => s + (p.mesh ? p.mesh.indices.length / 3 : 0), 0);
46
+ const cap = caps[a.lod];
47
+ return tris > cap ? [
48
+ {
49
+ lod: a.lod,
50
+ finding: {
51
+ gate: "budget",
52
+ message: `${tris} triangles > ${cap}`,
53
+ fix: "drop detail at this LOD (ctx.lod / ctx.pick) — never raise a cap to make a test pass"
54
+ }
55
+ }
56
+ ] : [];
57
+ }));
58
+ }
59
+ function assertParts(asset, selectors, o = {}) {
60
+ failOn(`${asset.name} parts`, compileLods(asset, o).flatMap((a) => selectors.filter((s) => !a.parts.some((p) => glob2(s).test(p.name))).map((s) => ({
61
+ lod: a.lod,
62
+ finding: {
63
+ gate: "parts",
64
+ message: `no part matches '${s}'`,
65
+ fix: "engines bind to these names: add the part/group at this LOD (gate its geometry, not its pivot)"
66
+ }
67
+ }))));
68
+ }
69
+ function assertMeasure(asset, m, o = {}) {
70
+ const [a] = compileLods(asset, { lods: [o.lod ?? 0] });
71
+ const got = a ? measure2(a, m) : null;
72
+ const tol = m.tolerance ?? 0.02;
73
+ const bad = got === null || Math.abs(got - m.value) / m.value > tol;
74
+ failOn(`${asset.name} measure`, bad ? [
75
+ {
76
+ finding: {
77
+ gate: "measure",
78
+ message: got === null ? `'${m.label}': no part matches ${JSON.stringify(m.parts ?? m.between)}` : `${m.label}: ${got.toFixed(3)} m on ${m.axis.toUpperCase()}, want ${m.value} m (±${tol * 100}%)`,
79
+ fix: "rebuild the part from the spec number; never edit the spec to match the model"
80
+ }
81
+ }
82
+ ] : []);
83
+ return got ?? Number.NaN;
84
+ }
85
+ function assertMotionClear(asset, o = {}) {
86
+ failOn(`${asset.name} motion`, compileLods(asset, o).flatMap((a) => clashes2(a).map((finding) => ({ finding, lod: a.lod }))));
87
+ }
88
+ // src/testing/hash.ts
89
+ function hashBytes(bytes) {
90
+ let h1 = 2166136261;
91
+ let h2 = 3421674724;
92
+ for (let i = 0;i < bytes.length; i++) {
93
+ const b = bytes[i] ?? 0;
94
+ h1 = Math.imul(h1 ^ b, 16777619);
95
+ h2 = Math.imul(h2 ^ b ^ h1 >>> 24, 16777619);
96
+ }
97
+ const hex = (n) => (n >>> 0).toString(16).padStart(8, "0");
98
+ return `${hex(h2)}${hex(h1)}`;
99
+ }
100
+ // src/testing/snapshot.ts
101
+ function snapshotHash(asset, o = {}) {
102
+ const a = compile2(asset, {
103
+ lod: o.lod ?? 0,
104
+ ...o.seed !== undefined ? { seed: o.seed } : {}
105
+ });
106
+ return hashBytes(exportGlb2(a, o.glb ?? {}).glb);
107
+ }
108
+ function assertDeterministic(asset, o = {}) {
109
+ for (const lod of o.lods ?? ALL_LODS) {
110
+ const once = snapshotHash(asset, { lod, ...o.seed !== undefined ? { seed: o.seed } : {} });
111
+ const twice = snapshotHash(asset, { lod, ...o.seed !== undefined ? { seed: o.seed } : {} });
112
+ if (once !== twice)
113
+ throw new Ts23dError2("T3D_QA_FAILED", {
114
+ cause: `${asset.name} LOD${lod} is not byte-deterministic (${once} vs ${twice})`,
115
+ fix: "remove ambient state from build(): read ctx.rng/ctx.seed only — no Math.random, Date, or module-level counters"
116
+ });
117
+ }
118
+ }
119
+ export {
120
+ ALL_LODS,
121
+ assertBudget,
122
+ assertDeterministic,
123
+ assertMeasure,
124
+ assertMotionClear,
125
+ assertParts,
126
+ assertQaPass,
127
+ compileLods,
128
+ describeFinding,
129
+ hashBytes,
130
+ snapshotHash
131
+ };
132
+
133
+ //# debugId=DE0A36904BC8E38564756E2164756E21
134
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,13 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/testing/compiled.ts", "../src/testing/assert.ts", "../src/testing/hash.ts", "../src/testing/snapshot.ts"],
4
+ "sourcesContent": [
5
+ "// Shared plumbing for the assertions: compile an asset at the LODs asked for, and turn QA\n// findings into one thrown Ts23dError an agent can act on (code, every finding, the first fix).\n\nimport { type Asset, type CompiledAsset, compile, type Lod, Ts23dError } from '../core/index.ts';\nimport type { Finding } from '../qa/index.ts';\n\nexport interface LodOptions {\n /** LODs to check. Default all three. */\n readonly lods?: readonly Lod[];\n readonly seed?: number;\n}\n\nexport const ALL_LODS: readonly Lod[] = [0, 1, 2];\n\nexport const compileLods = (asset: Asset, o: LodOptions = {}): CompiledAsset[] =>\n (o.lods ?? ALL_LODS).map((lod) =>\n compile(asset, { lod, ...(o.seed !== undefined ? { seed: o.seed } : {}) }),\n );\n\nexport const describeFinding = (f: Finding, lod?: Lod): string =>\n `${lod !== undefined ? `LOD${lod} ` : ''}${f.gate}${f.part ? ` [${f.part}]` : ''}: ${f.message}`;\n\n/** Throw T3D_QA_FAILED listing every finding; no-op when there are none. */\nexport function failOn(what: string, found: ReadonlyArray<{ finding: Finding; lod?: Lod }>): void {\n if (found.length === 0) return;\n const lines = found.map(({ finding, lod }) => ` - ${describeFinding(finding, lod)}`);\n throw new Ts23dError('T3D_QA_FAILED', {\n cause: `${what}: ${found.length} finding(s)\\n${lines.join('\\n')}`,\n fix: found[0]?.finding.fix ?? 'read the findings above',\n });\n}\n",
6
+ "// Assertions for a recipe's own `bun test` (or any runner): each compiles the asset, checks one\n// property, and throws a Ts23dError with the findings and a fix — no test framework imported.\n// it('passes QA', () => assertQaPass(tiger_1));\n// it('has its pivots', () => assertParts(tiger_1, ['turret', 'gun', 'wheel_l_*']));\n\nimport type { Asset, Lod, Measure } from '../core/index.ts';\nimport {\n clashes,\n DEFAULT_GATES,\n DEFAULT_LOD_GATES,\n type Gate,\n glob,\n type LodGate,\n measure,\n runLodQa,\n runQa,\n} from '../qa/index.ts';\nimport { compileLods, failOn, type LodOptions } from './compiled.ts';\n\nexport interface QaOptions extends LodOptions {\n /** Per-LOD gates. Default the build's DEFAULT_GATES. */\n readonly gates?: readonly Gate[];\n /** Chain gates over all compiled LODs. Default DEFAULT_LOD_GATES. */\n readonly lodGates?: readonly LodGate[];\n}\n\n/** The same gate `t3d build` runs: every LOD passes QA, plus the LOD-chain gates. */\nexport function assertQaPass(asset: Asset, o: QaOptions = {}): void {\n const lods = compileLods(asset, o);\n const found = lods.flatMap((a) =>\n runQa(a, o.gates ?? DEFAULT_GATES).map((finding) => ({ finding, lod: a.lod })),\n );\n const chain = lods.length > 1 ? runLodQa(lods, o.lodGates ?? DEFAULT_LOD_GATES) : [];\n failOn(`${asset.name} QA`, [...found, ...chain.map((finding) => ({ finding }))]);\n}\n\n/** Triangles per LOD at or under `caps` (default: the asset's own budget). */\nexport function assertBudget(\n asset: Asset,\n caps: readonly [number, number, number] = asset.budget.triangles,\n o: LodOptions = {},\n): void {\n failOn(\n `${asset.name} budget`,\n compileLods(asset, o).flatMap((a) => {\n const tris = a.parts.reduce((s, p) => s + (p.mesh ? p.mesh.indices.length / 3 : 0), 0);\n const cap = caps[a.lod];\n return tris > cap\n ? [\n {\n lod: a.lod,\n finding: {\n gate: 'budget',\n message: `${tris} triangles > ${cap}`,\n fix: 'drop detail at this LOD (ctx.lod / ctx.pick) — never raise a cap to make a test pass',\n },\n },\n ]\n : [];\n }),\n );\n}\n\n/** Each selector (name or glob) matches at least one part at every LOD checked. */\nexport function assertParts(asset: Asset, selectors: readonly string[], o: LodOptions = {}): void {\n failOn(\n `${asset.name} parts`,\n compileLods(asset, o).flatMap((a) =>\n selectors\n .filter((s) => !a.parts.some((p) => glob(s).test(p.name)))\n .map((s) => ({\n lod: a.lod,\n finding: {\n gate: 'parts',\n message: `no part matches '${s}'`,\n fix: 'engines bind to these names: add the part/group at this LOD (gate its geometry, not its pivot)',\n },\n })),\n ),\n );\n}\n\n/** One spec dimension at LOD0, the way the `measures` gate checks `real.measures`. */\nexport function assertMeasure(asset: Asset, m: Measure, o: { lod?: Lod } = {}): number {\n const [a] = compileLods(asset, { lods: [o.lod ?? 0] });\n const got = a ? measure(a, m) : null;\n const tol = m.tolerance ?? 0.02;\n const bad = got === null || Math.abs(got - m.value) / m.value > tol;\n failOn(\n `${asset.name} measure`,\n bad\n ? [\n {\n finding: {\n gate: 'measure',\n message:\n got === null\n ? `'${m.label}': no part matches ${JSON.stringify(m.parts ?? m.between)}`\n : `${m.label}: ${got.toFixed(3)} m on ${m.axis.toUpperCase()}, want ${m.value} m (±${tol * 100}%)`,\n fix: 'rebuild the part from the spec number; never edit the spec to match the model',\n },\n },\n ]\n : [],\n );\n return got ?? Number.NaN;\n}\n\n/** Every moving part sweeps clear of everything else (the `clashes` gate), at every LOD. */\nexport function assertMotionClear(asset: Asset, o: LodOptions = {}): void {\n failOn(\n `${asset.name} motion`,\n compileLods(asset, o).flatMap((a) => clashes(a).map((finding) => ({ finding, lod: a.lod }))),\n );\n}\n",
7
+ "// A stable content hash for snapshot tests: 64-bit FNV-1a (two 32-bit lanes), pure JS, so the\n// same bytes give the same hex string on Bun, Node and the browser — no runtime hash API needed.\n\nexport function hashBytes(bytes: Uint8Array): string {\n let h1 = 0x811c9dc5;\n let h2 = 0xcbf29ce4;\n for (let i = 0; i < bytes.length; i++) {\n const b = bytes[i] ?? 0;\n h1 = Math.imul(h1 ^ b, 0x01000193);\n h2 = Math.imul(h2 ^ b ^ (h1 >>> 24), 0x01000193);\n }\n const hex = (n: number): string => (n >>> 0).toString(16).padStart(8, '0');\n return `${hex(h2)}${hex(h1)}`;\n}\n",
8
+ "// Determinism and snapshot helpers: the GLB an asset compiles to, hashed. Pin a hash in a test to\n// catch any unintended geometry change; compile twice to prove the recipe has no ambient state.\n\nimport { type Asset, compile, type Lod, Ts23dError } from '../core/index.ts';\nimport { exportGlb, type GlbOptions } from '../export/index.ts';\nimport type { LodOptions } from './compiled.ts';\nimport { ALL_LODS } from './compiled.ts';\nimport { hashBytes } from './hash.ts';\n\nexport interface SnapshotOptions {\n readonly lod?: Lod;\n readonly seed?: number;\n /** Exporter options; default the plain optimised GLB (no textures, no clips). */\n readonly glb?: GlbOptions;\n}\n\n/** 16-hex-digit content hash of the asset's GLB at one LOD. */\nexport function snapshotHash(asset: Asset, o: SnapshotOptions = {}): string {\n const a = compile(asset, {\n lod: o.lod ?? 0,\n ...(o.seed !== undefined ? { seed: o.seed } : {}),\n });\n return hashBytes(exportGlb(a, o.glb ?? {}).glb);\n}\n\n/** Compile + export twice per LOD; the bytes must match. */\nexport function assertDeterministic(asset: Asset, o: LodOptions = {}): void {\n for (const lod of o.lods ?? ALL_LODS) {\n const once = snapshotHash(asset, { lod, ...(o.seed !== undefined ? { seed: o.seed } : {}) });\n const twice = snapshotHash(asset, { lod, ...(o.seed !== undefined ? { seed: o.seed } : {}) });\n if (once !== twice)\n throw new Ts23dError('T3D_QA_FAILED', {\n cause: `${asset.name} LOD${lod} is not byte-deterministic (${once} vs ${twice})`,\n fix: 'remove ambient state from build(): read ctx.rng/ctx.seed only — no Math.random, Date, or module-level counters',\n });\n }\n}\n"
9
+ ],
10
+ "mappings": "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",
11
+ "debugId": "DE0A36904BC8E38564756E2164756E21",
12
+ "names": []
13
+ }
@@ -0,0 +1,13 @@
1
+ import { type Asset, type Lod } from '../core/index.js';
2
+ import { type GlbOptions } from '../export/index.js';
3
+ import type { LodOptions } from './compiled.js';
4
+ export interface SnapshotOptions {
5
+ readonly lod?: Lod;
6
+ readonly seed?: number;
7
+ /** Exporter options; default the plain optimised GLB (no textures, no clips). */
8
+ readonly glb?: GlbOptions;
9
+ }
10
+ /** 16-hex-digit content hash of the asset's GLB at one LOD. */
11
+ export declare function snapshotHash(asset: Asset, o?: SnapshotOptions): string;
12
+ /** Compile + export twice per LOD; the bytes must match. */
13
+ export declare function assertDeterministic(asset: Asset, o?: LodOptions): void;
package/docs/README.md ADDED
@@ -0,0 +1,56 @@
1
+ # ts23d docs
2
+
3
+ **These docs are versioned with the package:** the copy in `node_modules/@developerz.ai/ts23d/docs/` always matches the installed code, and works offline.
4
+
5
+ **One owning doc per fact.** The idea docs say what and why; ADRs record decisions and the options they rejected; the architecture docs say where things go. The code wins on any conflict. Open an issue when you find one.
6
+
7
+ ## Start here
8
+
9
+ | If you want to… | Read |
10
+ |---|---|
11
+ | Know what this is and isn't | [idea/01-vision.md](idea/01-vision.md) |
12
+ | Write a recipe | [idea/02-dsl.md](idea/02-dsl.md) → [idea/09-kinds.md](idea/09-kinds.md) |
13
+ | Drive it from an agent | [idea/05-agent-loop.md](idea/05-agent-loop.md) |
14
+ | Decide if your asset fits | [idea/07-what-fits.md](idea/07-what-fits.md) · [landscape.md](landscape.md) |
15
+ | Add code to the library | [architecture/README.md](architecture/README.md) · [../CONTRIBUTING.md](../CONTRIBUTING.md) |
16
+ | Decode an error | [architecture/errors.md](architecture/errors.md) |
17
+ | See what's built vs planned | [plans/roadmap.md](plans/roadmap.md) |
18
+ | Release a version | [../PUBLISHING.md](../PUBLISHING.md) |
19
+
20
+ ## Idea: what and why
21
+
22
+ | Doc | Covers |
23
+ |---|---|
24
+ | [01-vision.md](idea/01-vision.md) | The pitch, origin, principles, non-goals |
25
+ | [02-dsl.md](idea/02-dsl.md) | `defineAsset`, the `ctx` API, composition with `ctx.use`, determinism rules |
26
+ | [03-ir.md](idea/03-ir.md) | Mesh IR, parts, units, axes, LODs |
27
+ | [04-materials.md](idea/04-materials.md) | Trim sheet, palettes, vertex colour, the procedural sheet painter, TSL / Godot shader sources |
28
+ | [05-agent-loop.md](idea/05-agent-loop.md) | The write → build → shot → read loop, contact sheet layout |
29
+ | [06-qa.md](idea/06-qa.md) | Gates: shipped vs planned |
30
+ | [07-what-fits.md](idea/07-what-fits.md) | Fit matrix by asset category |
31
+ | [08-neural-adapters.md](idea/08-neural-adapters.md) | Optional local-GPU models for organic shapes, image sources |
32
+ | [09-kinds.md](idea/09-kinds.md) | Domain builders: building, vehicle, vessel, vegetation, creature, scene |
33
+ | [10-sculpting.md](idea/10-sculpting.md) | How artists sculpt, mapped onto SDF edit lists; brushes, skin, FFD, forms |
34
+ | [11-materials-authoring.md](idea/11-materials-authoring.md) | Node-graph material authoring vs the trim-sheet painter; curvature and edge wear |
35
+ | [12-blender-bridge.md](idea/12-blender-bridge.md) | Optional headless Blender adapter: design, determinism, feasibility (planned) |
36
+ | [13-asset-pipeline-research.md](idea/13-asset-pipeline-research.md) | Pro asset pipeline, trim sheets, texel density, CC0 libraries and licences |
37
+
38
+ ## Decisions
39
+
40
+ Index with status: [decisions/README.md](decisions/README.md).
41
+
42
+ ## Architecture: where things go
43
+
44
+ | Doc | Covers |
45
+ |---|---|
46
+ | [architecture/README.md](architecture/README.md) | Module tiers and the import rule |
47
+ | [architecture/adding-a-primitive.md](architecture/adding-a-primitive.md) | New geometry builder |
48
+ | [architecture/adding-a-kind.md](architecture/adding-a-kind.md) | New domain builder |
49
+ | [architecture/errors.md](architecture/errors.md) | Every `T3D_*` code: cause, fix |
50
+
51
+ ## Other
52
+
53
+ | Doc | Covers |
54
+ |---|---|
55
+ | [plans/roadmap.md](plans/roadmap.md) | M0–M6 milestones |
56
+ | [landscape.md](landscape.md) | Neutral survey of AI 3D generators (as of 2026-10) |
@@ -0,0 +1,68 @@
1
+ # Architecture
2
+
3
+ **Imports only go down a tier.** A module imports from strictly lower tiers, never sideways, never up, and only through the other module's `index.ts`. `scripts/boundaries.ts` enforces it in `bun run verify`; the executable copy of the table below is `scripts/lib/tiers.ts`. Change both together.
4
+
5
+ ## Tiers
6
+
7
+ | Tier | Module | Job |
8
+ |---|---|---|
9
+ | 0 | `core` | Errors, seeded RNG, vector math, the Mesh IR, `defineAsset` / `compile`, mesh transforms (`place`), world transforms |
10
+ | 1 | `grammar` | String mini-languages: split grammar, Whyte notation |
11
+ | 1 | `material` | Trim-sheet layout, palettes, `paintTrimSheet`, TSL and Godot shader sources |
12
+ | 2 | `primitives` | Geometry builders → `Mesh`: `box`, `lathe`, `cylinder`, `prism`, `beam`, `planar`, `sweep`, `loft`, `heightfield`, `triangulate`; planned `tiled`, `cell`, `sdf` |
13
+ | 2 | `neural` | Optional AI adapters: local-GPU mesh generators, `importGlb`, image sources (all planned) |
14
+ | 2 | `passes` | Whole-mesh post-processing: `grime`; planned `optimize` (weld, vertex-cache reorder, ACMR) |
15
+ | 3 | `kinds` | Domain builders: building, vehicle, vegetation (`tree`, `trees`); planned vessel, creature |
16
+ | 3 | `qa` | Gates over a `CompiledAsset` |
17
+ | 3 | `export` | `CompiledAsset` → GLB |
18
+ | 3 | `render` | CPU rasteriser, PNG encoder, contact sheet; planned `photoMatch` |
19
+ | 4 | `cli` | `t3d build / shot / hero / review / list` |
20
+ | 4 | `testing` | assertions for users' recipe tests (subpath `/testing`) |
21
+ | 5 | `src/index.ts` | Re-exports every public module |
22
+
23
+ ```
24
+ src/index.ts (5) cli (4)
25
+ │ │
26
+ ┌──────────┬───┴──────┬──────────┤
27
+ kinds qa export render (3)
28
+ │
29
+ primitives neural passes (2)
30
+ │
31
+ grammar material (1)
32
+ │
33
+ core (0)
34
+ ```
35
+
36
+ Rules the guard prints with a `fix:`:
37
+
38
+ | Violation | Fix |
39
+ |---|---|
40
+ | Import from a same or higher tier | Move the shared code lower, or invert the dependency |
41
+ | Deep import (`../core/mesh.ts`) | Import from `../core/index.ts`; export what you need there |
42
+ | Module missing from the tier table | Add it to `scripts/lib/tiers.ts` and this table |
43
+
44
+ ## Data flow
45
+
46
+ ```
47
+ recipe.ts ─► defineAsset ─► compile(asset, { lod }) ─► CompiledAsset { parts[] }
48
+ ├─► runQa ─► Finding[]
49
+ ├─► toGlb ─► .glb
50
+ └─► contactSheet ─► .png
51
+ ```
52
+
53
+ `Mesh` is the only geometry type crossing modules ([IR](../idea/03-ir.md)).
54
+
55
+ ## Module conventions
56
+
57
+ - `index.ts` per module, one header comment stating the module's job, named re-exports only.
58
+ - Declared-but-unbuilt API lives in a `planned.ts` with its final signature, throwing `notImplemented(what, plan?)`. Recipes and docs can target it; it fails loudly until built.
59
+ - Public subpath per module: `@developerz.ai/ts23d/<module>` ([ADR 006](../decisions/006-single-package-subpath-exports.md)).
60
+
61
+ ## Guides
62
+
63
+ | Doc | |
64
+ |---|---|
65
+ | [adding-a-primitive.md](adding-a-primitive.md) | New geometry builder |
66
+ | [adding-a-kind.md](adding-a-kind.md) | New domain builder |
67
+ | [errors.md](errors.md) | Every `T3D_*` code |
68
+ | [glb-production.md](glb-production.md) | Production GLB rules, validator results, per-engine import table, gap list |
@@ -0,0 +1,44 @@
1
+ # Adding a kind
2
+
3
+ **A kind is a library of builder functions `(ctx, options) => void | value`.** Builders add named parts to the caller's `ctx`; the recipe keeps control of layout, naming and LOD. It lives in `src/kinds/` (tier 3) and may import `core`, `grammar`, `material`, `primitives`, `neural`, `passes`.
4
+
5
+ ## Checklist
6
+
7
+ | Step | Rule |
8
+ |---|---|
9
+ | 1. Signature | If it's in `src/kinds/planned.ts` (today only `creature`), keep that signature and move it to its own file |
10
+ | 2. Duplicate check | Read the shipped kinds first — `building.ts` (`facade`, `setbacks`), `vehicle.ts` (`axle`, `whyteAxles`, `trackRun`, `propeller`), `vegetation.ts` (`tree`, `trees`, `treeReal`), `roof.ts` (`roof`, `roofMesh`), `openings.ts` (`opening`), `mass.ts`, `hull.ts`, `head.ts` (`head`, `HEADS`). Extend one of them; don't re-add what already ships |
11
+ | 3. Domain params | Take the parameters the domain uses: Whyte `2-6-2`, length/beam/draft, species + height, roof pitch in degrees. Not raw coordinates |
12
+ | 4. Names | Every part prefixed by a caller-supplied `prefix`/`name`. Follow the engine contract: `axle_*` / `wheel_*` spin about Y, `prop_*` / `rotor_*` about their own axis, `door_*` hinge at the pivot |
13
+ | 5. Pivots | Movable pieces get a `ctx.group` at the hinge, the mesh inside it. Yaw on the group, motion on the child |
14
+ | 6. LOD | Read `ctx.lod`: drop details, lower segments. Masses survive to LOD2 |
15
+ | 7. Randomness | Only `ctx.rng.fork('<kind>:<prefix>')`, so adding the kind doesn't shift other draws |
16
+ | 8. Real units | Defaults from real references, cited in a comment (e.g. standard gauge 1.435 m) |
17
+ | 9. Export | Named export from `src/kinds/index.ts` |
18
+ | 10. Test | Next to it: part names, part count per LOD, QA passes on a minimal asset using it |
19
+ | 11. Recipe | At least one `recipes/*/*.ts` using it. Its contact sheet is the review artefact |
20
+ | 12. Docs | [09-kinds](../idea/09-kinds.md), [07-what-fits](../idea/07-what-fits.md), [roadmap](../plans/roadmap.md), `CHANGELOG.md` |
21
+
22
+ ## Shape
23
+
24
+ ```ts
25
+ // Vessel helpers: hulls from naval-architecture params, lofted from sections.
26
+
27
+ import type { BuildContext, Vec3 } from '../core/index.ts';
28
+ import { loft } from '../primitives/index.ts';
29
+
30
+ export interface HullOptions {
31
+ readonly length: number; // LOA, metres
32
+ readonly beam: number;
33
+ readonly draft: number;
34
+ readonly freeboard: number;
35
+ readonly color: Vec3;
36
+ }
37
+
38
+ export function hull(ctx: BuildContext, o: HullOptions): void {
39
+ const stations = [24, 12, 6][ctx.lod] ?? 6;
40
+ // sections from sheer + keel curves → loft → ctx.part('hull', …)
41
+ }
42
+ ```
43
+
44
+ A kind that needs a missing primitive adds the primitive first ([adding-a-primitive.md](adding-a-primitive.md)), in its own PR.
@@ -0,0 +1,49 @@
1
+ # Adding a primitive
2
+
3
+ **A primitive is a pure function `(options) => Mesh`.** No `ctx`, no parts, no RNG unless a `seed` is an option. It lives in `src/primitives/` (tier 2) and may import `core` and `material` only.
4
+
5
+ ## Checklist
6
+
7
+ | Step | Rule |
8
+ |---|---|
9
+ | 1. Signature | One file per primitive (`tiled.ts`, `lattice.ts`). Every planned primitive has shipped; a new one is a new file |
10
+ | 2. Options | Readonly interface `XOptions`, exported. Sizes in metres. `color: Vec3` (linear), `strip?: StripId` (default `'plain'`), `at?: Vec3` |
11
+ | 3. Placement | Base at `at` (z = 0 = ground) unless the shape has a natural centre (axles, `lathe` with `axis`). Say which in the doc comment |
12
+ | 4. Geometry | `MeshBuilder`: `vertex({ p, n, uv, color })`, `quad(a, b, c, d)` counter-clockwise from outside |
13
+ | 5. UVs | Map into `stripRect(strip)` by world metres, so texel density matches across assets. V cannot wrap: cut faces into bands of the strip's V metres (see `strip-uv.ts`), or mirror V for organic surfaces. `box` still stretches V over the face; use `tiled` or kinds' `mass` for true-scale walls |
14
+ | 6. LOD | Take a resolution option (`segments`, `resolution`). The recipe picks it from `ctx.lod`; the primitive never reads LOD |
15
+ | 7. Contact | If the shape rests on something, put a vertex at the contact point (see the `lathe` ring offset; the floating-parts gate caught a coarse wheel missing its rail) |
16
+ | 8. Export | Named export from `src/primitives/index.ts` |
17
+ | 9. Test | `x.test.ts` next to it (see `prism.test.ts`): triangle count, bounds, normals point out, deterministic output |
18
+ | 10. Use it | Add or update a recipe in `recipes/` that uses it, so `scripts/recipes.ts` gates it |
19
+ | 11. Docs | Tick it in [roadmap](../plans/roadmap.md); update [07-what-fits](../idea/07-what-fits.md) if fit changed; add to `CHANGELOG.md` under `[Unreleased]` |
20
+
21
+ ## Skeleton
22
+
23
+ Real shipped references: `prism.ts`, `beam.ts`, `planar.ts`, `tiled.ts`, `lattice.ts`.
24
+
25
+ ```ts
26
+ // A quad tiling one trim strip at true scale: walls, roofs, decks.
27
+
28
+ import { cross, length, type Mesh, MeshBuilder, normalize, type Vec3 } from '../core/index.ts';
29
+ import { type StripId, stripRect } from '../material/index.ts';
30
+
31
+ export interface TiledOptions {
32
+ readonly origin: Vec3; // one corner
33
+ readonly u: Vec3; // edge along the strip, metres
34
+ readonly v: Vec3; // the other edge
35
+ readonly color: Vec3;
36
+ readonly strip: StripId;
37
+ }
38
+
39
+ export function tiled(o: TiledOptions): Mesh {
40
+ const rect = stripRect(o.strip);
41
+ const n = normalize(cross(o.u, o.v));
42
+ const reps = length(o.u) / rect.metres; // true-scale tiling along U
43
+ const b = new MeshBuilder();
44
+ // 4 vertices: origin, +u, +u+v, +v; uv u from 0 to reps across the strip's rect
45
+ return b.build();
46
+ }
47
+ ```
48
+
49
+ Done = `bun run verify` green, including the recipe that uses it.
@@ -0,0 +1,47 @@
1
+ # Errors
2
+
3
+ **Every failure is a `Ts23dError` with a stable `code`, a `cause` in the message, and a `fix`.** The reader is usually an agent: act on `fix`, don't parse prose. Codes are stable across minor versions. Source: `src/core/errors.ts`.
4
+
5
+ ```
6
+ T3D_PART_UNKNOWN: part 'gun_barrel' parents to 'gun', which does not exist yet
7
+ fix: add the parent (ctx.group or ctx.part) before its children
8
+ ```
9
+
10
+ `--json`: `{"ok":false,"error":{"code":"…","message":"…","fix":"…"}}`, exit 1.
11
+
12
+ ## Library codes
13
+
14
+ | Code | Thrown by | Cause | Fix |
15
+ |---|---|---|---|
16
+ | `T3D_NOT_IMPLEMENTED` | Anything still in a `planned.ts` (`creature`), `/neural`, and whatever the roadmap lists as unbuilt | Declared API, not built yet. The message names the doc tracking it | Use a shipped alternative ([roadmap](../plans/roadmap.md)), or implement it ([adding a primitive](adding-a-primitive.md), [adding a kind](adding-a-kind.md)) |
17
+ | `T3D_GRAMMAR_SYNTAX` | `parseSplit`, `split`, `parseWhyte` | Bad split term, empty split, a repeat with stretch terms, more than one repeat; or a Whyte string that isn't three even numbers | Split: `sym:<metres>`, `sym:~`, `sym:~<weight>`, `{a:1 \| b:2}*`, joined by `\|`. Whyte: `'4-4-0'`, `'2-8-2'` |
18
+ | `T3D_GRAMMAR_OVERFLOW` | `layoutSplit`, `split`, `facade` | Fixed terms sum to more than the strip length | Shrink a fixed term or make one a stretch (`sym:~`) |
19
+ | `T3D_PART_DUPLICATE` | `ctx.part`, `ctx.group`, `ctx.use` | A part name added twice in one asset | Suffix the loop index: `wheel_0`, `wheel_1`; give each `ctx.use` a unique `prefix` |
20
+ | `T3D_PART_UNKNOWN` | `ctx.part`, `ctx.group` | `parent` names a part not added yet | Add the parent first |
21
+ | `T3D_RECIPE_INVALID` | `defineAsset`, `ctx.part`, every primitive and kind | Asset name not `[a-z][a-z0-9_]*`; a part with both `yaw` and `motion`; or a primitive/kind given impossible input (zero-length edge, bevel ≥ half a side, roof pitch out of range, SDF grid over the cell cap) | Rename to snake_case; put yaw on a parent `ctx.group`, motion on the child; otherwise the printed `fix:` names the bad option and its valid range |
22
+ | `T3D_NO_ASSET_EXPORT` | CLI loader | The module exports no `defineAsset` result | `export const my_thing = defineAsset({ … })`. Named export, no default |
23
+ | `T3D_QA_FAILED` | `/testing` assertions (`assertQaPass`, `assertBudget`, `assertMeasure`, …) | A recipe test found QA findings; the message lists every one. The CLI itself reports findings and exits 1 instead | Fix each finding's `fix:` line |
24
+ | `T3D_RENDER_OPTIONS` | `beauty`, `t3d hero` / `review` flags, render metrics | Bad image size, camera angle or render option | The printed `fix:` names the valid range |
25
+
26
+ ## Repo tooling codes
27
+
28
+ In `ErrorCode`, raised by this repo's scripts and test tooling rather than by the library at runtime.
29
+
30
+ | Code | Where | Cause | Fix |
31
+ |---|---|---|---|
32
+ | `T3D_AMBIENT_RANDOM` | Test preload (`scripts/test-setup.ts`) | Code under test called `Math.random` | Use `ctx.rng` or `createRng(seed)` |
33
+ | `T3D_RELEASE` | `scripts/release.ts` | Bad version string, missing `## [Unreleased]`, or tree not stamped at the version | The printed `fix:` (usually `bun run release <x.y.z>`) |
34
+ | `T3D_BENCH` | `scripts/bench.ts --write` | `README.md` has no bench block | The printed `fix:`; the markers are `<!-- bench:start -->` / `<!-- bench:end -->` on their own lines |
35
+
36
+ Guards (`boundaries`, `determinism`, `filesize`, `recipes`) print `file:line`, message and `fix:` without a code.
37
+
38
+ ## QA findings are not errors
39
+
40
+ A gate returns `Finding { gate, part?, message, fix }`. Findings don't throw; `t3d build` prints them all and exits 1. Gate list: [06-qa](../idea/06-qa.md).
41
+
42
+ ## Adding a code
43
+
44
+ 1. Add it to `ErrorCode` in `src/core/errors.ts`. `T3D_` + area + problem, upper snake case.
45
+ 2. Throw `new Ts23dError(code, { cause, fix })`. `cause` names the offending value; `fix` is an action, ideally a literal snippet.
46
+ 3. Add a row here in the same PR.
47
+ 4. Never rename or reuse a code. Retire by leaving it in the union, documented as unused.