Ctrl K
ComunidadGuías…

Cargo.toml

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
[workspace]
resolver = "3"
members  = ["crates/nika-types", "crates/nika-error", "crates/nika-catalog", "crates/nika-catalog-codegen", "crates/nika-catalog-verify", "crates/nika-chart", "crates/nika-cadence", "crates/nika-arm", "crates/nika-kernel", "crates/nika-kernel-ai", "crates/nika-kernel-core", "crates/nika-kernel-runtime", "crates/nika-kernel-plugin", "crates/nika-kernel-mock", "crates/nika-schema", "crates/nika-check", "crates/nika-check-analyzer", "crates/nika-check-wasm", "crates/nika-source", "crates/nika-store", "crates/nika-vocab", "crates/nika-lints", "crates/nika-graph", "crates/nika-bm25", "crates/nika-screen", "crates/nika-event", "crates/nika-extract", "crates/nika-exec-runner", "crates/nika-sandbox-seatbelt", "crates/nika-sandbox-landlock", "crates/nika-blob", "crates/nika-clock", "crates/nika-fs", "crates/nika-fx", "crates/nika-http", "crates/nika-ocr", "crates/nika-a11y", "crates/nika-input", "crates/nika-browser", "crates/nika-pack", "crates/nika-proof", "crates/nika-providers", "crates/nika-providers-access", "crates/nika-infer-local", "crates/nika-verb-infer", "crates/nika-verb-exec", "crates/nika-verb-invoke", "crates/nika-verb-agent", "crates/nika-builtin", "crates/nika-cel", "crates/nika-registry-client", "crates/nika-runtime", "crates/nika-runtime-laws", "crates/nika-execution", "crates/nika-service-execution", "crates/nika-cli", "crates/nika-cli-host", "crates/nika-cli-host-typesafe", "crates/nika-session", "crates/nika-session-change", "crates/nika-session-agent", "crates/nika-session-host", "crates/nika-session-intelligence", "crates/nika-trace", "crates/nika-tui-core", "crates/nika-tui", "crates/nika-tui-view", "crates/nika-lsp", "crates/nika-mcp", "crates/nika-dap", "crates/nika-display", "crates/nika-onboard", "crates/nika-onboard-knowledge", "crates/nika-compile", "crates/nika-compile-reader", "crates/nika-compile-cognition", "crates/nika-compile-fidelity", "crates/nika-compile-trigger", "crates/nika-compile-clauses", "crates/nika-compile-seats", "crates/nika-compile-behavior", "crates/nika-models", "crates/nika-cap", "crates/nika-pck-manifest", "crates/nika-tmpl", "crates/nika-migrate", "crates/nika-harness", "crates/nika-secret", "crates/nika-dataflow", "crates/nika-serve"]
# Excluded so cargo does not try to descend into untracked main-leftover
# manifests under crates/ (the orphan working tree carries them but they
# are not part of the diamond workspace).
exclude = [
  "crates/nika-acp",
  "crates/nika-core", "crates/nika-daemon", "crates/nika-display", "crates/nika-engine",
  "crates/nika-init",
  "crates/nika-lsp-core", "crates/nika-macros",
  "crates/nika-media", "crates/nika-policy", "crates/nika-sdk", "crates/nika-security",
  "crates/nika-storage", "crates/nika-vault",
  "crates/nika-verb-fetch", "crates/nika",
]

[workspace.package]
version      = "0.124.3"
edition      = "2024"
license      = "AGPL-3.0-or-later"
authors      = ["Thibaut Melen <thibaut@supernovae.studio>"]
rust-version = "1.91"
repository   = "https://github.com/supernovae-st/nika"
homepage     = "https://supernovae.studio"

# ─────────────────────────────────────────────────────────────────────────────
# Diamond layer assignments — enforced by scripts/ci/check-layering.sh.
# L0 = zero I/O, zero async. L0.5 = trait-only. L4 = interface crates.
# See docs/architecture/crate-layer-registry.md for the full discipline.
# ─────────────────────────────────────────────────────────────────────────────

