Team Cereustooling wiki

Make a stage

Partly checkedagainst the code on 2026-11-12 11:43

A stage is one self-contained change on top of a published Eclipse release: a folder with the files it ships, its rowlists, and a stage.json that the release pipeline reads. eb stage make writes stage.json for you from a stage.toml you fill in.

Checked against the code. Not run for this page: no stage was made while writing it.

EB means py -3.12 -I -B S:/eclipse-build/eb.py.

Before you start

  • The base release tree must exist: S:/souls-script-kt/output/eclipse-release-<base>/depth6-online-mods. stage make stops with stage: base release tree ... not found without it.
  • Pick a stage folder. Stages for release 0.0.NN live in S:/eclipse-00NN-stage/<name>.
  • Pick an id, for example fix-0106/my-fix. Other stages refer to it.

Steps

  1. Create the stage.

    EB stage init S:/eclipse-00NN-stage/<name> --id fix-00NN/<name> --base <base release, e.g. 0.0.105> --title "<one line>"
    

    --id and --base are required. --title is optional. It writes stage.toml and, if there is none, a README.md stub with the headings What changed, How it was built, Checks, Not proven. If stage.toml already exists it stops with ... exists; edit it.

  2. Build your files twice, into two folders inside the stage: work/run-A and work/run-B. Run each build as an eb job (run-heavy-jobs.md). Each run folder holds the files at their release paths, for example work/run-A/mod/chr/c9240.anibnd.dcx.

  3. Fill in stage.toml (fields below).

  4. Write stage.json.

    EB stage make S:/eclipse-00NN-stage/<name>
    

stage.toml

This is the template stage init writes:

id = "fix-00NN/name"
title = "..."
kind = "fix"
risk = "low"
base_release = "0.0.105"
changelog = [""]
test = [""]
not_proven = []
approved = ""

[build]
command = ""          # how this stage's files are built (recorded in stage.json provenance)
runs = []             # e.g. ["work/run-A", "work/run-B"]: every shipped file must be identical in all of them

# [[file]]
# path = "mod/chr/cXXXX.anibnd.dcx"
# why = ""

# [[rowlist]]
# path = "rowlist-x.tsv"
# tool = "polish"
# order = 300
# expect = { set = 0, added = 0 }
Field Meaning
id The stage id. Required.
title One line for the release candidate notes. Not player text. Required.
kind fix, port, placement, skin, weapon or binary. Required. A DLL stage is binary.
risk low, medium or high. Required. Anything other than low changes the intro line of the changelog draft.
base_release The published release the stage was built on. Required.
changelog Player lines, in player words: no ids, no tool names. The changelog draft is built from them.
test What Stan should try in game.
not_proven What has not been proven.
approved Who approved shipping it, and their words.
touches Optional. Mod paths and regulation:<Param> you say the stage touches. The release check notes any difference.
merges Optional. Copied into stage.json as written. See pipeline/stage.schema.json for the shape.
[build] command How the files are built. Recorded only, never run.
[build] runs Build folders, relative to the stage folder or absolute. With two or more, every shipped file must be byte-identical in all of them.

[[file]]: a whole file that goes into the mod tree

Key Meaning
path Path in the release tree, for example mod/chr/c9240.anibnd.dcx. Never mod/regulation.bin: regulation changes come only from rowlists.
from Optional source path, relative to the stage folder or absolute. Default: <first run>/<path>.
why What changed in this file and why.
base_stage Only for a chained file (below).
base_sha256, base_stage_json Optional, only together with base_stage.

[[rowlist]]: regulation changes

Key Meaning
path The rowlist file, relative to the stage folder or absolute.
tool polish (default) or tablerows.
order Required. The release applies all lists in (order, stage id) order, in one chain.
expect Required. The counts the stage saw when it applied the list on its base: set and added for polish, added for tablerows. A polish list with DELROW lines also gives deleted. A list whose counts add up to 0 is refused by the release check.
overrides Optional list of stage ids whose SET cells this list overwrites on purpose. This list must run later.
why Optional.

