Skip to content

v0.99.0

Choose a tag to compare

@github-actions github-actions released this 10 Jul 07:56
57621d1

0.99.0 - 2026-07-10

Added

  • nika:image_fx — deterministic artistic effects, the 26th builtin
    (stdlib §Media graduate #3).
    The image editing deferred row comes
    home zero-dep: 15 op families (dither · palette · duotone · pixelate ·
    halftone · grain · vignette · chromatic aberration · scanlines ·
    glitch · ascii …) over a hand-rolled PNG codec (full RFC 1951 dynamic
    Huffman inflate · 5-filter decode · CRC), seeded and byte-identical —
    the recipe rides the PNG tEXt chunk (image_fx/v1), the artifact
    sha256 rides the trace chain, and a re-run with the same inputs
    idempotently skips.
  • nika:chart — deterministic chart artifacts, the 27th builtin
    (stdlib §Media graduate #4).
    Rows + a semantic spec compile to
    byte-identical SVG (sha256 → trace chain): five closed types (bar ·
    line · area_band · scatter · heatmap), typed semantics (usd ·
    duration_ms · timestamp · category …), out: must end in .svg (the
    attestation surface) and compile_to: vega_lite writes the .vl.json
    sibling. Zero dependencies; parity proven byte-exact across
    architectures (wasm32-wasip1 ≡ aarch64).
  • nika check --model <provider/model> — the static preview of the
    run override: the envelope is re-priced AS IF the flag replaced the
    file's default (per-task model: still wins), so what check shows IS
    what run will refuse or allow.
  • Egress to outputs — the workflow boundary earns its valve. The
    capture-taint law is deliberate (the provider saw the key — its
    response is not provably clean), but a workflow that calls an
    authenticated API and RETURNS the result had no sanctioned path: the
    embedded api-upload-and-create template failed its own audit (the
    night battery's catch), documented as the one known gap. The gap
    closes the way its own note asked: egress: [{ to: "outputs" }] on
    the secret declassifies the workflow boundary itself — sink-only,
    secret-specific, never authorizes a send, default-deny when absent
    (spec 01-envelope §egress). KNOWN_GAP is empty: every embedded
    template now passes its own audit, with zero exceptions.
  • The MODELS rung — every model: must resolve in THIS binary. The
    ladder validated tools but never models: a vendor-cataloged provider
    the resolver cannot drive (azure/…) and a bare model id
    (gpt-5-turbo) both audited green — the bare one even wore a
    conjured price. Both are findings now (exit 2) with the fix taught
    in-line; pricing refuses to price what cannot resolve (unpriced beats
    conjured); the --json payload carries models_resolve +
    model_findings[]; and the SAME law guards the MCP nika_check lane
    (nika_providers::resolve_refusal — the two machine lanes cannot
    disagree).
  • nika wire learns opencode and hermes — the two ecosystems
    that natively read what nika init writes get first-class MCP wiring
    (wire all now covers 8 targets). OpenCode: project-local
    opencode.json, its own mcp.nika shape, idempotent merge. Hermes:
    ~/.hermes/config.yaml under the Zed contract — create when missing,
    recognize current, otherwise hand back the exact snippet and leave a
    foreign YAML byte-identical.
  • OpenRouter calls carry the app-attribution pair (HTTP-Referer: https://nika.sh + X-Title: Nika) — runs surface as Nika on the
    public rankings instead of an anonymous key. Openrouter-profile only;
    peers may 400 on surprise headers (proven both directions).
  • The plugin ships three slash commands (/nika:check ·
    /nika:explain · /nika:new) — born under .agents/plugins/nika/
    per the marketplace mirror law; the commands read the --json
    payload, not the prose.
  • nika explain --forecast — learned truth before a run. Duration,
    cost and risk priors computed from YOUR local traces (.nika/traces/)
    — deterministic stats, never a model call, never the network. The
    honesty ladder is a type: never-run says so · one run is « last run » ·
    2-4 runs earn a min–max range · p50/p90 bands are earned at n ≥ 5
    (Hyndman & Fan type-7, the numpy/R default). Costs compose the
    floor whenever unpriced spend participates — absence stays a dash,
    never $0. Retried-then-passed counts as flaky, never failed; cache
    hits and other-model runs are excluded from bands and named. The
    section auto-appears in nika explain <file> once 3 runs exist; the
    flag forces it, and --json gains a versioned forecast key
    (internally-tagged rungs — consumers tolerate unknown kinds).
  • The missing-input trap is taught at check timenika check
    prints an [inputs] HINT when a nika:read path that resolves
    statically (a literal, or one ${{ vars.X }} with a literal default)
    does not exist here; never an error — the file may appear at run
    time, and anything dynamic is never guessed
    (nika_schema::check::static_read_paths, the pure half).
  • The release tarball is funnel-gatedscripts/ci/funnel-e2e.sh
    plays the stranger's first path against the EXACT tarball about to
    ship (clean HOME · offline · content asserts); a broken first-run
    never uploads.

Fixed

  • The run card advertises the full 64-hex chain headtrace verify printed the whole sha256 while the run card truncated to 32,
    so the taught receipts loop could only prefix-match. Byte-exact ==
    now closes it (CI-assertable).
  • The broken editor modeline names itself — cause, not symptom. A
    weak copier de-comments the # yaml-language-server: line; YAML then
    fails at the first mapping (« line 14, nika: v1 ») while the fault
    is line 1 — repair loops chased the symptom forever (0/13 measured on
    a 14B grid). Both forms now teach the fix on the offending line, and
    the class is mirrored spec-side as conformance fixtures 014/015 —
    writing them un-crashed the oracle's scan-failure path.
  • The cost floor prices the EFFECTIVE model. The delegation idiom
    agents are taught (--model <p/m> --max-cost-usd <usd>) never met
    the pre-start refusal — the floor was computed from the file's model
    while the run used the override. The budget preflight now re-prices
    the effective envelope; the mock-override preview idiom still passes.
  • The PNG heatmap speaks the SVG's quantized bins — the design pass
    quantized the SVG cells onto the legend's 8 shared bins while the PNG
    projection of the same recipe kept the continuous ramp; one shared
    fill law now feeds both surfaces (every legend swatch IS a color a
    cell can wear).
  • Fold verdicts are terminal kinds only — a journal truncated after
    its opening line no longer surfaces workflow_started as if the
    crashed run had reached a state; nika context reads it as
    honestly-unknown.

Changed

  • The chart design pass — per-mode palettes, computable, never
    eyeballed.
    The six-check validator refuted « Okabe-Ito is CVD-safe
    on both modes » (4 slots outside the dark lightness band · the yellow
    at 1.29:1 on white): dark becomes a SELECTED palette (same seven
    hues, its own steps, all checks green against #0f1318; light
    re-steps one slot, yellow → gold), series and diverging bins ride CSS
    classes through the prefers-color-scheme seam (ONE byte-stable
    document renders both themes), heatmap cells quantize onto the
    legend's 8 shared bins with a 2px surface gap, bars cap at 24px with
    a rounded data-end and square baseline, and the diverging midpoint
    goes near-surface graphite in dark — « no change » must recede, never
    glow. A BOTH-lists-style test guards the style block against palette
    drift.
  • nika-dap::stats::conformal_upper — the forecast's first THEOREM.
    A distribution-free, finite-sample upper prediction bound (split
    conformal, order-statistic form): for exchangeable runs the NEXT one
    falls at or below the k-th order statistic with probability ≥ k/(n+1),
    exactly k/(n+1) for continuous data (arXiv:2411.11824 Theorem 3.2). The
    level arrives as a rational (the f64 route mis-computes the exact
    feasibility frontier — 0.9·10 ceils to 10); nine runs earn a
    guaranteed 90% bound, nineteen earn 95%. Proven by a deterministic
    leave-one-out property test that COUNTS the theorem, never samples
    it. Renderer wiring lands with forecast-R3.
  • nika-dap is its own crate — the trace-forensics plane has one
    home.
    The DAP replay server moves out of nika-cli (the crate sat
    at 98.9% of its size cap before the forecast landed), and the seams
    every forensic reader shares descend with it: the tolerant NDJSON
    reader (recover_events), the tamper-evidence chain walk
    (chain::walk + ONE CHAIN_GENESIS the sink now imports — three
    private sha256 copies unified), and the source-identity hashes.
    nika-cli re-exports every seam at its old path — zero behavior
    change, nika dap answers exactly as before.

What's Changed

  • docs(changelog): append v0.98.0 by @github-actions[bot] in #308
  • feat(nika-cli): the DAG draws itself in the terminal — real wires, never a lie by @ThibautMelen in #309
  • feat(nika-cli): wire zed — context_servers with a JSONC-honest fallback by @ThibautMelen in #310
  • feat(nika-cli): trace retention — bounded by default, never silently (ADR-100) by @ThibautMelen in #311
  • fix(nika-cli): doctor sees zed — the wire target it could not diagnose by @ThibautMelen in #314
  • feat(nika-event): task_recovered — the repair becomes readable in the kind stream by @ThibautMelen in #313
  • feat(nika-cli): doctor + explain speak the display seam by @ThibautMelen in #315
  • feat(nika-cli): nika context — the whole workspace truth in one call by @ThibautMelen in #312
  • docs/readme mirror verbs by @ThibautMelen in #316
  • docs: readme freshness, manifesto emergence, first-run feedback forms by @ThibautMelen in #317
  • docs(readme): brand header — the lockup hotlinks the canonical kit by @ThibautMelen in #318
  • ci(coherence): pack CONTENT pin + agents-mirror pin join the nightly by @ThibautMelen in #322
  • docs(readme): the constellation — every sibling repo, one table by @ThibautMelen in #329
  • fix(hygiene): vector 9 follows the org storefront — canonical tap name + the two new repos by @ThibautMelen in #336
  • refactor(nika-catalog): session-2b splits along its rule families by @ThibautMelen in #326
  • fix: the V-arc findings — the stranger's first path holds by @ThibautMelen in #327
  • feat(nika-dap): admit to workspace — all 12 gates passed by @ThibautMelen in #325
  • feat(hygiene): vector 9 gains counts parity — the vitrine tracks canon.yaml by @ThibautMelen in #337
  • docs(privacy): the public surface drops its two studio-internal paths by @ThibautMelen in #343
  • fix(changelog): the conformal cite says Theorem by @ThibautMelen in #340
  • feat: nika:image_fx — deterministic artistic effects (stdlib §Media graduate #3) by @ThibautMelen in #338
  • docs(privacy): the rules index drops its operator memory slugs by @ThibautMelen in #344
  • feat(nika-chart): nika:chart builtin — deterministic chart artifacts (stdlib §Media #3) by @ThibautMelen in #339
  • feat(provider): openrouter calls carry the app-attribution pair by @ThibautMelen in #347
  • fix(cli): the run card advertises the full 64-hex chain head by @ThibautMelen in #348
  • docs(readme): the model bench earns its line by @ThibautMelen in #350
  • feat(nika-chart): the design pass — per-mode palettes, quantized cells, capped bars by @ThibautMelen in #349
  • fix(nika-schema): the broken modeline names itself — cause, not symptom by @ThibautMelen in #351
  • fix(nika-chart): the PNG heatmap speaks the SVG's quantized bins by @ThibautMelen in #355
  • refactor(nika-dap): the trace forensics come home — the cli keeps the render by @ThibautMelen in #356
  • feat(agents): the plugin grows its three slash commands by @ThibautMelen in #357
  • fix(cli): the cost floor prices the EFFECTIVE model — and check previews it by @ThibautMelen in #352
  • feat(cli): the MODELS rung — every model resolves in THIS binary by @ThibautMelen in #353
  • feat(cli): wire learns opencode and hermes — the kit's two native readers by @ThibautMelen in #354
  • feat(mcp): nika_check carries the MODELS rung — the third lane closes by @ThibautMelen in #358
  • feat(nika-schema): egress to outputs — the workflow boundary earns its valve by @ThibautMelen in #359
  • docs(changelog): the 0.99 preflight — the night's ships enter the record by @ThibautMelen in #360
  • feat(run): the epilogue seam — and the run learns to say recovered and still-running by @ThibautMelen in #361
  • chore(release): v0.99.0 — the audit tells the whole truth, the run narrates its own by @ThibautMelen in #362

Full Changelog: v0.98.0...v0.99.0