[workspace.metadata.diamond]
# WIP crates: in the workspace but pre-admission (no complete 12-gate table
# yet). SINGLE SOURCE for the admitted-vs-WIP split — scripts/crate-metrics.sh
# is the projector that reads this; refresh-status.sh + check-crate-specs.sh
# query the projector (never re-hardcode the list). When a crate is admitted,
# remove it from this array — one edit, here, period.
wip = ["nika-chart", "nika-fx", "nika-proof", "nika-store", "nika-harness", "nika-execution", "nika-service-execution", "nika-serve", "nika-session", "nika-session-change", "nika-session-agent", "nika-session-host", "nika-session-intelligence", "nika-tui", "nika-tui-view"]
# nika-pack · the embedded language pack (spec snapshot + manifest hashes ·
# proposal branch feat/nika-pack · pure data · include_dir · zero I/O).
layers.nika-chart = "L0"
# nika-chart · deterministic chart artifacts (CHT master plan · stdlib §Media
# graduate #3 candidate · zero-dep · byte-identical SVG → trace chain).
# nika-cadence · the arming-registry grammar (the arm: block of nika.yaml,
# D-2026-08-10-N3) + the pure next-slot calculator · hand-counted 5-field
# cron (zero cron library — the count is the TYPE) · embedded IANA tzdb ·
# the DST shift DECLARED in the Slot type (N1) · WIP (the 12-gate admission
# lands at V3⑪ of the arming-registry plan).
layers.nika-cadence = "L0"
# nika-tui-core · the TUI session LAW (session model · derivation · plan
# seating · claims) in one crate, native + WASM (D-2026-08-11-N6 · T28) ·
# the parity proof rides the studio's fixtures bit-exact · WIP (gates
# 1-6+8 green · swarm + consumer swap owed).
layers.nika-tui-core = "L4"
# nika-tui · the Ratatui renderer of the session · inline-first · one terminal owner (ADR-139)
layers.nika-tui = "L4"
# nika-tui-view · the viewers of the object in view (pure · typed facts and bytes in, styled
# lines out) · size-cap member of the nika-tui unit (D-2026-07-09-N1 · ADR-143 · 2026-09-30) ·
# lateral L4→L4 edge nika-tui → nika-tui-view, never back.
layers.nika-tui-view = "L4"
layers.nika-pack = "L0"
# nika-proof · the spec-15 proof layer's hash primitives + the one receipt ·
# split from nika-runtime 2026-07-29 (the 15k crate-size cap · the
# nika-dap/nika-cap precedent) · nika_runtime::proof re-exports it whole, so
# every consumer path (`…::proof::{preimage, receipt, …}`) holds unchanged.
layers.nika-proof = "L0"
# nika-cli · the operator surface (D-2026-06-10-N6 first-15-min suite) · seeded
# 2026-06-11 with the display fold + trace verbs per docs/crate-specs/nika-cli.md.
layers.nika-cli = "L4"
layers.nika-cli-host = "L4"
# nika-cli-host-typesafe · the TypeSafe System One decision seat · size-cap member of the nika-cli
# unit (D-2026-07-09-N1 · the ADR-110 amendment) · lateral L4→L4 edge nika-cli-host →
# nika-cli-host-typesafe, never back.
layers.nika-cli-host-typesafe = "L4"
# nika-arm · the descriptor-rooted ARM custody and one firer shared by
# the CLI and every later execution interface (ADR-114/117).
layers.nika-arm = "L4"
# nika-serve · the L4 remote execution projection. W05 admitted its durable
# descriptor-rooted state plane; W06 stages authenticated loopback HTTP.
# SSE, OpenAPI/SDK, and full crate admission remain later carriers.
layers.nika-serve = "L4"
# nika-trace · the flight-recorder reader (the trace verbs · evidence ·
# receipt · the learned-truth forecast · the bin's trace arm) · split from
# nika-cli 2026-08-11 (the 15k crate-size cap · D-2026-07-09-N1 one unit,
# two members · the ADR-110 cli-host precedent) — re-exported at the
# historical verbs:: paths, so every consumer reads unchanged.
layers.nika-trace = "L4"
# nika-dap · the DAP replay server + the shared forensic seams (recover ·
# chain) · split from nika-cli's verbs/dap 2026-07-09 (the
# crate-size cap · the nika-cap precedent) · source_id re-homed to
# nika-event 2026-07-22 (the run-composer descent needed the hash at L≤3).
layers.nika-dap = "L4"
layers.nika-display = "L4"
layers.nika-onboard = "L4"
# nika-onboard-knowledge · the knowledge door: the strict admission of a Foundry release, the
# embedded releases, the catalogue and the authoring pack · size-cap member of the nika-onboard
# unit (D-2026-07-09-N1 · the ADR-137 amendment) · lateral L4→L4 edge nika-onboard →
# nika-onboard-knowledge, never back.
layers.nika-onboard-knowledge = "L4"
# nika-compile · the stateless Compile core · size-cap member of the nika-onboard unit
# (D-2026-07-09-N1 · ADR-137 · 2026-09-21) · lateral L4→L4 edge nika-onboard → nika-compile,
# never back.
layers.nika-compile = "L4"
# nika-compile-reader · the frozen deterministic reader and the typed plan it produces ·
# size-cap member of the same unit (D-2026-07-09-N1 · the ADR-137 precedent · 2026-09-21) ·
# lateral L4→L4 edge nika-compile → nika-compile-reader, never back.
layers.nika-compile-reader = "L4"
# nika-compile-cognition · the seats' doors (COLD · native · sketch · transform · knowledge ·
# decision seats) · size-cap member of the same unit (D-2026-07-09-N1 · ADR-140 · 2026-09-23) ·
# lateral L4→L4 edges cognition → core, fidelity and reader; none points back to cognition.
layers.nika-compile-cognition = "L4"
# nika-compile-fidelity · the laws a candidate document is judged by, the seat's sketch and the
# plan a candidate states · size-cap member of the same unit (D-2026-07-09-N1 · ADR-141 ·
# 2026-09-24) · lateral L4→L4 edges nika-compile → nika-compile-fidelity → nika-compile-reader,
# never back.
layers.nika-compile-fidelity = "L4"
# nika-compile-trigger · the trigger reading of a request (its words, cadence, time of day,
# multiples, cron fields and clause form) · size-cap member of the same unit (D-2026-07-09-N1 ·
# ADR-142 · 2026-09-30) · lateral L4→L4 edges nika-compile → nika-compile-trigger →
# nika-compile-reader, never back.
layers.nika-compile-trigger = "L4"
# nika-compile-clauses · how one clause of a request reads above the reader (the parts a verifier
# asks alone, the prohibition reading, the clause key, the stated spellings) · size-cap member of
# the same unit (D-2026-07-09-N1 · ADR-145 · 2026-10-07) · lateral L4→L4 edges
# nika-compile-cognition → nika-compile-clauses → nika-compile-reader, never back.
layers.nika-compile-clauses = "L4"
# nika-compile-seats · the decision seats and the rehearsal port a host lends a preparation, with
# the reasoning record their calls share · size-cap member of the same unit (D-2026-07-09-N1 ·
# ADR-146 · 2026-10-07) · lateral L4→L4 edges nika-compile-cognition → nika-compile-seats →
# nika-compile, never back.
layers.nika-compile-seats = "L4"
# nika-compile-behavior · the behavioural contract a request states and its typed judgment over
# rehearsals, with the date-time shape classifier the judge and the candidate laws both read ·
# size-cap member of the same unit (D-2026-07-09-N1 · ADR-149 · 2026-10-09) · lateral L4→L4
# edges nika-compile-fidelity → nika-compile-behavior → nika-compile-reader, never back.
layers.nika-compile-behavior = "L4"
# nika-models · the local-models unit (ONE canonical dir · Hub pull · serve
# glue) · split from nika-cli's verbs/model 2026-07-12 (the crate-size cap ·
# the nika-onboard/nika-display precedents).
layers.nika-models = "L4"
layers.nika-lsp = "L4"
layers.nika-check-wasm = "L4"
# nika-check-wasm · the static check surface compiled to the browser (parse +
# conformance over nika-schema/nika-check · wasm-bindgen transport ·
# differential-gated vs the CLI · admitted ADR-107 · npm via the release train).
# nika-mcp · the in-binary MCP server (announce floor `nika mcp`) · hand-rolled
# newline-delimited JSON-RPC 2.0 over stdio (serde_json only · zero SDK) ·
# exposes the static read-only surface (nika_check · nika_explain) as MCP tools.
layers.nika-mcp = "L4"
# nika-session · the native session (bare `nika` on a terminal · ADR-125) · a host
# runtime over the installed engine — the snapshot, the chosen intelligence, the
# context broker, the hallucination guard — never a workflow.
layers.nika-session = "L4"
# nika-session-change · the project change a proposal writes, its review, its outcome and the
# consent record · size-cap member of the nika-session unit (D-2026-07-09-N1 · ADR-144 ·
# 2026-10-06) · lateral L4→L4 edge nika-session → nika-session-change, never back.
layers.nika-session-change = "L4"
# nika-session-agent · the conversation the Session's selected intelligence leads: the loop over
# one model and the Session's tools (no step, turn or token quota), the person's steering and
# follow-up lines, the Session tree and its compaction · member of the nika-session unit
# (ADR-153 · the ADR-144 pattern) · lateral L4→L4 edges nika-session → nika-session-agent →
# nika-session-change, never back.
layers.nika-session-agent = "L4"
# nika-session-host · the native Session over a wire: one host adapter around the actual
# SessionRuntime, its NDJSON machine door and its HTTP routes · size-cap member of the
# nika-session unit (D-2026-07-09-N1 · ADR-144 pattern) · lateral L4→L4 edge
# nika-session-host → nika-session, never back.
layers.nika-session-host = "L4"
# nika-session-intelligence · the intelligence a session reasons, routes and authors with: the
# census and the choice, the reasoners, the line router and the authoring door (the seat, its
# context and the round) · size-cap member of the nika-session unit (D-2026-07-09-N1 · ADR-150 ·
# 2026-10-09) · lateral L4→L4 edge nika-session → nika-session-intelligence, never back.
layers.nika-session-intelligence = "L4"
layers.nika-types = "L0"
layers.nika-error = "L0"
layers.nika-event = "L0"
layers.nika-cap = "L0"
layers.nika-pck-manifest = "L0"
layers.nika-tmpl = "L0"
layers.nika-clock = "L1"
# nika-fs · Phase-B slice step 4 (announce ladder · D-2026-06-10-N6 cascade) ·
# implements kernel io::fs {FsRead,FsWrite,FsMeta,FsList} · tokio::fs + globset ·
# atomic write (temp+rename per kernel CANCEL SAFETY contract) · typed FsError
# (Pattern A · FCI-023bis · NIKA-110..119).
layers.nika-fs = "L1"
# nika-fx · deterministic artistic image effects (dither · palette · duotone ·
# halftone · retro · glitch · ascii) · pure-algo zero-dep · byte-identical
# artifacts (attested styled media) · behind nika:image_fx · FX master plan.
layers.nika-fx = "L1"
# nika-blob · Phase-B slice step 6 (announce ladder · D-2026-06-10-N6 cascade) ·
# implements kernel io::blob BlobStore via blake3 CAS · sharded fs layout ·
# atomic temp+rename (unique temp) · sidecar .mime (put/stat round-trip) · size cap.
layers.nika-blob = "L1"
# nika-exec-runner · Phase-B slice step 7 (announce floor `exec` · D-2026-06-10-N6) ·
# implements kernel io::process {ShellRun,ShellCancel} via tokio::process · command
# blocklist (NFKC + zero-width + quote/basename bypass defenses) · kill_on_drop + concurrent drain.
layers.nika-exec-runner = "L1"
# nika-sandbox-seatbelt · macOS CommandSandbox impl (ADR-095 Layer 6 · the
# per-platform sandbox pair named by plugin::sandbox) · wraps a command in
# sandbox-exec with an SBPL profile from permits · no unsafe, no FFI.
layers.nika-sandbox-seatbelt = "L1"
# nika-sandbox-landlock · Linux CommandSandbox impl (ADR-095 Layer 6 · the
# Linux half of the per-platform sandbox pair) · wraps a command in bwrap with a
# namespace jail from permits · no unsafe, no FFI · Landlock LSM hardening owed.
layers.nika-sandbox-landlock = "L1"
# nika-http · Phase-B slice step 5 (announce ladder · D-2026-06-10-N6 cascade) ·
# implements kernel io::http {HttpGet,HttpPost} via reqwest · SSRF defense
# (static + DNS-resolve + per-hop redirect re-check) · response size cap.
layers.nika-http = "L1"
# nika-harness · the harness access class client (D-2026-08-04-N1 P3 · Lane A) ·
# hand-rolled ACP wire-v1 over JSON lines · impl of the kernel AgentBackend seam ·
# docs/crate-specs/nika-acp.md §2bis (the SDK stays quarantined · never linked).
layers.nika-harness = "L1"
# nika-secret · workflow secret RESOLUTION (descended from nika-runtime
# 2026-08-06 at the 15k wall · pure · the scrub half stays behind).
layers.nika-secret = "L1"
# nika-dataflow · the run's pure dataflow — TaskRecord + the ${{ }}/CEL/jq
# evaluation over it (descended from nika-runtime in the v0.115 development
# line · zero I/O, zero async, zero clock). Mechanical sort makes pure logic
# L0; ADR-027's explicit fanout policy records why the five sibling inputs are
# one cohesive evaluation unit rather than disguising the crate as an effect.
layers.nika-dataflow = "L0"
# nika-providers · Phase-B slice step 8.5 (announce ladder · D-2026-06-10-N6) ·
# implements kernel ai::provider {ProviderInferDyn,ProviderStreamDyn,ProviderMeta} ·
# 14 canonical profiles over 3 wire formats · transport via kernel http (no reqwest here).
layers.nika-providers = "L1.5"
# nika-providers-access · the probe facts, the access plan and the route identity · size-cap
# member of the nika-providers unit (D-2026-07-09-N1 · the ADR-122 member note) · lateral L1.5
# edge nika-providers → nika-providers-access, never back.
layers.nika-providers-access = "L1.5"
# nika-infer-local · sovereign local inference sidecar (ADR-091) · all-Rust
# replacement for the ollama dependency · OpenAI-compat surface (reuses the
# nika-providers wire) · subprocess-isolated · candle backend feature-gated
# off (`local-infer`) · v1 scaffold = protocol + Backend seam + MockBackend.
layers.nika-infer-local = "L1.5"
# nika-verb-infer · Phase-B slice step 9 (announce ladder · D-2026-06-10-N6) ·
# FIRST L2 verb crate · one-shot inference per spec 02-verbs.md §infer ·
# resolves provider/model via nika-providers · structured-output floor
# (ResponseFormat + bounded schema-validation retry) · NIKA-430..433.
layers.nika-verb-infer = "L2"
# nika-verb-exec · announce-ladder s10 · the exec verb per spec 02-verbs.md §exec ·
# kernel ShellRunDyn injected (TokioShell prod · MockShell test) · pre_validated
# never set (s7 blocklist floor) · capture one-obvious-way split · NIKA-440..442.
layers.nika-verb-exec = "L2"
# nika-verb-invoke · announce-ladder s11 · the invoke verb per spec 02-verbs.md §invoke ·
# kernel ToolExecuteDyn injected (engine builtin+MCP dispatcher) · closed nika:/mcp:
# namespace validated before dispatch · NIKA-450..452.
layers.nika-verb-invoke = "L2"
# nika-verb-agent · the 4th verb (s12 · multi-turn ReAct loop · D-2026-05-22-N18) · seeded
# 2026-06-11 against the ToolDefinitionProvider seam per docs/crate-specs/nika-verb-agent.md.
layers.nika-verb-agent = "L2"
layers.nika-registry-client = "L2"
layers.nika-runtime = "L3"
layers.nika-runtime-laws = "L3"
# nika-execution · the one descriptor-rooted admission boundary shared by
# every interface: captures root/child/skill/import bytes once, checks the
# immutable closure, then gives runners no filesystem capability.
layers.nika-execution = "L3"
# nika-service-execution · the ONE shared production execution driver over an
# admitted world: it joins nika-runtime (generic wave-ordered execution) and
# nika-execution (byte admission) so the local CLI/ARM surface and the service
# surface run the SAME composition root and the SAME child-composition
# decisions. Descended out of nika-runtime at the 15k prod-LOC wall
# (nika-proof/nika-secret precedent · runtime measured 16024 > 15000 before
# the split). Same-layer L3 by the mechanical sort — it consumes two L3 peers
# and no interface.
layers.nika-service-execution = "L3"
# nika-builtin · announce-ladder s16 · the 22 stdlib v0.1 builtins behind ONE dispatcher
# implementing the three kernel tool seams (ToolExecuteDyn+ToolBatchDyn+ToolDefinitionProviderDyn) ·
# composes the L1 effects (fs · http · clock · event-sink) · spec docs/crate-specs/nika-builtin.md.
layers.nika-builtin = "L1.5"
# nika-extract · the 9 fetch extract modes (pure byte→structured transform · zero
# I/O · consumed by nika-builtin nika:fetch per admission steps 12+13).
layers.nika-extract = "L1.5"
layers.nika-catalog = "L0"
layers.nika-catalog-codegen = "L0"
layers.nika-catalog-verify = "L4"
layers.nika-schema = "L0"
# nika-check · the static judgment crate (the workflow analyzer — Core
# conformance + the derived DAG edges — plus the `nika check` pre-flight
# ladder: cost ceiling · secret-leak IFC · capability-escape fit · trifecta
# · policy · gate reachability · RunCertificate) · split from nika-schema
# 2026-07-21 (the 15k crate-size wall · the nika-graph/nika-dap precedents)
# — L0 not L1: pure/sync/zero-I/O, and THREE L0 consumers (nika-lints ·
# nika-graph · nika-schema's own skill.rs) make any higher layer an
# upward-dep violation per check-layering.sh. Parser there, judgment here.
layers.nika-check = "L0"
layers.nika-check-analyzer = "L0"
layers.nika-source = "L0"
# nika-vocab · the .nika configuration vocabulary (capture/decode/retry/
# duration/secret/var+output declarations) · third member of the nika-schema
# architectural unit (size-cap split · D-2026-07-09-N1 · the nika-source
# precedent) — re-exported wholesale at nika_schema::types.
layers.nika-vocab = "L0"
# nika-migrate · the .nika envelope migrations (W1 map · W2 equivalence-
# or-stop flow) · the repairs `check --fix` applies · split from nika-cli's
# src/migrate.rs 2026-07-15 (the crate-size cap · the nika-source/nika-vocab
# precedent) — pure std, zero deps, consumed by nika-cli's fix verb.
layers.nika-migrate = "L0"
layers.nika-lints = "L0"
# nika-graph · the canonical graph projection (graph_format: 2 · spec 03
# §graph-projection) · split from nika-schema 2026-07-13 (the crate-size
# cap · the nika-dap/nika-models precedents) — one projector, every surface.
layers.nika-graph = "L0"
# nika-cel · the cel-subset/0.1 expression engine (lexer · parser · typed computer
# over a Resolver) · the ONE CEL surface shared by nika-schema (static shape) +
# nika-runtime (the expr seam) · spec docs/crate-specs/nika-cel.md.
layers.nika-cel = "L0"
layers.nika-kernel = "L0.5"
layers.nika-kernel-ai = "L0.5"
layers.nika-kernel-core = "L0.5"
layers.nika-kernel-runtime = "L0.5"
layers.nika-kernel-plugin = "L0.5"
layers.nika-kernel-mock = "L0.5"
# nika-bm25 · W3 admission target · single-crate-feature-gated per devil's
# advocate 2026-05-12 audit (Option E supersedes 2-crate split) · ADR-038
# binding · spec docs/crate-specs/nika-bm25.md · `kernel` feature default-on
# Diamond-internal · external crates.io consumers `--no-default-features`
layers.nika-bm25 = "L1"
# nika-store · F-P8 signed-memory substrate (SMSR · spec docs/crate-specs/nika-store.md) ·
# signed-write/verified-recall over `.nika/memory/<store>/` · minisign over the JCS
# envelope · the run-signing key INJECTED (custody stays L4) · NIKA-605.
layers.nika-store = "L1"
# nika-screen · M2.1 first computer-use L1 effect crate (ADR-081 guards 6+7) ·
# implements kernel io::screen ScreenCapture · xcap backend (B.3) · NIKA-1000..1099.
layers.nika-screen = "L1"
# nika-ocr · M2.2 second computer-use L1 effect crate (no mandatory guard) ·
# implements kernel io::ocr OcrEngine · ocrs pure-Rust backend (B.3) · NIKA-1100..1199.
layers.nika-ocr = "L1"
layers.nika-a11y = "L1"
# nika-input · M2.4 fourth computer-use L1 effect crate · FIRST write-side ·
# implements kernel io::input InputDeviceDyn · enigo cross-platform backend ·
# ADR-081 Guards 1+2 MANDATORY · NIKA-1300..1399.
layers.nika-input = "L1"
# nika-browser · M2.5 fifth computer-use L1 effect crate · CDP web arm ·
# implements kernel io::browser BrowserAutomationDyn · chromiumoxide backend (B.3) ·
# ADR-081 Guard 5 MANDATORY (selector clickjacking) · NIKA-1400..1499.
layers.nika-browser = "L1"

