Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
edd210a
Add ClayInspector for file-based QML introspection
MisterGC Mar 28, 2026
abf6f22
Add ClayInspector unit and integration tests
MisterGC Mar 28, 2026
5158fd4
Add Clay Crew: flag overlay, enriched tree, find(), trace, docs
MisterGC Mar 30, 2026
6302f7d
Fix Box2D debug draw, Circle convention, and debug flags
MisterGC Mar 31, 2026
a58c56e
Add ChipMood procedural music generator with desktop SoftSynth
MisterGC Apr 2, 2026
8d97a11
Add GridPathfinder plugin and NavigateTo behavior
MisterGC Apr 2, 2026
a032144
ClayWorld2dCamera with follow and look-ahead modes
MisterGC Apr 6, 2026
8718014
Replace ChipMood with ChipTracker step sequencer and extend SoftSynth
MisterGC Apr 11, 2026
2f07cb0
Rewrite chipmood sandbox as ChipTracker step sequencer
MisterGC Apr 11, 2026
c128ca1
Inspector: attach diagnostics to null-root snapshot/eval/tree responses
MisterGC Apr 18, 2026
d1c724e
Inspector: capture QML load errors on initial load and across reloads
MisterGC Apr 18, 2026
7a43462
Inspector: publish lifecycle state to .clay/inspect/state.json
MisterGC Apr 18, 2026
af0c111
Dojo: crash-loop guard with exponential backoff and machine-readable …
MisterGC Apr 18, 2026
896ca29
Inspector: append-only events.jsonl with bounded rotation
MisterGC Apr 18, 2026
288e789
Inspector: echo requestId and commit response.json atomically
MisterGC Apr 18, 2026
e3a1d6b
Inspector: add reload and waitForRoot actions for deterministic timing
MisterGC Apr 18, 2026
2d97f1a
clay_sound: add engine spine (note event, voice, instrument, schedule…
MisterGC Apr 18, 2026
66a7078
clay_sound: move per-note DSP into OscillatorVoice/Instrument; SoftSy…
MisterGC Apr 18, 2026
33ab5db
clay_sound: add SynthInstrument QML type with one-shot trigger + sand…
MisterGC Apr 18, 2026
a728acd
clay_sound: add SampleInstrument + PCM engine types; reimplement Soun…
MisterGC Apr 18, 2026
d072f37
clay_sound: wire ChipMood + MoodPlayer into plugin, add PcmBuffer::sa…
MisterGC Apr 18, 2026
2ffc2e5
dojo: add .dojoignore to exclude sandbox-dir files from reload [#113]
MisterGC Apr 18, 2026
5b766d1
clay_sound: add Song data model + JSON parser + unit tests [#113]
MisterGC Apr 18, 2026
e62a40e
clay_sound: add SongPlayer (play/pause/stop/seek/loop) + tests [#113]
MisterGC Apr 18, 2026
24e2987
clay_sound: SongPlayer hot-reload preserves playhead [#113]
MisterGC Apr 18, 2026
cd32a9f
clay_sound: add SynthInstrument.bake() synth-to-sample helper [#113]
MisterGC Apr 18, 2026
f372b5e
clay_sound: extend sandbox with Pattern/Bake/Status labs + demo song …
MisterGC Apr 18, 2026
dd29434
clay_sound: document SynthInstrument, SampleInstrument, SongPlayer [#…
MisterGC Apr 18, 2026
860ad25
clay_sound: sandbox Studio tab — sample bank + tracker + genre preset…
MisterGC Apr 18, 2026
d20e9e8
clay_sound: Studio retro widget library (stage 5a) + F1 help + Vim to…
MisterGC Apr 19, 2026
2b2baa7
clay_sound: Studio sample bank uses 4 live SlotPanels (stage 5b) [#113]
MisterGC Apr 19, 2026
2ad1317
clay_sound: stack SlotPanels as rack-mount rows (stage 5b.1) [#113]
MisterGC Apr 19, 2026
2bd9ca8
clay_sound: chunky low-res scope + step graph (pixel blocks, v-snap) …
MisterGC Apr 19, 2026
fbc6410
clay_sound: retro transport + cartridge preset row + BOSS FIGHT (stag…
MisterGC Apr 19, 2026
dc43dcd
clay_sound: tracker polish — playhead glow + trail + bar bands (stage…
MisterGC Apr 19, 2026
b188195
clay_sound: split studio demo into studio/ subdir, add preview loop +…
MisterGC Apr 19, 2026
7bf7d19
clay_sound studio: vim cursor, normal/insert/append/replace modes for…
MisterGC Apr 19, 2026
4878486
clay_sound studio: pulsing cursor halo, jump (f) labels, audition not…
MisterGC Apr 19, 2026
cc1e052
clay_sound studio: home-row jump labels, focus mode (j/k adjust), und…
MisterGC Apr 19, 2026
ec9edd9
clay_sound studio: fix jump action clobbering focus submode [#113]
MisterGC Apr 19, 2026
885f9c9
clay_sound studio: add d{h,j,k,l} jump for slot secondary knob (DECAY…
MisterGC Apr 19, 2026
88f662c
clay_sound studio: <Space> globally toggles play in any mode except i…
MisterGC Apr 19, 2026
2f79e83
clay_sound studio: use Shortcut for vim entry keys to survive focus t…
MisterGC Apr 19, 2026
38871ab
clay_sound: remove studio demo, migrated to standalone chiptrack repo…
MisterGC Apr 19, 2026
cdae2a5
clay_sound: extract Voice waveform enum to unblock WASM build [#113]
MisterGC Apr 21, 2026
8b69260
clay_sound: unify desktop and WASM audio path via Qt Multimedia [#113]
MisterGC Apr 21, 2026
e1845e2
docs: bump addressable to 2.9.0 to address CVE [#113]
MisterGC Apr 21, 2026
f26bb60
docs: fix Gemfile.lock dep range for addressable 2.9.0 [#113]
MisterGC Apr 21, 2026
5169eea
clay_sound: replace M_PI with local constant for MSVC portability [#113]
MisterGC Apr 21, 2026
9ff5e84
clay_sound: skip hot-reload tests on Windows (flaky QFileSystemWatche…
MisterGC Apr 21, 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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ docs/webdojo-examples/*/
!docs/webdojo-examples/welcome/
docs/webdojo-examples/index.json

# Clay Crew inspect/crew session data
.clay/

# Temp/personal files
aqtinstall.log
test_simple.qml
Expand Down
4 changes: 2 additions & 2 deletions docs/Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
GEM
remote: https://rubygems.org/
specs:
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
addressable (2.9.0)
public_suffix (>= 2.0.2, < 8.0)
base64 (0.3.0)
bigdecimal (3.2.2)
colorator (1.1.0)
Expand Down
2 changes: 2 additions & 0 deletions docs/_data/docs_nav.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
children:
- title: Dojo - Live Reloading
url: /docs/manual/dojo/
- title: Inspector
url: /docs/manual/inspector/
- title: Logging Overlay
url: /docs/manual/logging/
- title: Plugin Development
Expand Down
158 changes: 158 additions & 0 deletions docs/clay-crew-concept.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
# Clay Crew — AI-Agent Collaboration for Clayground

**Closing the feedback loop between AI agents and interactive applications.**

---

## 1. The Problem

Clayground's dev loop is built for humans: edit QML, the Dojo reloads, you see the result. AI agents cannot see. They can write QML but have no way to verify the result — did the dungeon render? does the enemy move? does combat work?

Even for humans, the feedback loop has gaps: you can see the screen but can't easily answer "what's the player's exact health?" or "did the boss AI transition states correctly over the last 10 seconds?"

## 2. The Solution

An **in-app inspector** with a file-based protocol, plus **query functions on the canvas/world** components. The inspector handles generic concerns (protocol, screenshots, tracing). The canvas/world handle domain-aware queries (spatial search in the right coordinate system).

### Why file-based?

1. **Zero dependencies** — no HTTP server, no socket library, no port management
2. **Debuggable** — `cat .clay/inspect/response.json` shows exactly what the agent sees
3. **Composable** — any tool that reads files can consume the output
4. **No port conflicts** — works in Docker without networking configuration
5. **Persistent** — snapshots and traces are saved for post-hoc review

### Why in-app?

An external tool would need to connect to a debug port and speak an undocumented binary protocol. The in-app inspector simply calls `grabToImage()`, reads properties via `QMetaObject`, and evaluates expressions via `QQmlExpression` — everything is already available in-process.

## 3. Architecture

```
┌─────────────────────────────────────────────────────────────┐
│ Dojo Process │
│ │
│ ┌──────────────┐ ┌────────────────────────────────────┐ │
│ │ Sandbox.qml │ │ ClayInspector (C++) │ │
│ │ (the app) │ │ │ │
│ │ │ │ • file protocol (request/response) │ │
│ │ flagInfo() │ │ • snapshot, eval, tree, trace │ │
│ │ (optional) │ │ • screenshot capture │ │
│ │ │ │ • log/warning/error capture │ │
│ │ ┌────────┐ │ │ • Ctrl+F flag, Ctrl+T trace │ │
│ │ │Canvas/ │ │ │ │ │
│ │ │World2d │ │ └────────────────────────────────────┘ │
│ │ │ │ │ │
│ │ │ find() │ │ .clay/inspect/ │
│ │ │(QML/JS)│ │ ├── request.json (agent writes) │
│ │ └────────┘ │ ├── response.json (inspector writes) │
│ └──────────────┘ ├── screenshot.png │
│ └── trace.jsonl │
│ │
│ .clay/crew/ │
│ ├── flag_<ts>.json (Ctrl+F) │
│ └── flag_<ts>.png │
└─────────────────────────────────────────────────────────────┘
```

### What lives where

| Component | Responsibility | Why there |
|-----------|---------------|-----------|
| **ClayInspector** (C++, tools/loader/) | Protocol, eval, tree dump, trace, screenshots, flags | Needs QTimer, file I/O, QMetaObject introspection, message handler access |
| **ClayCanvas.find()** (QML/JS, plugins/clay_canvas/) | Spatial/conditional entity search (2D) | Knows pixelPerUnit, world bounds, Y-axis inversion, content children |
| **ClayWorld2d.find()** (QML/JS, plugins/clay_world/) | Override with physics-aware search | Knows Box2D world, can enrich with velocity/body state |
| **flagInfo()** (user's Sandbox.qml) | Domain-specific state snapshot | Only the developer knows what matters for their app |

## 4. Inspector Actions

### snapshot — Point-in-time state

Returns: `rootProperties` (auto-captured), `flagInfo` (if defined), `eval` results, `logTail`, `warnings`, `errors`, optional screenshot.

### eval — Expression evaluation

Evaluates JS/QML expressions in the sandbox root context. Bridges to `canvas.find()` and any QML function.

### tree — Structural dump with LOD

Two detail levels: **overview** (compact, used in flags) and **full** (adds vector properties, state, childrenRect). Smart property filtering skips Qt framework noise, keeps only app-level state. Truncation summaries surface rare/named items in large child lists.

### find — Spatial/conditional search (via eval → canvas.find)

Defined on ClayCanvas, overridable by World2d/3d. Filter by type, objectName, distance (world units), and arbitrary JS conditions. Distance is unambiguous — the canvas owns the coordinate system.

### trace — Temporal observation

Records watched expressions at configurable intervals to JSONL. Stops on a condition (`stopWhen`), timeout, or manual request. Returns a summary with first/last/min/max/changes per expression. Enables behavioral verification without screenshots.

## 5. Human Interaction

### Ctrl+F — Flag a Moment

Screenshot freeze → type annotation → saves flag JSON (annotation + state + tree) and PNG. Max 5 flags retained. The agent reads flags to understand what the human saw and what needs fixing.

### Ctrl+T — Toggle Trace

Starts/stops the currently configured trace. The agent configures what to watch; the human controls when to record.

### flagInfo() — Developer-Defined State

Optional function on the sandbox root. Returns domain-specific state the framework can't infer. Called at snapshot/flag time.

## 6. The Autonomous Agent Workflow

```
1. Edit QML
2. qmllint ──────── syntax/type errors? ──→ fix
3. snapshot ─────── "No sandbox root"? ──→ engine crash
│ (unknown component, missing import,
│ circular dependency — linting can't
│ catch these)
4. eval + find ──── entities exist? structure correct?
│ positions right? state as expected?
5. trace ────────── behavior correct over time?
│ stop condition met? (= success)
│ or timeout? (= bug)
6. ✓ Verified ──── commit / move on
```

Each layer is more expensive than the previous. The agent stops at the first layer that gives confidence.

## 7. The Collaborative Workflow

```
Human Agent
│ │
│ Ctrl+F: "skeleton stuck here" │
│ ──────────────────────────────→ │
│ │ reads flag JSON + tree
│ │ uses find() to locate skeleton
│ │ fixes pathfinding code
│ │
│ │ sets up trace on skeleton.state
│ Ctrl+T: starts trace │
│ plays game, lures skeleton │
│ Ctrl+T: stops trace │
│ ──────────────────────────────→ │
│ │ reads trace summary
│ │ identifies the stuck transition
│ │ fixes the bug
```

## 8. File Protocol — Synchronization

`response.json` is the **single synchronization point**. The agent writes `request.json` and watches for `response.json` to change.

During a trace, do NOT read `trace.jsonl` — it is being actively written. Wait for the trace to stop (response.json updates with summary). Only then is `trace.jsonl` safe to read.

No race conditions: all inspector logic runs on the Qt main event loop (single-threaded).

---

*Concept based on Clayground's Clay Crew implementation, March 2026.*
47 changes: 47 additions & 0 deletions docs/docs/manual/dojo.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ Dojo is the primary development tool for Clayground projects. It monitors your s
|----------|--------|
| `Ctrl+G` | Toggle guide overlay |
| `Ctrl+L` | Toggle logging overlay |
| `Ctrl+F` | [Flag a moment]({{ site.baseurl }}/docs/manual/inspector/#ctrlf--flag-a-moment) — screenshot + annotation |
| `Ctrl+T` | [Toggle trace]({{ site.baseurl }}/docs/manual/inspector/#ctrlt--toggle-trace) recording |
| `Ctrl+1` to `Ctrl+5` | Switch between loaded sandboxes |

## How Live-Reloading Works
Expand All @@ -50,6 +52,50 @@ At the heart of Dojo is a sophisticated hot-reload system. When you save a QML f

The 50ms debounce window catches rapid file changes from editor auto-saves.

## Ignoring Files — `.dojoignore`

Dojo watches the sandbox directory recursively, so **any** file change in
that tree (including data files your sandbox edits live, song sources,
generated caches, etc.) triggers a full scene reload. For files that your
sandbox handles itself at runtime — e.g. a song file being hot-reloaded
by `SongPlayer` — that full reload is counter-productive: it drags the
playhead back to zero and throws away the live state you were tuning.

Drop a `.dojoignore` file next to your `Sandbox.qml` to exclude paths
from the reload trigger. Same spirit as `.gitignore`:

```text
# ignore a single file, anywhere under the sandbox dir
notes.txt

# ignore all song sources
*.song.json

# ignore an entire subdirectory and its contents
songs/

# anchor to the sandbox dir (exact path)
data/level1.json
```

Semantics:

| Pattern | Matches |
|--------------------------|----------------------------------------------------------------|
| `name` | any file/dir named `name` under the sandbox tree |
| `*.ext` | basename wildcard, matches in any subdirectory |
| `name/` | the directory and everything beneath it |
| `sub/file.txt` | path-anchored (no match on `other/sub/file.txt`) |
| `/file.txt` | path-anchored (leading `/` optional; same meaning as above) |
| `**` | any number of path segments |

Comments start with `#`; blank lines are ignored. The file is re-read
automatically when you save it, so you can add/remove patterns without
restarting the dojo.

`.dojoignore` only ever *subtracts* from the watched set — it cannot make
the dojo watch files it would otherwise miss.

## Dynamic Plugin Development

Beyond QML hot-reloading, Dojo supports live development of C++ plugins:
Expand All @@ -71,5 +117,6 @@ The format is `--dynplugin <source_dir>,<binary_dir>`. Dojo detects when your pl

## Next Steps

- Use the [Inspector]({{ site.baseurl }}/docs/manual/inspector/) for structured state snapshots and flagging moments
- Learn about the [Logging Overlay]({{ site.baseurl }}/docs/manual/logging/)
- Create your own [plugins]({{ site.baseurl }}/docs/manual/plugin-development/)
1 change: 1 addition & 0 deletions docs/docs/manual/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ The Clayground manual covers the development tools and workflows in detail.
## Development Tools

- **[Dojo - Live Reloading]({{ site.baseurl }}/docs/manual/dojo/)** - The primary development environment with hot-reload
- **[Inspector]({{ site.baseurl }}/docs/manual/inspector/)** - File-based introspection, snapshots, and flagging moments
- **[Logging Overlay]({{ site.baseurl }}/docs/manual/logging/)** - Real-time debugging and property watching
- **[Plugin Development]({{ site.baseurl }}/docs/manual/plugin-development/)** - Creating your own Clayground plugins

Expand Down
Loading
Loading