From 097fefa229da1ba61af1f1e02ce30cb76711f6f8 Mon Sep 17 00:00:00 2001 From: A Tobey Date: Wed, 2 Sep 2026 20:42:32 -0400 Subject: [PATCH] docs(changelog): the unreleased section shortens to the house rule MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The rule says a bullet is one line — the change, and at most one clause of reason — and that the whole unreleased section gets shortened before it is retitled for a release. It had drifted a long way from that: 47 bullets, 41 of them running past a single line, 120 lines total. Someone scanning for what changed was reading the reasoning behind it instead. Now 46 bullets, none longer than two wrapped lines, 95 lines. The reasoning did not disappear; it lives in the pull requests, which is where the rule says it belongs. Shortening surfaced a wrong fact, which is the better find. The kaish bullet said "upgraded to 0.17.1 (from 0.14.1)" while a separate Fixed bullet announced "Bump kaish-kernel to 0.14.1" — the same cumulative jump stated twice, from a baseline that was not the released one. v0.3.0 shipped on kaish-kernel **0.14.0** (checked with `git show v0.3.0:Cargo.toml`), so a reader upgrading from the last release was told the wrong starting point. It now reads "from 0.14.0", once, and 0.14.1's user-visible fix — the explorer's shell dropping piped stdin — stays in Fixed as the fix rather than as a version bump. Compression was checked for loss, not assumed: diffing the vocabulary of both versions turned up four things a user would act on that the first pass had dropped, and all four are back — that a slow generation returns a `job-N` handle, that base64 `content` is still the way in for an image that is not a file, the four image formats `write_cas` accepts by signature, and the twenty-fold cost spread across operations, since an exact number is the whole point of publishing one. Co-Authored-By: Claude Opus 5 --- CHANGELOG.md | 149 +++++++++++++++++++++------------------------------ 1 file changed, 61 insertions(+), 88 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a41a08..9c309e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,123 +17,96 @@ record. Each later release appends a new section at the top. ### Added -- **A `bfl` backend kind** — Black Forest Labs' FLUX image family through `generate`, - five named operations, polled in-call for a fast generation and as a `job-N` handle - only past that budget. -- **A `gemini-images` backend kind** — Gemini image generation through `generate`, the - same face as every other image backend. Takes input images; has no named operations. -- **`generate` shows what the model said** above the digests, for a backend whose image - generation is a conversation and answers with words as well as bytes. -- **Transient provider failures (rate limits and overloads) are retried with backoff** - instead of failing the whole call. -- **`kaibo cas write FILE`** stores an image from the command line and prints its - digest — the CLI half of `write_cas`, so an operator can put an image in without an - MCP client. -- **`generate` reaches an OpenAI-compatible images backend's `edits` and `variations` - routes** through the same `op` parameter, over multipart where `generations` is JSON. +- **`bfl` and `gemini-images` backend kinds** — the FLUX and Gemini image families + through `generate`. +- **A slow generation comes back as a `job-N` handle** rather than holding the call, once + it runs past the in-call budget. +- **`kind = "dashscope"`** — Alibaba's wan image family, so `generate` runs on a + DashScope subscription. - **`generate` reaches Stability's edit, control and upscale routes** through a new `op` parameter — twelve operations where three were wired. -- **Each operation's cost is published on the `op` parameter** in the provider's own - unit, unconverted — so a model sees the twenty-fold spread before it picks a route. +- **`generate` reaches an OpenAI-compatible backend's `edits` and `variations` routes** + through the same `op`. +- **Each operation's cost is published on the `op` parameter**, in the provider's own + unit, so a model sees the twenty-fold spread before it picks a route. - **An unrecognized `op`, or one on a backend with no operations, is refused** rather than run as a text-to-image generation. -- **`generate` takes input images by digest** — `inputs [{"field": "image", "digest": - "..."}]` is image-to-image on Stability's `ultra` and `sd3` routes, reusing an image - already in the store rather than re-sending it. A field name may repeat, for the - operations that take several source images under one name. -- **`generate` carries several named input parts**, so an operation taking - `init_image`+`style_image`, or an image plus an optional mask, is reachable. +- **`generate` takes input images by digest**, reusing an image already in the store, + and carries several named parts where an operation needs them. - **A media backend with no input-image route refuses a call that carries one**, rather - than silently generating from the prompt alone and returning an unrelated image. + than generating from the prompt alone. - **An unknown or non-image input digest refuses before the provider is called**, so a typo never costs a generation. -- **`write_cas` stores an image in kaibo's media store and returns its digest** — the - deposit half of `read_cas`, and how an image reaches kaibo at all. +- **`generate` shows what the model said** above the digests, for a backend that answers + with words as well as bytes. +- **`write_cas` stores an image and returns its digest** — the deposit half of + `read_cas`, and how an image reaches kaibo at all. - **`write_cas` takes a `path` and reads the file itself**, so an image costs no tokens; base64 `content` remains for an image that is not a file. -- **`write_cas` reads the format from the bytes**, so png/jpeg/gif/webp are accepted by - signature and there is no `mime` to state or get wrong. -- **`[telemetry]` exports the GenAI metrics signal** — token usage, call and phase - durations, turns per phase, and tool calls per phase, as the conventions name them. +- **`write_cas` reads the format from the bytes** — png, jpeg, gif and webp by + signature, so there is no `mime` to state or get wrong. +- **`kaibo cas write FILE`** — the CLI half, so an operator can deposit an image without + an MCP client. +- **Transient provider failures are retried with backoff** instead of failing the call. +- **`[telemetry]` exports the GenAI metrics signal** — token usage, durations, turns and + tool calls per phase. - **`gen_ai.invoke_agent.tool_calls` answers whether a consult driver delegated**, - split by `synth` / `explorer`, without reading a single trace. -- **`[telemetry] traces` and `[telemetry] metrics`** — per-signal switches, so - `traces = false, metrics = true` exports kaibo's spend and latency and nothing else. - No metric can carry prompts, so that posture is safe by construction. + without reading a single trace. +- **`[telemetry] traces` and `[telemetry] metrics`** — per-signal switches; no metric can + carry prompts, so metrics-only is safe by construction. - **`[telemetry] metrics_endpoint`** — omit it and kaibo derives the sibling of - `endpoint`, the same rule `logs_endpoint` follows. -- **`OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` turns telemetry on by itself**, for a - platform that collects metrics and not traces. -- **`kind = "dashscope"`** — a media backend for Alibaba's wan image family, so - `generate` can run on a DashScope subscription. + `endpoint`. +- **`OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` turns telemetry on by itself**, for a platform + that collects metrics and not traces. - **kaibo reads the standard `OTEL_*` environment**, including `OTEL_SDK_DISABLED`. -- **`[telemetry] capture_content`** — off by default, so exported spans carry no prompts, +- **`[telemetry] capture_content`** — off by default, so spans carry no prompts, completions, or tool payloads. - **`[telemetry] capture`** — export one named attribute without exporting all of them. -- **Backend keys can come from a command** — `[backends.] api_key_cmd = ["op", - "read", "op://Vault/Item/Field"]` runs the declared command (no shell, stdin closed, - 30s ceiling, output never logged) and uses its trimmed stdout as the API key: a - 1Password / `pass` / `gh auth token` credential without a secret in a file. -- **Key sources are declared, never seeded** — the built-in backends no longer read - `ANTHROPIC_API_KEY` / `~/.anthropic-key.txt` / etc. out of the box; an operator names - the source (`api_key_env`, `api_key_file`, or `api_key_cmd`) in config.toml once, and - `api_key_file` + `api_key_cmd` together is a load error naming both. +- **Backend keys can come from a command** — `api_key_cmd = ["op", "read", "op://…"]` + runs it with no shell, stdin closed, and the output never logged. ### Changed -- **kaish upgraded to 0.17.1** (from 0.14.1) — the read-only shell gains symlink - support, pipeline-stage compound statements, `set -o pipefail`, and base-aware - arithmetic. -- **`readlink -f` and `realpath` resolve a path again** — both failed on every operand - before, naming neither the operand nor its target. -- **`grep -rn PATTERN` is what kaibo teaches now**, without the trailing `.` — kaish - 0.16 prefixes hits with the operand as written, so the bare form is the one that - yields repo-relative `file:line` citations. -- **A refused external command explains itself** — `curl: external commands are not - available in this build of the shell` rather than a bare `command not found`, still - exit 127. -- **`ls -l`, `stat`, `readlink`, and `find -type l` describe a symlink itself** instead - of following it, so a link is visible as a link. A link pointing outside the project - shows its target path; every read that would follow it out is still refused. +- **kaish upgraded to 0.17.1** (from 0.14.0) — the read-only shell gains symlinks, + compound statements in pipes, `set -o pipefail`, and base-aware arithmetic. +- **`ls -l`, `stat`, `readlink`, and `find -type l` describe a symlink itself** — one + pointing outside the project shows its target path. +- **Every read that would follow a link out of the project is still refused**, so the + target's contents, permissions, and existence stay unreachable. - **The directories above the project list again** — each names only the next component - down to the project, so the shell shows the root path the caller already gave it. -- **A compound statement can feed a pipe** — `for f in …; do …; done | grep x` is no - longer a parse error. + down to the project. +- **`readlink -f` and `realpath` resolve a path again** — both failed on every operand. +- **A compound statement can feed a pipe** — `for f in …; do …; done | grep x` parses. +- **`${#v}` counts characters, not bytes** — `v=日本語; echo ${#v}` answers 3. +- **Arithmetic refuses a leading zero and reads other bases** — `$((0xff))` is 255. - **`yes` and `no` are ordinary strings**, not lexer errors, so `echo yes` runs. -- **`${#v}` counts characters, not bytes**, and a non-ASCII value no longer fails to - lex — `v=日本語; echo ${#v}` answers 3. -- **Arithmetic refuses a leading zero and reads other bases** — `$((007))` names the - spelling that works, `$((0xff))` is 255. - -- **kaibo now fetches a generated artifact's URL when that is how a provider delivers - it**, over TLS and size-bounded, instead of refusing it — otherwise the operator - fetches the link by hand with their key. -- **Every outbound request now identifies itself as `kaibo/`** — kaibo's - traffic previously carried no `User-Agent` at all. +- **`grep -rn PATTERN` is what kaibo teaches now**, without the trailing `.`, so + citations come back repo-relative. +- **A refused external command explains itself** — `curl: external commands are not + available in this build of the shell`, still exit 127. +- **kaibo fetches a generated artifact's URL when that is how a provider delivers it**, + over TLS and size-bounded, instead of refusing it. +- **Every outbound request identifies itself as `kaibo/`** — kaibo's traffic + previously carried no `User-Agent` at all. - **Telemetry turns on when `OTEL_EXPORTER_OTLP_ENDPOINT` is set** — safe now that content is redacted by default. - **An explicit `[telemetry] enabled = false` beats the environment**, and `OTEL_SDK_DISABLED` beats every source. -- **A failed batch now names where the failure happened** — the provider accepted the - batch and failed it afterward, so a bare provider string no longer reads as a kaibo bug. -- **A failed batch now counts its unspent prompts** and points at `batch_submit`, in the - rendered poll and as `submitted` in `batch get --json`. -- **A failed batch now names the cast that ran it**, the provenance footer a completed - batch already carried. -- **Setup guidance steers toward declaring a key source in config.toml** (with - `kaibo example-config` for the shape) instead of exporting an env var. +- **A failed batch names where it failed, counts its unspent prompts, and names the cast + that ran it** — a bare provider string used to read as a kaibo bug. +- **Setup guidance steers toward declaring a key source in config.toml** instead of + exporting an env var. - **Breaking: an upgrading operator must add a key source to every backend they use** — - the built-ins no longer seed one, so a cast built on an undeclared backend silently - drops out of the roster; add `api_key_env`/`api_key_file`/`api_key_cmd` per backend to - bring it back (`kaibo example-config` shows the shapes). + a cast on an undeclared backend silently drops out of the roster. +- **Key sources are declared, never seeded** — name `api_key_env`, `api_key_file`, or + `api_key_cmd` per backend (`kaibo example-config` shows the shapes). ### Fixed - **The README's cosign floor said 3, and 2.5 verifies a release** — the old floor turned away working installs. -- **Bump `kaish-kernel` to 0.14.1** — the explorer's shell no longer drops piped or - buffered stdin across `read`/`grep`/`cat`, and a loop or `if` that exits early keeps - what it already printed. +- **The explorer's shell no longer drops piped or buffered stdin** across + `read`/`grep`/`cat`, and a loop that exits early keeps what it already printed. ## [0.3.0] — 2026-08-13