v0.114.0 #1150
v0.114.0
#1150
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
Remote execution as a loopback door. Default
nika servestays theresident ARM firer.
--bind+--workflows+--token-fileopensauthenticated HTTP: jobs, SSE, OpenAPI. The worker runs the POST-time
snapshot, not live files. Cancel, artifacts and
/v1/runstay 404.The workflow envelope is unchanged since v0.113.0. The project file's
retired
nika: v1tag now refuses. Pre-1.0 real semver puts this at aminor bump.
Added
nika serve --bindis authenticated loopback HTTP. Pair it with--workflowsand--token-file(credential bytes never enter argv).Default
nika serveis still the resident ARM firer. The verb is onnika --help. Listen line prints the bound address, including port 0.Job cancel and artifacts stay 404 until those authorities exist.
GET /v1/jobs/{id}/events. Framesare
{sequence,kind,status}only.GET /v1/openapi.jsonis the liveroute table; cancel, artifacts and
/v1/runare omitted.nika doctornames the HTTP door when a token file is present.Owner-only mode is OK; group/world-readable is a fail with the umask
077 fix. The row never claims TLS — that is the reverse proxy.
Silent when the cwd has no
.nika/serve.token(the door is opt-in).systemd and Caddy examples live in
docs/ops/.Changed
nika checknames the ancestornika.yamlspend cap.nika runalready filled
--max-cost-usdfrom that file; check printed « nototal ceiling » and advised adding the flag, on a tree that already
had one (issue 1050). The COST line still prices the workflow; a
BUDGETfootnote (and a presence-gatedrun_budgetobject on--json) now says the number andnika.yaml:line.--max-cost-usdstill wins.
run --dry-runand--helpstay silent — this is thesurface that contradicted the file.
nika try/nika runno longer waits on the macOS keychainafter a green card. The card printed, then
SecKeychainFindGenericPasswordblocked the main thread: a pipe cannot complete an ACL prompt. The
keychain is skipped when stderr is not a TTY (file/env custody stay);
a disabled journal (
nika try·--no-trace-file) does not consult itat all.
nika:readof a file puts those bytes into
.nika/traces/in the clear — correctfor a replayable journal, unnamed until an auditor derived it (issue
1047). The receipt paragraph now says hash-chained is not confidential.
nika spec --canonsays the error-code count is the floor. An agentread
count: 103plus twoNIKA-BUILTIN-*rows as the builtin-codefamily. The spec now carries a
scope:sibling (nika-spec 282); this pinvendors it. Per-builtin and per-provider codes still live in
nika explain.nika.yaml).nika:carried afrozen
v1tag while a workflow'snika:names the file: one key, twogrammars, and every surface reading both had to know a special rule. It now
carries the project's kebab-case name, the same grammar the workflow
envelope gives its own
nika:. The reasoning is this repo's own, writtenwhen the workflow envelope was nuked — a field with one legal value is not a
version, so nothing is traded away, and the project gains a name it never
had. The retired tag refuses here and nowhere else: a pre-nuke workflow
carried a
workflow:block beside itsnika: v1and still refuses on thatkey, so
v1stays free to be an ordinary workflow name; a pre-nuke projectfile had no companion key, so without a refusal the same bytes would quietly
stop meaning « schema v1 » and start meaning « a project named v1 ». Only a
whole marker qualifies —
vault,v2rayandv1-migrationstay names.Migration is one line:
nika: v1→nika: <your-project-name>.Fixed
no longer mark interrupted while effects continue. Queued jobs persist
their workflow name and are re-enqueued on the next incarnation.
cannot run bytes the client never admitted. GET names
execution_idand
trace_idafter readmit. The service sandbox is the workflow root.Added
nika checknames the exact builtin when a utility is 1:1.sleep,date,uuidgen, the digest family,yq,grep/rg/agandfindused to be silent — or, for
date/sha256sum, a family catalogue.Rule
native-first/006answers with one builtin and its argument shape(
nika:wait·duration:) so the author types the next line, not amenu. It sits at the foot of the ladder and never steals a more specific
family.
echostays silent on purpose: it is the universal placeholder,not a builtin.
agent:loop (opt-in seam). Past 16 KiB atool result's full text leaves the conversation for the blob store —
the content hash IS the locator — and the model keeps a 2 KiB preview
plus the pointer, so the context window stops re-paying bytes it cannot
use. Nothing is discarded, and a store refusal keeps the full text:
the spill is an optimization of the model's reading, never a gate on
the data. Seat it with
AgentVerb::with_spill; without the seam theloop is byte-unchanged.
nika checkjudges a project file as a project. It applied the nine-keyWORKFLOW envelope to every document, so a project file came back
NIKA-PARSE-002 missing required envelope field: tasks— on a filenika init --project-filehad just written — and following that finding'sown advice converted a correct project file into a broken workflow. The
discriminant is the spec's, normative and covering every document
(
01-envelope§The type discriminant): atasks:key means WORKFLOW, itsabsence means PROJECT. Deliberately not the filename, so it still holds for
a registry blob, an HTTP body or a fence pasted into a chat. A project now
audits in its own vocabulary — exit 0 clean, 2 on a finding — and says what
it governs rather than a count it never stated.
nika checknotes a file whose name and filename have drifted apart.Copy
foo.nika.yamltobar.nika.yaml, forget the header, and every traceand journal event keeps saying
foo. It is a NOTE and never a finding:divergence is usually deliberate (an ordering prefix such as
01-helloisstripped before comparing), and the exit code is untouched. The filename is
a location
git mvmay change; the name is an identity that rides traces.Fixed
nika check's audited line names the declared blast radius. Thedefault card said
permits declared; the grants themselves livedbehind
--infer-permitsand--json(persona 4). Cost was alreadyon the card. The cell now lists the exec / tools / fs / net / env
grants (an explicit empty block is
{}, absent is stillnone).--quietand the shareable card titled
✔/✓on a run that repaired atask (
task_recoveredthen Ok). Exit 0 is still correct — recoveredis a success cause. The headline and the card title now carry the
warn mark; the storyboard already named
N recovered(persona 14).trace lsstill sayscompleted(no newTraceStatethis cut).--infer-permitsno longer pastes a host-file grant. Anika:readof/etc/passwd(or~/.ssh/…) under an absentpermits:block printedfs.read: ["/etc/passwd"]; applying thatblock greened check and run (persona 7). G-09 already withheld the
shovel on a declared boundary; the AUTH-006 companion and the
inferred YAML still handed it. Escaping paths (absolute · home ·
..-climb) stay a note. The printed repair is the tool conjunctonly.
nika checkno longer panics on a decorative verb glyph. Copying⛨permits:/◇infer:from nika.sh into a file, then running theadvertised
nika check, dumpedannotate-snippets(byte index N is not a char boundary) with no NIKA code and no--fixhint. Thesnippet painter widened a point span by one BYTE into a 3-byte glyph;
it now snaps to a char boundary and widens by one CHAR. MCP already
taught
did you mean permits?— the CLI default path matches thatcalm.
nika try 10-compose-pipelinestages the child it invokes. Therehearsal room used to hold only the parent; check then died
NIKA-COMP-001on./10-compose-child.nika.yaml(e2e S2 17/18 on81c1138). Fixture materialize already carried
examples/fixtures/ingredients; a relative
workflow: "./….nika.yaml"pack sibling isthe same class.
for_eachover a constant that is not an array is refused at check, notat dispatch.
const: { items: "x" }withfor_each: ${{ const.items }}audited clean, then died at the run with
NIKA-VAR-006— a linter's answer,not a verifier's, and exactly the gap ADR-092 exists to close. The static
lane already caught a typed non-array var but exempted every untyped one,
on the rationale that « a
--varoverride could pass an array ». That ruleis inputs-only:
--varsets aninputs:value and refuses unknown keys, andspec 01 §const is normative — a constant is « immutable across the run and
never caller-supplied ». An untyped constant's literal IS its run value, so
a non-array can never become one. Untyped entries are legal in
const:alone, arrays and typed declarations are untouched, and all 59 shipped
templates and examples still audit clean.
nika explainanswers the tokennika checkprinted in[brackets],including a hint. A HINT row put
jq-as-map(ornative-first/006)in the same slot as
NIKA-PARSE-019, so the next gesture wasnika explain jq-as-mapand the answer wasunknown code. A findingcarries
code; a hint carrieskind— real in the data, invisiblein the render. Explain now resolves the printed identity (the kind,
or the numbered native-first rule) and teaches the class; MCP
nika_explainspeaks the same text.nika checknames the line of a PARSE refusal. A CONFORM findingalready carried a rustc-grade frame (
path:line:col+ caret). A PARSEfinding —
NIKA-PARSE-017duplicate key,NIKA-PARSE-005unknownfield, any span the parser held — printed the code and left the author
to find the site. Duplicate keys are the worst of that class: the
message says
"a" appears twice, so greppinga:returns both, andneither is wrong on its own. The colliding key's span was in the
loader's hand and discarded (
span: None). It now rides the sameframe CONFORM uses, under the same
PARSE ✗first line.nika armno longer refuses a project that sets its retention or itsprovenance floor. Two readers parse
nika.yaml— the project reader(
ceiling·traces.keep·registry.floor·arm) and the cadencegrammar. The grammar refused
traces:andregistry:by name as« round 2 » keys with a remedy that was false (« retention stays with
the env vars ») while the project reader had just accepted them and the
retention ladder and the provenance gate consume them — the project
starter's own
traces:line madenika armexit 2. Measured2026-08-18. The grammar now admits the project's other rungs OPAQUE and
judges nothing about them (they are judged where they are owned); the
cadence domain's own deferred keys (
signature:·budget:) stayrefused by name. A test derived from the project reader's closed key
set pins the parity: every key it admits,
nika armreads green.Install
Tarballs below: macOS arm64 / x64 · Linux x64 / arm64, plus
SHA256SUMS.Verify: three independent proofs
Provenance
Built from tag
v0.114.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.113.0...v0.114.0
This discussion was created from the release v0.114.0.
All reactions