Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
8f4f089
fix(docs): remove corrupted text characters
Aug 4, 2026
1e8b2ac
feat(core): route explicit 3D prompts to threed_basic
Aug 4, 2026
3c0143b
feat(templates): add minimal three.js game archetype
Aug 4, 2026
21ef3d3
Merge pull request #1 from wh000wh000/feat/threed-basic-v1-release
wh000wh000 Aug 4, 2026
a3f5b76
feat(templates): add threed_basic manual collision
Aug 4, 2026
3a0b59a
docs(templates): define threed collision contract
Aug 4, 2026
fb526de
Merge pull request #2 from wh000wh000/feat/threed-v1-1-manual-collision
wh000wh000 Aug 4, 2026
d243bde
fix(templates): remove dead 3D screen config
Aug 4, 2026
2cf29c0
docs(templates): require consumed 3D config
Aug 4, 2026
74a7c9f
fix(core): specialize 3D config merge guidance
Aug 4, 2026
6c9e4d8
Merge pull request #3 from wh000wh000/feat/threed-v1-2-config-contract
wh000wh000 Aug 4, 2026
b49c27f
docs(templates): keep 3D smoke bridge read-only
Aug 4, 2026
41b6173
Merge pull request #4 from wh000wh000/fix/threed-v1-4-readonly-smoke-…
wh000wh000 Aug 4, 2026
ab0c546
fix(templates): stabilize 3D pause lifecycle
Aug 4, 2026
4e4fdf5
fix(templates): serve 3D favicon by path
Aug 4, 2026
2d02ced
Merge pull request #5 from wh000wh000/fix/threed-v1-5-browser-shell
wh000wh000 Aug 4, 2026
16aefc2
fix(gdd): preserve ordered 3D objectives
Aug 4, 2026
158924c
docs(threed): bind explicit mechanic semantics
Aug 4, 2026
fe50c67
Merge pull request #6 from wh000wh000/fix/threed-v1-6-objective-seman…
wh000wh000 Aug 4, 2026
2104e1d
fix(gdd): keep 3D verification faithful
Aug 4, 2026
f5f5090
docs(threed): require path-only final acceptance
Aug 4, 2026
09f5364
Merge pull request #7 from wh000wh000/fix/threed-v1-7-verification-in…
wh000wh000 Aug 4, 2026
e49cdde
docs(debug): keep screenshot evidence path-only
Aug 4, 2026
495242e
Merge pull request #8 from wh000wh000/fix/threed-v1-8-path-only-debug
wh000wh000 Aug 4, 2026
1247c2c
fix(templates): close 3d restart lifecycle
Aug 4, 2026
ad46d70
docs(threed): require final GDD reconciliation
Aug 4, 2026
0067c66
fix(templates): align camera-relative strafe
Aug 4, 2026
c5060bf
Merge pull request #9 from wh000wh000/fix/threed-v1-9-scaffold-truth
wh000wh000 Aug 4, 2026
58975c4
docs(threed): anchor final claims to source
Aug 4, 2026
efadb39
Merge pull request #10 from wh000wh000/fix/threed-v1-9-scaffold-truth
wh000wh000 Aug 4, 2026
f1a6d76
fix(assets): normalize generated image canvases
Aug 4, 2026
17dde56
Merge pull request #11 from wh000wh000/fix/threed-v1-9-asset-normaliz…
wh000wh000 Aug 4, 2026
6c74949
docs(threed): protect generated runtime contracts
Aug 4, 2026
e56c202
Merge pull request #12 from wh000wh000/fix/threed-v1-9-generated-runt…
wh000wh000 Aug 4, 2026
b42ebe6
docs(threed): require baseline evidence for provenance
Aug 4, 2026
a64d87d
Merge pull request #13 from wh000wh000/fix/threed-v1-9-gdd-provenance…
wh000wh000 Aug 4, 2026
867428b
docs(threed): require final spawn and tuning evidence
Aug 5, 2026
16e1fdb
style(threed): preserve existing manual formatting
Aug 5, 2026
c8b04bd
Merge pull request #14 from wh000wh000/fix/threed-v1-9-gdd-source-truth
wh000wh000 Aug 5, 2026
4fb99d8
docs(threed): require final render config truth
Aug 5, 2026
347ba6d
Merge pull request #15 from wh000wh000/fix/threed-v1-9-gdd-config-truth
wh000wh000 Aug 5, 2026
45080bc
docs(threed): require stable route clearance
Aug 5, 2026
a5f40bb
Merge pull request #16 from wh000wh000/fix/threed-v1-9-route-margin
wh000wh000 Aug 5, 2026
cb63c1c
fix(gdd): require a real 3d gameplay loop
Aug 5, 2026
9b9354f
docs(threed): make collection a fallback
Aug 5, 2026
9d3640d
fix(gdd): preserve no-fail 3d prompts
Aug 5, 2026
3e2dd9b
Merge pull request #17 from wh000wh000/fix/threed-v1-9-core-loop-cont…
wh000wh000 Aug 5, 2026
e2716cc
fix(core): require 3d decision source truth
Aug 5, 2026
8b18789
docs(threed): require branch coverage evidence
Aug 5, 2026
3345d43
Merge pull request #18 from wh000wh000/fix/threed-v1-9-decision-truth
wh000wh000 Aug 5, 2026
765f22b
fix(gdd): require 3d feasibility ledger
Aug 5, 2026
58e2837
docs(threed): close gameplay budget before acceptance
Aug 5, 2026
0a3e28b
Merge pull request #19 from wh000wh000/fix/threed-v1-9-feasibility-le…
wh000wh000 Aug 5, 2026
6f9901f
fix(gdd): distinguish derived and observed gameplay evidence
Aug 5, 2026
846c8d7
docs(threed): require exact-strategy playthrough provenance
Aug 5, 2026
d1f2b7c
docs: record workspace test routing pitfall
Aug 5, 2026
a3c9a8f
Merge pull request #20 from wh000wh000/fix/threed-v1-9-evidence-prove…
wh000wh000 Aug 5, 2026
5d76ec1
Merge pull request #21 from wh000wh000/fix/text-encoding-cleanup
wh000wh000 Aug 5, 2026
ffdfdd2
docs(pixelforge): add integration execution pack
Aug 5, 2026
fc20f3a
Merge pull request #22 from wh000wh000/chore/pixelforge-integration-pack
wh000wh000 Aug 5, 2026
c4d8c08
fix(core): prevent mirrored authored count config
Aug 5, 2026
fed1ff1
docs: record patch isolation lapse
Aug 5, 2026
ae91822
Merge pull request #23 from wh000wh000/fix/threed-v1-pipeline-closure
wh000wh000 Aug 5, 2026
e37c624
fix(core3d): preserve initial HUD progress
Aug 6, 2026
e487335
docs: record repeated patch isolation lapse
Aug 6, 2026
c6d580e
test(core3d): require HUD order anchors
Aug 6, 2026
648ab8c
Merge pull request #24 from wh000wh000/fix/threed-v1-9-hud-initial-pr…
wh000wh000 Aug 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions agent-test/docs/asset_protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,30 @@ If generating \*too many assets**, split into **2 separate tool calls\*\* to avo
| `image` | `key`, `description` | PNG 386\*560 (portrait) | Yes |
| `audio` | `key`, `description`, `audioType`, `duration?`, `genre?`, `tempo?` | WAV (8-bit chiptune) | N/A |

