diff --git a/README.md b/README.md index 86ae371..6c3bee9 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,7 @@ Start here: - [Project Brief](docs/PROJECT_BRIEF.md) - [ComponentPlan v0.1 Spec](docs/COMPONENT_PLAN_SPEC.md) - [LLM Authoring Contract](docs/LLM_AUTHORING_CONTRACT.md) +- [Complex Build Authoring Workflow](docs/COMPLEX_BUILD_AUTHORING.md) - [Implementation Plan](docs/IMPLEMENTATION_PLAN.md) ## Relationship with MinePilot diff --git a/docs/AGENT_TOOLKIT.md b/docs/AGENT_TOOLKIT.md index e5a7d2e..8ee8fab 100644 --- a/docs/AGENT_TOOLKIT.md +++ b/docs/AGENT_TOOLKIT.md @@ -5,6 +5,7 @@ This guide is for coding and harness agents that author CraftDAG build plans in Use it with: - `docs/llm.txt` +- `docs/COMPLEX_BUILD_AUTHORING.md` for semantic / mesh / hybrid route selection and reproducible freeform authoring - `docs/COMPONENT_PLAN_SPEC.md` - `docs/LLM_AUTHORING_CONTRACT.md` - `docs/LARGE_BUILDS.md` @@ -20,20 +21,21 @@ natural-language build intent -> materials, layers, preview, schematic export ``` -ComponentPlan is the primary agent-authored format. Agents should not directly hand-place hundreds of low-level boxes unless they are debugging the compiler or writing a tiny fixture. +ComponentPlan is the primary agent-authored format for semantic architecture. For complex briefs, select the route first using `docs/COMPLEX_BUILD_AUTHORING.md`; mesh/freeform candidates enter through the adapter and still converge on VoxelPlan. Agents should not directly hand-place hundreds of low-level boxes unless they are debugging the compiler or writing a tiny fixture. ## Recommended Loop 1. Read `docs/llm.txt`. -2. Pick the nearest example from `examples/component-plans`. -3. Draft or edit one ComponentPlan JSON file. -4. Run validation through the test suite or a small local script using `validateComponentPlan`. -5. Expand with `expandComponentPlan` when debugging generated CraftDAG node IDs. -6. Compile with `compileComponentPlan` to inspect voxel output. -7. Inspect materials, layers, budget diagnostics, and support diagnostics. -8. Repair the ComponentPlan. -9. Repeat until valid and recognizable. -10. Export or hand the plan to MinePilot preview once package versions are aligned. +2. For a complex build, read `docs/COMPLEX_BUILD_AUTHORING.md` and write its short route record before authoring. +3. If semantic pressure wins, pick the nearest example from `examples/component-plans`; if mesh/freeform wins, follow the pinned OBJ → adapter workflow and preserve its evidence. +4. Draft or edit ComponentPlan JSON for the semantic route or semantic part of a hybrid. +5. Run validation through the test suite or a small local script using `validateComponentPlan`. +6. Expand with `expandComponentPlan` when debugging generated CraftDAG node IDs. +7. Compile semantic output with `compileComponentPlan`; convert mesh output with the adapter. Both produce VoxelPlan. +8. Inspect materials, layers, budget diagnostics, support diagnostics, and preview. +9. Repair the smallest failing source and preserve route-specific evidence. +10. Repeat until valid and recognizable, or stop and switch/downscope per the complex-build guide. +11. Export or hand the final VoxelPlan to MinePilot preview once package versions are aligned. ## Current Commands diff --git a/docs/COMPLEX_BUILD_AUTHORING.md b/docs/COMPLEX_BUILD_AUTHORING.md new file mode 100644 index 0000000..86e3999 --- /dev/null +++ b/docs/COMPLEX_BUILD_AUTHORING.md @@ -0,0 +1,163 @@ +# Complex Build Authoring Workflow + +This guide helps an Agent choose and execute the right CraftDAG authoring route for a complex build. It complements [`LLM_AUTHORING_CONTRACT.md`](LLM_AUTHORING_CONTRACT.md), which remains the source of truth for ComponentPlan JSON and its schema. + +## Mental model + +Choose a representation for the shape and edits the build needs. Build size alone does not choose the route. All routes end at the ordinary `VoxelPlan` consumed by preview, material, layer, and schematic tools. + +```text +semantic architecture +brief → ComponentPlan → CraftDAG → VoxelPlan + +freeform geometry +brief/reference → source-controlled 3D source → deterministic OBJ + → @i365dev/craftdag-adapter-mesh → VoxelPlan + +bounded hybrid +semantic ComponentPlan → VoxelPlan A ─┐ +geometry subsystem → adapter → VoxelPlan B ─┴→ deterministic final VoxelPlan +``` + +Do not convert a mesh back into ComponentPlan. Do not add a landmark-specific primitive to force a route to fit. + +## Route selection + +Before authoring, write a short route record. Score the pressures as `low`, `medium`, or `high`, with one sentence of evidence for each non-low score. + +| Route | Select when | +| --- | --- | +| **Semantic** | Architectural decomposition is meaningful; repeated bays, levels, rooms, doors, circulation, or later semantic repair matter; current ComponentPlan vocabulary expresses the form without coordinate tables or one-off hacks. | +| **Mesh/freeform** | Silhouette or continuous form dominates; compound curvature or sculptural geometry matters; semantic parts would mainly describe approximation mechanics; a procedural 3D source is substantially clearer; and the shape remains recognizable at the target voxel scale. | +| **Hybrid** | Most of the build is naturally semantic and one bounded subsystem is geometry-heavy; that subsystem has a clear spatial boundary and can be compiled independently; final composition can use an explicit deterministic placement and overlap contract. | + +Use this compact record outside strict ComponentPlan JSON: + +```yaml +route: semantic | mesh | hybrid +intent: +semantic_pressure: — +geometry_pressure: — +hybrid_boundary: +target_scale: +stop_condition: +``` + +Choose the route with the clearest representation and cheapest reliable repair. A large conventional castle may remain semantic; a small organic statue may be mesh-first. A pagoda or palace can be semantic overall and hybrid only if a roof/eave subsystem is independently bounded and demonstrably cheaper as geometry. These are examples, not type rules. + +Evidence already supports keeping ordinary houses, towers, and the Roman Colosseum semantic, while the mesh frontend is a narrow option for freeform, organic, and sculptural forms. The MinePilot Roman Colosseum work also showed that useful ellipse and repeated-arcade architecture can remain semantic; complexity alone is not a reason to switch. + +## Semantic route + +1. Read [`LLM_AUTHORING_CONTRACT.md`](LLM_AUTHORING_CONTRACT.md) and the nearest example under `examples/component-plans`. +2. Keep the route record separate from strict ComponentPlan JSON. Author named sections, assemblies, and instances where they express real architectural structure. +3. Build and use the ComponentPlan CLI commands from [`AGENT_TOOLKIT.md`](AGENT_TOOLKIT.md): validate, compile, inspect materials/layers/support, then preview and repair. +4. Repair the smallest diagnosed component or downscope. Do not replace semantic authoring with hundreds of coordinates merely to pass validation. + +Use semantic authoring when interiors, openings, circulation, repeated architectural modules, or source-aware repair are part of the intent. See [`LARGE_BUILDS.md`](LARGE_BUILDS.md) for sections and assemblies. + +## Mesh/freeform route + +The mesh adapter currently consumes a deterministic OBJ subset and returns a regular `VoxelPlan`. Blender is an optional upstream authoring tool, never a CraftDAG runtime dependency. Prefer code-native procedural source or a headless Blender script over GUI-only edits because source and export settings can be reviewed and rerun. + +### Source and artifact layout + +Keep inputs with the MinePilot build or its source repository, not in CraftDAG core. A repeatable per-build layout can be: + +```text +builds//mesh/ + source/ # procedural source or .blend + headless export script + generated/model.obj # deterministic generated artifact + generated/voxel-plan.json + evidence.json # route, tool versions, options, dimensions, counts, hashes +``` + +The source/script is the source of truth. Treat OBJ and VoxelPlan as generated artifacts. Preserve generated OBJ and evidence with a review when they are needed to reproduce a production result; do not commit large generated geometry as an unrelated CraftDAG benchmark. + +Pin the Blender or procedural-tool version, generator dependencies, seed, coordinate convention, scale, and export settings. Code-native and procedural exporters SHOULD produce byte-stable OBJ where practical. Some upstream producers, including Blender exports, may vary raw OBJ serialization order while preserving the same geometry; for those producers, raw OBJ byte identity is not a hard invariant. Use canonical/normalized geometry equivalence, or a canonical geometry hash when an existing tool provides one, to compare geometry. Do not rely on GUI state, ambient scene objects, current selection, machine-specific paths, or unseeded randomness. + +### Convert OBJ reproducibly + +Pin `@i365dev/craftdag-adapter-mesh` in the consuming build repository's package manifest and lockfile. Call its current API from a source-controlled Node script there: + +```bash +node builds//mesh/source/voxelize.mjs +``` + +The wrapper imports `objToVoxelPlan` from the pinned package, reads `generated/model.obj`, and writes stable JSON. When validating changes to the adapter itself from a CraftDAG checkout, build that package with `pnpm --filter @i365dev/craftdag-adapter-mesh build` before running the same wrapper against the local package output. Make every conversion option explicit: + +```js +const plan = objToVoxelPlan(objText, { + targetHeight: 64, + maxBlocks: 100_000, + voxelMode: "surface", + defaultBlock: "minecraft:stone", + name: " mesh subsystem", +}); +``` + +Choose the smallest `targetHeight` that preserves the required silhouette. Start around 32 or 64 blocks high and compare a preview; increase resolution only when a named important feature disappears. `maxBlocks` is a hard cap on both normalized bounding-box volume and occupied blocks, so choose it from the MinePilot build budget and pass it explicitly. Use `surface` for open meshes and thin shells, including organic forms where a solid fill fuses limbs or wings. Use `solid` only for a bounded, closed mesh when the filled interior is wanted. The adapter uses one explicit `defaultBlock`; OBJ materials, groups, transforms, and textures are not carried through. + +Run the complete source generator and voxelizer twice from a clean checkout using the pinned source, toolchain, and options. The final normalized VoxelPlan MUST be deterministic. Compare source hashes, geometry equivalence (or canonical geometry hashes when available), and VoxelPlan hashes/output. Record the raw OBJ SHA-256 as provenance whenever an OBJ is produced; a changed raw OBJ hash alone does not invalidate a run when canonical geometry is equivalent and the final VoxelPlan remains deterministic. Hash the exact source files and exact VoxelPlan output bytes with SHA-256. Record the command, tool and adapter versions, seed, all conversion options, `plan.size`, `plan.blocks.length`, source and VoxelPlan hashes, raw OBJ hash, and any available canonical geometry hash in `evidence.json`. + +### Review and repair + +Inspect the VoxelPlan through MinePilot preview and downstream material/layer/schematic paths. Repair only the source geometry, deterministic generator, scale, voxel mode, or palette; keep every attempt and its hashes in the evidence record. + +Use a bounded loop: + +1. One Luna-class authoring attempt. +2. At most two evidence-driven source/parameter repairs, changing one cause at a time. +3. If the failure appears to be an authoring/tool misunderstanding, allow one fresh Luna retry with the evidence and route constraints. +4. Stop mesh work if the result is still unrecognizable at the allowed block budget, the source remains nondeterministic, repair cost exceeds a semantic plan, or important structure is lost at practical scale. Switch to ComponentPlan when semantics fit, otherwise simplify the requested form. +5. Use a stronger model only when a concrete remaining failure points to a capability gap in the ordinary model. Record that failure and why code or a fresh Luna attempt cannot address it first. + +Do not ask a model to emit block lists or repeatedly inspect huge VoxelPlan JSON. Keep voxelization, bounds, budgets, sorting, and hashing deterministic. + +## Hybrid route + +Keep each frontend independent: + +```text +semantic ComponentPlan → VoxelPlan A +geometry source → OBJ → adapter → VoxelPlan B +A + B → final VoxelPlan +``` + +Use this only for a real spatial boundary, such as an otherwise semantic building with one independently authored sculpture. Specify each part's stable ID, input plan hash, translation/alignment in one shared coordinate frame, final bounds and block budget, deterministic part order, and an explicit overlap rule before composing. A safe first contract is **reject all overlapping occupied positions**; move or reshape parts if they collide. Do not let iteration order silently decide which block wins. + +The core exposes `VoxelPlan` (`version`, `name`, `size`, `origin`, `blocks`) and `VoxelGrid`. The grid bounds-checks positions and `setBlock` replaces an existing block at the same position; there is no reusable checked composition API that handles transforms, overlap policy, budgets, and provenance together. For a one-off hybrid, a consuming workflow can translate each input block into a chosen final frame, preflight bounds and total unique positions, reject collisions, then insert blocks in stable part/coordinate order. Preserve `sourceNodeId` with a part prefix where present and record part IDs, transforms, and input/output hashes in the evidence manifest. Keep the final object an ordinary VoxelPlan. + +This PR documents that manual bounded contract; it does not add a core composition helper. If MinePilot needs repeated hybrid composition, the precise future helper is a deterministic `composeVoxelPlans(parts, { bounds, maxBlocks, overlap: "reject" })` that accepts stable part IDs, VoxelPlans, and integer translations; validates translated bounds and unique occupied positions before emission; sorts output deterministically; and preserves/prefixes source identity. Add other overlap policies only for a demonstrated product case. + +Do not build a scene graph, CAD boolean system, generic CSG, arbitrary transforms, or mesh-to-ComponentPlan reconstruction. + +## Evidence and MinePilot handoff + +For every complex build retain: + +- the route record and short reason for the selected representation; +- source commit and tool/dependency versions; +- exact deterministic regeneration command and all mesh conversion options; +- source, OBJ, and VoxelPlan SHA-256 hashes; +- target scale, bounds, voxel mode, block budget, material policy, actual dimensions, and block count; +- bounded repair attempts, route switches, or model escalations and their concrete evidence; +- fixed-view preview, support/material/layer review, and schematic round-trip evidence when applicable; +- final VoxelPlan and its source/part identity manifest. + +Hand MinePilot one candidate containing the final VoxelPlan, route record, and artifact manifest. For a hybrid, include part IDs, per-part source hashes/versions and transforms, plus the final composed digest. Do not introduce a second target format or publish an unreviewed repair automatically. MinePilot #84 should use this handoff in its existing local `BuildPreview`, six fixed views, digest binding, visual review, and artifact-verification flow; its normal quality gates and human publication boundary stay authoritative. The local review bridge belongs in MinePilot, not this CraftDAG workflow PR. + +## Anti-patterns + +- Choosing mesh because the build is large, or choosing semantic because it is called a castle or temple. +- Forcing sculptural forms into a long coordinate table or forcing ordinary architecture through a mesh. +- Treating a generated OBJ as the only source when a procedural generator exists. +- Using uncontrolled Blender scene state or an unseeded procedural model. +- Leaving `targetHeight`, `voxelMode`, `maxBlocks`, or `defaultBlock` to an implicit default in a production record. +- Repairing meshes indefinitely, increasing block budgets without visual evidence, or escalating to a frontier model before one fresh Luna attempt. +- Silently overwriting overlaps when composing hybrid plans. +- Adding a landmark primitive, Blender dependency, mesh reverse-compiler, or generic scene/CAD framework for one build. + +## Repository skill convention + +This repository currently has no `.agents/` or `.codex/skills/` repository-local Agent skill convention. Its supported authoring surface is documentation plus the CLI/API in `AGENT_TOOLKIT.md`. Keep this workflow canonical here; do not add a new skill infrastructure for this task. diff --git a/docs/LLM_AUTHORING_CONTRACT.md b/docs/LLM_AUTHORING_CONTRACT.md index 89807f1..6afcd96 100644 --- a/docs/LLM_AUTHORING_CONTRACT.md +++ b/docs/LLM_AUTHORING_CONTRACT.md @@ -4,7 +4,9 @@ This is the model-facing contract for agents that generate Minecraft build plans For short prompt context, start with `docs/llm.txt`. For repository-based harness agents, also read `docs/AGENT_TOOLKIT.md`. -For product workflows, generate `ComponentPlan` first. Raw CraftDAG is the lower-level compiler IR and should mainly be used for fixtures, tests, debugging, and fallback generation. +For complex briefs, decide semantic vs mesh/freeform vs hybrid from representation fit using `docs/COMPLEX_BUILD_AUTHORING.md` before writing the plan. This workflow does not replace the ComponentPlan schema or its authoring rules. + +For semantic architecture, generate `ComponentPlan` first. For complex briefs, select semantic, mesh/freeform, or hybrid using `docs/COMPLEX_BUILD_AUTHORING.md`; mesh geometry enters through the adapter and need not be reconstructed as ComponentPlan. Raw CraftDAG remains the lower-level compiler IR and should mainly be used for fixtures, tests, debugging, and fallback generation. ```text natural language / future reference input diff --git a/docs/llm.txt b/docs/llm.txt index 6d00b71..456299f 100644 --- a/docs/llm.txt +++ b/docs/llm.txt @@ -1,11 +1,12 @@ CraftDAG model authoring quick context Goal -Author ComponentPlan JSON for Minecraft builds. ComponentPlan is the agent-authored DSL. CraftDAG expands it to low-level CraftDAG IR, compiles it to VoxelPlan target state, and can export Sponge .schem files. +Author semantic Minecraft builds as ComponentPlan JSON. For complex briefs, first choose semantic, mesh/freeform, or hybrid from representation fit. ComponentPlan expands through CraftDAG to VoxelPlan; OBJ mesh enters through adapter-mesh and also ends at VoxelPlan. Both use the existing preview and export path. Primary docs - docs/COMPONENT_PLAN_SPEC.md: complete ComponentPlan schema and semantics. - docs/LLM_AUTHORING_CONTRACT.md: model-facing rules, anti-patterns, and examples. +- docs/COMPLEX_BUILD_AUTHORING.md: choose semantic, mesh/freeform, or hybrid by representation fit; includes reproducible OBJ → VoxelPlan workflow and evidence rules. - docs/LARGE_BUILDS.md: sections, assemblies, instances, and large-build decomposition. - docs/SHAPE_PRIMITIVES.md: large-form, facade, support, landscape, path, rock, stair, and dome primitives. - docs/AGENT_TOOLKIT.md: harness-agent workflow and current command contracts. @@ -21,6 +22,7 @@ Authoring rules 8. Use sections for large builds that are hard to reason about in one coordinate space. 9. Downscope before producing huge flat component arrays. 10. If validation fails, repair the plan instead of loosening schema or validation. +11. For complex builds, write the short route record in `docs/COMPLEX_BUILD_AUTHORING.md` first; size alone never selects mesh. Allowed ComponentPlan components Foundation, Platform, Beam, RoomShell, Compartment, Corridor, StairRun, FloorStack, TaperedVolume, SteppedTier, VerticalSetbackVolume, SteppedDome, RectRing, EllipseRing, PathRepeat, RailingRun, ArcadeRun, SupportBracket, TreeCanopy, OrganicPatch, PathRun, RockCluster, Light, Door, Window, Opening, Portal, GableRoof, FlatRoof, SupportPost, Repeat, Instance. @@ -65,4 +67,4 @@ Current limitations - Do not use nested Instance inside assemblies. - Do not synthesize arbitrary redstone circuits yet. - Do not require exact landmark replication, sculpture-level details, or smooth curves. -- Ring/radial array primitives are future work; approximate with assemblies and existing primitives for now. +- Do not assume generic curves, arbitrary mesh materials, or mesh-to-ComponentPlan recovery; use only the documented components and bounded OBJ adapter contract.