What is wrong
.soldeerignore still names .gitmodules and /lib, REUSE.toml annotates a file that does not exist, and .github/copilot-instructions.md still documents a full submodule-era build recipe that cannot run. All of it is residue from the submodule → soldeer migration.
Everything dangling in this repo
Submodule paths that no longer exist
.soldeerignore line 18 — .gitmodules. There is no .gitmodules in the tree and git ls-files --stage reports zero gitlinks.
.soldeerignore line 42 — /lib. There is no lib/ directory. foundry.toml sets libs = ['dependencies'], so forge resolves everything under dependencies/ and never creates lib/. foundry.toml line 8 already says so in a comment: "All Solidity dependencies are Soldeer-managed; no git submodules remain."
Neither can come back. rainix CI runs a no-submodules check that fails on a root .gitmodules or any committed gitlink.
This repo has already dropped foundry.lock itself and left no reference to it behind — that half is genuinely done.
Stale documentation asserting the same dead layout
-
.github/copilot-instructions.md lines 87–90 — the "Fallback if end-of-session ./prep-all.sh fails early" recipe:
nix develop -c forge install
nix develop -c bash -c '(cd lib/rain.interpreter && rainix-sol-prelude && rainix-rs-prelude && rainlang-prelude)'
nix develop -c bash -c '(cd lib/rain.interpreter/lib/rain.interpreter.interface/lib/rain.math.float && rainix-sol-prelude && rainix-rs-prelude)'
nix develop -c bash -c '(cd lib/rain.interpreter/lib/rain.metadata && rainix-sol-prelude && rainix-rs-prelude)'
Every one of those cd targets is a nested submodule path that does not exist, so all three lines fail immediately. forge install is the submodule command; the soldeer equivalent is forge soldeer install. rain.interpreter is not even a dependency of this repo any more — soldeer.lock carries rain-interpreter-interface 0.1.0, not the interpreter itself. This is a documented fallback that has no chance of working, offered at exactly the moment someone's build is already broken.
Other dangling references found while checking
REUSE.toml line 22 — "typeshare.toml",. There is no typeshare.toml in the tree and .gitignore does not list one, so the annotation matches nothing in any state.
Deliberately not in scope. .soldeerignore also names .DS_Store, .env, .pre-commit-config.yaml and the build/publish outputs (/out, /cache, /dependencies, /target, /node_modules, /broadcast, /deployments). Those are absent from a clean checkout by design — OS junk, local developer files, or artifacts generated at forge soldeer install / forge build / forge script / cargo build / npm install time and therefore present when soldeer push runs. They are correct ignores and must stay.
Nothing else references any of it. .github/workflows/, flake.nix, foundry.toml, Cargo.toml, crates/, packages/, script/, subgraph/, remappings.txt, .gitignore, AGENTS.md, CLAUDE.md, README.md and the rest of the tree were grepped and are clean.
Which of these actually get removed
REUSE.toml and .soldeerignore fail in opposite directions, so the same absent path is residue in one and a live rule in the other.
REUSE.toml describes files that exist. An annotation naming a path that is not there describes nothing, so it is residue and it goes — that is typeshare.toml above. reuse lint (the rainix-sol legal job) tolerates a dangling annotation, which is why it survived; what it does not tolerate is the reverse, dropping the annotation of a file that is there. Proved live in rain.lib.memkv — removing the annotation for the tracked soldeer.lock makes reuse lint exit 1.
.soldeerignore is a publish filter, not a description of the tree. An entry naming an absent path is a forward-looking rule: it is the thing that keeps that path out of the published package if anyone ever adds it. So the test for deleting an entry is impossible, not absent — an entry may only go if the path it names can never exist again.
Lines 18 and 42 pass that test, and they pass it structurally rather than by observation: rainix CI's no-submodules check fails the build on a root .gitmodules or any committed gitlink, and /lib is that same vendored-submodule directory. (foundry.lock, only ever written for lib/ submodule dependencies, is in the same class — it is already gone from here.) While that check stands neither can be recreated, so those two filter entries can never match anything again. They are genuinely dead, and they are the only .soldeerignore lines this issue removes.
Every other entry — .env, /target, /node_modules, .pre-commit-config.yaml, whatever a given repo happens to list — is either matching something today or merely not yet added. Deleting one of those cleans nothing up; it arms a leak, so that the day someone adds the file it ships inside the published soldeer package. Proved live in rain.lib.memkv — dropping the /soldeer.lock line took forge soldeer push --dry-run from 14 entries to 15, with soldeer.lock now inside the package.
Nothing catches an over-deletion. No CI job reads .soldeerignore, so the mistake goes green and only surfaces later, when someone adds the file and it silently publishes.
Context
This is the tail of an unfinished migration, not a convention.
Across the repos that consume rain.solmem via soldeer, nine have already dropped foundry.lock (raindex, rain.verify, rain.tofu.erc20-decimals, rain.flare, rain.dia, rain.erc4626.words, rainlang, rain.merkle, S01-Issuer/st0x.deploy) and eight still carry one (rain.solmem, rainlang.interface, rain.extrospection, rain.math.float, rain.string, rain.lib.memkv, rain.intorastring, rain.datacontract), each with its own issue.
Deleting the file was never the whole job — every one of those nine left dangling .gitmodules and/or lib/ references behind. This issue covers raindex only.
The same residue exists in a further 17 rainlanguage repos outside that consumer set, 10 of which also still carry a dead foundry.lock. They are out of scope here. flow and rain.tier.interface genuinely still use git submodules, so their .gitmodules and lib/ entries are correct and must be left alone.
Done when
What is wrong
.soldeerignorestill names.gitmodulesand/lib,REUSE.tomlannotates a file that does not exist, and.github/copilot-instructions.mdstill documents a full submodule-era build recipe that cannot run. All of it is residue from the submodule → soldeer migration.Everything dangling in this repo
Submodule paths that no longer exist
.soldeerignoreline 18 —.gitmodules. There is no.gitmodulesin the tree andgit ls-files --stagereports zero gitlinks..soldeerignoreline 42 —/lib. There is nolib/directory.foundry.tomlsetslibs = ['dependencies'], so forge resolves everything underdependencies/and never createslib/.foundry.tomlline 8 already says so in a comment: "All Solidity dependencies are Soldeer-managed; no git submodules remain."Neither can come back. rainix CI runs a
no-submodulescheck that fails on a root.gitmodulesor any committed gitlink.This repo has already dropped
foundry.lockitself and left no reference to it behind — that half is genuinely done.Stale documentation asserting the same dead layout
.github/copilot-instructions.mdlines 87–90 — the "Fallback if end-of-session./prep-all.shfails early" recipe:Every one of those
cdtargets is a nested submodule path that does not exist, so all three lines fail immediately.forge installis the submodule command; the soldeer equivalent isforge soldeer install.rain.interpreteris not even a dependency of this repo any more —soldeer.lockcarriesrain-interpreter-interface0.1.0, not the interpreter itself. This is a documented fallback that has no chance of working, offered at exactly the moment someone's build is already broken.Other dangling references found while checking
REUSE.tomlline 22 —"typeshare.toml",. There is notypeshare.tomlin the tree and.gitignoredoes not list one, so the annotation matches nothing in any state.Deliberately not in scope.
.soldeerignorealso names.DS_Store,.env,.pre-commit-config.yamland the build/publish outputs (/out,/cache,/dependencies,/target,/node_modules,/broadcast,/deployments). Those are absent from a clean checkout by design — OS junk, local developer files, or artifacts generated atforge soldeer install/forge build/forge script/cargo build/npm installtime and therefore present whensoldeer pushruns. They are correct ignores and must stay.Nothing else references any of it.
.github/workflows/,flake.nix,foundry.toml,Cargo.toml,crates/,packages/,script/,subgraph/,remappings.txt,.gitignore,AGENTS.md,CLAUDE.md,README.mdand the rest of the tree were grepped and are clean.Which of these actually get removed
REUSE.tomland.soldeerignorefail in opposite directions, so the same absent path is residue in one and a live rule in the other.REUSE.tomldescribes files that exist. An annotation naming a path that is not there describes nothing, so it is residue and it goes — that istypeshare.tomlabove.reuse lint(therainix-sollegaljob) tolerates a dangling annotation, which is why it survived; what it does not tolerate is the reverse, dropping the annotation of a file that is there. Proved live in rain.lib.memkv — removing the annotation for the trackedsoldeer.lockmakesreuse lintexit 1..soldeerignoreis a publish filter, not a description of the tree. An entry naming an absent path is a forward-looking rule: it is the thing that keeps that path out of the published package if anyone ever adds it. So the test for deleting an entry is impossible, not absent — an entry may only go if the path it names can never exist again.Lines 18 and 42 pass that test, and they pass it structurally rather than by observation: rainix CI's
no-submodulescheck fails the build on a root.gitmodulesor any committed gitlink, and/libis that same vendored-submodule directory. (foundry.lock, only ever written forlib/submodule dependencies, is in the same class — it is already gone from here.) While that check stands neither can be recreated, so those two filter entries can never match anything again. They are genuinely dead, and they are the only.soldeerignorelines this issue removes.Every other entry —
.env,/target,/node_modules,.pre-commit-config.yaml, whatever a given repo happens to list — is either matching something today or merely not yet added. Deleting one of those cleans nothing up; it arms a leak, so that the day someone adds the file it ships inside the published soldeer package. Proved live in rain.lib.memkv — dropping the/soldeer.lockline tookforge soldeer push --dry-runfrom 14 entries to 15, withsoldeer.locknow inside the package.Nothing catches an over-deletion. No CI job reads
.soldeerignore, so the mistake goes green and only surfaces later, when someone adds the file and it silently publishes.Context
This is the tail of an unfinished migration, not a convention.
Across the repos that consume
rain.solmemvia soldeer, nine have already droppedfoundry.lock(raindex, rain.verify, rain.tofu.erc20-decimals, rain.flare, rain.dia, rain.erc4626.words, rainlang, rain.merkle, S01-Issuer/st0x.deploy) and eight still carry one (rain.solmem, rainlang.interface, rain.extrospection, rain.math.float, rain.string, rain.lib.memkv, rain.intorastring, rain.datacontract), each with its own issue.Deleting the file was never the whole job — every one of those nine left dangling
.gitmodulesand/orlib/references behind. This issue covers raindex only.The same residue exists in a further 17 rainlanguage repos outside that consumer set, 10 of which also still carry a dead
foundry.lock. They are out of scope here.flowandrain.tier.interfacegenuinely still use git submodules, so their.gitmodulesandlib/entries are correct and must be left alone.Done when
.soldeerignorelines 18 and 42 removed.soldeerignoreline left exactly as it isREUSE.tomlline 22 (typeshare.toml) removed.github/copilot-instructions.mdfallback recipe rewritten against the soldeer layout, or deleted if it no longer has a purpose.gitmodules,lib/orforge installremains anywhere in the tree outsidedependencies/