### 1.2.0 3D Image Assets (`threed_basic`)

Three.js games use the same `generate_game_assets` image pipeline. These are
2D images applied to geometry; they are not 3D models and do not create a new
tool type.

| 3D role | Existing type | Required description/runtime contract |
|---|---|---|
| skybox | `background` | equirectangular sky texture, `1024*1024`, no background removal |
| surface texture | `image` | seamless or centered surface art, runtime display/source <= `1024*1024` |
| billboard sprite | `image` | one centered subject, transparent background/removal allowed |
| circular floor patch | `image` | top-down circular patch, transparent outside edge |

- Asset Registry `displaySize` remains GDD/runtime metadata; never pass it as
an unsupported MCP parameter. Source textures and declared display size must
not exceed `1024*1024`.
- Keep every 3D image in the normal Asset Registry/display list and generated
`asset-pack.json`; key and URL consistency rules below are unchanged.
- `colormap` is allowed only for matte/non-glossy art. Never colormap glossy,
translucent, emissive, metallic, or skybox art.
- Allowed runtime consumers are `Texture`, `MeshStandardMaterial.map`, scene
background, and `SpriteMaterial`. Never request GLB/FBX/OBJ, normal maps,
model generation, or a text-to-3D API.

**CRITICAL — Parameter restrictions:**

- `type: "image"` accepts ONLY `key` and `description`. **Do NOT pass `size`, `resolution`, or any other parameter** — the output is always 386\*560 PNG. Game code scales the image via `setScale()` or `setDisplaySize()`. Icons, projectiles, and small sprites all use the same output size; scale in code.
Expand Down
12 changes: 12 additions & 0 deletions agent-test/docs/debug_protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,18 @@ asset-pack.json → animations.json → Character.ts animKeys
3. Use browser tools to verify visual behavior
4. Continue with other tasks while server runs