# ─────────────────────────────────────────────────────────────────────────────
# Per-layer banned external deps (runtime-binding crates forbidden at layers
# that must stay runtime-agnostic). Enforced by
# scripts/hygiene/check-layer-deps.sh (vector 33).
#
# L0 = pure data + logic, no async runtime, no I/O binding.
# L0.5 = trait-only surface, uses `trait_variant` for async-fn desugaring
#        (no direct tokio/futures dep in the trait crate itself).
# L1+ = effect impls may bind to tokio and its ecosystem.
# ─────────────────────────────────────────────────────────────────────────────
layer-bans.L0 = ["tokio", "tokio-util", "tokio-stream", "tokio-macros", "rayon", "async-std", "smol", "futures", "futures-util", "futures-core", "futures-channel", "async-channel", "reqwest", "hyper", "h2", "axum", "actix-web"]
layer-bans."L0.5" = ["tokio", "tokio-util", "tokio-stream", "rayon", "async-std", "smol", "reqwest", "hyper", "h2", "axum", "actix-web"]

# ─────────────────────────────────────────────────────────────────────────────
# Workspace-wide lint policy. Every member crate MUST opt in via:
#     [lints]
#     workspace = true
# ─────────────────────────────────────────────────────────────────────────────

[workspace.lints.rust]
unsafe_code                    = "forbid"
unused_must_use                = "deny"
elided_lifetimes_in_paths      = "warn"
unreachable_pub                = "warn"
explicit_outlives_requirements = "warn"
unused_extern_crates           = "warn"
# Declare `cfg(loom)` as a known config flag so `#[cfg(loom)]` in
# nika-types::cancel (and any future concurrent primitive) doesn't
# emit `unexpected_cfgs` warnings on normal `cargo build`. Loom tests
# run explicitly via `RUSTFLAGS="--cfg loom"`.
unexpected_cfgs                = { level = "warn", check-cfg = ['cfg(loom)'] }

