Repository navigation
0.4.0 - 2026-11-02
Release Notes
Added
--model-forworks with--harness pi: each session's Pi is launched
with its role's model, and the run'smodels.jsonlists every model of
the map, keeping the settings your~/.pi/agent/models.jsonhas for
each. A role's model without--context-window-fortakes the window
that file lists for it, and its inputs unless--visionis given.
--swap-modelsworks with Pi too. See ADR 0011.tenaz init --swap-modelskeeps one model of a--model-formap
loaded at a time, for models that do not fit in memory together: before
each session Tenaz unloads the others and loads that session's model,
so each review costs two loads. At everytenaz runstart it loads
each model once, alone, and stops the run if one will not load. Needs
--engine load-api(Sushi, mlx-serve).tenaz run --swap-modelsand
--no-swap-modelschange it; it is kept aslaunch.swapModelsin
run.json,status --jsonhasswap_models, andtenaz statussays
the models are loaded one at a time. When swapping, the
journal'sleaserecords name the model of eachloadandunload,
and record a model the engine dropped by itself asevicted. See ADR
0015.
Changed
- With fx, an engine error that came with an error status now starts
with that status, as Pi's errors do, then the engine's message:
503: <message>, or500alone when there is no message. The message
of an SSE body is that of its firsterrorchunk. Pi puts the raw body
after the status instead. It shows in the session'sprovider-error
watchdog event andimage_refusal, the journal'simage-continuation
refusal, the image continuation note andtenaz watch. - The agent skill no longer offers to pipe the install script into
sh:
it gives Homebrew, a release archive with its checksum and attestation,
orcargo install, and points to the README for the rest. skills.sh's
Snyk audit flagged the script's URL as an unverifiable dependency. - The journal's
leaserecords end withreadywhenever the lease loads
the LLMs back: also at the start of a run, after an engine error, and
after a failed reload or unload, not only after a media or heavy job. - A context budget held at the ceiling a failed raise set, for twice the
sessions a raise waits for then (8 to 32 with the default
capacityRecoverSessions), is raised past it, halfway to the largest
configured budget, and the log says so; an overflow sets the ceiling
again. The ceiling used to last the whole run: in the Digger below the
Mine run of 2026-10-30 it was set at 58419 while memory was short, and
the budget stayed there for hours after the pressure was gone, with
sessions reaching 77257 tokens unharmed. See ADR 0014.
Fixed
- When the engine cannot take the preflight's requests,
tenaz runnow
stops with the engine's error and says it is the engine's. It used to
report no reasoning, no cached prefix and a failed tool call, and advise
another model. This covers an engine out of memory (mlx-serve answers
503), one that answers 502, 503 or 504, and one not reached.
--allow-weak-enginedoes not accept such a preflight, so the next run
measures it again. For an engine out of memory it says to free memory
or reload the model, as the run's retries do. Other engine errors, such
as a refused image or a 400 or 500 not about memory, are still left to
the checks and the flag.run.json'spreflightkeeps the engine's
errors inengine_errors. The log andtenaz statusshow such a
preflight as not judged, with the count of errors, instead of its
checks, and the log names the first error. A failed preflight points
to.tenaz/private/preflight.fx-acp.logonly with fx: Pi keeps no log
of it. See ADR 0016. - The preflight line of the log and of
tenaz statusshows the image
check (vision=trueorvision=false) for a vision model. A preflight
that failed only on the image used to read like a pass. - The log's preflight line shows
(accepted weak)when
--allow-weak-engineruns past a failed preflight, astenaz status
does. The log used to be written before the run took the flag into
account. - The preflight line of the log and of
tenaz statusstarts with
settled=falsewhen the preflight's session did not finish. Such a
preflight fails, but its line used to read like a pass. - The engine proxy ends a streamed event at a blank line written with
\r\n\r\nor\n\r\n, as well as\n\n. With an engine that framed
its events that way, the proxy used to report an error inside the
stream only when the stream ended. When the request offered a tool to
repair, the whole reply reached the harness only then, not repaired,
and when its first event held arguments of a call to that tool, the
rest of the reply was dropped.
Install tenaz 0.4.0
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/aartiles/tenaz/releases/download/v0.4.0/tenaz-installer.sh | shInstall prebuilt binaries via Homebrew
brew install aartiles/tap/tenazDownload tenaz 0.4.0
| File | Platform | Checksum |
|---|---|---|
| tenaz-aarch64-apple-darwin.tar.gz | Apple Silicon macOS | checksum |
| tenaz-x86_64-unknown-linux-gnu.tar.gz | x64 Linux | checksum |
Verifying GitHub Artifact Attestations
The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:
gh attestation verify <file-path of downloaded artifact> --repo aartiles/tenazYou can also download the attestation from GitHub and verify against that directly:
gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>