Compare commits

...
Author SHA1 Message Date
02f4564442
fix(examples): restart ball ids when the scene is cleared
World_Reset kept counting, so after one reset the ball dropped from
60 m was ball 10, not the ball 5 the plain build's output and the log
from before the reset name. The agent in the first check noticed and
worked around it. Clear now restarts ids at 1, so Reset brings back
balls 1 to 5.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 18:24:35 +01:00
8e7f8c5f3b
fix(tooling): build first, then start the app, then list it
The notes had agents start `crafter-build <flag> -r` in the background
and run `crafter-debug ls --wait 60s` straight after. That raced the
build: the first agent to follow them ran the plain build's stub, which
said "no debug build yet" and exited, since the client `ls --wait` needs
is one of the things the debug build compiles, and it polled by hand
until the build was done.

The race came from the order, so the order changes: build with the flag
in the foreground, which ends once the app and the client are built,
then start the app with -r in the background, then `ls --wait`, which
now only waits for what it is for, the app registering. A launcher that
polls for the build instead was tried and dropped: a shell loop that
reruns itself each second, and waits out its whole --wait when no build
is coming at all.

The consumer notes, the client's guide and the README say so, and the
stub and the not-yet-built launcher name the step that was skipped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 18:24:35 +01:00
6 changed files with 17 additions and 11 deletions

View file

@ -12,7 +12,8 @@ Runtime debugging for AI agents, and for people. An app built with Crafter.Debug
Breakpoints and memory stay with a debugger; `crafter-debug debugger` prints how to attach one. Breakpoints and memory stay with a debugger; `crafter-debug debugger` prints how to attach one.
```console ```console
$ crafter-build --debug-api -r & # the app's debug build, in the background $ crafter-build --debug-api # the app's debug build, and the client with it
$ crafter-build --debug-api -r & # the app, in the background
$ ./build/crafter-debug ls --wait 60s $ ./build/crafter-debug ls --wait 60s
game id 4f1c09a2b7e3d851 pid 3 (sandbox 48211) up 4s port 41207 game id 4f1c09a2b7e3d851 pid 3 (sandbox 48211) up 4s port 41207
$ ./build/crafter-debug call Lobby_Start && ./build/crafter-debug wait --frames 30 $ ./build/crafter-debug call Lobby_Start && ./build/crafter-debug wait --frames 30

View file

@ -16,6 +16,7 @@ void Basic::World::Reset() {
void Basic::World::Clear() { void Basic::World::Clear() {
balls.clear(); balls.clear();
nextId = 1;
time = 0; time = 0;
fastest = 0; fastest = 0;
} }

View file

@ -43,8 +43,9 @@ export namespace Basic {
Physics physics; Physics physics;
Floor floor; Floor floor;
// Removes every ball and drops the scene's five. // Removes every ball and drops the scene's five, as balls 1 to 5.
void Reset(); void Reset();
// Removes every ball; ids start again from 1.
void Clear(); void Clear();
// Returns the new ball's id. // Returns the new ball's id.
std::int32_t Spawn(float x, float y, float vy, float radius); std::int32_t Spawn(float x, float y, float vy, float radius);

View file

@ -974,13 +974,15 @@ memory are a debugger's job; `crafter-debug debugger` prints how to attach one.
## The loop ## The loop
1. Build and start the app from its debug build, in the background (it does 1. Build with the debug flag, in the foreground: `crafter-build --debug-api`
not exit): `crafter-build --debug-api -r` (use the project's own flag). (use the project's own flag). That build compiles this client too.
2. `./build/crafter-debug ls --wait 60s` until it is listed. 2. Start the app in the background, since it does not exit:
3. `cmds` and `help <command>` to see what it offers, `get '*'` for its state. `crafter-build --debug-api -r`.
4. Act and observe: `call`, `set`, `pause --when`, `wait`, `step`, `trace`, 3. `./build/crafter-debug ls --wait 60s` until it is listed.
4. `cmds` and `help <command>` to see what it offers, `get '*'` for its state.
5. Act and observe: `call`, `set`, `pause --when`, `wait`, `step`, `trace`,
`log --level warn`, `screenshot` (open the PNG it prints with Read). `log --level warn`, `screenshot` (open the PNG it prints with Read).
5. `quit` when done. Killing the background task may leave the app running 6. `quit` when done. Killing the background task may leave the app running
if crafter-build's alias lacks --die-with-parent; `ls` shows leftovers. if crafter-build's alias lacks --die-with-parent; `ls` shows leftovers.
## Commands ## Commands

View file

@ -4,7 +4,8 @@ This app can be driven while it runs: call its commands, read and set its state,
### Driving it ### Driving it
- Start the debug build in the background, since it does not exit: `crafter-build <debug flag> -r`. - Build with the debug flag first, in the foreground: `crafter-build <debug flag>`. That build also compiles the client `./build/crafter-debug` runs. The first one takes a few minutes.
- Then start the app in the background, since it does not exit: `crafter-build <debug flag> -r`.
- From the project directory, use `./build/crafter-debug`: - From the project directory, use `./build/crafter-debug`:
- `ls --wait 60s` until it is listed; `status`, `cmds`, `help <command>`, `get '*'` - `ls --wait 60s` until it is listed; `status`, `cmds`, `help <command>`, `get '*'`
- `call <command> key=value ...`, `set <path> <value>` - `call <command> key=value ...`, `set <path> <value>`

View file

@ -87,7 +87,7 @@ namespace Crafter::Debug {
"# project with {0}: runs the crafter-debug client that build compiled.\n" "# project with {0}: runs the crafter-debug client that build compiled.\n"
"client={1}\n" "client={1}\n"
"if [ ! -x \"$client\" ]; then\n" "if [ ! -x \"$client\" ]; then\n"
" echo \"crafter-debug: the client is not built yet; build with: crafter-build {0}\" >&2\n" " echo \"crafter-debug: the client is not built yet; let crafter-build {0} finish first, which builds it with the app\" >&2\n"
" exit 2\n" " exit 2\n"
"fi\n", "fi\n",
flag, ShellQuote(client.string())); flag, ShellQuote(client.string()));
@ -113,7 +113,7 @@ namespace Crafter::Debug {
return std::format( return std::format(
"#!/bin/sh\n" "#!/bin/sh\n"
"# Written by Crafter.Debug (Debug::Use): this project has no debug build yet.\n" "# Written by Crafter.Debug (Debug::Use): this project has no debug build yet.\n"
"echo \"crafter-debug: no debug build yet; build with: crafter-build {}\" >&2\n" "echo \"crafter-debug: no debug build yet; build with: crafter-build {0}, then start the app in the background with: crafter-build {0} -r\" >&2\n"
"exit 2\n", "exit 2\n",
flag); flag);
} }