[workspace.lints.clippy]
# Group levels (priority = -1 so individual lints below win)
correctness = { level = "deny", priority = -1 }
suspicious  = { level = "warn", priority = -1 }
perf        = { level = "deny", priority = -1 }
pedantic    = { level = "warn", priority = -1 }

# Core "diamond" lints — zero tolerance on production src/
unwrap_used    = "deny"
expect_used    = "warn"
panic          = "deny"
todo           = "warn"
unimplemented  = "warn"
unreachable    = "warn"
dbg_macro      = "deny"
# Iterating a HashMap/HashSet is ordering-nondeterminism by construction —
# poison for an engine whose outputs, manifests and goldens must be
# byte-stable. BTree/sorted structures everywhere (measured: 0 violations
# across 40 crates when adopted · the ruff workspace carries the same lint).
iter_over_hash_type = "deny"
print_stdout   = "warn"
print_stderr   = "warn"
# Per-function 100-LOC soft cap (ADR-023). Function modularity discipline.
too_many_lines = "warn"

# World-class discipline (post-blueprint v1.1 audit · 2026-05-12)
# `must_use_candidate` + `let_underscore_must_use` DEFERRED to ratchet sprint ·
# existing codebase ships 126 candidate sites · enabling either at warn breaks
# `-D warnings` CI gate · queue as standalone refactor with `#[expect(...)]`
# baseline per uv pattern · v0.85 milestone target.

