Files
Sylpheed/docker/agent/loop-task.md
Sylpheed RE agent 965c3f70fd port: make the Godot menu shell the agent's primary objective
Sets a new mission: boot the real disc through developer splash -> intro video
-> title -> main menu -> submenus in Godot 4, interactively, with no gameplay,
no 3D and no emulator.

docs/port/MISSION.md defines it -- eight gated milestones, each finished by an
ARTIFACT rather than by compiling, plus the Ready Room as an explicitly gated
stretch goal with a one-iteration probe that decides go/no-go. GP_READY_ROOM is
1106 entries with 6 recoverable names and is ISL-scripted, so it is either a
week or a quarter, and the agent must not start it on its own authority.

Architecture, per the user's decision: the Godot project is INDEPENDENT of the
Rust viewer and never reads a disc format. An offline Rust exporter converts the
disc into open formats; Godot reads only those. No GDExtension, no Rust in the
Godot project, and sylpheed-viewer is off limits -- it stays the human's
verification tool with its static-data rule intact.

docs/port/FORMAT.md specifies the open format, versioned, because modding is the
port's second goal and that makes the layout a deliverable rather than a temp
directory: JSON over XML (Godot parses JSON natively; its XMLParser is SAX),
names never hashes, provenance in every generated file, and unknowns listed
rather than guessed.

The discipline the whole thing rests on is the derived/authored split. `export/`
is regenerated wholesale and never hand-edited; `authored/` is hand-written and
survives a re-export. Three things this milestone needs are NOT on the disc in
any decoded form -- which button does what, paint order, and menu sound cues --
so they live in `authored/` with a stated `why`. Deleting an authored entry
because the exporter can now emit it IS the measure of progress.

`export/` is gitignored: it is generated from the user's own disc and this stays
a clean-room repo.

Container: adds a pinned Godot 4 (windowed under Xvfb for screenshots, plus a
headless wrapper). ffmpeg already carries libtheora, which is the video target --
Godot 4 plays only Ogg Theora natively and the disc's ADV.wmv is WMV3/WMA Pro.

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

111 lines
5.5 KiB
Markdown

Build the Godot menu port of Project Sylpheed, one milestone at a time.
## Your objective
`Syplheed-Reborn/docs/port/MISSION.md` — read it every iteration. It defines the
milestones (P0…P7 plus a gated S1), the gate each one must pass, and the two
decisions already made. Work the **lowest unfinished milestone**; do not skip
ahead because a later one looks more interesting.
Reverse engineering has not stopped, but it is no longer the goal. An RE item
earns attention when the port is blocked on it, and the write-up still goes in
`docs/re/` under the usual convention.
## Read these first, every iteration
Short on purpose, and the reason this prompt is short:
1. `docs/port/MISSION.md` — the objective, the milestones, what is out of scope.
2. `docs/port/FORMAT.md` — the export schema. It is **versioned**; changing it is
a deliberate act with a version bump, not a silent edit.
3. `docs/re/REFUTED.md` — claims already tested and dead. Grep it for your nouns
before designing anything.
4. `docs/re/METHOD.md` — the traps this corpus has already paid for.
5. `docs/re/INDEX.md` — what is already decoded. Re-deriving a ✅ row is not a
finding.
6. `docker/agent/AGENT.md` — the container's tooling.
`docs/re/disc-atlas.html` is the map of how the assets reference each other —
useful when you need to find what feeds what.
**These files are the memory.** A finding that lives only in your context is lost
when the container dies.
## Each iteration
1. **Pick the lowest unfinished milestone** from MISSION.md. If you are mid-item,
continue it rather than starting another.
2. **Build the smallest thing that reaches its gate.** The gate is an *artifact*
a validating JSON file, a screenshot, a human-clickable build — never "it
compiles".
3. **Keep derived and authored apart.** `export/` is regenerated wholesale and is
never hand-edited; `authored/` is hand-written and survives a re-export. If you
are tempted to hand-fix a file under `export/`, the fix belongs in the exporter
or in `authored/`. Every `authored/` entry carries a `why`.
4. **Write down what you learned** — in `docs/port/` for port decisions, in
`docs/re/` for anything about the disc.
* Refuted something → a line in `REFUTED.md`.
* Bitten by a general trap → a line in `METHOD.md`.
* Closed a format → update its `INDEX.md` row.
5. **Commit** to `auto/<topic>`, one logical change per commit.
6. **Publish**: `push-work`. Every iteration that produced a commit.
7. **Say plainly what you did not settle**, and stop.
## Hard rules
* **Never commit game assets.** `export/` is generated from the user's own disc
and is gitignored. Code, schemas, authored mappings and docs only. If you are
about to commit a sprite PNG or a transcoded video, stop.
* **No Rust in the Godot project, no GDExtension.** If Godot cannot read
something, the exporter emits it differently. The wall between the two halves is
the design, not an inconvenience.
* **Do not touch `crates/sylpheed-viewer`.** The Explorer is the human's
verification tool, it is independent of the port, and it keeps its
static-data-only rule. Do not refactor it to share code with the exporter.
* **Never commit to `main`**, never rebase a shared branch, never delete a branch,
never rewrite history.
* **Do not touch another agent's worktree.** `git worktree list` first; branches
marked `+` are checked out elsewhere.
* **One emulator at a time** — `run-canary` enforces it with a lockfile.
* **Measure the oracle; never infer it.** If you need to know what the real game
does, run it. This applies with full force to the keyframe time unit and to any
transition timing.
* **Do not improvise around a blocker.** If a milestone needs a decision only the
user can make — a new dependency, a scope change, the Ready Room go/no-go —
write what you found, note it in MISSION.md, and move to the next thing you can
actually finish.
## Verifying
* `build-reborn test` wires up `SYLPHEED_DISC`; without it the disc tests
self-skip and a green run means almost nothing.
* `sylpheed-cli screen render` is the reference renderer. When Godot draws a
screen, diff it against the CLI's composite of the same build — they should
agree, and where they do not, one of them is wrong and you must say which.
* Godot runs headless in this container (`godot --headless`), and
`screenshot` captures the windowed one under Xvfb.
* A regenerated artifact that comes out byte-identical is strong evidence a
change was additive. When it does change, check that every diff line pairs.
## Publishing
`push-work` pushes the current branch to origin. It refuses anything that is not
`auto/*` and never force-pushes, so the consolidated line stays a human's
decision. Run it **every iteration that produced a commit** — not at the end of
some longer arc, which is exactly when a container dies.
If it reports no credentials, say so in your reply and continue working. Do not
improvise another route out: no remote rewrite, no credential helper of your own,
no alternate transport. A push that is blocked is a blocked push.
## Pacing
One milestone step plus its write-up is a good iteration; a marathon is not. Stop
with a clean commit, a push, and an honest list of what is still open.
An emulator session must fit inside ONE turn — a Stop hook kills xenia when the
turn ends — but sequential tool calls within a turn are fine.
The loop runs on a fixed interval set by the harness, so you do **not** need to
arm the next wakeup yourself. Spend that attention on the write-up instead.