### 2.2 Screenshot Evidence Is Path-Only

- Save screenshots as files under the current game workspace and report their
relative paths. Never embed real media in source, config, HTML, Markdown, or
chat/tool output.
- Never call `ReadMediaFile` or another media-read tool for screenshots, even
after compression or through a sub-agent. That still injects Base64/Data URLs
into the generation session.
- Use smoke's WebGL, non-blank pixel, error-array, and visible-DOM assertions for
automated verification. Human visual review happens outside the generation
session by opening the reported path.

---

## 3. Test Infrastructure
Expand Down
163 changes: 163 additions & 0 deletions agent-test/docs/modules/threed_basic/design_rules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
# threed_basic Design Rules

## 1. Product shape

Build one short, finishable 3D experience around an explicit core loop. Use
three.js, simple geometry, lights, fog, a sky texture, and DOM overlays.
Collection is the reference scaffold fallback, not the archetype definition.

Before assets or level coordinates, declare a Core Gameplay Contract:

| Contract | Required evidence |
| ---------- | ------------------------------------------------------------------------------------------- |
| Verbs | what the player repeatedly does through keyboard/mouse input |
| Loop | one 20-60 second action-feedback-decision cycle that repeats at least twice |
| Demand | one meaningful choice, timing, navigation, observation, or resource tradeoff |
| Pressure | an observable fail condition plus recovery, or an explicit no-fail tension/progression rule |
| Feedback | visible DOM/world response for progress, danger, success, and failure |
| Escalation | at least three authored beats that intensify the same loop |
| Outcome | exact reachable win and lose conditions |

Immediately follow the contract with a Gameplay Feasibility Ledger. This is a
small arithmetic table, not a new runtime framework:

| Evidence | Required |
| -------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| Loop signature | cue -> player action -> decision -> state change -> feedback -> repeat |
| Winning trace | each required transition, its deadline, derived action/travel time, resource delta, and resulting state through the exact win condition |
| Losing trace | one missed/low-priority/counterfactual decision whose same rules reach the declared failure or recovery response |
| Closure | handled events equal the authored event count; terminal health/time/progress satisfies the exact outcome predicate |
| Provenance | label each trace `DERIVED` or `OBSERVED`; only the exact played route, strategy, and terminal state may be `OBSERVED PASS` |

Derive travel time from final authored distance and movement speed, and derive
state deltas from the final damage, recovery, timer, and threshold consumers.
Carry the resulting state across every escalation threshold and recompute later
rows with the active beat or phase. A substitute route, stand-in mechanic, or
partial cycle proves only the transitions it exercised; it cannot upgrade the
target trace to observed. Final observed terminal values override conflicting
estimates.
If the ledger does not close, tune the authored data before calling the design
playable. Recompute it after every Phase 6 tuning edit; do not leave aggregate
counts that disagree with the final playthrough.

Do not reskin move-and-collect when the prompt asks for avoidance, timing,
switching, delivery, pursuit, defense, or another mechanic. Every private state
field and declarative SceneMap array in the contract must name its final runtime
consumer; do not invent a generic gameplay framework.

When the prompt explicitly requests peaceful or no-fail play, preserve that
semantics: state that there is no lose condition and specify how tension,
recovery, and progression still make the loop legible. Never add game over just
to fill the contract table.

Do not add physics, touch controls, multiplayer, imported 3D models, or any
text-to-3D service. 2D Phaser templates are unrelated and must remain unchanged.

Explicit prompt mechanics are binding. Never reinterpret ordered or sequential
objectives as unordered collection to match the scaffold. Keep the existing
public API and implement the requested rule with the smallest private state in
`GameScene`, such as one next-objective index over the authored `SceneMap` order.

## 2. Required runtime contract

| Area | Required |
| --------- | ---------------------------------------------------------------------------------- |
| Renderer | `WebGLRenderer`, `PerspectiveCamera`, resize handling, visible non-black frame |
| World | primitives or custom low-poly geometry, ambient + directional light, fog |
| Collision | player circle stays on an authored floor patch and outside static obstacle circles |
| Input | WASD and arrow keys; mouse drag/look; ESC pause |
| HUD | DOM in `#ui-root`; canvas stays dedicated to three.js |
| Pause | resolve `gameSceneKey ?? currentLevelKey ?? LevelManager.getFirstLevelScene()` |
| Win | one explicit, reachable completion condition |