[workspace.lints.rustdoc]
# Compile-time doc discipline (was script-only via check-doc-private-items.sh)
broken_intra_doc_links     = "deny"
private_intra_doc_links    = "warn"
invalid_codeblock_attributes = "deny"
bare_urls                  = "warn"

# ─────────────────────────────────────────────────────────────────────────────
# Shared dependencies. Populated when Phase 1 extract-ready crates land.
# Rule (RUST_ENFORCEMENT §2): pin once here, downstream = `.workspace = true`.
# ─────────────────────────────────────────────────────────────────────────────

[workspace.dependencies]
# Pin once here, downstream uses `.workspace = true` (RUST_ENFORCEMENT §2).
thiserror  = "2.0"
minisign   = { version = "0.9", default-features = false }   # the seal/signature primitive (nika-dap custody · nika-store F-P8 envelopes)
regex      = "1.11"     # nika-builtin L1.5 — nika:grep pattern engine (RE2-class · no backrefs · the portable subset)
include_dir = "0.7"   # nika-pack L0 · compile-time spec-pack embedding
sha2 = "0.10"         # nika-pack dev · manifest integrity hashing + nika-event L0 · the source-identity hash
hmac = "0.12"         # nika-cli L4 — ADR-111 Standard Webhooks signature (RustCrypto · pairs with sha2)
miette     = "7.6"
serde      = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
toml_edit  = "0.25"   # nika-cli L4 — `nika wire codex` patches ~/.codex/config.toml (comment-preserving)
marked-yaml  = "0.8"
serde-saphyr = { version = "1.0.0", features = ["miette"] }
phf        = { version = "0.14", features = ["macros", "unicase"] }
unicase    = "2.9"

