diff --git a/CHANGELOG.md b/CHANGELOG.md index 5af0186..19404e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,94 @@ Pre-v1.0.0 tags followed the pi npm version (`v{pi_version}[letter]`). --- -## Unreleased +## v1.8.12 — 2026-08-31 + +**`pi` `0.84.3` → `0.84.4`, and `pi-atelier` `v0.8.2` → `v0.10.0`.** Both audited +by the routine in `Dockerfile.variant` rather than adopted on sight, and the +audit notes live next to the pins where the next reader will meet them. + +**pi 0.84.4 (published 2026-08-28) carries no `Breaking Changes` and no +`Removed` heading** — checked by grepping the section, 0 matches, which is worth +stating because 0.84.3 *did* have one. It was adopted for three fixes that land +on machinery this fleet runs every day, not for the feature list: + +- **#6879** — a large tool result crossing the auto-compaction threshold used to + be sent to the provider *before* compaction. Pi now compacts between tool + execution and the next assistant response inside the same run. That is the + shape of nearly every session on these boxes, where a single `event_list` or + palace search returns hundreds of KB. +- **#8345** — a resumed session corrupted its next appended entry when the JSONL + file lacked a trailing newline. That file is the memory feeder's *input*, so + the failure would have surfaced as unexplained gaps in `wing_conversations` + rather than as an error. Measured on tor-ms22 before bumping: 49/49 + transcripts end in a newline and 0 lines fail `json.loads` — this corpus was + never bitten, and we now know that rather than hope it. +- **#8537** — extension messages sent with `triggerTurn: false` *while the agent + is running* were inserted between a tool call and its result, so + order-validating providers rejected the replayed history. **The mempalace + mailbox is outside that precondition**: it delivers at `agent_settled`, when + no inference is in flight, with `{deliverAs: "steer"}` and deliberately no + `triggerTurn`. 0.84.4 also leaves the documented steer semantics untouched + ("delivered after the current assistant turn finishes executing its tool + calls, before the next LLM call"), so RFC 003 §7.11 stands as written. Recorded + because this fix is precisely what would make a *mid-run* delivery safe, which + is the only reason we would ever change that call. + +Also new and relevant, though nothing here uses them yet: `ui_prompt_start` / +`ui_prompt_end` extension events (the `docs/extensions.md` diff is add-only — no +steer or `triggerTurn` semantics moved), and an RPC `clear_queue` that returns +and removes queued steering messages. The second one can discard an +already-delivered but unconsumed mailbox steer; that is survivable because the +mailbox re-delivers on `MEMPALACE_MAILBOX_RESURFACE_MS` (default 3600000), and it +is written down here so a future "the mailbox lost a message" report has a +candidate cause. The three new `PI_HYPERLINKS` / `PI_IMAGE_PROTOCOL` / +`PI_TRUE_COLOR` environment variables were grepped against this whole repo: no +collisions with anything the image sets. + +**The bump moved one documented mechanism, so `docs/observational-memory.md` §3 +moved with it.** Pi's own `docs/compaction.md` gained exactly one paragraph in +0.84.4: the `autoCompact` threshold is now *also* checked mid-run, after a tool +batch's results are appended and before the next assistant response, skipped only +when that batch ends the run and no queued message needs another response. Our +doc said compaction is "checked when pi goes idle, so it never interrupts a +turn". That was only ever true of observational-memory's **own** trigger +(`compaction-trigger.ts` hooks `agent_settled`); read as a statement about pi it +is now false. `session_before_compact` (`compaction-hook.ts`) therefore has +**two** entry points and the second can fire inside a turn — harmless for the +ledger fold, which makes no model call, but a doc that ships a false promise +about when a hook runs is worse than one that admits two paths. The §3 mermaid +diagram gained the second edge, and the whole file re-passes the bundled mermaid +checker (6 blocks, 44 labels, 0 soft-wrapped, no cut glyphs at 1280px and +800px). + +**pi-atelier `v0.8.2` → `v0.10.0` is two minor releases and both are UI-only** — +Sidebar kept calm during an active Turn, composer frame and Status Rail polish, +fullscreen-copy-safe Sidebar, Windows path normalisation, Workspace Pulse +deferred until pi trusts the project. Neither release carries a BREAKING notice. +The coupling that matters runs the *opposite* way to this pin's hard-earned +floor: v0.9.0 renders the Sidebar as a separate split-layout child and therefore +"raises the minimum supported Pi version to 0.84.0", and — unlike the +0.7.1-under-pi-0.84 startup-hang precedent, which its metadata never encoded — +this time `peerDependencies` says so (`>=0.84.0`, up from `>=0.80.7`). Satisfied +with room to spare by `PI_VERSION=0.84.4`. It also pairs deliberately with a +0.84.4 feature: atelier keeps Sidebar content out of the fullscreen transcript +selection while pi adds `fullscreenCopyOnSelect` and Ctrl+X for the selection +itself. Both executable floors (`scripts/smoke-test.sh`, +`scripts/recreate-sanity-check.sh`) compare with `sort -V`, so `0.10.0 >= 0.7.1` +is evaluated correctly — verified by running the comparison, because the string +form of that test reads `0.10.0` as *older* than `0.7.1`. + +**While bumping the pins, the README's own pin table turned out to have been +wrong since v1.8.6.** It advertised pi `0.84.2` and mempalace `3.7.1` in the very +table whose purpose is to tell a reader what is pinned and where. Both rows went +stale in the *same* commit — `93f986e` (v1.8.6, "adopt pi 0.84.3 + mempalace +3.8.0") moved both `ARG`s and neither table row; the rows themselves date from +`29b6209` (v1.8.0) and `2ebf00d` (v1.8.4). Only atelier's row was still true. +All three corrected now, and the `--expected-version 0.84.3` example in the +recreate-sanity section updated too, since that one is a copy-pasteable command +that would now fail against a 0.84.4 image. Worth noting how it survived two +releases: nothing checks prose against the `ARG`s, so this table has to be +remembered by hand on every pin bump, and once it was not. **`credential-incident-response` gained the section its own guidance had been missing, and §2 gained a precondition it should always have carried.** Docs only; @@ -190,6 +277,40 @@ while `~/.bashrc` carries the image's), so the skel file is re-seeded on every recreate. A `$HOME/.bash_aliases` that is bind-mounted from the host is still never overwritten, which is the existing contract. +### Dependency audit (2026-08-31) + +Every component checked against upstream by direct command, not assumed: + +| Component | Baked in v1.8.11 | Upstream now | Action | +|---|---|---|---| +| **pi** | `0.84.3` (pinned) | **`0.84.4`** is npm latest | bumped + audited (above) | +| **pi-atelier** | `v0.8.2` (pinned) | **`v0.10.0`** highest tag | bumped + audited (above) | +| mempalace | `3.8.0` (pinned) | `3.8.0` is PyPI latest | none | +| skillset (mempalace fallback snapshot) | `a12fe5e` | `a12fe5e` == `origin/main`, 0 commits since | none — `--check` reports OK, no NOTICE | +| mempalace-toolkit | `21023e7` | `21023e7` | none | +| pi-toolkit | `0e1369e` | `0e1369e` | none | +| pi-extensions | `2022887` | `2022887` | none | +| pi-fork | `bf702b4` | `bf702b4` | none | +| pi-observational-memory | `ce9fc98` | `ce9fc98` (v3.0.4, peerDeps `*` → no pi floor to clear) | none | +| pi-studio (studio variant) | `3328b3d` | `3328b3d` | none | +| floating `*_VERSION=latest` tools (16) | — | 14 already at latest; `git-lfs` `3.7.1`→`3.8.0` (feature, no breaking section), `uv` `0.12.6`→`0.12.7` (patch) | adopted implicitly by the rebuild; named here per this repo's floating-ref rule | +| node | major pin `22`, installed `v22.23.2` | `v22.23.2` is the newest 22.x | none — a newer LTS *line* (24.x) exists and is deliberately not tracked | + +Two method notes, because both would have produced a confident wrong answer: + +- **An annotated tag's `ls-remote` SHA is the tag object, not the commit.** + `refs/tags/v0.8.2` is `6e07bf85` while `refs/tags/v0.8.2^{}` is `159f34cf` — + the value actually baked. Comparing the un-dereferenced form reported + `pi-atelier` as *drifted from its own pin*, which would have been a false + integrity alarm about the one component whose pin is load-bearing. Always + deref with `^{}` before calling a pin broken. +- **`git ls-remote --tags | sort -V | tail` is not a "latest release" proxy.** + `typst/typst` carries date-style tags (`v23-03-28`) and `mikefarah/yq` carries + `vTestA`/`vTestB`; both sort *after* the real releases. `Dockerfile.base` + itself resolves `latest` by reading the `Location` of + `curl -sI …/releases/latest`, so replaying that exact step is both + noise-immune and the same source of truth the build will see. + --- ## v1.8.11 — 2026-08-27 diff --git a/Dockerfile.variant b/Dockerfile.variant index 4cb5e42..1f68259 100644 --- a/Dockerfile.variant +++ b/Dockerfile.variant @@ -57,6 +57,32 @@ ARG USER_NAME=developer # v0.74.0..v0.75.5; discovered + fixed in v0.75.5b, 2026-05-23). The `latest` # branch below is kept only for a deliberate local `docker build` override. # +# AUDITED AT 0.84.4 (2026-08-31, was 0.84.3): NO "Breaking Changes" and no +# "Removed" heading in the 0.84.4 section (grepped, 0 matches) — unlike 0.84.3, +# whose heading is described in the paragraph below and stays audited. Adopted +# for three fixes that land on machinery this fleet actually runs: +# - #6879 large tool results crossing the auto-compaction threshold were sent +# to the provider BEFORE compacting; pi now compacts between tool execution +# and the next assistant response in the same run. This is the shape of +# nearly every session here (multi-hundred-KB logstream/palace tool output). +# - #8345 a resumed session corrupted its next appended entry when the JSONL +# lacked a trailing newline. That file is the memory feeder's own input. +# Measured on tor-ms22 before the bump: 49/49 transcripts end in a newline, +# 0 lines fail json.loads — the bug had not bitten this corpus. +# - #8537 extension messages sent with `triggerTurn: false` WHILE THE AGENT IS +# RUNNING were inserted between a tool call and its result, so +# order-validating providers rejected the replayed history. The mempalace +# mailbox is outside that precondition — it delivers at `agent_settled` +# (idle) with `{deliverAs:"steer"}` and deliberately no `triggerTurn` — and +# 0.84.4 leaves the documented steer semantics unchanged, so RFC 003 §7.11 +# still holds. Recorded because the fix is what would make a future mid-run +# delivery safe, which is the only reason we would ever change that call. +# One doc consequence, fixed in this same release: pi's own docs/compaction.md +# gained exactly one paragraph — the autoCompact threshold is now ALSO checked +# mid-run, after a tool batch's results are appended. See +# docs/observational-memory.md §3, which had said compaction is only checked +# when pi goes idle. +# # AUDITED AT 0.84.3 (2026-08-25, was 0.84.2): upstream's notes carry a # "Breaking Changes" heading — `GoogleThinkingLevel` renamed to # `GoogleApiThinkingLevel`. INERT FOR THIS IMAGE: all four vendored companions @@ -69,9 +95,7 @@ ARG USER_NAME=developer # `.agents/skills//` directories were not discovered, and root Markdown # files such as README.md / AGENTS.md inside a skill dir were reported as # broken skills unless they declared valid skill frontmatter. -# pi-atelier needs no companion bump: v0.8.2 clears the >=0.7.1 floor that -# pi >= 0.84 requires (see PI_ATELIER_REF below). -ARG PI_VERSION=0.84.3 +ARG PI_VERSION=0.84.4 ARG PI_TOOLKIT_REF=main ARG PI_EXTENSIONS_REF=main # Repo URLs default to the canonical gitea origin but are overridable so a @@ -101,15 +125,31 @@ ARG PI_OBSMEM_REF=master # pin and PI_VERSION together, checking atelier's CHANGELOG for the pi # version it claims to track. # +# AUDITED AT v0.10.0 (2026-08-31, was v0.8.2 — two minor releases): no +# BREAKING notice in either release, and both are UI-only (Sidebar calm during +# an active Turn, composer frame + Status Rail, fullscreen-copy-safe Sidebar, +# Windows path normalisation, Workspace Pulse deferred until pi trusts the +# project). The one coupling that matters runs the OPPOSITE way to the floor +# above: v0.9.0 renders the Sidebar as a separate split-layout child and +# therefore "raises the minimum supported Pi version to 0.84.0", which its +# peerDependencies do encode this time (`>=0.84.0`, up from `>=0.80.7`). +# Satisfied with room to spare by PI_VERSION 0.84.4 above — and note that both +# executable floors (scripts/smoke-test.sh, scripts/recreate-sanity-check.sh) +# compare with `sort -V`, so 0.10.0 >= 0.7.1 is evaluated correctly rather than +# as the string comparison that would read 0.10.0 as older than 0.7.1. +# Pairs deliberately with pi 0.84.4's own fullscreen selection-copy controls: +# atelier keeps Sidebar content out of the transcript selection, pi adds +# `fullscreenCopyOnSelect` + Ctrl+X for the selection itself. +# # No `npm install` step, unlike pi-fork/pi-observational-memory/pi-studio: # pi-atelier declares ZERO runtime dependencies (only peerDeps, satisfied by # the baked pi) and has no build step — pi loads its TypeScript directly from # the /opt checkout. Adding an install here would be a no-op that only costs # build time. ARG PI_ATELIER_REPO=https://github.com/michaelmjhhhh/pi-atelier.git -ARG PI_ATELIER_REF=v0.8.2 +ARG PI_ATELIER_REF=v0.10.0 # Human-readable tag PI_ATELIER_REF was resolved from; recorded as a label. -ARG PI_ATELIER_VERSION=v0.8.2 +ARG PI_ATELIER_VERSION=v0.10.0 RUN set -e && \ # git_fetch_ref: clone-equivalent helper that accepts EITHER a branch name diff --git a/README.md b/README.md index 97472bb..7253e45 100644 --- a/README.md +++ b/README.md @@ -1093,7 +1093,7 @@ persisted volumes survived, and pi runtime wiring is intact: ```bash ./scripts/recreate-sanity-check.sh # auto-detects variant ./scripts/recreate-sanity-check.sh --expected-image-version 1.8.9 # assert the pi-devbox release tag -./scripts/recreate-sanity-check.sh --expected-version 0.84.3 # assert the pi coding agent version +./scripts/recreate-sanity-check.sh --expected-version 0.84.4 # assert the pi coding agent version ``` Those are **two different versions**, and the flags are not interchangeable: @@ -1132,9 +1132,9 @@ resolved to `latest` at build time: | Component | Pin | Where | |---|---|---| -| pi | `0.84.2` | `ARG PI_VERSION` — `Dockerfile.variant` | -| pi-atelier | `v0.8.2` | `ARG PI_ATELIER_REF` — `Dockerfile.variant` | -| mempalace | `3.7.1` | `ARG MEMPALACE_VERSION` — `Dockerfile.base` | +| pi | `0.84.4` | `ARG PI_VERSION` — `Dockerfile.variant` | +| pi-atelier | `v0.10.0` | `ARG PI_ATELIER_REF` — `Dockerfile.variant` | +| mempalace | `3.8.0` | `ARG MEMPALACE_VERSION` — `Dockerfile.base` | The objective is **not** to freeze versions. Bumping is routine — usually one line plus a changelog note. The objective is that adopting a new upstream diff --git a/docs/observational-memory.md b/docs/observational-memory.md index ddc8c03..045d2f7 100644 --- a/docs/observational-memory.md +++ b/docs/observational-memory.md @@ -21,8 +21,9 @@ palace, see > Verified on pi-devbox **v1.8.9** (`release_tag v1.8.9`, source `aac4a1c`), > which bakes pi-observational-memory **v3.0.4** at commit `ce9fc98` — the value > in `/etc/pi-devbox/build-manifest.json` → `components.pi-observational-memory`. -> Every number below was read from that tree, from pi 0.84.3's own docs, or from -> the live container. +> Every number below was read from that tree, from pi's own docs, or from the +> live container. The pi-side mechanics were first read at pi **0.84.3** and +> re-checked at **0.84.4** (v1.8.12), which moved one of them — see §3. --- @@ -93,6 +94,7 @@ flowchart TD S(["agent_settled"]) --> C{"81k tokens
since compacting?"} C -- yes --> CP["ctx.compact()"] CP --> H(["session_before_compact"]) + A(["pi autoCompact
idle, or mid-run
after a tool batch"]) --> H H --> F["fold the ledger
no model call"] F --> VIS["compacted memory"] ``` @@ -105,10 +107,16 @@ flowchart TD a *successful same-turn* reflection **and** an active pool above `observationsPoolTargetTokens` [10000]. Not a third worker on a third threshold. -- **compaction** — `compactAfterTokens` [81000], checked when pi goes idle, so it - never interrupts a turn. Pi will also compact on its own when the context is - nearly full (`contextTokens > contextWindow - reserveTokens`, `reserveTokens` - [16384]). +- **compaction** — `compactAfterTokens` [81000], checked at `agent_settled`, so + *this* trigger never interrupts a turn. Pi will also compact on its own when + the context is nearly full (`contextTokens > contextWindow - reserveTokens`, + `reserveTokens` [16384]), and **from pi 0.84.4 that check also runs mid-run** — + after a tool batch's results are appended, before the next assistant response, + skipped only when the batch ends the run and no queued message needs another + response. So `session_before_compact` has **two** entry points and the second + one can fire *inside* a turn. Harmless for the fold itself, which makes no + model call, but worth stating plainly: "never interrupts a turn" was only ever + true of the observational-memory trigger, and reads as a promise about pi's. ## 4. What compaction actually does to your context