port: the container agent answers the questions, it does not build the port
Some checks failed
Some checks failed
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>
This commit is contained in:
@@ -1,49 +1,60 @@
|
||||
Build the Godot menu port of Project Sylpheed, one milestone at a time.
|
||||
Answer the open questions the Godot menu port is blocked on, one 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.
|
||||
`Syplheed-Reborn/docs/port/MISSION.md` — read it every iteration. It lists the
|
||||
open questions Q1…Q9 plus a gated probe S1, and the gate each one must pass.
|
||||
|
||||
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.
|
||||
**You do not build the port.** A separate agent does that, from what you produce.
|
||||
Your deliverable is decoded, verified, written-down answers with the evidence.
|
||||
If you find yourself designing an export schema or writing GDScript, you have
|
||||
crossed the line — go back to the question you were answering.
|
||||
|
||||
This is still reverse engineering. What changed is what earns attention: an item
|
||||
is worth doing when the menu port is blocked on it.
|
||||
|
||||
## 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.
|
||||
1. `docs/port/MISSION.md` — the open questions, their gates, what is out of scope.
|
||||
2. `docs/port/HANDOFF.md` — what the port agent has been told so far. **Update it
|
||||
when you answer something.** An answer not reachable from that page has not
|
||||
been delivered.
|
||||
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.
|
||||
finding; asking whether its values *resolve* is.
|
||||
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.
|
||||
`docs/re/disc-atlas.html` maps 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.
|
||||
1. **Pick one question** from MISSION.md, preferring the one that blocks the port
|
||||
earliest and whose first step is cheapest. If you are mid-question, continue it
|
||||
rather than starting another.
|
||||
2. **Do the smallest experiment that could settle it**, and try to *refute* your
|
||||
hypothesis before believing it. Run the known-positive through any new filter
|
||||
first; a filter that fails its own control is dead, not tuneable.
|
||||
3. **Classify the answer honestly.** Every answer is exactly one of:
|
||||
* **decoded** — the field, plus a disc-wide check;
|
||||
* **measured** — not on the disc in any form you found, but here is what the
|
||||
running game does, and here is the capture;
|
||||
* **undecodable, with reach** — you looked here, here and here, and this is
|
||||
why it is not there.
|
||||
|
||||
Never a fourth thing. *Measured* and *undecodable* mean the port agent will
|
||||
author that value by hand, and it must know it is authoring rather than
|
||||
transcribing. Labelling a guess as a decode puts it into the port wearing the
|
||||
badge of a measurement.
|
||||
4. **Write it down** in `docs/re/` under the ✅/🟡/❔ convention, with the evidence
|
||||
and the *reach* of any negative, then update the row in `docs/port/HANDOFF.md`.
|
||||
* 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.
|
||||
@@ -53,39 +64,40 @@ when the container dies.
|
||||
|
||||
## 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.
|
||||
* **Do not build the port.** No Godot project, no GDScript, no asset pipeline, no
|
||||
export schema, no transcoding. Those belong to the port agent.
|
||||
* **Do not touch `crates/sylpheed-viewer`.** The Explorer is the human's tool for
|
||||
exploring and verifying the RE work; it keeps its static-data-only rule and the
|
||||
port does not depend on it.
|
||||
* **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.
|
||||
* **Measure the oracle; never infer it.** Most of the open questions are about
|
||||
*behaviour* — timing, transitions, what a button does, what a d-pad press does
|
||||
at the end of a list. Those cannot be answered from the file. An iteration that
|
||||
reasons about the game without running it is a red flag unless the question is
|
||||
a pure static-format one.
|
||||
* **Do not improvise around a blocker.** If a question needs a decision only the
|
||||
user can make, or the container cannot do it, write what you found, note it in
|
||||
MISSION.md, and move to the next question you can actually finish.
|
||||
|
||||
## The S1 probe
|
||||
|
||||
One iteration, then **stop and write the go/no-go**. Do not start Ready Room work
|
||||
on your own authority — MISSION.md §S1 says why.
|
||||
|
||||
## 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.
|
||||
* Verify with an **artifact**, not with "it compiles": `sylpheed-cli screen
|
||||
info` / `screen render` / `mesh render` / `save info`, a capture, a screenshot.
|
||||
* Commit the reference data beside the finding, so the port can be built without
|
||||
a disc in the loop during development.
|
||||
* 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 exactly.
|
||||
|
||||
## Publishing
|
||||
|
||||
@@ -100,8 +112,8 @@ 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.
|
||||
One experiment 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.
|
||||
|
||||
Reference in New Issue
Block a user