trait-variant = "0.1"
bytes         = { version = "1", features = ["serde"] }
http-body-util = "0.1"  # nika-serve L4 — bounded HTTP body collection for the W06 listener
hyper         = { version = "1", features = ["http1", "server"] }  # nika-serve L4 — HTTP/1.1 loopback listener (no TLS)
hyper-util    = { version = "0.1", features = ["tokio"] }  # nika-serve L4 — Tokio IO adapter for Hyper
subtle        = "2.6"   # nika-serve L4 — constant-time Bearer digest compare
blake3        = "1"     # nika-blob L1 — content-addressed hashing (CC0-1.0 OR Apache-2.0 · allowlisted)
serde_json_canonicalizer = "0.3"   # nika-runtime L3 — RFC 8785 JCS bytes under the ADR-099 resume keys (MIT · rides the existing serde_json/ryu stack)
annotate-snippets = "0.12"          # nika-cli L4 — rustc-grade painted diagnostics (rust-lang org · cargo depends on it · MIT OR Apache-2.0)
anstyle = "1"                       # nika-cli L4 — the Style type annotate-snippets' renderer consumes (colour stays OUR seam mapping)
unicode-normalization = { version = "0.1", default-features = false }   # nika-types L0 (the shared argv exec-floor predicate · #605) — NFKC confusable-bypass defense in the command blocklist · no_std-compatible (the L0 leaf's no-std seam stays intact) · MIT OR Apache-2.0
nix           = { version = "0.31", default-features = false, features = ["signal"] }   # nika-exec-runner L1 (unix) — safe killpg wrapper for process-group kill (encapsulates the unsafe signal FFI → crate stays unsafe_code = forbid · MIT)
futures-core  = "0.3"
parking_lot   = "0.12"
tokio         = { version = "1", features = ["rt", "macros", "time", "signal"] }   # signal: nika-cli L4 — `nika serve` (W5) stops clean on ctrl-c/SIGTERM (signal-hook-registry already vendored via the tree)
rustix        = { version = "=1.1.4", default-features = false, features = ["std", "process"] } # safe waitid(WNOWAIT) on Linux/macOS; already locked
cap           = { version = "=0.1.2" }   # nika-cli L4: the isolated jq helper caps its heap allocations (safe API over GlobalAlloc · keeps unsafe forbid · ROOT review control/e02-cap-dependency-review.root.json)
stacker       = { version = "=0.1.25" }  # nika-runtime-laws L3: a nested run's guaranteed native stack, grown on the same thread (rust-lang/stacker · safe API over psm · keeps unsafe forbid · MIT OR Apache-2.0)
globset       = "0.4"   # nika-fs L1 — FsList::glob matcher (literal_separator · MIT OR Unlicense)
reqwest       = { version = "0.12", default-features = false, features = ["rustls-tls", "gzip", "brotli", "deflate", "http2"] }   # nika-http L1 + nika-catalog-verify L4 — pin once (RUST_ENFORCEMENT §2) · rustls (no openssl) · transparent gzip/br/deflate decode + h2 ALPN (the web compresses · pure-Rust miniz_oxide/brotli-decompressor/h2 · zstd SKIPPED: C dep)
url           = "2"     # nika-http L1 — SSRF URL parsing (also transitive via reqwest · pinned aligned)
base64        = "0.23"  # nika-cli L4 — the trace anchor's Rekor/RFC 3161 wire encoding (also transitive via minisign · pinned aligned)
ed25519-dalek = { version = "2", default-features = false, features = ["alloc", "digest", "hazmat"] }   # nika-cli L4 — raw RFC 8032 sign/verify for the Rekor v2 entry signature (Ed25519ph — the server refuses pure ed25519) + checkpoint verification (BSD-3-Clause · pure Rust)
der           = { version = "0.7", default-features = false, features = ["alloc", "derive", "oid"] }   # nika-cli L4 — RFC 3161 TimeStampReq build + TimeStampResp/TSTInfo parse (RustCrypto · Apache-2.0 OR MIT)
cms           = { version = "0.2", default-features = false, features = ["alloc"] }   # nika-cli L4 — the TSA token's CMS SignedData verification (RustCrypto · Apache-2.0 OR MIT)
p384          = { version = "0.14", default-features = false, features = ["ecdsa", "sha384"] }   # nika-cli L4 — the Sigstore TSA leaf is ECDSA P-384/SHA-384 (RustCrypto · Apache-2.0 OR MIT)

