Files
Sylpheed/docs/port/port-loop-task.md
MechaCat02 65cefa74c3
Some checks failed
CI / Native — macos-latest (push) Has been cancelled
CI / Native — windows-latest (push) Has been cancelled
CI / WASM — Web (push) Has been cancelled
CI / Formatting (push) Has been cancelled
CI / Native — ubuntu-latest (push) Has been cancelled
monorepo: one repository for the decoders, the port and the corpus
Merges the Godot port into the reverse-engineering repository, preserving both
histories -- 1019 commits of corpus plus the port's 31, brought in by subtree
merge and then moved into place so git can follow each file across the rename.

The reason is not tidiness. The two-repo split forced the exporter to depend on
the decoders by pinned revision, and that created a whole class of failure that
now disappears: a sha reachable only from a topic branch, orphaned by a
squash-merge, breaking a fresh checkout silently at build time. It also forced a
live read-only mount of one agent's working tree into another's container, which
is why a contract file could move mid-iteration. With a path dependency, a
decoder change and the exporter change it requires land in the same commit or
not at all.

Canary stays separate: it is a fork tracking upstream.

New structure for the long term:

  docs/game/     how the game is NAVIGATED -- menus, modals, prompts, alerts,
                 and in-game flight. Written so nobody rediscovers it. Mostly
                 open questions on purpose; the in-game tutorials are the
                 resource for the flight half.
  docs/port/MODDING.md
                 modding as a constraint on the exporter TODAY, not a later
                 feature: one logical asset in one file (the disc splits nearly
                 everything, and resolving that is the exporter's job), names a
                 person recognises, PNG/OGG/OGV/JSON only, base-and-overrides so
                 re-exporting is always safe, provenance in every file.
  data/base + data/mods
                 generated tree and drop-in overrides, both gitignored
  exchange/      transient inter-agent files, deliberately outside history
  docs/agents/   the team protocol

Both the README and the navigation doc lead with the correction that cost the
most: the oracle is the real game under Xenia Canary. Reborn's renderer is a
hypothesis under test, it has been wrong, and treating it as ground truth
propagated into three documents and both agents before a human caught it.

Scripted modding stays possible without being built: no screen name is hardcoded
in GDScript and there is no native code in port/, which is what Godot Mod Loader
needs to be able to substitute behaviour later.
2026-08-29 11:34:46 +02:00

94 lines
4.6 KiB
Markdown

Build the Godot menu port, one milestone at a time.
## Your objective
`docs/MISSION.md` — read it every iteration. It defines the milestones P0…P7 and
the gate each must pass, the wall between the exporter and Godot, and the
derived/authored split.
**You do not reverse engineer.** A separate container agent does that, in the
Syplheed-Reborn repository, mounted read-only at `/reborn`. You have no emulator
and no oracle, so a guess of yours is indistinguishable from a fact and will be
believed later. If you need an answer the disc has not given you, write it in
`docs/BLOCKED.md` and move to another milestone.
## Read these first, every iteration
1. `docs/MISSION.md` — milestones, gates, scope.
2. `/reborn/docs/port/HANDOFF.md`**the contract.** What is decoded, what was
measured off the running game, and what is known undecodable.
**It is a live read-only mount of the RE agent's working tree**, so it updates
itself and there is nothing to pull — `git -C /reborn pull` cannot work (the
mount is read-only) and should not: it would move another agent's checkout.
`git -C /reborn log -1` shows where they are.
Because it is live, **it can move under you mid-iteration.** Anything you
copied out of it earlier — `docs/BLOCKED.md` especially — may already be
stale. Re-check it against HANDOFF before trusting it.
3. `docs/FORMAT.md` — the open format. It is versioned and it is yours to
revise, but a change is a deliberate act with a version bump.
4. `docs/BLOCKED.md` — what you are waiting on, so you do not re-discover it.
`/reborn/docs/re/disc-atlas.html` maps how the assets reference each other.
## Each iteration
1. **Pick the lowest unfinished milestone.** If it is blocked on an RE answer,
record that in `docs/BLOCKED.md` and take the next one that is not.
2. **Build the smallest thing that reaches its gate.** The gate is an artifact —
a validating JSON file, a screenshot, a clickable build — never "it compiles".
3. **Keep derived and authored apart.** `export/` is regenerated wholesale and
never hand-edited. A fix you are tempted to make there belongs in the exporter
or in `authored/`, and every `authored/` entry carries a `why`.
4. **Write down what you decided**, in `docs/`. A decision that lives only in
your context is lost when the container dies.
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 gitignored and generated from the
user's own disc. Code, schemas, `authored/` mappings and docs only.
* **No Rust in `port/`, no GDExtension.** If Godot cannot read something, the
exporter emits it differently.
* **Do not vendor or reimplement `sylpheed-formats`** — it is pinned by revision.
In particular do not reimplement media assembly: `sylpheed_formats::media`
already handles segment-spanning entries, multi-sub-wave banks and the
continuous cutscene-voice stream, and that last one is the easiest thing here
to get subtly wrong.
* **`/reborn` is READ-ONLY.** Never commit there, never edit it. It belongs to
the other agent and you share no working tree with it.
* **Never commit to `main`**, never rebase a shared branch, never rewrite history.
* **Do not adopt a runtime dependency on your own authority.** Propose it.
## Verifying
* `sylpheed-cli screen render` (built from `/reborn`) is the reference renderer.
When Godot draws a screen, diff against the CLI's composite of the same build.
Where they disagree, one of them is wrong — say which, and why, rather than
tuning until they match.
* Godot runs headless (`godot-headless`), and windowed under Xvfb with
`screenshot` for a capture.
* A regenerated `export/` 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.
## 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.
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.