## 3. Asset registry rules

3D assets are still ordinary images produced by `generate_game_assets`.

| Key role | Tool type | Max/source rule | three.js use |
| ------------------- | ------------ | --------------------------------------------------------------- | -------------------------------- |
| `skybox_texture` | `background` | `1024*1024`; `displaySize: 1024*1024` in GDD | equirectangular scene background |
| `floor_patch` | `image` | generated image; declare display size <= `1024*1024` | `CircleGeometry` material map |
| objective billboard | `image` | semantic key, one centered subject, transparent removal allowed | `SpriteMaterial` |
| surface texture | `image` | <= `1024*1024`; no glossy colormap | `MeshStandardMaterial.map` |

Never request a model, mesh, GLB, FBX, normal map, or text-to-3D output. Do not
use `colormap` for glossy, translucent, emissive, or sky assets.
Keep every image, audio file, and screenshot as a separate file inside the game
workspace. Reference runtime assets through `asset-pack.json` and relative paths;
never inline real media as Base64 or a Data URL in source, config, HTML, or GDD.

## 4. Level and camera budget

Use 8-14 floor patches and 8-16 low-poly decorations. Add only the objective,
hazard, switch, gate, patrol, trigger, or collectible entries consumed by the
chosen loop; do not keep the scaffold collectible budget when collection is not
the mechanic.
Keep the camera far plane under 250 and cap device pixel ratio at 2. Manual
distance checks are enough for pickups and static collision; do not introduce a
physics dependency. Give every obstacle an explicit `collisionRadius` instead
of deriving gameplay collision from rendered scale.

Mathematical overlap is not a playable lane. Shrink every floor patch by the
player collision radius, then require each authored neighbor pair to keep an
intersection half-width of at least two player radii. The spawn, every required
pickup center, and the finish trigger center must themselves be playable after
that shrink and must sit outside every expanded obstacle circle. Do not place a
finish center inside a lighthouse or other blocker and rely on the trigger
radius reaching a thin boundary crescent.

For a branched route, list intended neighbor pairs and forbidden cross-lane
transitions after the same shrink. A claimed committed choice is false if the
final floor union still lets the player switch lanes. The final uninstrumented
play check must finish every branch and attempt each claimed blocked switch;
testing only one branch does not prove a meaningful route decision.

Every `gameConfig.json` leaf must have one literal runtime consumer. Do not keep
aliases for the same value: if pickup code moves from
`levelConfig.collectRadius` to another path, delete the old leaf in the same
edit. The current linear fog consumes `renderConfig.fogNear` and `fogFar`; do
not add `fogDensity` unless the implementation changes and the superseded
linear-fog leaves are removed. Derive authored counts from `SceneMap` arrays
unless a separately consumed completion threshold is required.
Camera near/far values are source literals unless the final camera constructor
or update path reads an exact named config leaf. Fog distance and DPR fields do
not make a camera far plane config-backed.

## 5. GDD completion notes

The GDD must end with:

- the actual generated keys and their runtime consumers;
- a config leaf-to-consumer table with no duplicate or unconsumed leaf;
- any placeholder/fallback used;
- `3D scope: primitives + generated image textures; no model generation`;
- the command evidence from build and smoke.
- the final feasibility ledger totals and observed win/lose terminal states.

After Phase 6 changes, reconcile the GDD body itself against the final
`SceneMap`, config, asset-pack, and uninstrumented playthrough. Correct stale
numbers and consumers in place; an appendix may explain why a value changed,
but must not leave an older contradictory value as a second truth.

Treat each `gameConfig.json` description as part of that final truth. If a
consumer changes from a config leaf to a literal or another leaf, correct the
description and every GDD consumer table instead of leaving the old consumer
claim behind.

Implementation details need source anchors, not memory. Before keeping an
internal variable name, numeric mesh position, or texture behavior such as UV
repeat in the GDD, copy it from the final runtime source and verify that exact
consumer still exists. Otherwise state only the stable player-visible behavior;
delete invented implementation detail instead of preserving a plausible claim.

## 6. Verification integrity

Acceptance must test the declared win condition without strengthening or
replacing it. Optional collectibles, checkpoints, and side objectives cannot
become pass gates unless the prompt explicitly makes them required.

A complete-playthrough PASS must run against the final uninstrumented artifact.
Read-only diagnostic probes may explain a failure, but they cannot be required
for the final PASS. Save screenshots as files and report their paths; use the
official smoke pixel/WebGL assertions instead of reading screenshots back into
the generation session.
115 changes: 115 additions & 0 deletions agent-test/docs/modules/threed_basic/template_api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# threed_basic Template API

