Skip to content

v0.112.0

Choose a tag to compare

@github-actions github-actions released this 20 Aug 23:37
· 140 commits to main since this release
974fc55

What

The instrument-honesty release. Three features and sixteen fixes, several
of which began as a measurement disagreeing with what a surface said. A cargo
test binary can no longer open the OS keychain — an ACL is bound to the
requesting binary, and a test binary's hash changes on every compile, so the
prompt could never be answered once and for all. nika check's JOURNEY rung
counts model endpoints instead of tasks, ending a card that contradicted
itself four lines apart: COST read no infer/agent tasks while JOURNEY read
3 model endpoints. A fan-out that recovered now says so in its record and
not only in its prose, which is what spec 13 requires of the pair. And the
exec: fit lane gained an fs arm, so a leg jailed away from its own script
is refused at check instead of exiting 126 under a green card.

Added

  • nika list names every workflow below the current directory. Output is
    stable and root-relative, nested workflows are included, project metadata
    and hidden/build directories stay out, and an incomplete walk refuses
    instead of presenting a partial inventory as exhaustive.
  • Bare nika on a terminal opens one continuous thread. Model turns
    stream through the existing agent: runtime; /workflow posts a workflow
    into the thread, /run executes it there, and Ctrl-C interrupts the active
    turn without closing the outer conversation.

Removed

  • BREAKING — VirtualClock loses its dead time-mover (nika-clock).
    VirtualClock::advance and VirtualClock::elapsed_total are removed:
    advance documented itself as « the ONLY mover of virtual time » while
    having zero production callers — virtual time never moved, so under
    run: { clock: virtual } (or entropy: none | seeded(N), which imply
    it) a task timeout: budget raced an instantly-ready timer and every
    deadline was already settled at dispatch. The clock is now honestly
    FROZEN by construction (Copy bases, no shared offset): an author who
    needs a real deadline honored against real work must not declare
    clock: virtual. Wiring the task timeout: budget to the exec
    runner's own deadline (linger: false) is a follow-up wave.
  • The exec runner's process-group kill is removed
    (nika-exec-runner).
    terminate_group (SIGTERM→SIGKILL the whole
    process group) plus the process_group(0) spawn setup were correct
    and tested but unreachable in production — they fired only on
    TimedOut/Cancelled, and the engine never assigns
    ShellCommand.timeout nor invokes cancel. Cancellation stays
    kill_on_drop (INV-011 · future-drop, the ADR-016 primary); detached
    grandchildren are no longer group-killed on the embedder-facing
    timeout/cancel arms, and the nix dependency goes with them.

Changed

  • BREAKING — the event error codes leave the Shield reservation
    (nika-event).
    NIKA_420/421/422 (serialize failed · buffer full ·
    lock poisoned) were minted inside the locked Shield band (380-429), so
    a full event buffer surfaced as « Shield security policy blocked the
    operation » — a refusal its reader would read as security. They are
    renumbered into their own Observability band (800-819) as
    NIKA_801/802/803, constants renamed with them.

