v0.112.0 #1088
v0.112.0
#1088
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
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 rungcounts model endpoints instead of tasks, ending a card that contradicted
itself four lines apart: COST read
no infer/agent taskswhile JOURNEY read3 model endpoints. A fan-out that recovered now says so in its record andnot 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 scriptis refused at check instead of exiting 126 under a green card.
Added
nika listnames every workflow below the current directory. Output isstable 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.
nikaon a terminal opens one continuous thread. Model turnsstream through the existing
agent:runtime;/workflowposts a workflowinto the thread,
/runexecutes it there, and Ctrl-C interrupts the activeturn without closing the outer conversation.
Removed
VirtualClockloses its dead time-mover (nika-clock).VirtualClock::advanceandVirtualClock::elapsed_totalare removed:advancedocumented itself as « the ONLY mover of virtual time » whilehaving zero production callers — virtual time never moved, so under
run: { clock: virtual }(orentropy: none | seeded(N), which implyit) a task
timeout:budget raced an instantly-ready timer and everydeadline was already settled at dispatch. The clock is now honestly
FROZEN by construction (
Copybases, no shared offset): an author whoneeds a real deadline honored against real work must not declare
clock: virtual. Wiring the tasktimeout:budget to the execrunner's own deadline (
linger: false) is a follow-up wave.(
nika-exec-runner).terminate_group(SIGTERM→SIGKILL the wholeprocess group) plus the
process_group(0)spawn setup were correctand tested but unreachable in production — they fired only on
TimedOut/Cancelled, and the engine never assignsShellCommand.timeoutnor invokescancel. Cancellation stayskill_on_drop(INV-011 · future-drop, the ADR-016 primary); detachedgrandchildren are no longer group-killed on the embedder-facing
timeout/cancel arms, and the
nixdependency goes with them.Changed
(
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 everyrecompile — 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=offnow skips thecustody, and a test binary skips it by default whether or not anyone
remembers the flag. An installed
nikaandcargo runland outsidedeps/and keep their custody unchanged. All eight keyring call sitessit 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 toevery task, so a body of builtin invokes read
3 model endpointswhilethe COST rung four lines above read
no infer/agent tasks— one cardcontradicting itself.
model_endpoint_ofalready typed the task andthrew 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 checkjudges every secret sharing one effect independently. Asink 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_eachitem aliases nowproduce one consent verdict per distinct secret while the existing
singular output-propagation trace stays unchanged and bounded. Literal
for_each.itemssecret references also appear in the data journey.nika checknow judges the script anexec:interpreter must open.The runtime jails every
exec:child to the declaredpermits.fsset, soexec: ["bash", "leg.sh"]with nofs.readgrant could never open itsown script — measured on seatbelt, the leg exits 126 with empty
stdout. The audit was ✔ on all fourteen lanes and the run rendered it
✔ legwith rc 0: a leg that did nothing, reported as a success. Theexec:fit lane gained an fs arm beside its net arm (which shipped2026-07-29 for the same sentence one boundary over), so the escape is a
NIKA-SEC-004finding at check with the one-line repair. The claim isnarrow on purpose — only a literal argv whose program is an interpreter,
on its script positional, through a literal
cwd:; everything else staysthe 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-permitslearned the same fact in the same change, so theboundary 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 gatefour lines above twoNIKA-SEC-014rows proving that samegate 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 wasbought 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-errorcrate-spec band table matches the one-voiceregistry. It still read
330-379 Binding/template · 380-429 Providerwhile 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
Tarballs below: macOS arm64 / x64 · Linux x64 / arm64, plus
SHA256SUMS.Verify: three independent proofs
Provenance
Built from tag
v0.112.0byrelease.ymlon GitHub-hosted runners. Provenance is published twice: GitHub's native
build attestation (proof 2) and the SLSA generator's
multiple.intoto.jsonlrelease 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
This discussion was created from the release v0.112.0.
All reactions