Files
Sylpheed/docker/agent/AGENT.md
Sylpheed RE agent ecbd70f69a port: the container agent answers the questions, it does not build the port
Corrects the split I got wrong in b5a1938. The container is for reverse
engineering, now focused on the menu port; a SEPARATE agent builds the port from
its investigation results. My previous version had the container agent writing
the exporter and the Godot project, which is not the intent.

This lands on the research/engineering line that was already in the estimate:
the container agent takes the research half, the port agent the engineering half.

docs/port/MISSION.md is now a list of open QUESTIONS (Q1-Q9) rather than build
milestones, ordered by what blocks the port earliest -- the keyframe time unit,
which build is which screen state, paint order for the six screens, button ->
GamePart, navigation semantics, the boot sequence driver, transitions, menu
audio bindings, and video binding. Each is done when a written result with
evidence exists, not when something compiles. S1, the Ready Room probe, stays
gated at one iteration and a go/no-go.

Most of these are BEHAVIOUR questions -- timing, transitions, what a d-pad press
does at the end of a list -- so the mission and the loop prompt both push hard
on measuring the oracle rather than reasoning from the file.

docs/port/FORMAT.md is deleted. The export schema is the port agent's design and
was not mine to specify. It is replaced by docs/port/HANDOFF.md, the single page
the port agent reads: a status table, what is already settled and can be relied
on today, and the facts that will trip the port up (the WMV3/WMA Pro intro, the
Static.slb size over-declaration, the voice-vs-music downmix, JNGL_001).

The derived/authored idea survives as the thing it always was -- a finding, not
a design. Every answer must be classified DECODED, MEASURED or UNDECODABLE-with-
reach, and never a fourth thing, because measured and undecodable both mean the
port agent is authoring that value and has to know it. Labelling a guess as a
decode would put it into the port wearing the badge of a measurement.

Reverts the Godot install from the RE container, its AGENT.md section, and the
export/ gitignore entry -- none of that belongs on this side of the wall.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-28 17:16:47 +02:00

3.0 KiB

Notes for an agent working inside this container

Read this before starting a dynamic-RE run. Everything here is something that already went wrong once.

The container fixes three old traps for you

  • The display outlives the turn. Xvfb and openbox are children of PID 1, not of your shell. The old "Xvfb dies on its own every few minutes" note is gone — you no longer have to wrap a whole session in one blocking foreground call to keep it alive.
  • The toolchain is real. tools/re-capture/rebuild_canary.sh exists because the old box had no cmake/ninja/clang and only runtime sonames, so it hand- relinked object files. Do not use it here. Use build-canary.
  • numpy and Pillow are installed. entities2.py, flight_probe.py and the image oracles work. Their absence used to look like a logic bug.

Method (the part that matters more than the tooling)

  • Measure the oracle; never infer it. A session with zero Canary runs is a red flag.
  • Trace upstream to where data first goes wrong, rather than patching the symptom you can see.
  • Try to refute before believing. Record demotions rather than editing them away — docs/re/README.md has the /🟡/ convention, and a withdrawn result is more useful than a quietly deleted one.
  • A probe that never performs the action will "prove" the action does not exist. The "targeting is automatic" conclusion came from a sweep that only ever tapped once; target select is Ⓐ pressed twice.
  • Do not poll faster than the guest updates — it manufactures a clean curve out of noise. rate-curve-aliased-BAD.csv is committed as the bad example.

Running the emulator

run-canary                       # correct audio/pad/display flags baked in
pad.py tap A ; pad.py dpad down  # scripted input (--hid=file, no uinput)
screenshot ~/shots/now.png       # cropped to the GAME surface, not the window
python3 tools/re-capture/gmem.py find hex:820af844 400
  • One emulator at a time. run-canary enforces it with a lockfile.
  • Boot is slow cold, ~25 s once the shader/code caches are warm — so a launch-and-dump fits in a single call.
  • Screens: classify by whole-image statistics (screen_id.py), not named pixels. Named-pixel oracles are only valid while the game image sits at a known place, and nothing errors when it moves.

Verifying your own work

  • Reborn's disc-gated tests self-skip without SYLPHEED_DISC. A green run with it unset means almost nothing. build-reborn test wires it up for you.
  • Prefer a headless self-verify over "it compiles": sylpheed-cli mesh render, screen render, save info all produce checkable artifacts.
  • A Bevy system-parameter conflict is invisible to the type checker and panics at startup. If you touch viewer systems, run the binary, don't just build it.

Reporting

State what you measured, what you assumed, and what you could not settle. If a result is withdrawn, say so and keep the reasoning — that is the corpus's whole convention, and the reason its numbers can be trusted.