Fixed

  • A cargo test binary no longer opens the OS keychain. A macOS keychain
    ACL is bound to the requesting BINARY, and a test binary is
    target/<profile>/deps/<name>-<hash> whose hash changes on every
    recompile — so "Always Allow" grants a binary that will never exist
    again and the prompt returns forever, on every worktree, with no
    operator-side gesture that stops it. NIKA_KEYCHAIN=off now skips the
    custody, and a test binary skips it by default whether or not anyone
    remembers the flag. An installed nika and cargo run land outside
    deps/ and keep their custody unchanged. All eight keyring call sites
    sit behind the flag, held there by a ratchet that walks the crate's own
    source.

  • The JOURNEY rung counts model endpoints, not tasks. The envelope
    model: is a fallback for a task that HAS a model · it was applied to
    every task, so a body of builtin invokes read 3 model endpoints while
    the COST rung four lines above read no infer/agent tasks — one card
    contradicting itself. model_endpoint_of already typed the task and
    threw the answer away on the next line. Across the shipped corpus 45 of
    99 cards carried an inflated count; each is now exactly the number of
    infer:/agent: tasks the file declares, and no verdict changed.

  • nika check judges every secret sharing one effect independently. A
    sink that referenced two secrets previously retained only the first IFC
    trace, so clearing that first edge could hide an uncleared second edge.
    Direct references and task-local with: / for_each item aliases now
    produce one consent verdict per distinct secret while the existing
    singular output-propagation trace stays unchanged and bounded. Literal
    for_each.items secret references also appear in the data journey.

  • nika check now judges the script an exec: interpreter must open.
    The runtime jails every exec: child to the declared permits.fs set, so
    exec: ["bash", "leg.sh"] with no fs.read grant could never open its
    own script — measured on seatbelt, the leg exits 126 with empty
    stdout. The audit was ✔ on all fourteen lanes and the run rendered it
    ✔ leg with rc 0: a leg that did nothing, reported as a success. The
    exec: fit lane gained an fs arm beside its net arm (which shipped
    2026-07-29 for the same sentence one boundary over), so the escape is a
    NIKA-SEC-004 finding at check with the one-line repair. The claim is
    narrow on purpose — only a literal argv whose program is an interpreter,
    on its script positional, through a literal cwd:; everything else stays
    the runtime's verdict, and the verdict models the jail (which binds a
    grant's literal prefix and never globs) rather than the stricter lexical
    walk. --infer-permits learned the same fact in the same change, so the
    boundary it writes cannot self-refuse the workflow it came from. Swept
    over the shipped corpus: 63 of 63 unchanged.

  • The TRIFECTA tick is derived, so it cannot outlive the gate that
    bought it.
    Measured on 0.111.0, one card printed ✔ TRIFECTA … without a human gate four lines above two NIKA-SEC-014 rows proving that same
    gate lets the effect fire on 'no'; a control run with the prompt deleted
    raised NIKA-SEC-009, so the trifecta was complete and the tick was
    bought entirely by a rubber stamp. The lane credited a blocking prompt
    (one task, one key lookup) while the consent lane ran the full
    refusal-substitution walk — and the clearance discarded WHICH gate it
    credited, so a trifecta cleared by a gate and one cleared by a missing
    leg were the same empty vec. The clearance now publishes its credit and
    the rung withholds the tick where another lane refutes it, pointing at
    the code that owns the repair. No second finding: the consent row
    already names the defect and teaches the fix.

  • The nika-error crate-spec band table matches the one-voice
    registry.
    It still read 330-379 Binding/template · 380-429 Provider
    while the registry moved Provider to 330-379 (2026-05-11) and reserves
    380-429 for Shield. The stale rows invited exactly the collision the
    reservation exists to prevent.

Install

brew install supernovae-st/tap/nika          # macOS · Linux
curl -LsSf https://nika.sh/install.sh | sh   # script install
docker run --rm ghcr.io/supernovae-st/nika:0.112.0 --version

Tarballs below: macOS arm64 / x64 · Linux x64 / arm64, plus SHA256SUMS.

Verify: three independent proofs

# 1 · checksum: the bytes you hold are the bytes CI hashed
sha256sum -c SHA256SUMS --ignore-missing     # macOS: shasum -a 256 -c

# 2 · attestation: GitHub-signed build provenance for this exact artifact
gh attestation verify nika-<platform>-0.112.0.tar.gz --repo supernovae-st/nika

# 3 · SLSA provenance: the intoto asset, verifiable offline
slsa-verifier verify-artifact nika-<platform>-0.112.0.tar.gz \
  --provenance-path multiple.intoto.jsonl \
  --source-uri github.com/supernovae-st/nika --source-tag v0.112.0

Provenance

Built from tag v0.112.0 by release.yml
on GitHub-hosted runners. Provenance is published twice: GitHub's native
build attestation (proof 2) and the SLSA generator's multiple.intoto.jsonl
release asset (proof 3). The release itself is a claim on the
machine-verified timeline: https://nika.sh/timeline

What's Changed

Full Changelog: v0.111.0...v0.112.0