Imported from Gundorada-Workshop/DarkCloud-Toolkit (
AGENTS.md). Install upstream withnpx skills add Gundorada-Workshop/DarkCloud-Toolkit. Copyright stays with the author.
AGENTS.md — how to work in this repository
1. Mission
Finish the Dark Cloud port: a native Windows application that reads the retail disc, plays
back and edits its data, and re-implements the game's own logic faithfully enough that a relinked,
grown image boots and behaves. The application is src/ (129,472 lines of first-party C++, of
which src/Archives/ is 53,385 lines of ported engine — re-measure with find src -name '*.cpp' | xargs wc -l before repeating either number; both drift). Everything that reads, writes,
authors, verifies, builds or drives it is one Node application, dta.
The measure of progress is not lines written. It is gates: 192 C++ harnesses that link the port's own code and assert what it does, plus the format round-trips that prove a parser can reproduce retail bytes exactly. A claim with no gate behind it is a hypothesis.
This repository is distinct from DCFM_TrackA_PortTooling-PRIVATE, its private sibling.
-PRIVATE commits everything it depends on (disc image, vendored trees) and is never pushed —
pure versioning. THIS repo is the eventual public dev distro: README.md/CONTRIBUTING.md
already frame it as MIT-licensed and PR-welcoming, .gitignore blocks the disc image and every
large vendored dependency by design, and "never commit game data" is a hard rule enforced by
CONTRIBUTING.md, not just convention. Large dependencies (rom/, vendor/, pcsx2/, derived
data/) may be present in the working tree for local building and gate-running, but are
gitignored, not committed — that is deliberate, not a gap to "fix" by committing them. Recent
fixes and dev tooling get ported here FROM -PRIVATE (gates, probes, app/, harness/); the
disc image and vendored source trees do not.
2. Read first, and what is authoritative
| question | the only authority |
|---|---|
| which phase is live / what is still open | docs/DEV_ROADMAP.md's own phase checklist |
| where anything is | dta.config.json + app/core/paths.mjs. Nothing else may spell a path. |
| does the port work | dta gate run — the C++ harnesses, with their result fingerprint |
| does a parser work | its corpus round-trip, byte-exact, with the corpus named |
| what retail does | refs/trackb where Track B has proven it; otherwise app/re on the real ELF |
| what we have learned | .claude/memory/MEMORY.md |
A carried-forward number in a document is a claim, not a measurement. Re-derive it from the authority before repeating it. The old tree's own docs were wrong about A4/A5 being open and about a gate's pass count; both were found by re-running, not by reading.
3. The one application
dta doctor what this checkout can and cannot do, and why
dta check [suite] the gate suites; every suite proves it can fail
dta serve the daemon + web console on 127.0.0.1:1339
dta tui the terminal twin
dta iso … the disc, the containers, the write guard, the corpus enumerator
dta fmt … binary formats: parse AND write, each with a corpus round-trip
dta model … authoring: glTF/GLB <-> MDS + side-cars, the .blend writers
dta audio … banks, sequences, the tone chain
dta elf … the retail executable as data: model, delink, relocate, disassemble
dta relink … the relinkable image (A1-A6)
dta stb … the .stb script VM: format, text form, assembler, externals
dta re … the RE workbench: what does retail actually do here?
dta product build build the port (Debug) dta gate build|run|list|report
dta headless … speak to the built app dta pcsx2 … emulator parity
dta log [file] a headless run's log, filtered by level (--strict fails on ERR/EXC)
dta governor what the machine is doing, and what that allows right now
dta pcsx2 fork … the emulator as source patches: status|fetch|apply|revert|ensure|check
dta pcsx2 build … build the patched emulator, governed: status|configure|build|deploy|install
dta trackb sync|status|diff|adopt the decompiled source, read-only
dta vendor import the relocation itself, with a digest ledger
verb: 'dir/*' reaches any module under app/dir/. A module with no exported cli(argv) is run
as a script with the same arguments — which is how a family arrives before it is fully converted.
The machine is shared, and everything heavy goes through the governor. MSBuild, DCFM, PCSX2
and ninja are started only by the dta verbs, which sample the whole machine once a second (CPU,
free memory, process start latency, and the active time of the disks the work lands on), run
everything below normal CPU priority and low I/O priority, admit one heavy process at a time and
narrow their lanes under pressure (app/core/governor.mjs, disk.mjs, lowio.mjs; dta doctor
shows the current level). The disk limit is the user's: work gives way at 75 % and 85 % active,
nothing new starts at 95 %. After a fresh clone run dta governor helper once (it builds the
100-line native helper that lowers I/O priority; dta doctor warns while it is missing). Never start one of them by
hand beside a running dta, never stack two heavy jobs, and never mount the ISO — DCFM's own VFS
reads the image file. After a headless run, read the log review it prints and fix what it shows.
Never call anything on E: or any path outside this repository (see Hard Rule 1). There is
no legacy/ directory in this checkout — that was -PRIVATE's parity-comparison scaffold from an
earlier phase of the port and does not exist here; do not assume it does.
4. Hard rules
- Self-contained. Every path this application runs resolves inside the repository. The one
exception is MSVC — a licensed host toolchain that cannot be vendored — located by
app/core/msvc.mjsand reported by doctor.dta check corefails on anything else, including any path inlocal.config.json. - Every change ships with a gate whose check is proven able to fail. Use
suite.mutant(...). A suite with no mutant announces that fact in its own footer, because a check that cannot fail proves nothing. - Never push without being asked. This repo is the eventual public distro (see §1) — unlike
-PRIVATE it is not a pure versioning archive — but going public is still a deliberate, human
decision, not something an agent triggers by pushing or opening a PR unprompted.
originIS the public repository, so a push is the export: rundta distro auditbefore one. It reads the tracked set and fails on a never-publish path, a user-profile path naming an account, or a path naming the maintainer's checkout layout (write<projects>\namein prose, a made-up root such asE:\\Elsewherein a test).dta check distroruns the same audit. The end-user release isdta distro package: an allow-list (the Release executable, the licences, the documents the README links to) that declines to carry the development half. - Never commit game data, the disc image, or a large vendored dependency.
.gitignorealready blocksrom/,vendor/,pcsx2/, and the derived corpora underdata/— seeCONTRIBUTING.md's "Never commit game data" section, which is the authority on what "derived fact, not copied bytes" means in practice. - Node for all new tooling. No bash. No new Python except where the interpreter is not ours —
which means exactly one thing: the process is
blender.exe. - Do not rewrite a C++ gate harness in Node. Its assertions are the product's own code executing. A Node rewrite tests the rewrite.
- Do not add a second parser for a format that has one. Find the authoritative module and extend it. Where two readings are deliberate (a spec reading and a mirror of the product's reading), they live in ONE module behind a mode flag, never in two files.
- A gate must be able to notice an empty corpus.
assertCorpusNonEmpty(). Five gates in the old tree printed0/0and exited 0. - Disclose what was not measured beside every clean number: which corpus, how many files, which gates were skipped and why. "5031 passed" without "of the ISO corpus, 0 skipped" is half a sentence.
5. How to work
- Tools do the bulk reading.
dta re decomp,dta elf dis,dta fmt … inspect— not raw hexdumps pasted into context. - Generic, not special-case. A fix that names one file is usually a fix in the wrong place.
- Evidence grades, highest first: retail bytes reproduced byte-exactly > Track B's matched decompilation > the product's own C++ under a gate > a vendor header or SDK source > a corpus census > a plausible reading. Say which grade a claim rests on.
- One agent at a time on the same tree. The build lock is real and the object directories are shared.
- Milestone protocol:
dta check all --strict(a suite BLOCKED on an absent prerequisite must not pass for a milestone) →dta gate run --all→git add -A && git commit→ a memory fact file plus itsMEMORY.mdline → updatedocs/DEV_ROADMAP.md's phase checklist.
6. Report format
Lead with what changed and what it is proven by. Then: gates green / total, the three re-measured unit gates if they were touched, corpus round-trip counts with the corpus named, and what was skipped. Never report a gate result whose source fingerprint no longer matches the tree without saying it is stale.
7. Out of scope here
The byte-exact decompilation itself — that is Track B, driven by dtb. Its checkout has moved at
least once (this document cited <projects>\DCFM_TrackB_DecompTooling; the live checkout
found and configured this pass was <projects>\dc1-decomp-tooling — same project, dtb
tooling, decomp/dc1/ layout, re-derived and re-named since). Do not hardcode either path: read
trackb.source from local.config.json, or ask dta doctor, which reports it live. Where its
output is available (a Track B checkout configured at trackb.source) it is imported read-only
via dta trackb sync; this repo does not build it. refs/trackb is gitignored — decided
2026-09-17: the decompiled source is NOT published, it lives in the dev checkout and a clone
regenerates it with dta trackb sync. refs/trackb and data/migration.json ARE
now present and populated in THIS checkout (synced 2026-09-17 from the checkout above, 137 files /
40 cited units; see [[dta-trackb-source-was-unconfigured]] in this repo's own memory) — the
data/migration.json sources block is still redacted, per Phase 10's own reasoning, since
nothing in this repo's tooling reads it. Always check dta doctor's live report before assuming
either is or is not present; both states are normal depending on whether trackb.source is set.