# Forward-pinned shared deps (used by Phase 1+ crates).
# Pinning here keeps versions aligned when downstream crates opt in via
# `.workspace = true`. Per RUST_ENFORCEMENT §2.
strsim   = "0.11"   # nika-error Phase C suggest() — Levenshtein for "did you mean"
smallvec = "1.13"   # SmallVec adoption per RUST_2026_BEST_PRACTICES (hot-path vecs)
tracing  = "0.1"    # L1+ effect crates (fs/http/process/...) structured logging
ocrs     = "0.12"   # nika-ocr L1 (M2.2) — pure-Rust OCR engine (rten runtime · no C dep · keeps unsafe forbid)
rten     = "0.24"   # nika-ocr L1 — Model::load_file for .rten weights (ocrs ^0.24 normal dep · pinned aligned)
accessibility = "0.2"   # nika-a11y L1 (M2.3 · macOS-gated) — safe AXUIElement API (TreeWalker · encapsulated ApplicationServices unsafe · keeps unsafe forbid)
core-foundation = "0.10" # nika-a11y L1 (M2.3 · macOS-gated) — CFString/CFType for AXAttribute generic reads (value · subrole)
atspi    = "0.30"   # nika-a11y L1 (M2.3-bis · Linux-gated · ADR-083) — pure-Rust async AT-SPI2 D-Bus client (root_accessible_on_registry · get_children · get_role · State::Sensitive) · CI-pending verify on a Linux/AT-SPI host
enigo    = "0.6"    # nika-input L1 (M2.4 · ADR-083 cross-platform) — synthetic pointer+keyboard (macOS CGEvent · Windows SendInput · Linux X11/Wayland · per-OS unsafe encapsulated → keeps unsafe forbid) · API tarball-verified 0.6.1
chromiumoxide = { version = "0.9", default-features = false, features = ["bytes"] }   # nika-browser L1 (M2.5 · ADR-083) — CDP browser automation (tokio-native · kill_on_drop child per INV-011) · fetcher EXPLICITLY out (default-features=false pins the sovereign surface · a future default-flip is caught by cargo, not silently activating a browser download) · API tarball-verified 0.9.1
png      = "0.18"   # nika-browser L1 — Page.captureScreenshot PNG → RGBA8 kernel Frame decode (pure · headless-testable)
futures-util  = { version = "0.3", default-features = false, features = ["std"] }   # nika-browser L1 — StreamExt::next to drain the CDP Handler stream (one owned task per session)
jsonschema = { version = "0.49", default-features = false }   # nika-verb-infer L2 — structured-output schema validation (draft 2020-12 · no network resolver per sovereignty floor)
jaq-core = "3.1"        # nika-builtin L1.5 — nika:jq · THE data language (jq parser+compiler+interpreter · MIT · API source-verified 2026-06-11)
jaq-std  = "3.0"        # nika-builtin L1.5 — jq stdlib filters (map · select · group_by …)
jaq-json = { version = "2.0", features = ["serde"] }   # nika-builtin L1.5 — jq Val type + serde bridge to serde_json::Value
json-patch = "4.2"      # nika-builtin L1.5 — nika:json_diff (RFC 6902 diff) + nika:json_merge_patch (RFC 7396 · null-deletes)
jiff     = "0.2"        # nika-builtin L1.5 — nika:date · strftime grammar · Unlicense OR MIT · named tz resolved via jiff-tzdb below (NOT jiff's system-preferring .in_tz)
jiff-tzdb = "0.1"       # nika-builtin L1.5 — the EMBEDDED IANA tzdb · nika:date resolves named zones from THIS (bundled · deterministic · zero system read), never jiff's default which prefers /usr/share/zoneinfo on Unix · CC-BY-4.0 OR ... (tzdata public-domain)
serde_yaml_bw = "2.5"   # nika-builtin L1.5 — nika:convert yaml leg + nika:validate format:yaml (panic-free fork · spec-named reference impl)
toml_convert = { package = "toml", version = "1.1" }   # nika-builtin L1.5 — nika:convert toml leg (alias avoids clash if a config-toml dep lands later)
csv      = "1.4"        # nika-builtin L1.5 — nika:convert csv leg (quoting-aware · spec-named reference impl)
htmd          = "0.5"    # nika-extract L1.5 — mode markdown|article HTML→Markdown (Apache-2.0 · API source-verified 2026-06-12)
dom_smoothie  = "0.18"   # nika-extract L1.5 — mode article Readability (MIT · Article fields content+text_content verified docs.rs)
scraper       = "0.27"   # nika-extract L1.5 — modes text|selector|metadata|links CSS-select DOM (ISC)
feed-rs       = "2.3"    # nika-extract L1.5 — mode feed RSS/Atom/JSON-Feed normalize (MIT)
quick-xml     = "0.41"   # nika-extract L1.5 — mode sitemap urlset+index parse (MIT)
encoding_rs   = "0.8"    # nika-builtin L1.5 — nika:fetch charset-aware decode for extraction modes (Apache-2.0/MIT/BSD-3 · the encoding the web actually uses · same crate reqwest text() uses)
ego-tree      = "0.11"   # nika-extract L1.5 — scraper public tree API (Edge traversal for the text-mode walk · ISC · pinned aligned with scraper 0.27)
wasm-bindgen = "0.2"    # nika-check-wasm L4 — the browser transport boundary (bindgen CLI pinned to the lock minor at build)
getrandom    = "0.3"    # nika-check-wasm L4 — wasm32 entropy backend door (features chosen crate-side per target)
getrandom-02 = { package = "getrandom", version = "0.2" }  # nika-check-wasm L4 — the OLDER getrandom generation still in the graph, same door
uuid     = { version = "1", features = ["v7", "v4", "serde"] }   # ADR-033 UUIDv7 IDs (nika-error L0) · v4 for nika:builtin nika:uuid
clap     = { version = "4.5", features = ["derive"] }       # L4 CLI surface (completions + man derive from this tree)
ratatui  = { version = "0.30", features = ["scrolling-regions"] }   # nika-tui L4 · the inline viewport with scroll regions (ADR-139)
crossterm = { version = "0.29", features = ["event-stream", "bracketed-paste"] }   # nika-tui L4 · one reader thread on poll slices · paste as data (ADR-139)
ratatui-textarea = "0.9"   # nika-tui L4 · the composer spike behind a wrapper (ADR-139 · exit criterion written)
clap_complete = "4.5"   # L4 CLI — shell completions generated from the clap tree (nika-cli spec §9)
lsp-server = "0.10"      # nika-lsp L4 — sync stdio JSON-RPC message loop (rust-analyzer's · MIT)
lsp-types  = "0.97"     # nika-lsp L4 — LSP 3.17 protocol types (Diagnostic · Position · CompletionItem · MIT)
zeroize  = "1.8"    # ADR-034 Secret zeroize-on-drop (nika-kernel L0.5) — 1.8 adds heap-String zeroing

