Status: Superseded by ADR-294 — its D1-D4 are D17-D20 there
Date: October 1, 2026
Target Version: Nikaia 0.0.318
Answers: the owner’s question of whether the move to Nikaia would be
cheaper done in bigger pieces, and the cost the move to describe (#124) made
visible: a helper written four times, a table of which tool may read which, and
names that collided
Related: ADR-250 (the road to Stage 1), ADR-047
D1 (a package is a directory, and its files are one namespace), ADR-196
D1 (a Nikaia piece joins the Rust program as an ordinary module),
ADR-002 D4 (the committed pre-lowering), Part I 9.1
Every .nika in crates/nikaia-std/src/tools/ was lowered as a program of one
file, to a .rs beside it that lib.rs included as a module of its own. A tool
could not name another tool’s function at all, and a tool that had to read
another’s types - the ledger’s records, the syntax tree, the Rust grammar’s
items - had it put beside itself by a table in sysroot.rs (BESIDE), with
lib.rs writing the matching use super::…::*.
What that cost, counted when describe moved (0.0.308-0.0.316):
slice written four times, split_top_level twice, generic_of,
bounds_send and is_plain twice, find_text twice - each a copy because
the tool that had it could not be named;lib.rs, and names that collided the moment two
tools were read together: the grammar’s Item was not the tree’s;Box<dyn Error>.src/tools is a package.Its files share one namespace (Part I 9.1, ADR-047 D1): a name declared in any
of them is written as it is in any other, a private helper is the package’s,
and two files may not declare the same name. The names that collided are
renamed once - rust.nika’s Item is RustItem, manifest.nika’s Shape is
DependencyShape, ledger.nika’s Line is LedgerLine, template.nika’s
State is ScanState, signature.nika’s Written is WrittenFn, http1’s
and surface’s read are read_head and read_items - and the copies are
removed: one slice, one find_text, one split_top_level, one Refused for
the three files that each declared the same one.
nikaia lower-std checks every file with the others beside it, against std’s
ledger and the tools’ described one (ADR-252 D4.3), and lowers them into one
file, src/tools/package.rs: one preamble, then each file’s items. BESIDE
and the per-file .rs are gone.
At the end of package.rs stands one module per file - tools::ty,
tools::ledger, tools::rust - that re-exports what that file declares pub
and its grammars. nikaia_std::tools::ty::Ty is the path it was, and the name
is one name underneath. The Rust lib.rs writes beside the package because
Nikaia cannot say it - a Span’s usize doors, the call that turns a generated
parser into a result - is listed by the file it serves (sysroot::HAND_WRITTEN)
and joins that file’s module.
ADR-250 D3 holds here too: an error type declared in another file of a package
is the package’s own (emit::declared_errors reads every file beside the one
being lowered), which is as true of a program’s package as of this one.
package.rs is one large generated file instead of seventeen; the diff of a
change to one .nika is still that file’s lines.scripts/self_hosting.py counts the .nika files as before.All of it, at 0.0.318.