Repository navigation
Description
What changes, and when
rainlanguage/rainix#392 adds a
codegen witness to the rainix-copy-artifacts reusable workflow. This repo's
.github/workflows/git-clean.yaml calls that workflow at @main, so the check
arrives the moment #392 merges — not when this repo chooses to adopt it. The
next push after that merge fails until a manifest is committed.
Why the check exists
rainix-copy-artifacts currency-checks committed generated sources by re-running
the codegen hooks and then git diff --exit-code. That proves the committed
content is current, but it is structurally blind to a generator that has
stopped emitting a file: the committed copy is already correct, so nothing is
rewritten, nothing differs, and the job is green over a dead emitter. Reproduced
with a control in
rainlanguage/rain.factory.deploy#35.
Seeing that needs an independent statement of which committed files are
generated. That is script/codegen-manifest.txt: one repo-relative path per line,
# comments and blank lines ignored. The witness marks every git-tracked file's
mtime before the first hook and verifys after the last, calling a file
written when it exists and its mtime moved. Any declared path nothing wrote
fails the job by name.
Why this repo is affected
Hook present: script/Build.sol. No script/codegen-manifest.txt today.
What to add
script/codegen-manifest.txt:
src/generated/candidate/AddressRegistry.sol
src/generated/candidate/MigrationRegistry.sol
src/lib/LibAddressRegistryDeploy.sol
src/lib/LibMigrationRegistryDeploy.sol
src/lib/LibAddressRegistryReleased.sol
src/lib/LibMigrationRegistryReleased.sol
src/lib/LibReleasedSuites.sol
How that was derived
script/Build.sol declares two generated contracts — AddressRegistry and
MigrationRegistry — and generatedContracts() is the only list every hook reads.
Against src/lib/LibRainDeploySnapshot.sol in this repo:
regenerateSnapshots()→writeSnapshot(..., recordRoot(), CANDIDATE, <Contract>, ...)
→src/generated/candidate/<Contract>.sol, one per contract.regenerateLibs()→writeAliasLib(...)→src/lib/Lib<Contract>Deploy.sol;
writeReleasedSuitesLib(...)→src/lib/Lib<Contract>Released.sol;
writeReleasedSuitesAggregate(...)→src/lib/LibReleasedSuites.sol
(RELEASED_SUITES_LIBRARY, inLIB_DIR = "src/lib").
Every one of those seven paths is committed today, and no other file under
src/generated/candidate/ or matching src/lib/Lib*{Deploy,Released}.sol is.
Deliberately excluded
src/generated/0_1_7/, 0_1_8/, 0_1_10/, 0_1_11/ — frozen release snapshots,
written only by cutRelease(), never by the run() the copy-artifacts job calls.
Declaring them would fail every run. src/lib/LibAddressRegistry.sol and
src/lib/LibMigrationRegistry.sol are hand-maintained, not emitted (the generated
alias libs are the ...Deploy.sol pair).
Reconciling against the job
The failing verify step prints the manifest that run would justify — the set
of git-tracked files the hooks actually wrote in CI. Treat that printout as the
oracle and the list above as a cross-check derived by reading the hooks. A
difference either way is information, not noise:
- listed above, absent from the printout — that emitter may already be dead, or
the file is generated by something the copy-artifacts job does not run. - printed, absent from above — an incidental write inside the witness window
(forge buildis in there), or a generated file this reading missed.
Undeclared-but-written paths are a printed note, never a failure — the check is
a subset assertion, not set equality — so a conservative first manifest is safe and
an over-eager one is not.
Adoption
One commit adding script/codegen-manifest.txt. No workflow edit and no
RAINIX_SHA bump: #392 wires the witness as a composite action resolved at
@main, so nothing in this repo pins the check's version.
Filed while tracking the org-wide adoption cost of rainlanguage/rainix#392. The
paths above were derived by reading this repo's own hooks and committed tree, not
by running the job.
Activity
thedavidmeister commentedon Oct 5, 2026
Rewritten: the mechanism changed and the consequence is the opposite of what
this issue said.
What was wrong
This issue said rainix#392 reads
script/codegen-manifest.txt, and thatgit-cleanhere "goes red the moment #392 merges".Neither holds. #392 (still open, created 2026-09-20) has no manifest file at
all. The generator declares its own paths on stdout —
rainix-codegen owns <path>andrainix-codegen wrote <path>— and theworkflow tees that into a log the new
codegen-declarationaction reads. Itsdescription says why: "Only the generator knows which paths it owns rather than
deliberately leaves frozen, so it declares them on stdout."
And it ends: "A repo whose hooks declare nothing is a no-op."
The actual item
script/Build.soldeclares nothing. So when #392 merges, nothing here goes red— the witness is simply inert, and
git-cleanstays green while providing noneof the coverage the witness exists to add.
That is the same shape as the blindness #392 was built for
(rain.factory.deploy#35): a check that is green because it has no subject. One
level up, and silent, so nothing will prompt us.
What to do
script/Build.solemitsrainix-codegen owns <path>for each path its hooksown, and
rainix-codegen wrote <path>when it writes one.generatedContracts()is already the single list every hook reads, so the declaration derives from it
rather than being a second list to keep in step — which is the whole point of
the stdout form over a committed manifest.
The paths, from
generatedContracts():src/lib/LibRainDeploy.solis tracked and hand-written, not generated, so it isnot declared.
Timing
#392 is unmerged, and nothing breaks when it merges, so there is no deadline —
only an absence that will not announce itself.
[-]Add script/codegen-manifest.txt: git-clean goes red when rainlanguage/rainix#392 merges[/-][+]script/Build.sol declares no codegen paths, so rainix's codegen witness will be a silent no-op here[/+]thedavidmeister commentedon Oct 5, 2026
Closing — there is no issue here.
rainix#392 is unmerged, so the witness does not exist to adopt. When it does
merge, nothing here breaks and nothing here gets worse: this repo keeps exactly
the coverage it has today. What is missing is an upstream capability not yet
taken up, and rainix#392 being open is what tracks that.
My comment above rewrote this from an obsolete premise into a thinner one rather
than concluding it should not exist. The correction to the premise stands and is
worth keeping on the record — #392 reads a stdout declaration rather than
script/codegen-manifest.txt, and a repo that declares nothing is a no-op, sothe "git-clean goes red when #392 merges" claim in the title and body was wrong
— but the conclusion drawn from it was not a reason for an issue.