What stage make does

  1. Stops if id, title, kind, risk or base_release is empty.
  2. With two or more runs: copies every [[file]] from each run into .eb-stage-check/ in the stage folder, makes the .dcx copies canonical (the same as eb dcx normalize), and compares them. If any differ it stops with stage: these files differ between the build runs (not reproducible, not shipped): and the list. The check folder is removed afterwards.
  3. Copies each file into the stage folder at its release path and makes .dcx files canonical.
  4. Hashes each file and the file it replaces in the base release tree (base_sha256; null for a new file). A file identical to the one it replaces stops the run: ... is identical to ...; leave it out.
  5. Hashes each rowlist.
  6. Writes stage.json and prints wrote .../stage.json: N files, M rowlists, 2 build runs identical. With fewer than two runs it prints no build-twice check (give [build] runs) instead.

Chained files (base_stage)

Use this when your file was built on another stage's version of the same path, for example a sound bank that already holds another stage's sounds.

[[file]]
path = "mod/sd/cs_c4340.bnk"
base_stage = "fix-0088/ds3-arts-088"
  • Make the base stage first. stage make finds its stage.json by id in the folders beside your stage folder. If it lives elsewhere, set base_stage_json = "<path to its stage.json or its folder>".
  • base_sha256 is optional. Left out, it is read from the base stage's stage.json. If you give both, they must agree.
  • stage.json then records base_stage and base_sha256 for the file. No merges entry is needed.
  • The release check orders the two stages by it. If the base stage later ships a different file, or is missing from the release while the base tree does not hold that file, the check fails with STALE CHAIN (check-and-build-a-release.md). Rebuild on the new file and run stage make again.

What stage.json contains

Schema eclipse-stage/1, described in pipeline/stage.schema.json. stage make writes:

  • schema, id, title, kind, risk, base_release, stage_dir (the stage folder), readme;
  • files: per file path, source, sha256, base_sha256, and base_stage / why when given;
  • rowlists: per list path, sha256, tool, order, expect, and overrides / why when given;
  • merges, touches, changelog, test, not_proven, approved;
  • provenance: made_by (eb stage make), eclipse_build (the eclipse-build commit, with (dirty) when the repo has uncommitted changes), stage_toml_sha256, build_command, build_runs, runs_identical, dcx_canonical, made.

The schema allows more keys that stage make does not write (binaries, sha_lists, seed_deltas, source_patches, when variants). A stage that needs them is not covered by this page.

The provenance gate

eb release check and eb release build look for the provenance block in every stage.

  • For a release from 0.0.89 on, a stage without it is refused with a line that starts GATE FAIL <id>: no provenance.
  • The same gate fails a stage whose merge steps pin tools that live only in souls-script-kt/.tmp or a Claude scratchpad.
  • This also covers a stage carried over from an older release. Give it a stage.toml and run stage make on it.
  • EB_GATE=warn turns the failure into a warning. It is for an emergency only; say so in the release notes.

How to tell it worked

stage.json exists in the stage folder and has a provenance block with "runs_identical": true. Then run the release check on it: check-and-build-a-release.md.

What goes wrong

Message Cause
stage.toml: <field> is empty A required field is not filled in.
stage: <path> missing in build run <dir> A [[file]] is not in one of the runs folders.
stage: these files differ between the build runs The build is not reproducible. Fix the build; do not ship one of the two.
stage: <path> has no source (set from, or [build] runs) No from, no runs, and the file is not already in the stage folder.
stage: rowlist <path> not found Wrong rowlist path.
stage: base_stage <id>: no stage.json with that id beside ... Make the base stage first, or set base_stage_json or base_sha256.
stage: eb dcx normalize failed A .dcx file could not be made canonical. See cache-and-dcx.md.
Source files this page documents (3)
  • eb:tools/stage.py
  • eb:pipeline/stage.schema.json
  • eb:eb.py

Changed one of these? Update this page: build/start-a-stage.md (how).