Summary
Current main no longer boots Claude-of-Duty. World construction dies with:
[boot] init failed TypeError: Set.prototype.add is not a function
TypeError: Set.prototype.add is not a function
at solidSlabs (src/world/util.js:591)
at buildBuilding
at WorldSystem.init
at createConfig
Set.prototype.add is of course a builtin, so a receiver that reached this point is not being recognised as a Set.
The code
src/world/util.js:591 — nothing exotic:
export function solidSlabs(w, h, holes) {
const xs = new Set([-w / 2, w / 2]);
for (const o of holes) {
xs.add(Math.max(-w / 2, o.x - o.w / 2));
xs.add(Math.min(w / 2, o.x + o.w / 2));
}
const cuts = [...xs].sort((a, b) => a - b);
// …
}
Regression window
| base |
result |
d36a1af0c (+ the root_reload cap fix, now upstream as b0bb990db) |
boots, renders |
890514a6d |
fails as above |
That is 108 commits. Both bases have the root_reload fix, so it is not that.
What does NOT reproduce
Every reduction I tried passes on 890514a6d. Compiled and run individually:
new Set() + .add()
class Tracked extends Set overriding add and calling super.add
- a
Set held in a class field, mutated through a method
.add reached by computed key — (d as any)["add"](5)
new Set([1, 2, 3]) then .add(4) — literal elements
new Set([-w / 2, w / 2]) then .add(...) — computed elements
- the whole
solidSlabs body reproduced standalone, with holes
- the game's real
solidSlabs, imported from src/world/util.js and called directly — 75 MB binary, correct output
Number 8 is the informative one: the same function, same module, same import graph, compiled and called on its own, works. It only fails inside the full program.
That points at something context-dependent rather than at the lowering of this function in isolation — specialization driven by the real call sites (src/world/kit.js:106 passes openings) is my first guess, but I have not confirmed it.
Reproducer
git clone <claude-of-duty>
perry compile src/native/main.ts -o dist/cod
./dist/cod
Fails during world init, ~60 s in, before any window content.
I could not narrow it further without full game builds (~35 min each), which makes a 108-commit bisect impractical on my side. Someone able to bisect this range in CI should land on it quickly, and I am happy to test any candidate commit.
Note
An unrelated observation from the same comparison, in case it is a useful signal: the compiled binary grew from 106 MB to 151 MB across this same 108-commit window, with identical auto-optimize flags and near-identical runtime/stdlib archive sizes (26.7 -> 27.0 MB, 35.0 -> 35.3 MB). So the growth is in generated code.
Summary
Current
mainno longer boots Claude-of-Duty. World construction dies with:Set.prototype.addis of course a builtin, so a receiver that reached this point is not being recognised as a Set.The code
src/world/util.js:591— nothing exotic:Regression window
d36a1af0c(+ theroot_reloadcap fix, now upstream asb0bb990db)890514a6dThat is 108 commits. Both bases have the
root_reloadfix, so it is not that.What does NOT reproduce
Every reduction I tried passes on
890514a6d. Compiled and run individually:new Set()+.add()class Tracked extends Setoverridingaddand callingsuper.addSetheld in a class field, mutated through a method.addreached by computed key —(d as any)["add"](5)new Set([1, 2, 3])then.add(4)— literal elementsnew Set([-w / 2, w / 2])then.add(...)— computed elementssolidSlabsbody reproduced standalone, with holessolidSlabs, imported fromsrc/world/util.jsand called directly — 75 MB binary, correct outputNumber 8 is the informative one: the same function, same module, same import graph, compiled and called on its own, works. It only fails inside the full program.
That points at something context-dependent rather than at the lowering of this function in isolation — specialization driven by the real call sites (
src/world/kit.js:106passesopenings) is my first guess, but I have not confirmed it.Reproducer
Fails during world init, ~60 s in, before any window content.
I could not narrow it further without full game builds (~35 min each), which makes a 108-commit bisect impractical on my side. Someone able to bisect this range in CI should land on it quickly, and I am happy to test any candidate commit.
Note
An unrelated observation from the same comparison, in case it is a useful signal: the compiled binary grew from 106 MB to 151 MB across this same 108-commit window, with identical
auto-optimizeflags and near-identical runtime/stdlib archive sizes (26.7 -> 27.0 MB, 35.0 -> 35.3 MB). So the growth is in generated code.