releaselanguage
2026-08-19 · the first published nine-key binary · Linux builders jail before the gates run
The second refusal, one layer down.
v0.109.1 fixed the fossil
envelope in the release gates and died on both Linux builders one leg
later: [consent-run] exit=3 want=4 — since 0.109.0 a workflow that
declares permits: refuses to start on a host with no sandbox backend
(NIKA-1710), and a GitHub Linux runner has no bubblewrap. The macOS
builders, where seatbelt exists, passed both gates confined. No asset
shipped under v0.109.1 either; the binaries were fine both times.
This patch is the same tree plus the second fix and is the version
consumers install.- The Linux release builders install bubblewrap before the gates run.
The Diamond CI tests-leg recipe (apt bubblewrap · detach
ubuntu-24.04’s AppArmor bwrap profile · keep unprivileged userns open)
now runs on the two Linux builders, so the funnel e2e and the trust
battery run confined there exactly as they do on macOS — never a
waiver. A gate that spends an
execunderpermits:proves the jail as a side effect; a host that cannot jail says so (NIKA-1710) instead of being waved through.
nika check --fix moves the
mechanical parts.releaselanguagebreaking
2026-08-19 · the first published nine-key binary · the release gates speak the live envelope
The release the release gate refused.
v0.109.0 was tagged from
f58a17396 and its own pre-upload gates killed all four builders: the
funnel e2e and the trust battery still authored their fixtures in the
fourteen-key envelope (nika: v1 + workflow:) the nine-key engine
refuses at parse. No asset was published under that tag; the binaries
were fine and the gate was the fossil, exactly as v0.106.0 died on
2026-07-27 when the battery spent an exec without a permits: block.
v0.109.0 stays a tag with no release; this patch ships the same tree
plus the gate fix and is the version consumers install. The language
change itself is the v0.109.0 entry below.- The release gates speak the live envelope (funnel e2e · trust
battery). Four fixtures move from
nika: v1+workflow:tonika: <id>. Nothing else in the gates changes: the consent-dirty leg still expectsNIKA-SEC-014atguardandcheck, the consent-pause leg still expects exit 4 with the resume line, the trust battery still runs its exec underpermits.exec. - Hygiene vector 50 ·
check-release-gate-envelope. The two gates run only at tag time, so a language change on main could leave them teaching the previous envelope for weeks with nothing red on any push. The vector greps both scripts for the dead envelope forms on every push and is RED on any hit — proven by mutation (one restored fixture → red).
nika check --fix moves the
mechanical parts, the table below names the hand moves.releaselanguagebreaking
2026-08-18 · the nine-key release — tagged, no binary shipped (install 0.109.1)
The nine-key release. The envelope shrinks from fourteen keys to nine
and a workflow written for 0.108.0 will not check on 0.109 · this is the
flag-day the 0.106.0 front page announced as possible, and it lands
whole. The identity moves onto
nika: itself (nika: <id> · a
kebab-case name · the workflow: block, its id: and its
description: are gone), the value authorities are exactly three
(inputs · const · secrets · config: died with the block),
types: · policy: · assert: leave the envelope, and the task body
loses its second grammars: cleanup is a real task on an unwind edge
(on_finally: is dead · graph_format: 3 carries the finally node),
output: is spelled extract:, declassify: and inert: merge into
one door (lift:), fail_workflow is gone (on_error is recover or
skip), the two fan-out knobs live INSIDE for_each:, and group:
arrives (fan-in · NIKA-DAG-008). Two P0 close at the surface users
install: an expression sees only its INPUT (the ambient env leaves the
jaq function set at the three seams, with a pinned inventory of natives
that reddens if a future jaq adds one), and a third-party receipt can no
longer write the operator’s clipboard (every field rides escape_tty).
The refusal a 0.108.0 file meets first now TEACHES where each retired
key’s role went, instead of unknown field.Tagged 2026-08-18 · no binary shipped under this number. The tag’s
own release gate refused the upload (its fixtures still spoke the
fourteen-key envelope), so nothing was published as 0.109.0. The first
published nine-key binary is 0.109.1, the same tree plus the gate
fix — that is the version to install.① The envelope · fourteen keys become nine (ADR-113). The live
envelope is nika · model · inputs · const · secrets ·
permits · run · tasks · outputs. Every other top-level key
refuses, and the refusal names the destination:② The task body · one grammar per thing.
③ What
nika check --fix migrates · and what it does not. The rungs
are idempotent and equivalence-or-stop · r1-identity (new ·
nika: v1 + workflow: {id, description} · the block, the pre-W1
scalar workflow: <id>, the one-line flow form, a bare top-level
description: · become nika: <id> with the prose demoted to a #
comment ABOVE it, never dropped · it STOPS, never guesses, when nika:
already names something else, when the block carries a foreign key,
when the id is not kebab-case, or when there is no id at all) ·
w1-map (a tasks: sequence becomes the map · atomic or nothing) ·
w2-flow (depends_on + body tasks.* reads become with: bindings
and after: predicates) · d1-split (the pre-0.103 string command:)
· esplit (vars: → inputs: / const: · classify-not-rename) ·
predicates (succeeded → success). One --fix runs them all in
one loop, so a 0.108.0 file whose only sins are the identity and the
tasks list heals to green in one command. Every round is a transaction:
a repair whose text no longer parses is rolled back and reported, and
the file is written once, from committed text only.Still hand migrations in this release · the on_finally:
restructuring (cleanup becomes its own task on an unwind edge),
output: → extract:, declassify:/inert: → lift:, config: →
inputs: (a classification), and the for_each re-nesting · the
refusal teaches each destination at the point of refusal and --fix
leaves the file untouched rather than write a document its own checker
would reject. Measured on the pack that ships inside this binary:
0.108.0 passes 0/40 of these examples · 0.109 passes 40/40 · every
existing file outside this repo sits on the 0.108.0 side of that line
until it is migrated.④ Two P0, closed where users install. An expression sees only its
input (#959): a nika:jq expression could read the ambient environment
(env.PATH) under an ABSENT permits block while check printed « the
body is pure compute so nothing escapes »; the retained natives leave
the jaq function set at the three seams from ONE list, and a pinned
inventory of jaq natives reddens if a future jaq adds one. A third-party
receipt wrote the operator’s clipboard (#958): three fields of a proof
receipt reached the terminal without escape_tty while the helper
existed in the same file · a foreign evidence pack could emit OSC52;
every receipt field rides the escape, proven by mutation before
publication.⑤ The two trains. stable is the newest tag · what brew · the
Registry · nika-action and the starters install. next is main, at
<next>.0-dev between tags · a real semver prerelease ·
nika --version and every trace say which one they are. Stable
consumers move only when a tag they can install exists.releaseaccesssecurity
2026-08-05 · the access layer arrives · the check stops trusting what it cannot read
The access layer arrives; the check stops trusting what it cannot
read. Three steps of the access ratification land:
access picks
the path, model: picks the intelligence — a deterministic resolver
with a strict sovereign order (local < mock < harness < oauth < api),
an --access <path> pin on run and try judged at the launch gates
(unsatisfied refuses with NIKA-1800/1801/1802, never substitutes),
and the ACP harness class (nika-acp · ACP 2.0.0 = wire v1) with its
mock agent in a quarantined workspace and the kernel’s AgentBackend
seam. The zero-authority scan now refuses every exec spelling, the
shell form included. Fixed alongside: the doubled catalog-miss
advisory, the taught surfaces that misdirected, two more sandbox
tightenings, a resumed run that keeps its seat, and every pack skeleton
passing its own golden lane. Proven red-first, like everything on this
train.An outside audit measured the experience instead of the feature list
— five waves, seventy-two receipts, twenty-two P0s — and the arc closed
every one. Consent means consent: a non-affirmative answer fires zero
effects (
NIKA-SEC-014, minted spec-first with its conformance
fixtures). The hooks’ judge moved into the binary (nika guard,
fail-visible). Autonomy is graded before it is colored — the risk rung
never renders green past Supervised. The data journey names sources,
destinations and secrets before the run, and redaction works by
provenance: a one-byte secret dies the same death as a long one.The teaching grammar collapses to three doors. nika try [slug] is
the showroom — offline by default (the mock rehearsal · zero keys · zero
flags), nothing written, nothing owned; bare nika try lists what there
is to see. nika new takes ONE positional gesture: plain words route
across the whole catalog, an example slug lands verbatim WITH its
ingredients, a skeleton name instantiates (nika new '?' lists the
set). nika init founds. The old doors die loudly:A human gate can no longer kill a first run. A
nika:prompt with no
default: used to die in milliseconds on every text-mode run. The rider
is now armed on every lane: unattended runs pause durably (exit 4,
the pause journaled, never a failure frame), and at a terminal the gate
asks you directly — confirm [y/N], choice, or input — leaving a
paste-able resume line that carries the run’s own --var/--model.Around the core, the doors multiplied honestly: nika wire previews and
never rewrites unasked, six clients join the targets (grok · antigravity
· kimi · kiro · copilot · amp — wire all covers twenty-one), and
nika init writes the two project MCP doors (.mcp.json +
.agents/mcp_config.json), handing the read-only oracle to agent
surfaces with zero machine wiring. nika doctor gives every probed host
a capability receipt and names kit↔binary train drift with the exact
align command. Cost honesty grows an energy rung (NEP-0018 —
watt-hours beside dollars), and a priced backend that omits token usage
now fails closed.These docs teach 0.107 and only 0.107. The 0.106 value/permits grammar
is unchanged — what moved is the CLI’s teaching surface. Pin the tag
you run.Two flag-days land in one window, and both are the same idea: a thing
the file left implicit becomes a thing the file declares.① The E-split —
vars: and env: die into four named authorities.
One block for everything a workflow knew was a block that told you
nothing: whether a value came from the caller, from the deployment, or
from the file itself was invisible, and so was whether it could be
trusted. The family is now closed at four, one role each — inputs:
(the caller supplies it at launch) · config: (the deployment supplies
it, and it may appear in logs) · const: (the file owns it, immutable)
· secrets: (a governed store, masked). inputs.* and config.* are
untrusted (they come from outside the file); literals, const.* and
secrets.* are trusted — which is why a destination a permits:
entry pins belongs in const:, where no caller can move it out from
under the boundary.The old spellings refuse loudly, and they refuse with a classification,
not a rename: there is no mechanical vars: → inputs: (that is how you
end up with a caller-overridable output path). Each use is classified
into the authority its role commands; nika check --fix migrates the
provable cases and stops on the rest rather than guessing.② An absent permits: block declares ZERO authority. It used to mean
“engine floor only” — a hint, and a green check. It now means what its
absence always should have: no filesystem, no network, no shell, no
tools. Every effect the body requires is refused at check with
NIKA-AUTH-006 before a single token is spent, and any effect that
reaches run time fails the task with NIKA-SEC-004. A pure-compute
workflow still passes; permits: {} is the authored spelling of “I
touch nothing”; and under composition the absence is a wall — a parent’s
grants never flow down implicitly (NIKA-COMP-002). The repair is one
command: nika check --infer-permits walks the DAG and prints the
tightest boundary the body actually needs, ready to paste.Also in the window: an envelope
run: block declares the run’s
entropy and clock ({ entropy, clock }, closed) — randomness and
time stop being ambient, and entropy: { seeded: N } + clock: virtual
make two runs of the same file byte-identical. The dimensions couple, so
a declared contradiction refuses at parse (NIKA-PARSE-026 /
NIKA-PARSE-027).These docs teach 0.106 and only 0.106 — no dual grammar, no “if you are
on 0.105” branch. Pin the tag you run.The refonte reaches users — the file becomes a map.
workflow: is
an object (id: + description:), tasks: is a map keyed by id, and
precedence reads the way you think: the binding IS the edge
(with: x: ${{ tasks.a.output }} declares the data edge) · control-only
ordering is after: {producer: succeeded} against a closed predicate
set (succeeded · failed · skipped · terminal). The old forms die loudly
— a scalar workflow: is NIKA-PARSE-020, depends_on: is
NIKA-PARSE-024 — and nika check --fix machine-migrates the provable
cases. The proof layer opens: semantic hash + nika.lock +
receipt_format: 1, workflow composition (invoke: workflow:), and
nika:decide, the deterministic decision kernel. One security seat
ships in this tag: the lethal-trifecta judge (NIKA-SEC-009) refuses
private-read + untrusted-ingress + external-egress with no blocking
human gate on the path. The LSP learns the map end-to-end (server-side
rename · per-block keysets · semantic_document_format: 1). Every
surface you copy from re-baked the same day — the site, these docs, the
templates and the kit speak the released grammar (the serve-time door
law: what you copy runs on YOUR installed binary). Thinking-model note,
same honesty as the K3 seat: reasoning spends max_tokens — budget
generously or declare thinking:; an empty answer says why.Moonshot (Kimi) joins the canonical catalog — 17 providers (11 cloud
· 5 local · 1 test).
model: moonshot/kimi-k3 runs Kimi K3 first-class:
1M context, MOONSHOT_API_KEY, and the pricing snapshot makes
--max-cost-usd a hard ceiling on kimi spend (the promotion run
metered 0.0077 printed worst-case). K3 is a
thinking model — reasoning spends output tokens, so budget max_tokens
generously (512+; at 64 the answer comes back empty and the engine says
why). Weights are announced open on July 27; until then the hosted API
routes through Moonshot’s servers with training-by-default — read the
permits section of your workflow as the data-residency contract it is:
no declared egress, no call. Also in this wave: the lsp/graph/mcp test
fixtures that shipped red at the v0.103.0 tag now speak the argv form
(a CI-coverage gap banked as a finding), and the tag’s rustfmt drift is
cleared. Release branch cut from v0.103.0 — main is mid-refonte and
users never ship a transitional grammar. Spec side: ADR-105 + stdlib
16→17 + the escape-hatch doc now names the real variable
(NIKA_OPENAI_BASE_URL, complete endpoint, verbatim).The pre-1.0 window pays for itself — three breaking cuts in one wave,
spec and engine merged in the same window.
command: is argv-only
(["cargo", "test"] — execve, no shell: an interpolated value can
never break out of its argument) and the string form moves to
shell:, the explicit door — semantics ride the field, never
the YAML type. A bare ${{ tasks.X }} is now an error (NIKA-VAR-020):
name the projection — .output / .status / .error /
.duration_ms. And the gate algebra (upstream terminal × gate form →
downstream status) becomes a normative spec table — the when-status
pattern is a propagation choice, not redundancy. ~530 corpus sites
migrated; docs, site, editor, kit and registry re-taught in lockstep.Engine releaseThe LSP arc lands server-side: the pause after a colon answers
itself (space joins the triggers),
args: keys complete from the
tool’s own schema, mode: enums scope to the enclosing tool,
${{ vars./secrets./env. }} complete from the FILE’s declarations,
hover cards read the graph (wave k/N · transitive reach · model
fallback tiers), and references resolve closure-aware. Plus:
wave-sweep.sh (the one-command release sweep) and three new
coherence-bot probes born from drifts caught by hand.Engine releaseEvery release binary now carries
local-infer — nika model pull →
nika model serve → workflow infer against your own machine: no
cloud, no external daemon, no build-from-source wall (#518, the
release ruling, executed). CPU on every target on purpose (darwin
included) until candle’s quantized rms-norm Metal kernel is fixed.
The release funnel now pins the teaching both ways: a shipped binary
must never utter « built without local inference ».Engine releasereleaseclisovereignagents
2026-07-12 · the terminal sings · the models come home · the kit rides three surfaces
The terminal learns to sing: a verb band colors every task by its
verb, the spinner is a real live probe, and
nika run paints the DAG
as living wire-art in-frame — states, in-node spinners, edge
pulses — while nika inspect --format json|mermaid|dot becomes the
ONE graph projector (now projecting declared policy too: retry ·
timeout · on_error · outputs). nika init becomes a founding
wizard (recipes, themes, wiring — everything asked before the first
write) and equips a repo for 15 agent surfaces project-side,
Cursor subagents + seatbelt hooks included. The models come home:
nika model pull/list/rm (one models dir by construction, resumable
verified downloads) and nika model serve (the sovereign sidecar,
OpenAI-compatible on loopback) close the local loop — pull → serve →
workflow infer, trace-chained. nika check --fix is an in-binary
repair loop that converges; the machine dry-run ships one versioned
plan object; a paused run teaches its exact resume command; registry
refs run verified (nika run @org/flow). The agents kit becomes a
suite — 4 skills · 3 subagents · 5 commands · 3 seatbelt hooks in
ONE dialect across Claude Code, Cursor and Codex (probe-proven) —
and the LSP ships code actions: every check --fix rename lands
as a quickfix in any editor. Wire waves add claude-desktop, cline,
continue and qwen (12+ targets).releaseauditstdlib
2026-07-10 · the MODELS rung · two media builtins graduate · the boundary earns its valve
The check ladder earns its MODELS rung: every
model: must resolve
in THIS binary — a bare id (gpt-5-turbo) or a provider the resolver
cannot drive is a finding with the fix taught in-line, pricing refuses
to price what cannot resolve (unpriced beats conjured), and the MCP
nika_check lane obeys the same law. Two media builtins graduate:
nika:image_fx (15 deterministic op families — dither · duotone ·
halftone · glitch · ascii — over a hand-rolled zero-dep PNG codec, the
recipe riding the tEXt chunk) and nika:chart (five chart types
compiled to byte-identical SVG, parity proven across architectures);
both artifacts sha256-chain into the trace. Egress to outputs
closes the one documented information-flow gap: a sink-only,
secret-specific declassification of the workflow boundary itself —
every embedded template now passes its own audit, zero exceptions.
nika explain --forecast computes duration/cost/risk priors from YOUR
local traces (p50/p90 earned at n ≥ 5 — deterministic stats, never a
model call). nika wire covers opencode and hermes (8
targets), the missing-input trap teaches at check time, and the
release tarball is funnel-gated — a stranger’s broken first run
never uploads.releasestructured-outputonboarding
2026-07-08 · native answers · the checker closes run-fail gaps · one lexer
Structured output goes native per provider — Anthropic’s
output_config.format, Gemini’s responseJsonSchema (the lossy
converter dies), OpenAI strict-mode honesty (not/allOf stripped at
the wire instead of 400ing) — with a coercion ladder that repairs
case-folded enums, string numbers and singleton arrays before any PAID
retry. The checker closes gaps that used to fail at run: the compact
block-sequence bomb that aborted every check/run is caught as
NIKA-PARSE-001, max_turns bounds and for_each over a typed
non-array are check-time findings, and env: binds at run exactly
as checked. The ${{ }} scanner becomes its own crate (nika-tmpl),
shared by checker AND runtime — parity by construction. And the first
30 seconds learn to speak: nika welcome mirrors your machine,
nika explain <file> narrates a workflow (cost honesty included),
nika init briefs six agent surfaces, --max-cost-usd refuses to
start when the static floor already exceeds the budget.Every journal line carries a hash chain —
nika trace verify walks
it and names the first broken link; export and replay check the chain
before trusting the data. nika trace reproduce compares a recorded
run against a fresh one and classifies every task (reproduced ·
nondeterministic · authored · environment). The journal attests its
engine (engine_version + platform on workflow_started). Models
are priced before the first run — 602 rules refreshed from
models.dev, per-model rates in check --json (the VS Code preflight
shows $in/$out per 1M on this tag). check IS the dry-run — the
plan names what dispatches in which wave. doctor --json speaks
machine; bare nika init/new converse on a terminal; and the dap
drift warn tells a re-encode from an edit (workflow_sha256_lf).nika dap brings time-travel replay debugging over the run journal —
breakpoints in your .nika.yaml, step forward AND backward, recorded
outputs in the Variables pane; the VS Code extension’s F5 integration
lights up on this tag. nika trace export projects any journal to
OTLP/JSON lines (Jaeger · Grafana · Langfuse — cost rides
gen_ai.usage.cost). nika check --json gains the requirements
section (models · keys · secrets · env) so editors and CI state
blockers before any token. A typo’d field now teaches: « unknown
field infr — did you mean infer? ». Runs record their source
(workflow_sha256) and skips say why (when · blocked_by). Plus:
doctor —ping v2, strict boolean args, the opt-in CSV
formula-injection guard.The 5 local servers (Ollama · LM Studio · llama.cpp · LocalAI · vLLM)
join
nika catalog with descriptions, tags and seed models — keyless
by construction, and sovereign models stay unpriced, never « free ».
38 providers in the engine’s catalog inventory (the canonical spec
set stays 16). A bare nika now suggests the next command
instead of a wall of help text. Fixes: nika:write honors
create_dirs: false loudly, nika:date resolves named timezones
from the bundled db, nika:log neutralizes terminal control
sequences, and the MCP stdio transport bounds its line reads.Two media builtins take the stdlib to 25:
nika:image_generate
(generation and editing, local-first providers, provenance manifests,
content credentials preserved) and nika:tts_generate (one sovereign
/v1/audio/speech wire · a real deterministic WAV under mock). Every
run now writes .nika/traces/ by default and --task scopes execution
to one upstream cone. The catalog rides the wire (catalog/tools --json plus their MCP twins — the read-only tool set on protocol
2026-07-28), cost_usd rides task_completed without ever faking a
zero, Hugging Face and NVIDIA join the 16-provider canonical catalog,
and nika doctor --ping actually probes the local ports.The pack vendored into the binary carries the qwen3.5 teach-cascade:
the first
nika examples run 01-hello of a fresh install works against
the local models people actually pull in July 2026. Plus the README
daily-commands block — the full 0.93 user loop in one place.Provider-plane HTTP timeout rises to 180s: 2026 open-weight thinking
models (qwen3.5 · gemma4) no longer die at the cloud-calibrated 30s
ceiling.
nika run --resume lands durable-lite resume — the trace IS
the checkpoint, completed tasks replay as visible cache hits (ADR-099).
nika test golden harness + ADR-098 schema wire selection + the CLI
verdict card. nika-cap admitted (all 12 gates) — 40 of 42 crates.The MCP oracle grows the learning tools (
nika_schema ·
nika_examples · nika_template · nika_canon). nika wire codex
patches ~/.codex/config.toml; the Claude Code marketplace ships one
plugin dir for two ecosystems. Exec hardening: provider API keys
scrubbed from exec children · env keys restricted to POSIX names ·
browser navigation guarded against private/loopback SSRF.Explicit onboarding wiring in the CLI ·
nika examples run takes a
--model override with an offline mock hint · headless build fixes
(xcap backend default-off · atspi 0.29) · doctor recognizes the
workspace Cursor MCP config · release pipeline separates the dev
version from brew assets.Diamond’s first tagged public release. CLI binaries for four
platforms (macOS arm64/x64 · Linux arm64/x64) via Homebrew and the
install script, cut by the release pipeline on the tag.
nika-cli and
nika-extract admitted the same morning — the operator surface and the
9 fetch extract modes. Real semver toward a 1.0.0 public launch —
quality over speed. Everything before this tag is rewrite history.The sprint that turned a foundation into a runnable engine. June 10:
the kernel splits into four siblings (
core · ai · runtime ·
plugin) and the effect crates land — nika-fs, nika-http,
nika-blob, nika-exec-runner, nika-input. June 11: nika-pack,
nika-providers, nika-browser, and all four verb crates admitted
the same day — infer · exec · invoke · agent. June 12:
nika-runtime (the DAG scheduler). June 15-18: nika-lsp,
nika-mcp, nika-builtin, nika-schema. June 21: nika-cli +
nika-extract — and the v0.90.0 tag ships that evening.The month the language reached its final shape, in the open
nika-spec repo
(Apache-2.0): the nika: v1 envelope (one field, forever), the four
verbs locked (infer · exec · invoke · agent — everything else
is a tool under invoke), CEL + jq as the only two expression layers,
agent tools default-deny, and the stdlib curated down to 22 builtins
with zero capability loss. Meanwhile the climb continued:
nika-catalog-codegen (May 10), nika-bm25 (May 12), nika-event +
nika-clock (May 24), nika-screen + nika-ocr + nika-a11y
(May 25).Added
- 4 new hygiene vectors (30-33):
check-cancel-safety.sh,check-owned-strings.sh,check-unsafe-count.sh,check-layer-deps.sh— the suite reaches 33 active vectors. - Forward-compat reservations: 5 seams pre-planted for the memory
subsystem + WASM eras:
EmbeddingSpec,MemoryFrameRef.trust,RecallQuery.tenant,WasmPluginError::OutOfFuel+PluginCallContext,MemoryLifecycletrait. - Telemetry seeds:
SpanGuard.parent_span_id+ W3C Trace Context linkage;Timestamp(i64 unix_ns)+WallDurationinnika-types::timestampwith RFC 3339 Display. - Test depth: 14 new proptest properties (TrustLevel lattice
invariants, ID serde roundtrip); Loom interleaving tests for
CancelCtx; a mutation baseline fornika-error. - 5 new ADRs: ADR-029 → ADR-032 + ADR-035 (telemetry seams).
Changed
ObservabilitySinkdropped → 5 sibling channels (Event · Metrics · Trace · Audit · Billing).- Engine hygiene enforces RED as fail / YELLOW as suggestion for routine pushes.
Crate admitted:
nika-catalog-verify (L4, 600 LOC, 9 tests, all 12
gates green). The first L4 interface crate: validates all catalog
TOMLs at build time via cargo run -p nika-catalog-verify.Crates admitted:
nika-kernel (L0.5) + nika-kernel-mock (L0.5).
40 ISP traits with sealed supertrait discipline. trait_variant::make
for async dynamic dispatch. Pure-memory mocks for hermetic test
environments. Preludes re-export nika-types + nika-error types
for ergonomic downstream imports.Crate admitted:
nika-catalog (L0). TOML-driven provider + model +
capability catalog with build-time codegen, perfect-hash lookup, Cow-
heavy zero-copy types. At admission: 105 MCP servers, 32 LLM providers,
13 embedding models in the inventory. Schema FK-check enforced in
build.rs.Crate admitted:
nika-error (L0). Typed NIKA-XXX error hierarchy,
miette integration for L4 diagnostics, per-crate error range
allocation, proptest-backed roundtrip invariants.The rewrite starts. An orphan branch created from scratch (as
nika-diamond, renamed main in May 2026) — zero shared history with
the brouillon. The constraint that defines everything after:
every crate must fit in an AI context window. ≤15k LOC per crate,
≤1,500 per file, ≤100 lines per function, zero .unwrap() in src/,
and 12 admission gates before a crate joins the workspace. First
admitted crate: nika-types (L0 foundation). The versioning policy
said « forever v0.x » at the time; it was later amended to real semver
toward 1.0.The final sprint says everything about the pace: v0.73 → v0.79 in
three days (April 6-8), v0.79.3 on April 9. Fourteen weeks after the
first commit, the brouillon engine is a working 322k-LOC, 31-crate
system — and it has surfaced the lesson Diamond is built on: at that
scale the biggest correctness risk stops being algorithmic and
becomes context. No human or AI assistant could hold the system
in working memory, so refactors happened by pattern-match, and
pattern-match hallucinates. Four days later the rewrite began. The
era is preserved read-only on the branch that named it —
brouillon, a private archive; nothing ships from it. Diamond
reads it, then rewrites from scratch.February 18 is the day the language grows teeth:
invoke: and
agent: land in the AST and the runtime, the MCP client appears,
and the provider layer learns tool calling — all in one day. Then
the storm: v0.3 (February 19) → v0.10 (February 25) → v0.17
(March 2) → v0.21 with a first language server (March 5). March
alone counts 2,900+ commits — the month the brouillon engine
became an ecosystem: LSP, security releases, CI/CD, release
automation. The era even has a public spine: seven crates.io
releases, 0.20.0 (March 4) → 0.47.1 (March 26) — later yanked,
listed forever.The first commit lands on New Year’s Day 2026:
initial nika v0.1 with strict templating system — followed the same week by DAG
validation, event sourcing for the workflow audit trail, and
fine-grained executor events. The shape of everything that followed —
declarative workflows, a DAG, an audit trail — is visible in week
one. ~4,600 commits follow in fourteen weeks. The era carries the
name its git branch carries: brouillon — the draft.Nika started as a frustration in 2025: useful AI work kept
disappearing into chat histories. A great run — a research brief, a
review procedure, a data pipeline — lived and died inside one
conversation, unrepeatable and unownable. The bet: durable agent
work should be source code — one file you can run, diff, review,
and keep; local-first; any model; sovereign by default. The idea was
tested in code from the start — private prototypes through the
summer and fall of 2025, pre-git and testimony-grade, and the
timeline labels them exactly that. The
first repo commit followed on January 1, 2026.
Full history
CHANGELOG.md
Every crate admission, every hygiene vector deploy, every ADR
promotion. Source of truth on the
main branch.Commit history
Every commit on the
main branch: atomic, bisectable,
Co-Authored-By Nika 🦋.GitHub Releases
Binaries for every tag: macOS arm64/x64 · Linux arm64/x64 ·
checksums + per-release notes.
Live state
Current test counts, clippy, hygiene, admitted crate inventory.
Roadmap
What’s next: the 0.9x hardening train, the contract system and the
whole Connectome landing before 1.0, the 1.0.0 culmination, 1.x
minors completing the layered foundation, then the ecosystem tier.