nervネルフ

What survived the rewrite

Both originals were rewritten in Rust. Comparing each pair is a controlled experiment in which kinds of boundary survive a change of language — and the answer is narrow.

What happened to each

beforeafter
pi11 npm packages, 150,756 linesone crate. 145 pub mod, no workspace key, and a single 36,158-line file.
deepseek255 packages and a vendored DI framework, 307,345 lines20 crates, 8,390 lines, in two commits. The framework reduced to one trait that always says no.

deepseek's 39-fold shrink measures scope abandoned, not modularity won — its own README says as much: “This is not a Cordis port.” pi's is the interesting one, because nothing was abandoned. The packages simply stopped existing.

Why pi's boundary evaporated

pi-ts's package boundary was not held by discipline or by review. It was held by the npm resolver, which sits on the critical path of every build, plus a script that parsed every build program with the compiler's own API — at pre-commit and in CI.

Rust has exactly one construct with that resolver property, and it is the crate. Inside a crate there is no resolver at all. So the rewrite did not weaken the eleven-package graph; it deleted it. Violating any conceptual boundary in pi today costs seven keystrokes and nothing fails.

The measurement: under nerv's own hygiene rules, pi now holds a mutually recursive core of 23 modules on the strict reading and 57 on the broad one.

And pi is not a project that skipped its gates. Its module-reachability check runs in CI and passes cleanly at 240,000 lines: 144 declared, 141 reachable, 0 unreachable. It built the reachability gate and never built the direction gate — and a 57-module cycle is maximally reachable. nerv's own gate-reachable has exactly the same blind spot, which is why gate-cycles was written.

The invariant

Only the boundaries that were already data survived. The npm package graph, the entry-file budgets, the dependency-injection container, the import-closure verifier — deleted, stubbed, or rebuilt at a fraction of their expressiveness. What translated intact was declared dependencies between compilation units, because Cargo implements it, and a YAML patch file, because it is a file.

Which puts a sharp question to nerv: what here is data?

would survive a rewrite
the Lua layer — 9,034 lines across four programsyes. Tool declarations, provider catalogs, wire protocols and client stubs are files, not code.
the socket and pipe protocolsyes. A shape on a wire is a shape on a wire.
the crate graph inside each programonly if the next language has a resolver at that granularity
the module structure inside a crateno. This is exactly what pi lost.

The Lua layer is the closest thing in any of the six trees to the one deepseek-ts mechanism that came through its rewrite intact. That is an argument for putting more in it, not less.

The unit you pick is permanent

pi chose pub mod in its first commit. Five thousand commits later there is no path back — nothing in the tree even discusses the alternative. A crate costs twenty lines of manifest.

nerv's own tree shows the same force at work: the two programs with production module cycles are exactly the two with no gates. That is not a coincidence about those two programs; it is what happens wherever nothing refuses.