nikaia_<name>Status: Superseded by ADR-286 — its D1-D5 are D23-D27 there
Date: September 15, 2026
Target Version: Nikaia 0.0.8
Related: ADR-002 D1 (one CLI wraps Cargo, and a Rust
dependency already reaches it by version), ADR-053 D1 and D3
(one crate per package; a transitive package stays invisible),
ADR-047 D2 (a package by path, which stays), ADR-100
D1 and D3 (a fetched package is read through its ledger, hashed against its
sources), ADR-021 D2 (resolved versions are recorded in the
lockfile), ADR-046 D1 (the manifest key is the use name)
A version names a package only relative to somewhere packages of that name
live. nikaia.toml already says which version a package is; what a
consumer writing http = "1.2" lacks is where to look, what "1.2" ranges
over, and what it will find there. All three exist in the tool every Nikaia
build already runs: Cargo has an index, a version grammar, a lockfile and
git dependencies with a tag, and a Rust dependency already reaches it as
{ type = "rust", version = "1.5" }. What Nikaia has to decide is only the
name it publishes under, because a Nikaia package called http and the Rust
crate called http would otherwise be one name on one index.
nikaia_<name>; the package’s own name is <name>.http is nikaia_http on crates.io. The prefix is the index’s business and
never a program’s: no .nika file, no use, no diagnostic and no ledger
entry ever carries it.
nikaia.toml resolves through Cargo, and the generated manifest writes the rename.[dependencies]
http = "1.2" # crates.io: nikaia_http, Cargo's semver
http = { git = "https://…/http", tag = "v1.2" } # a tag instead of an index
http = { path = "../http" } # as before (ADR-047 D2)
regex = { type = "rust", version = "1.5" } # a Rust crate, as before
The first becomes http = { package = "nikaia_http", version = "1.2" } in
the generated Cargo.toml — Cargo’s own renaming, so the local name is the
use name and the prefix appears once, where Cargo reads it. "1.2" means
what it means to Cargo. The resolved version is recorded in nikaia.lock
(ADR-021 D2), and --locked means for it what it means there.
A key is an identifier, because it is a use name: http_server, not
http-server.
A published crate carries nikaia.toml, src/*.nika and nikaia.contracts,
and a Cargo.toml whose only job is to exist for the resolver — its name,
its version, and its own nikaia_ dependencies. Nothing lowered is
published: the lowering is the consuming compiler’s and keyed by its
fingerprint (ADR-021). The consumer asks Cargo where the crate
landed, reads its sources and its ledger from there, and emits it into its
own workspace as a member, exactly as a path dependency is emitted now
(ADR-053 D1). The stub is never linked.
nikaia_ is a convention the index does not enforce. A fetched crate with no
.nika sources or no nikaia.contracts is refused as not a Nikaia package,
naming the crate. One that has both is read the way any package with sources
is: its ledger is believed while the source hashes match and derived again
where they do not (ADR-100 D3).
The stub’s Cargo.toml lists them, so Cargo fetches the whole graph at once,
and a path dependency’s nikaia.toml is followed the same way. What the
consumer may name is unchanged: a transitive package is not in its ledger
and not in its namespace (ADR-053 D3); what it reads is its
direct dependency’s ledger, computed with that dependency’s own
dependencies in view (ADR-100 D5).
A second author can publish a library and a consumer can depend on it with one line, and nothing in the language changes: the prefix lives in one generated line, the version grammar is borrowed, the lockfile already had the column.
What the project gives up is a name space of its own. A Nikaia package lives on crates.io under a prefix, and an index of Nikaia’s own would be a second place to publish. That is a real thing to give up, and it is reversible: the compiler reads a directory, and where the directory came from is D3’s business alone.
What a squatter can do is take nikaia_foo first. D4 makes the crate
useless as a Nikaia package and names it; it does not free the name. That is
crates.io’s rule for every prefix and is accepted.
nikaia publish command. D3 says what a published crate holds;
generating the stub and running cargo publish is work, not a decision.nikaia.lock says under --locked for a
git tag that moved. Cargo’s answers, until a program meets a case where
they are wrong here.Nothing. http = "1.2" is refused today with the sentence Part III 13.3
used to carry, and a package’s own package dependencies are refused rather
than followed. The order of work:
git table are read, and the
generated Cargo.toml writes the rename (D2);nikaia_ crate landed
and reads it as a package (D3), refusing one that is not (D4);nikaia.toml and stub, in both arms (D5);cargo publish on it is the
whole of publishing.#99 carries it.