# Dev / test deps
criterion   = { version = "0.8", features = ["html_reports"] }
proptest    = "1.6"
insta       = { version = "1.42", features = ["yaml"] }
tempfile    = "3"   # nika-ocr dev — model-load error-path fixtures (with_models headless tests)
rstest      = "0.27"
expect-test = "1.5"  # inline snapshots, see ADR-015
expectrl    = "0.9"  # PTY e2e — the wizard's TTY-gated conversation (unix-only tests)

# ─────────────────────────────────────────────────────────────────────────────
# Release profile (post rust-perf audit 2026-05-12 · BLUEPRINT v1.2 §4 ship-now)
# ─────────────────────────────────────────────────────────────────────────────
# LTO=fat + codegen-units=1 unlock ~5-10% on hot loops (BGE-M3 cosine, BM25
# scoring, RRF fusion) per cargo-pgo + rust-compiler-team Kobzol research.
# Cost · 2× build time at release · `cargo build --release` only · dev builds
# unaffected. strip=symbols matches ADR-061 SLSA L3 byte-determinism target.
# panic=unwind KEPT · panic=abort breaks `cargo test` panic-catching + violates
# the propagate-errors discipline (forbidden for the surrounding tooling ·
# ambiguous for the engine · default unwind is the conservative choice). debug=line-tables-only
# preserves enough symbols for `cargo flamegraph` without bloating release binary.

[profile.release]
lto             = "fat"
codegen-units   = 1
strip           = "symbols"
panic           = "unwind"
debug           = "line-tables-only"
incremental     = false

[profile.bench]
inherits        = "release"
debug           = true

# The browser artifact's own profile (nika-check-wasm · additive, harms no
# other build): the workspace release keeps debuginfo for native profiling,
# which a served .wasm must not carry — measured 4.6M with it, and the fat
# LTO + size-opt pass exists to prune the L0 judgment hub's heavy corners
# (jaq · jsonschema) out of a parse+conform artifact.
[profile.wasm-release]
inherits = "release"
strip = "debuginfo"
debug = false
lto = true
opt-level = "z"
codegen-units = 1
# A trapped wasm instance never comes back (the jq-bomb work made that
# literal — the shadow stack does not restore), so unwinding machinery in
# the artifact would be dead weight implying a recovery the crate refuses
# to promise. No catch_unwind exists anywhere in the wasm dependency tree.
panic = "abort"

[patch.crates-io]
# dom_smoothie 0.18.0 breaks candidate score ties by its hash map's per-process
# iteration order: the same page yielded two different articles (nika PR 1503 · 2026-09-06 ·
# 40 identical runs → 30/10). The pinned rev carries the upstream-shaped fix (the
# candidates keep their first-scored order · readability.js parity); it drops the
# day upstream releases it.
dom_smoothie = { git = "https://github.com/supernovae-st/dom_smoothie", rev = "fd6db004615af3c14d20f90bfb43ca514db4e57d" }