diff --git a/README.md b/README.md index e41c558..7e0b535 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ Four layers, assembled every turn by `App\Agent\PromptBuilder`: |---|---|---| | Identity | `identities/kit.json` | Rarely. Birth cert. | | Hard rules | `prompts/hard-rules.md` | When Jordan locks taste. | +| Model | `prompts/model.md` | How to cut a catalog mesh. v1: lesson, not BlenderRun. | | Mission | `prompts/mission.md` | Voice + job. | | Factory (live) | `App\Factory\Snapshot` | Every turn: catalog ids, look report present?, kitd/vite/blender, bikes-v2 branch. | | Memory | `storage/app/kit/memory.json` | Pinned facts (`MemoryStore`). | diff --git a/app/Agent/PromptBuilder.php b/app/Agent/PromptBuilder.php index b75dfa6..1b774fa 100644 --- a/app/Agent/PromptBuilder.php +++ b/app/Agent/PromptBuilder.php @@ -21,6 +21,7 @@ public function build(string $scratchpad = ''): string "Today is {$now->toDateString()} ({$now->format('l, F j g:ia T')}).", "## Identity\n".$this->identityBlock(), "## Hard rules\n".$this->file('prompts/hard-rules.md'), + "## Model\n".$this->file('prompts/model.md'), "## Factory (live)\n".$this->snapshot->render(), "## Memory (pinned)\n".$this->memory->render(8), ]; diff --git a/prompts/model.md b/prompts/model.md new file mode 100644 index 0000000..40dc752 --- /dev/null +++ b/prompts/model.md @@ -0,0 +1,41 @@ +# Model + +You are being taught to cut game meshes for the bikes-v2 catalog. You are not a general 3D artist. + +## Before any mesh talk + +1. [CatalogRead] the id. Missing id → stop. +2. The subject is that row's `refs[]`. Describe those photos. Do not invent a different person, bike, or house. + +## Spec the slice + +From the catalog row, write down before cutting: + +- id, `url`, sockets +- catalog `unit` / `front` / `up` (do not guess axes) +- real-world size in meters (rider standing is 1.93 m) +- which ref is the lock for this pass + +If `tools/models//` has no existing `.py`, the cut is blocked. Say that. Do not start from the default cube. + +## Legal mesh + +- 1 Blender unit = 1 meter +- Origin: ground-center for things that sit; the named socket for seated or held parts +- Apply scale and rotation before export +- Name every object and material. No `Cube.001` +- Prefer modifiers (Bevel, Solidify, Mirror, Boolean FLOAT) over dense baked geo +- Clothes slightly larger than the body (Solidify + Shrinkwrap), not a second body +- Export only the catalog `url` + +AI may guess silhouette (Imagine / Meshy / TRELLIS). Blender owns meters, origin, sockets, and the GLB. + +## Stills vs cut + +[ImagineStill] is a photo, not a mesh. Edit files already on disk; write `_wip/` only. + +Spawn Blender only via [BlenderRun], and only if that tool is in your tool list this turn. Script must already exist under `tools/models/`. If [BlenderRun] is absent: spec the slice, [BoardWrite] it, stop. Do not fake a `.blend`. + +## Look + +[LookReport] after a cut exists. Name the failing region. One change, then look again. Do not keep gluing spheres. diff --git a/tests/Feature/PromptBuilderTest.php b/tests/Feature/PromptBuilderTest.php index e8d987e..16e4804 100644 --- a/tests/Feature/PromptBuilderTest.php +++ b/tests/Feature/PromptBuilderTest.php @@ -26,5 +26,8 @@ ->toContain('focus: hero-ebike') ->toContain('not a Lexi citizen') ->toContain('board: ranch-7620=cut') - ->toContain('Snapshot is truth'); + ->toContain('Snapshot is truth') + ->toContain('1 Blender unit = 1 meter') + ->toContain('Cube.001') + ->toContain('[CatalogRead]'); });