Skip to main content
← Back to list
01Issue
FeatureShippedSwamp CLIPublic
Assigneesskunk-ape

Relationships

↔ sibling #3200

#3194 stagecraft: upgrade stored factory definitions on read, so a format change does not break work in progress

Opened by skunk-ape · 10/8/2026· Shipped 10/8/2026

Problem

Every change to the factory definition format is a breaking change today, and it breaks work already in progress.

  • A factory definition carries schemaVersion: 1 (DEFINITION_SCHEMA_VERSION, engine/definition_schema.ts), and a run record carries schemaVersion: 1 (RUN_SCHEMA_VERSION, engine/run_record.ts). Anything with another version is refused. Nothing can read an older version.
  • A work item pins a copy of its factory definition when it is claimed. Every later step re-parses that copy with the current schema and checks it against the digest the run recorded (readPinned / checkPinned, engine/work_item_ops.ts). If the schema stops accepting a field, every work item in progress fails with "the pinned definition is invalid". Rewriting the pinned copy changes its digest, so that fails too.
  • DESIGN.md says swamp never upgrades stored data, only globalArguments. Stagecraft does not use swamp's model upgrades hook (upgradeAttributes), so a definition someone wrote is not upgraded either.

So stagecraft cannot change its definition format without stranding in-progress work items and making everyone hand-edit their definitions. #3190 is the first change that needs this: it replaces bindings with let plus passAsInputs.

Request

Upgrade stored definitions as they are read, through a chain of versioned steps that each keep the meaning exactly, so that a format change upgrades users instead of breaking them.

  1. Upgrade steps. One pure JSON-to-JSON function per version step (v1 to v2, v2 to v3, and so on). Each keeps the definition's meaning exactly.
  2. One read path for every stored definition (pinned copies, the factory's definition, the summary report): read schemaVersion, verify the digest against the stored form, apply the upgrade steps in memory, then parse with the current schema. The rest of the engine sees only the current form.
  3. Pinned copies are never rewritten. A work item claimed on v1 keeps its v1 copy and its digest, and keeps running after an upgrade.
  4. A definition someone wrote is upgraded by swamp: the factory model type declares upgrades whose upgradeAttributes run the same upgrade steps, so nobody hand-edits it.
  5. A version newer than the runtime is refused with a clear message, for example "this definition needs a newer stagecraft".
  6. Fixtures at each old version are tested on every release: each must read, upgrade to the expected current form, and give the same dispatch as before. Every future format change adds its step and a fixture.

The same pattern should be available for run records (RUN_SCHEMA_VERSION) when they first need to change. Building that is not required here.

Open questions for planning

  • The digest is computed over the parsed value at pin time (pin digests the parsed definition and stores jsonSafe of it). Confirm with a test that the digest of the stored copy as-is equals the recorded digest for existing records, so the digest check can run before the upgrade.
  • Anything that compares a factory's current definition digest with a work item's pinned digest (re-pin, a changed-definition notice) would see an upgraded definition as changed. Decide whether the comparison should be between upgraded forms.
  • Confirm when swamp runs upgradeAttributes and whether it writes the result back to the model's file.

Done

  • The definition can move to schemaVersion: 2 with an upgrade step, and a work item pinned at v1 before the change still dispatches, records and advances afterwards.
  • A factory definition at v1 is upgraded by swamp without anyone editing it.
  • Old-version fixtures are part of the test suite.
  • DESIGN.md documents the rule: a format change ships an upgrade step that keeps the meaning, plus a fixture.

#3190 (let + passAsInputs, {{binding}} in a stage's target) builds on this as the v1 to v2 step.

02Bog Flow
✓OPEN✓TRIAGED✓IN PROGRESS✓SHIPPED+ 1 MOREASSIGNED+ 5 MOREREVIEW+ 13 MOREPR_MERGED+ 2 MORESESSION_SUMMARIZED

Shipped

10/8/2026, 11:46:45 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
skunk-ape assigned skunk-ape10/8/2026, 8:58:57 PM
skunk-ape linked sibling of #320010/8/2026, 10:05:32 PM

Sign in to post a ripple.