## Scaffolded files

| File | Contract |
|---|---|
| `src/main.ts` | boots title, runtime, DOM HUD, pause, completion, render loop |
| `src/GameScene.ts` | owns renderer, scene, camera, world, and private gameplay state |
| `src/CollisionResolver.ts` | pure XZ road/obstacle movement resolution with substeps |
| `src/InputController.ts` | keyboard + mouse state only |
| `src/SceneMap.ts` | Editor-facing declarative positions via `initSceneMap()` |
| `src/ThreeSceneDefaults.ts` | shared light, fog, and background defaults |
| `src/gameConfig.json` | wrapped `{ value, type, description }` tuning fields |

## `GameScene` constructor

```ts
new GameScene(container, {
onProgress(collected, total) {},
onComplete() {},
onGameOver() {},
}, preloader.textures);
```

Required public methods:

| Method | Meaning |
|---|---|
| `update(deltaSeconds)` | advance input, collection, animation, and render |
| `setPaused(boolean)` | stop/resume simulation and clear held input |
| `isPaused()` | smoke/lifecycle observable pause state |
| `dispose()` | unbind input and release scene-owned geometry, material, renderer, and canvas resources before instance replacement |
| `resize()` | update camera aspect and renderer size |

`GameScene.dispose()` owns input listeners, geometry, materials, renderer state,
and its canvas. `Preloader` owns the shared texture map, so scene replacement
must not dispose those textures before the next scene reuses them.

## Smoke bridge

`window.__opengame3d` is an exact, read-only probe surface:

```ts
{ isPaused: () => boolean; renderer: 'three.js' }
```

Do not add `teleport`, time setters, collectible setters, mutable `state`, or
other gameplay shortcuts. Build, pause, completion, failure, and restart must
be verified through keyboard/mouse events and the visible DOM. Test time limits
with browser clock control or a pure unit check, not a shipped runtime setter.

## SceneMap

The reference `initSceneMap()` returns `playerSpawn`, `floorPatches`,
`collectibles`, and `obstacles`; its collection loop is a working fallback, not
a required genre. Change positions there instead of hard-coding level
coordinates inside the render loop. Add or replace declarative arrays at the
`// EXT` point only when the chosen Core Gameplay Contract has a real consumer.
Keep the public lifecycle API while implementing the smallest private state
needed by that loop.

Each obstacle declares `collisionRadius` independently from visual `scale`.
`resolveMovement()` keeps the full player circle inside at least one floor
patch, subdivides long moves to prevent tunnelling, and slides along an
unblocked axis. Dynamic bodies, impulses, and gravity remain v2 concerns.

For a single authored route, neighboring patches are ordered path segments, not
an arbitrary set. After subtracting the player radius from both patch radii,
their intersection half-width must remain at least two player radii. Spawn,
required pickup centers, and the finish center must pass the same floor and
expanded-obstacle predicate used by `resolveMovement()`.

For a branched route, array order no longer declares adjacency. Record intended
neighbor pairs and forbidden cross-lane pairs in the GDD, then test them against
the final floor union and expanded obstacles. If a supposedly committed branch
can cross into another lane, the decision contract is not implemented.

## Config ownership

The shipped config is a starting contract, not a compatibility registry. Keep
one leaf per runtime value and require a literal consumer for every leaf. When
renaming or regrouping a field, update its consumer and delete the old field in
the same change. Do not preserve unused 2D infrastructure fields in a 3D game.

Before build, search every config leaf outside `gameConfig.json`. A leaf with no
consumer is a failed implementation check, not a harmless preset.

## Texture keys

`Preloader` reads Phaser-compatible `asset-pack.json` sections and loads image
entries into `Map<string, THREE.Texture>`. The reference module recognizes
these fallback keys. A chosen loop may add semantic image keys when the final
`GameScene` consumes each one:

| Key | Fallback |
|---|---|
| `skybox_texture` | dark blue `Color` background |
| `floor_patch` | rough blue material |
| `energy_billboard` | emissive sphere primitive |

Missing optional textures must not throw or block the game.

## Pause data contract

Both `UIScene.init()` and `PauseUIScene.init()` accept:

```ts
{ gameSceneKey?: string; currentLevelKey?: string }
```

Resolve in this exact order:

```ts
data.gameSceneKey ?? data.currentLevelKey ?? LevelManager.getFirstLevelScene()
```
Loading