ADR-084
nika-catalog builtin set · reconciliation to spec 26 (42→26 stdlib collapse + json_merge cut)
accepted · 2026-05-27 · L0 · cites 7
0ADR-084 · nika-catalog reconciliation to spec 26 #
Context #
nika/spec/stdlib/builtins-v0.1.md (the canonical workflow language stdlib
per ADR-082 single-version-marker envelope nika: v1) ships 26 builtins
across 5 categories as of D-2026-05-22-N6 stdlib-collapse + 2026-05-27
nika:json_merge cut. The engine's nika-catalog::ALL_BUILTINS carried
63 entries across 10 categories as a fossil of pre-D-N6 era (engine
inventory grew during Sprint 2 + media planning before the spec
minimalism doctrine locked).
A monorepo-side §2.6 Signal 7 verify-the-auditor catch (2026-05-27 ·
studio/architecture/research/2026-05-27-g1-builtins-enum-codegen-design.md
§10 BLOCKER) surfaced the drift empirically · engine first-5 names were
aggregate · assert · chart · chunk · compare vs spec first-5
sleep · log · emit · assert · prompt. The drift gates the future
schemars-adoption G1 codegen (builtin-enum closed set in
workflow.schema.json for LSP-perfect completion · proposed-blocked
until catalog reconciliation lands).
This ADR locks the catalog reconciliation as the structural close.
Decision #
nika-catalog::ALL_BUILTINS and nika-catalog::types::builtin::BuiltinCategory
reconcile to spec source-of-truth nika/spec/stdlib/builtins-v0.1.md ·
- `ALL_BUILTINS` · 63 → 26 entries (46 legacy removed · 9 spec-only added · 17 keeps recategorised to the simplified 5-category enum).
- `BuiltinCategory` · 10 → 5 variants ·- KEEP · `Core` · `File` · `Data` · `Introspection` - ADD · `Network` (for `fetch` + `notify` · spec category) - REMOVE · `DataSprint2` · `CostRecords` · `Agent` · `MediaAlwaysOn` · `MediaCore` · `MediaOptIn` (6 variants · the 46 legacy entries that used them are all cut · zero workspace consumer matches on these variants per `grep -rn "BuiltinCategory::<v>" crates/`).
- `nika-schema::trust.rs` · 67 hardcoded
"nika:<name>"strings reduced to 26 across 3 trust categories (PROPAGATING 7 · PURE 14 · EXTERNAL 5 · the legacy REFERENCE category consolidated into PROPAGATING since they were semantically equivalent per the existing trust.rs comment · REFERENCE re-instates when media DEFERRED builtins land per LOCK-031). - Doc-comments ·
63 tools across 10 categories→26 tools across 5 categories(line 6 oftypes/builtin.rs).
Per-spec-category mapping (the canonical 26) #
- Category · N · Builtins
- Core · 7 · `sleep` · `log` · `emit` · `assert` · `prompt` · `done` · `wait_until`
- File · 5 · `read` · `write` · `edit` · `glob` · `grep`
- Data · 8 · `jq` · `json_diff` · `validate` · `json_merge_patch` · `csv_to_json` · `uuid` · `date` · `hash`
- Network · 2 · `fetch` · `notify`
- Introspection · 4 · `cost` · `records` · `dag_info` · `threads`
Total · 26. Alphabetically sorted in ALL_BUILTINS (binary-search
invariant preserved · unit-test sorted_order GREEN).
Trust-category mapping (per `nika-schema::trust.rs`) #
- Trust class · N · Builtins · Output trust
- PROPAGATING · 7 · `csv_to_json` · `glob` · `grep` · `jq` · `json_diff` · `json_merge_patch` · `read` · input
- PURE · 14 · `assert` · `cost` · `dag_info` · `date` · `done` · `emit` · `hash` · `log` · `records` · `sleep` · `threads` · `uuid` · `validate` · `wait_until` · Trusted
- EXTERNAL · 5 · `edit` · `fetch` · `notify` · `prompt` · `write` · Untrusted
Total · 26. Conservative classification · file edit is EXTERNAL (writes
to disk · observable side-effect) · file read/glob/grep are
PROPAGATING (input-trust passes through · no observable side-effect).
prompt is EXTERNAL because human/API input is by definition Untrusted
floor.
Consequences #
Positive #
- Spec ↔ engine parity ·
nika-catalognow mirrorsnika/spec/stdlibexactly · the catch-class « engine carries phantoms vs spec » closes structurally · future schemars-adoption G1 codegen (ADR-085 reserved) unblocks ·workflow.schema.jsonbuiltin_namecan ratchet from permissive pattern to closed enum derived fromALL_BUILTINS. - Trust surface lean · 67 → 26 hardcoded refs in
trust.rs· -61% surface area · easier to audit + verify the trust-floor invariant. - SemVer-clean enum simplification ·
BuiltinCategoryremoves 6 variants but#[non_exhaustive]is on the enum AND zero workspace consumers match on the removed variants · the breaking change is theoretical (cargo public-apiwill flag but no actual call-site breaks). - Forward-compat ·
Networkvariant added per#[non_exhaustive]ratchet · safely consumable when downstream wants per-category trust defaults. REFERENCE class consolidation into PROPAGATING is reversible if media builtins re-emerge (current LOCK-031 DEFERRED).
Negative #
- Public API surface change ·
BuiltinCategoryenum membership reshuffles ·cargo public-apidiff will show removed variants. Acceptable per ADR-002 (amended D-2026-06-20-N1 · real semver toward 1.0) · the workspace is pre-1.0 · breaking MINOR ratchets are allowed pre-launch. - Trust.rs REFERENCE category gone · the documentation-only split between PROPAGATING and REFERENCE (both passed input trust) is now collapsed · reintroduces when media DEFERRED builtins land. Cost · ~0 (semantically equivalent today · just a code-organization signal).
Neutral #
- Tests · +2 net new ·
legacy_builtins_unknown_post_d_n6(trust)+ `category_totals_match_spec_26` (trust) · plus `builtin_count` + `category_counts` + `is_known_builtin_works` updated for the new totals. 1170 baseline → 1172 tests GREEN.
Alternatives considered #
A · Keep 63 catalog · LSP codegen filters to spec 26 at build time #
REJECTED · the source-of-truth divergence stays · spec ↔ engine parity is never structural · drift recurs at each spec update · two truth sources is the anti-pattern this ADR closes.
B · Defer to L2 `nika-builtin` admission (the MEMORY-pointer framing) #
REJECTED post user-explicit override (« ship reconciliation now »
AskUserQuestion 2026-05-27). The L2-future framing remained valid as
long as no consumer needed the spec-26 set today · the schemars-adoption
G1 plan + the canon coherence work surfaced an immediate consumer signal
that overrode the LOCK-031 spirit · the user redirected accordingly.
Documented per dx/.claude/rules/socratic-research-discipline.md §5c
(Option D · don't pick least bad).
C · Mass-rename engine to keep 63 set + mark legacy as deprecated #
REJECTED · violates dx/.claude/rules/no-legacy-no-back-compat.md
NUKE-LEGACY doctrine + Class 1 single-canonical-set discipline ·
deprecated-alias drift accumulates · git history is the archive.
Gate verification #
This is a refactor of admitted-crate data + types (not a new crate admission) · the ADR-003 12-gate ceremony reduces to applicable gates ·
- Gate 2 TDD · ✓ existing tests updated to spec 26 · 2 new tests added · 1172 lib tests GREEN.
- Gate 3 IMPL · ✓
cargo check --workspaceGREEN. - Gate 4 CLIPPY · ✓
cargo clippy --workspace --all-targets -- -D warnings0 warnings (post 8 doc_markdown backtick fixes). - Gate 8 DOCS · ✓
cargo doc --no-deps -p nika-catalog -p nika-schema0 warnings. - Gate 12 ATOMIC · ✓ single commit · co-authored Nika 🦋.
cargo fmt --check✓ GREEN.cargo deny check✓ advisories/bans/licenses/sources ok.- Gates 1 / 5 / 6 / 7 / 9 / 10 / 11 · N/A for data refactor (no new crate · no new logic surface beyond data shape).
Companion artefacts #
nika-catalog/src/data/builtins.rs· 63 → 26 entries · 5-category reorganization · tests updated.nika-catalog/src/types/builtin.rs·BuiltinCategory10 → 5 variants · doc-comment refreshed.nika-catalog/src/lib.rs·all_builtins_non_emptytest 63 → 26.nika-schema/src/trust.rs· 67 → 26 hardcoded refs · 4 → 3 trust category lists · 2 new tests.studio/architecture/research/2026-05-27-g1-builtins-enum-codegen-design.md· §10 BLOCKER inventory + reconciliation scope (the design + audit trail · monorepo-side).nika/spec/stdlib/builtins-v0.1.md· the canonical source-of-truth (unchanged · this ADR mirrors it into the engine).
References #
nika/spec/stdlib/builtins-v0.1.md· spec canonical 26 + cuts- ADR-082 · envelope
nika: v1single-version-marker - D-2026-05-22-N6 · stdlib-collapse 42 → 27 (monorepo decision)
- 2026-05-27
nika:json_mergecut ·jaqsource-verified dx/.claude/rules/no-legacy-no-back-compat.md· NUKE-LEGACY disciplinedx/.claude/rules/cross-source-validation.md§2.6 Signal 7 verify-the-auditordx/.claude/rules/round-1-ship-pattern.md§6 LOCK-031 trigger-gated
🦋
read at v0.107.0 · the decision record ships with the engine