Provenance and verify
What the stamp on a generated asset holds, the drifts verify reports, and the four lint rules.
The stamp
Every asset DreamFX generates carries a provenance record:
| Field | Answers |
|---|---|
| Source path | which .dfs this asset came from |
| Source hash | whether that source has changed since |
| Generator version | which DreamFX built it |
| Module version GUIDs | whether the modules it calls have changed since |
The stamp has three direct uses: skipping unchanged sources (build), finding things out of step (verify), and recognising a generated asset — which is how the Content Browser menu knows to offer "Open Source" instead of "Export".
What verify catches
pwsh -File Plugins/DreamFX/.skill/dfx.ps1 verify -AllIt writes nothing — not the asset, not the stamp — and only compares. .dfe files are skipped: they
generate no asset, so there is nothing to compare.
| Code | Meaning |
|---|---|
| DFX7001 | the asset carries no DreamFX stamp: it was never generated from this source, or it was made by hand |
| DFX7002 | the asset is stale: it was generated from a different revision of this source |
| DFX7003 | the asset was generated by an older DreamFX (a warning; a rebuild is recommended) |
| DFX7004 | the asset does not exist: this source has never been built |
| DFX7005 | module version drift (an error under -StrictVersions) |
verify is the one step of the four-step CI that can catch this: someone edited a .dfs, did
not rebuild, and committed both. build alone never fails on it, because build fixes it. Only
comparing the stamp against the source shows that the committed asset and the committed text
disagree.
-StrictVersions promotes an R7 module version mismatch from warning to error. A release gate wants
that: assets built against different modules than the text describes must not ship.
The four lint rules
Lint reads source only and touches no asset, which is why it is the fastest step to fail:
| Code | Catches |
|---|---|
| DFX7101 | a GPU emitter with no FixedBounds. GPU emitters cannot compute their own bounds |
| DFX7102 | rate-based spawning (SpawnRate / SpawnPerUnit / SpawnPerFrame) with no upper bound |
| DFX7103 | randomness without Determinism = true, so it looks different on every run |
| DFX7104 | a renderer with no Material and no default DreamFX knows for its type — it will not draw |
DFX7102 does not treat SpawnParticlesInGrid as rate-based spawning: like SpawnBurst it is a
per-loop burst (X·Y·Z), bounded by the loop. A lint rule has to track the semantics, or it becomes
noise.
The same thing from the editor
Tools ▸ DreamFX ▸ Verify DFX runs the same pass and reports one toast:
| Toast | Condition |
|---|---|
DreamFX: {N} source(s) verified, all assets in step. | clean |
DreamFX: {Drifted} of {N} source(s) out of step ({Failed} failed). See the Output Log. | drift or failure |
What happens if you hand-edit a generated asset
The next rebuild wipes it, without asking. That is not a defect — it is the definition of the model: the text is the only truth.
A generated asset shows a warning banner in the editor with a link to its source file. Edit it there.
The build pipeline
What a build actually does — discovery, ordering, schema probing, writing, the Niagara compile, saving, stamping, and why an unchanged source is skipped.
Round trip and equivalence
The decompilation contract, how a gap surfaces, what each of the four verification layers answers, and three lessons in "all green is not the same as correct".