Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 93f986e90e | |||
| 26f223568d |
@@ -18,6 +18,19 @@ SSH_KEY_PATH=~/.ssh
|
||||
# the staged files and the palace dedup keys pointing at them cannot be
|
||||
# separated.
|
||||
#
|
||||
# That palace root is resolved with mempalace's own precedence
|
||||
# ($MEMPALACE_PALACE_PATH -> $MEMPAL_PALACE_PATH -> ~/.mempalace/config.json ->
|
||||
# ~/.mempalace/palace), and the feeders derive their stage FROM it
|
||||
# (<palace-root>/pi-stage). Neither the image nor the entrypoint exports it, by
|
||||
# design: pinning the palace without carrying the stage along re-creates the
|
||||
# very split that a shared root removed. Override it only to move the palace off
|
||||
# the default -- e.g. onto a different mount -- and only to a path with the SAME
|
||||
# persistence as the palace itself. A stage that outlives its palace (or dies
|
||||
# first) makes a scoped `mempalace sync` prune conversation drawers, because
|
||||
# their dedup key is the staged path. Setting it to the default buys nothing.
|
||||
# Unlike WORKSPACE_PATH/SSH_KEY_PATH above, this is a path INSIDE the container.
|
||||
# MEMPALACE_PALACE_PATH=/home/developer/.mempalace/palace
|
||||
#
|
||||
# To instead share ONE MemPalace across containers/harnesses (pi + opencode
|
||||
# + native), set the URL below. When set, the extension connects over HTTP
|
||||
# and NO local mempalace-mcp is spawned; the devbox-palace volume is then
|
||||
|
||||
+187
@@ -11,6 +11,193 @@ Pre-v1.0.0 tags followed the pi npm version (`v{pi_version}[letter]`).
|
||||
|
||||
---
|
||||
|
||||
## v1.8.6 — 2026-08-25
|
||||
|
||||
Patch release. Adopts the drift that accumulated in the ~2 days since v1.8.5
|
||||
(pi `0.84.3`, mempalace core `3.8.0`), then closes the documentation and
|
||||
observability gaps that v1.8.5 itself listed as "Still open". No component
|
||||
was adopted without an audit note recording *why* it is safe.
|
||||
|
||||
All moving refs re-resolved immediately before tagging (2026-08-25T13:28Z):
|
||||
pi-toolkit `0e1369e6`, pi-extensions `20228878`, mempalace-toolkit `0fe64c48`
|
||||
and pi-observational-memory `ce9fc982` all unchanged since v1.8.5;
|
||||
pi-fork `f1ff8087` → `bf702b4c`; pi-atelier holds at `v0.8.2` (floor for
|
||||
pi ≥0.84 satisfied); pi-studio's CI-resolved newest tag has moved again to
|
||||
`v0.9.51`. Base rebuild is forced (Dockerfile.base changed), so the 16
|
||||
floating base-tooling ARGs re-roll — expect ~67 min as for v1.8.5.
|
||||
|
||||
### Changed
|
||||
|
||||
- **`mempalace` core `3.7.1` → `3.8.0`.** Released 2026-08-23T21:19Z, hours
|
||||
after this project's own v1.8.5 tag the same day. Additive/reliability only
|
||||
— reviewed for MCP tool-schema changes before bumping, as always: none.
|
||||
`sync --apply` (PR #2320/#2322) no longer deletes a drawer solely because
|
||||
its `source_file` was unreachable *at that moment* — it asks for
|
||||
corroboration first. **This does not relax the standing landmine** against
|
||||
running `mempalace_sync` / `mempalace_delete_by_source` beyond dry-run on
|
||||
the shared central palace: that failure mode is paths *permanently* absent
|
||||
from whichever host runs the sync, not transient unavailability, and 3.8.0
|
||||
doesn't touch it. Server-side perf fix PR #2307 (long-running Chroma servers
|
||||
no longer invalidate their own HNSW cache on their own writes) likewise does
|
||||
not make `mempalace_reconnect` unnecessary — that tool covers *external*
|
||||
writes bypassing the in-process client, a different scenario. Full reasoning
|
||||
lives in the `Dockerfile.base` comment above `ARG MEMPALACE_VERSION`.
|
||||
**Deployment note:** synlig's central palace currently serves `3.7.1`
|
||||
server-side via `docker-compose.mempalace.yml` (which reuses this image) —
|
||||
this client bump introduces version skew until that stack is separately
|
||||
redeployed; sequence accordingly.
|
||||
|
||||
- **`pi` `0.84.2` → `0.84.3`.** Published 2026-08-24T11:09Z. Release notes
|
||||
carry one "Breaking Changes" line — `GoogleThinkingLevel` renamed to
|
||||
`GoogleApiThinkingLevel` — checked against all four vendored packages
|
||||
(`pi-fork`, `pi-observational-memory`, `pi-atelier`, `pi-studio`): zero
|
||||
references, inert here. 0.84.3 also fixes two skill-discovery bugs that
|
||||
land directly on this repo's own vendored-skill work: nested Markdown
|
||||
skills inside `.agents/skills/` grouping directories not being discovered,
|
||||
and root Markdown files (`README.md`/`AGENTS.md`) in skill directories being
|
||||
wrongly reported as broken skills.
|
||||
|
||||
### Added
|
||||
|
||||
- **Browser automation is now documented to humans, not just to agents.**
|
||||
`agent-browser` + Playwright + a headless Chromium (~625 MB — the single
|
||||
largest addition in the image) previously had zero mentions in `README.md`,
|
||||
`DOCKER_HUB.md` or `THIRD_PARTY.md`; it existed only in the agent-facing
|
||||
`AGENTS.md` managed block. Added a `README.md` "Browser automation"
|
||||
subsection, a `DOCKER_HUB.md` feature entry, and `THIRD_PARTY.md` license
|
||||
rows for `agent-browser` (Apache-2.0), Playwright (Apache-2.0), and Chromium
|
||||
(BSD-3-Clause for Chromium's own code plus a large set of bundled
|
||||
third-party components under their own licenses; the binary here is not
|
||||
compiled by this repo — it's Playwright's own "Chrome for Testing" download
|
||||
via `playwright install --with-deps chromium`).
|
||||
- **`THIRD_PARTY.md` gains rows for `pi-atelier` (MIT) and `mempalace` core
|
||||
(MIT per the GitHub repo; noted that the PyPI package's own metadata omits
|
||||
a license classifier, so verify against the repo's `LICENSE` rather than
|
||||
sdist/wheel metadata if clearance is needed from the artifact alone).**
|
||||
- **`typst` and `socat` added to `README.md`'s tooling inventory.** Both were
|
||||
already used in prose (typst as pandoc's `--pdf-engine`, socat by
|
||||
`studio-expose`) but missing from the "What's inside" lists, so the
|
||||
inventory didn't match what the image actually ships.
|
||||
- **`mempalace` core version recorded in `/etc/pi-devbox/build-manifest.json`.**
|
||||
Previously absent — a published image couldn't answer "which palace version
|
||||
shipped?", and a palace bug couldn't be correlated to an image version.
|
||||
Derived from the live installed binary (matching the manifest's existing
|
||||
ground-truth-not-build-args philosophy), degrading to `null` rather than
|
||||
failing the build if the binary is missing or its output format changes.
|
||||
Verified landed: new top-level `"mempalace_version"` key, sibling to
|
||||
`pi_version` rather than a member of `components{}` (that map is rendered
|
||||
truncated to 12 chars by `pi-devbox-version`, which would mangle a longer
|
||||
version string).
|
||||
- **New smoke assertions**, all landed in `scripts/smoke-test.sh`: (1) the
|
||||
`pi-observational-memory` clone is checked for the actual `ce9fc98`
|
||||
auth-fix markers pinned to their fix site, `src/runtime.ts`
|
||||
(`availability_recheck`, `providerCredentialConfigured`,
|
||||
`hasConfiguredAuth`) — not merely clone existence, and deliberately not a
|
||||
repo-wide grep: all three identifiers also appear under `tests/`, so a
|
||||
repo-wide search would stay green even with the fix reverted in
|
||||
`src/runtime.ts` alone; (2) the manifest's new `mempalace_version` field is
|
||||
asserted present, non-null, and equal to what `mempalace --version` reports
|
||||
live, so the manifest can't silently drift from the installed package —
|
||||
expected to fail against any pre-v1.8.6 image, by design; (3) a
|
||||
behavioural check for the mempalace-toolkit feeder's `--agent` default
|
||||
(see below — this one turned out to be possible after all).
|
||||
|
||||
### Fixed
|
||||
|
||||
- **A false claim was being published to Docker Hub on every release.**
|
||||
`DOCKER_HUB.md` advertised "neovim (LazyVim defaults)". Nothing in this
|
||||
repo installs LazyVim — the only nvim configuration is a 19-line
|
||||
`sysinit.vim` that sets `termguicolors`. `update-description` pushes this
|
||||
file verbatim (with `{{PI_VERSION}}` substituted) to the Hub description, so
|
||||
the error was public, not internal. Corrected to describe what's actually
|
||||
there.
|
||||
|
||||
### Component audit for this release
|
||||
|
||||
Checked against upstream 2026-08-25 (two days after v1.8.5's own audit):
|
||||
`mempalace` core moved `3.7.1` → `3.8.0` (see Changed, above — timing is
|
||||
notable: released *hours after* v1.8.5 tagged, so v1.8.5 could not have caught
|
||||
it no matter how carefully it was audited). `pi` moved `0.84.2` → `0.84.3`
|
||||
(see Changed). `pi-toolkit` `0e1369e6`, `pi-extensions` `20228878`,
|
||||
`pi-observational-memory` `ce9fc982`, and `pi-atelier` `v0.8.2` are all
|
||||
**unchanged** from v1.8.5 — in particular `pi-observational-memory` still sits
|
||||
exactly at the auth-fix commit with nothing landed upstream since, and
|
||||
`pi-atelier` is still the newest tag with the `≥0.7.1` floor for `pi ≥ 0.84`
|
||||
trivially satisfied. `pi-fork` has one upstream commit not adopted this
|
||||
release: `f1ff8087` → `bf702b4c`, a text-only rewording of the fork task
|
||||
preamble (no code-path change) — **left un-pulled** for this release since it
|
||||
is a moving ref CI resolves fresh at every build anyway; it will be adopted
|
||||
automatically on the next build regardless of this entry. `pi-studio` (studio
|
||||
variant) has drifted two tags upstream, `v0.9.48` (pinned at build time via
|
||||
CI's newest-semver-tag resolution) → `v0.9.51` at tag time, purely additive
|
||||
(watched PDF previews, opening PDFs directly in Studio, Studio header
|
||||
hide) — nothing to bump in this repo since studio-tag resolution happens in
|
||||
CI, not the Dockerfile, but note it **will** auto-adopt `v0.9.51` on the next
|
||||
studio-variant build. `mempalace-toolkit` unchanged — this release's manifest
|
||||
and pi-bump work in `Dockerfile.variant` stayed within that file's ownership
|
||||
and did not require a toolkit-side change.
|
||||
|
||||
### Still open
|
||||
|
||||
- **`MEMPALACE_VERSION` has no CI-side audit equivalent to `PI_VERSION`'s.**
|
||||
`PI_VERSION` is verified published-on-npm and warns (never silently adopts)
|
||||
on drift; `MEMPALACE_VERSION` is a literal Dockerfile string with zero
|
||||
references in `.gitea/workflows/docker-publish.yml`. Flagged in v1.8.5's
|
||||
audit as a gap; still a gap.
|
||||
- **`pi-devbox-version`'s human-readable output does not display
|
||||
`mempalace_version`.** Its render path is a fixed sequence
|
||||
(`release_tag`, `build_date`, `source_revision`, `pi`, then `components{}`)
|
||||
and the new top-level field isn't in it — only `--json` mode (which `cat`s
|
||||
the manifest directly) surfaces it today. One line in
|
||||
`rootfs/usr/local/bin/pi-devbox-version` would fix this; deferred since the
|
||||
field's stated purpose (correlating a palace bug to an image) is already
|
||||
served by `--json`, but worth doing in a follow-up if this becomes a
|
||||
routine manual check.
|
||||
|
||||
**Resolved during this release, not left open:** the feeder `--agent`
|
||||
default behavioural hook initially looked like it might need a
|
||||
mempalace-toolkit change (a `--print-config` flag that doesn't exist). It
|
||||
didn't — `mempalace-pi-session` assigns `AGENT` before argument parsing and
|
||||
`--help` exits 0 with no side effects, so `bash -x mempalace-pi-session
|
||||
--help` observes the real resolution (env interpolation and fallback)
|
||||
without needing a source change. The new smoke assertion exploits exactly
|
||||
that, checked both ways: with `MEMPALACE_PI_DEVICE` set it must resolve to
|
||||
`pi@<device>`; with it unset it must NOT be `pi@*` (catches a regression to
|
||||
the old unconditional `$USER`/`mempalace` default).
|
||||
`mempalace-toolkit` commit `c64ffa1` changed the feeder's `--agent` default
|
||||
from `$USER` to `pi@<device>`, but there is still no way for smoke to assert
|
||||
this default is actually in effect from this repo alone, since
|
||||
`mempalace-toolkit` is a separate repo this release does not modify. If the
|
||||
concurrent smoke-test work could not find an honest assertion from the
|
||||
existing `/opt/mempalace-toolkit` surface (help text, `--self-test`), this
|
||||
remains open pending a toolkit-side `--print-config`-style hook — a
|
||||
toolkit-repo change, not a pi-devbox one.
|
||||
- **16 base-tooling `ARG *_VERSION=latest` pins remain unrecorded.** (Corrected
|
||||
count — v1.8.5's entry said "~14"; the actual count from `Dockerfile.base`
|
||||
is 16, plus 5 more that float with no ARG at all: `rustup-init`, AWS CLI v2,
|
||||
Chromium-via-Playwright, Node's minor version via `setup_22.x`, and
|
||||
`DEBIAN_VERSION=trixie-slim` itself.) None of these are recorded anywhere
|
||||
once the build completes — not in the manifest, not in a label — so a
|
||||
published image cannot answer "which nvim/uv/chromium shipped?" without
|
||||
exec-ing in and asking the binary.
|
||||
|
||||
### Documentation
|
||||
|
||||
- **`.env.example` documents `MEMPALACE_PALACE_PATH`.** It was the only MemPalace
|
||||
variable the template never mentioned, while being the one that silently moves
|
||||
the feeders' stage: the palace root resolves as `$MEMPALACE_PALACE_PATH` →
|
||||
`$MEMPAL_PALACE_PATH` → `~/.mempalace/config.json` → `~/.mempalace/palace`, and
|
||||
the stage is derived from it (`<palace-root>/pi-stage`). The comment states the
|
||||
precedence, says why neither the image nor the entrypoint exports it (pinning
|
||||
the palace without carrying the stage re-creates the split a shared root
|
||||
removed — see v1.8.2), warns that a stage whose persistence differs from the
|
||||
palace makes a scoped `mempalace sync` prune conversation drawers whose dedup
|
||||
key is the staged path, and notes it is a *container* path unlike the
|
||||
host-side `WORKSPACE_PATH`/`SSH_KEY_PATH` above it. Found while auditing a live
|
||||
host whose `.env` sets the variable redundantly to the default.
|
||||
|
||||
---
|
||||
|
||||
## v1.8.5 — 2026-08-23
|
||||
|
||||
Patch release with two fixes in the container's skill wiring — one behavioural,
|
||||
|
||||
+8
-1
@@ -65,12 +65,19 @@ The entrypoint deploys/registers all of these on first container start. Re-runni
|
||||
### Document and image tooling
|
||||
|
||||
- **pandoc** — universal Markdown↔HTML/Org/RST/etc. conversion. Useful well beyond pi: agent-driven doc exports, format conversion, etc.
|
||||
- **Typst** — markup-based typesetting, used as pandoc's `--pdf-engine`
|
||||
- **graphviz** (`dot`) — diagram rendering pipelines
|
||||
- **imagemagick** (`magick`) — image conversion / resizing
|
||||
|
||||
### Browser automation
|
||||
|
||||
- **agent-browser** — CLI for driving a real browser (open pages, click/fill/`eval`, snapshot the DOM, screenshots) so agents can verify front-end work instead of guessing
|
||||
- **Playwright** + a headless **Chromium** are pre-installed and pinned together; `AGENT_BROWSER_EXECUTABLE_PATH` is preset to the baked browser, so `agent-browser open <url>` works out of the box with no setup
|
||||
- **socat** — TCP bridge used to expose the pi-studio server outside the container's loopback
|
||||
|
||||
### Modern CLI tooling
|
||||
|
||||
- **Editor**: neovim (LazyVim defaults), tmux (configured for 0-indexed sessions)
|
||||
- **Editor**: neovim (system-wide `termguicolors` default; bring your own config/plugins), tmux (configured for 0-indexed sessions)
|
||||
- **Search/nav**: ripgrep, fd, fzf, zoxide
|
||||
- **Display**: bat, eza, htop, tree
|
||||
- **Data**: jq, yq
|
||||
|
||||
+38
-1
@@ -396,7 +396,44 @@ ARG INSTALL_MEMPALACE=true
|
||||
# (refuse the write) rather than fail open. Neither affects the container's
|
||||
# normal MCP-server-plus-CLI-feeder pattern, which already serialised on the
|
||||
# same lock under 3.6.0.
|
||||
ARG MEMPALACE_VERSION=3.7.1
|
||||
#
|
||||
# 3.8.0 (2026-08-23, PyPI, released hours after this project's own v1.8.5 tag
|
||||
# the same day) is additive/reliability only — reviewed for MCP tool-schema
|
||||
# changes before bumping, as always: there are NONE. Two PRs matter:
|
||||
# - PR #2320/#2322: `sync --apply` no longer deletes a drawer solely because
|
||||
# its source_file was unreachable AT THAT MOMENT — it now asks for
|
||||
# corroboration first. This fixes losing a whole mined project to one
|
||||
# `sync --apply` while its volume happened to be unmounted.
|
||||
# IMPORTANT — do not over-read this fix: it addresses TRANSIENT
|
||||
# unreachability, not the standing landmine (documented in the operator's
|
||||
# global AGENTS.md) against running `mempalace_sync` / `mempalace_delete_by_source`
|
||||
# beyond dry-run on the SHARED central palace. On that palace most
|
||||
# source_file paths are PERMANENTLY absent from whichever host runs the
|
||||
# sync — a different machine's paths simply do not exist here, ever, not
|
||||
# merely "right now". That is a different failure shape than #2320/#2322
|
||||
# fixes. The landmine still stands; this bump does not relax it.
|
||||
# - PR #2307: long-running Chroma servers no longer invalidate their own
|
||||
# HNSW cache on their own writes (server-side perf fix). This does NOT
|
||||
# make `mempalace_reconnect` unnecessary — that tool exists for EXTERNAL
|
||||
# writes bypassing the in-process client (e.g. direct sqlite backfills,
|
||||
# CLI commands against a running server), a different scenario #2307
|
||||
# does not touch.
|
||||
#
|
||||
# Known gap, carried forward (flagged in prior release notes, not fixed here):
|
||||
# unlike PI_VERSION, which CI's resolve-versions job verifies is published and
|
||||
# warns — never silently adopts — on npm drift, MEMPALACE_VERSION has NO
|
||||
# equivalent CI-side audit (confirmed: zero references to MEMPALACE_VERSION in
|
||||
# .gitea/workflows/docker-publish.yml). This is a literal Dockerfile string
|
||||
# with no automated freshness or publish check.
|
||||
#
|
||||
# Deployment sequencing note for whoever ships this bump: synlig (the shared
|
||||
# central palace host) currently serves mempalace 3.7.1 SERVER-SIDE via
|
||||
# docker-compose.mempalace.yml, which reuses this same devbox image. Bumping
|
||||
# this ARG changes only the CLIENT version baked into pi-devbox images: it
|
||||
# introduces client/server skew until synlig's compose stack is separately
|
||||
# rebuilt/redeployed with the new pin. Not something to code around here —
|
||||
# just sequence the redeploy.
|
||||
ARG MEMPALACE_VERSION=3.8.0
|
||||
ENV UV_TOOL_DIR=/opt/uv-tools
|
||||
ENV UV_TOOL_BIN_DIR=/usr/local/bin
|
||||
RUN if [ "${INSTALL_MEMPALACE}" = "true" ]; then \
|
||||
|
||||
+33
-1
@@ -56,7 +56,22 @@ ARG USER_NAME=developer
|
||||
# current when it was first populated (shipped the same bytes for pi-devbox
|
||||
# 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.
|
||||
ARG PI_VERSION=0.84.2
|
||||
#
|
||||
# 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
|
||||
# (/opt/pi-fork, /opt/pi-observational-memory, /opt/pi-atelier, /opt/pi-studio)
|
||||
# were grepped for that symbol and reference it ZERO times, so nothing here
|
||||
# couples to the renamed type. Recorded because the heading will look alarming
|
||||
# to the next reader doing step 1 above — the audit is done, don't redo it.
|
||||
# Adopted for two fixes that land squarely on this repo's own vendored-skill
|
||||
# wiring (see devbox-skill-reconcile, v1.8.5): nested Markdown skills inside
|
||||
# `.agents/skills/<group>/` 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_TOOLKIT_REF=main
|
||||
ARG PI_EXTENSIONS_REF=main
|
||||
# Repo URLs default to the canonical gitea origin but are overridable so a
|
||||
@@ -297,6 +312,19 @@ RUN set -e; \
|
||||
mkdir -p /etc/pi-devbox; \
|
||||
rev() { git -C "$1" rev-parse HEAD 2>/dev/null || echo "unknown"; }; \
|
||||
PI_V="$(pi --version 2>/dev/null | head -n1 | tr -d '\r\n')"; \
|
||||
# mempalace CORE (the PyPI package behind the MCP tools) is installed in
|
||||
# Dockerfile.base via `uv tool install`, so no /opt clone reveals it and
|
||||
# until v1.8.6 the manifest could not answer "which palace shipped here?" —
|
||||
# a palace bug could not be correlated to an image, which is precisely the
|
||||
# correlation this file exists to provide. Read from the INSTALLED BINARY,
|
||||
# not from ARG MEMPALACE_VERSION, per the ground-truth rule above: that is
|
||||
# what catches an install which resolved to something other than the pin.
|
||||
# `mempalace --version` prints "MemPalace 3.7.1" — NAME-PREFIXED, unlike
|
||||
# pi's bare "0.84.2" — hence the $NF pick rather than a straight read. The
|
||||
# leading-digit test then rejects usage/error text (a renamed flag prints a
|
||||
# usage block) and degrades to JSON null, so this can never fail the build.
|
||||
MP_V="$(mempalace --version 2>/dev/null | head -n1 | tr -d '\r' | awk '{print $NF}')"; \
|
||||
case "$MP_V" in [0-9]*) MP_CORE="\"${MP_V}\"" ;; *) MP_CORE='null' ;; esac; \
|
||||
STUDIO_REV='null'; \
|
||||
if [ -d /opt/pi-studio/.git ]; then STUDIO_REV="\"$(rev /opt/pi-studio)\""; fi; \
|
||||
{ \
|
||||
@@ -305,6 +333,10 @@ RUN set -e; \
|
||||
echo " \"build_date\": \"${BUILD_DATE}\","; \
|
||||
echo " \"source_revision\": \"${SOURCE_REVISION}\","; \
|
||||
echo " \"pi_version\": \"${PI_V}\","; \
|
||||
# Sibling of pi_version, NOT a member of components{}: that map holds git
|
||||
# SHAs and `pi-devbox-version` renders it with .value[0:12], which would
|
||||
# silently truncate a longer version string.
|
||||
echo " \"mempalace_version\": ${MP_CORE},"; \
|
||||
echo " \"components\": {"; \
|
||||
echo " \"pi-toolkit\": \"$(rev /opt/pi-toolkit)\","; \
|
||||
echo " \"pi-extensions\": \"$(rev /opt/pi-extensions)\","; \
|
||||
|
||||
@@ -70,9 +70,27 @@ so `TERM=xterm-kitty` is understood. Override either in your own
|
||||
### Document and image tooling
|
||||
|
||||
- `pandoc` — universal Markdown↔HTML/Org/RST/etc. converter
|
||||
- `typst` — markup-based typesetting, wired up as pandoc's `--pdf-engine` (see
|
||||
[Generating a PDF with pandoc + typst](#generating-a-pdf-with-pandoc--typst))
|
||||
- `graphviz` — `dot` rendering for diagram pipelines
|
||||
- `imagemagick` — image conversion / resizing (invoked as `magick`)
|
||||
|
||||
### Browser automation
|
||||
|
||||
- `agent-browser` — CLI for driving a real headless browser: open pages,
|
||||
click/fill/`eval`, snapshot the DOM, take screenshots. Useful whenever a task
|
||||
involves a web UI or verifying how a page actually renders (live DOM, WebGL,
|
||||
layout, popup positioning) instead of guessing from source.
|
||||
- `playwright` + a pre-installed headless **Chromium** back it.
|
||||
`AGENT_BROWSER_EXECUTABLE_PATH` is preset to the baked browser via a stable
|
||||
`/usr/local/bin/agent-chrome` symlink (insulated from Playwright's
|
||||
per-version/arch install directory), so `agent-browser open <url>` works
|
||||
out of the box with no setup. Run `agent-browser skills get core --full`
|
||||
for the command set and workflow patterns.
|
||||
- `socat` — TCP bridge used by `studio-expose` to reach pi-studio's
|
||||
loopback-bound server from outside the container (see
|
||||
[Using pi-studio](#using-pi-studio--studio-variant))
|
||||
|
||||
### Language toolchains
|
||||
|
||||
- `python3` + `python3-venv` + `python3-pip` (system Python)
|
||||
@@ -787,8 +805,9 @@ docker inspect --format '{{json .Config.Labels}}' joakimp/pi-devbox:latest | jq
|
||||
`org.opencontainers.image.{version,revision,created}` plus
|
||||
`se.jordbo.pi-devbox.*-ref` record the intended pi version and companion
|
||||
refs. The on-disk `/etc/pi-devbox/build-manifest.json` records **ground
|
||||
truth** — the actual checked-out commit of each `/opt` clone and the live
|
||||
`pi --version` — so a tag is reconstructable after CI logs rotate:
|
||||
truth** — the actual checked-out commit of each `/opt` clone, the live
|
||||
`pi --version`, and (from v1.8.6) the live `mempalace --version` of the
|
||||
installed palace core — so a tag is reconstructable after CI logs rotate:
|
||||
|
||||
```bash
|
||||
docker run --rm --entrypoint= joakimp/pi-devbox:latest cat /etc/pi-devbox/build-manifest.json
|
||||
|
||||
@@ -18,8 +18,23 @@ for OS packages, the per-package copyright files inside the image at
|
||||
| pi-fork | github.com/elpapi42/pi-fork | MIT |
|
||||
| pi-observational-memory | github.com/elpapi42/pi-observational-memory | MIT |
|
||||
| pi-studio *(`-studio` variant only)* | github.com/omaclaren/pi-studio | MIT |
|
||||
| pi-atelier | github.com/michaelmjhhhh/pi-atelier | MIT |
|
||||
| pi-toolkit, pi-extensions, mempalace-toolkit | authored by the maintainer (Joakim Persson) | MIT |
|
||||
|
||||
## MemPalace (AI memory)
|
||||
|
||||
| Component | Upstream | License |
|
||||
| --- | --- | --- |
|
||||
| mempalace (core, MCP server) | github.com/MemPalace/mempalace (PyPI: `mempalace`) | MIT — the GitHub repo declares MIT; the PyPI package's own metadata omits a license classifier, so if you need clearance from the package artifact alone, verify against the repo's `LICENSE` file rather than the sdist/wheel metadata |
|
||||
|
||||
## Browser automation
|
||||
|
||||
| Component | Upstream | License |
|
||||
| --- | --- | --- |
|
||||
| agent-browser | github.com/vercel-labs/agent-browser (npm: `agent-browser`) | Apache-2.0 |
|
||||
| Playwright | github.com/microsoft/playwright (npm: `playwright`) | Apache-2.0 |
|
||||
| Chromium | chromium.googlesource.com/chromium/src | BSD-3-Clause for Chromium's own code, plus a large set of bundled third-party components each under their own license (see Chromium's own `LICENSE`/`about:credits`). The binary in this image is **not compiled here** — it is the build Playwright downloads for its pinned version ("Chrome for Testing"), installed via `playwright install --with-deps chromium` at `/usr/local/share/ms-playwright/`. Treat Playwright's own distribution terms for that build as authoritative over any summary here. |
|
||||
|
||||
## Tooling baked into the base image
|
||||
|
||||
| Component | Upstream | License (best effort) |
|
||||
|
||||
@@ -55,6 +55,10 @@ release_tag=$(jq -r '.release_tag' "$MANIFEST")
|
||||
build_date=$(jq -r '.build_date' "$MANIFEST")
|
||||
source_rev=$(jq -r '.source_revision' "$MANIFEST")
|
||||
pi_version_baked=$(jq -r '.pi_version' "$MANIFEST")
|
||||
# `// empty` matters: images built before v1.8.6 have no such field, and
|
||||
# `jq -r` renders a JSON null as the 4-char string "null" — which would
|
||||
# print as a bogus version rather than being treated as absent.
|
||||
mp_version_baked=$(jq -r '.mempalace_version // empty' "$MANIFEST")
|
||||
|
||||
if [ "$MODE" = "quiet" ]; then
|
||||
printf '%s (%s)\n' "$release_tag" "${source_rev:0:7}"
|
||||
@@ -71,6 +75,16 @@ if command -v pi >/dev/null 2>&1; then
|
||||
pi_version_live=$(pi --version 2>/dev/null | head -n1 | tr -d '\r\n')
|
||||
fi
|
||||
|
||||
# Same check for the palace, which matters more than it looks: mempalace is
|
||||
# the one component that is BOTH client (here) and server (synlig runs this
|
||||
# same image), so a skew between the two is a real failure mode rather than
|
||||
# cosmetic. `mempalace --version` prints "MemPalace 3.8.0" — name-prefixed,
|
||||
# unlike pi's bare "0.84.3" — hence $NF rather than reading the whole line.
|
||||
mp_version_live=""
|
||||
if command -v mempalace >/dev/null 2>&1; then
|
||||
mp_version_live=$(mempalace --version 2>/dev/null | head -n1 | awk '{print $NF}' | tr -d '\r\n')
|
||||
fi
|
||||
|
||||
printf 'pi-devbox %s\n' "$release_tag"
|
||||
printf ' built: %s (source %s)\n' "$build_date" "${source_rev:0:12}"
|
||||
if [ -n "$pi_version_live" ] && [ "$pi_version_live" != "$pi_version_baked" ]; then
|
||||
@@ -79,5 +93,15 @@ else
|
||||
printf ' pi: %s\n' "${pi_version_live:-$pi_version_baked}"
|
||||
fi
|
||||
|
||||
# Printed only when known, so this degrades quietly on pre-v1.8.6 images
|
||||
# instead of showing an empty or "null" palace line.
|
||||
if [ -n "$mp_version_live" ] || [ -n "$mp_version_baked" ]; then
|
||||
if [ -n "$mp_version_live" ] && [ -n "$mp_version_baked" ] && [ "$mp_version_live" != "$mp_version_baked" ]; then
|
||||
printf ' palace: %s \033[33m(baked as %s — drift detected)\033[0m\n' "$mp_version_live" "$mp_version_baked"
|
||||
else
|
||||
printf ' palace: %s\n' "${mp_version_live:-$mp_version_baked}"
|
||||
fi
|
||||
fi
|
||||
|
||||
printf ' components:\n'
|
||||
jq -r '.components | to_entries[] | select(.value != null) | " \(.key): \(.value[0:12])"' "$MANIFEST"
|
||||
|
||||
@@ -151,6 +151,33 @@ run "pi stage follows MEMPALACE_PALACE_PATH" '
|
||||
mempalace-pi-session --dry-run --reason smoke --sessions-dir "$(mktemp -d)" 2>&1) || true
|
||||
echo "$out" | grep -q "stage=/tmp/alt/.mempalace/pi-stage/"
|
||||
'
|
||||
# The feeder's --agent default is WHO a drawer is attributed to. mempalace core
|
||||
# records neither the machine nor the harness on a write, and one shared bearer
|
||||
# token means the server cannot tell clients apart, so toolkit c64ffa1 changed
|
||||
# this default from $USER to pi@$MEMPALACE_PI_DEVICE — the one string that makes
|
||||
# a write attributable to both. Nothing ever PRINTED the resolved value (the
|
||||
# banner shows mode= and stage= only), so an image built from a pre-c64ffa1
|
||||
# toolkit ref would ship unattributed writes with every check still green.
|
||||
#
|
||||
# `--help` assigns AGENT (script top) before it parses args, then exits 0 with
|
||||
# no side effects — so `bash -x` observes the REAL resolution, env interpolation
|
||||
# and fallback included, rather than grepping the source for a literal line that
|
||||
# any reformat would break. Two-sided on purpose: device set => pi@<device>;
|
||||
# device UNSET => must not be pi@anything. The second half is what fails against
|
||||
# the old unconditional $USER default, which ignored the device entirely.
|
||||
#
|
||||
# Probes the PATH entry (a symlink into the /opt clone) rather than that clone
|
||||
# path directly: this is the invocation the systemd/launchd timers and
|
||||
# entrypoint-user.sh actually use, so it is the default that reaches the palace.
|
||||
run "feeder resolves --agent to pi@<device> (drawer attribution)" '
|
||||
f=$(command -v mempalace-pi-session) || { echo "feeder not on PATH" >&2; exit 1; }
|
||||
with=$(MEMPALACE_PI_DEVICE=smoke-device bash -x $f --help 2>&1 | sed -n "s/^+* *AGENT=//p" | tail -n1)
|
||||
without=$(env -u MEMPALACE_PI_DEVICE bash -x $f --help 2>&1 | sed -n "s/^+* *AGENT=//p" | tail -n1)
|
||||
echo "resolved with-device=[$with] without-device=[$without]" >&2
|
||||
[ "$with" = "pi@smoke-device" ] || exit 1
|
||||
case "$without" in pi@*) exit 1 ;; esac
|
||||
echo ok
|
||||
'
|
||||
# Regression guard for the pi transcript exporter. If pi ever changes its
|
||||
# session JSONL shape, the exporter stops recognising sessions and the palace
|
||||
# silently gets nothing (or, worse, raw JSON chunked as prose). Feed it a
|
||||
@@ -263,6 +290,26 @@ run "pi-fork clone + node_modules" \
|
||||
"test -f /opt/pi-fork/package.json && test -d /opt/pi-fork/node_modules"
|
||||
run "pi-observational-memory clone + node_modules" \
|
||||
"test -f /opt/pi-observational-memory/package.json && test -d /opt/pi-observational-memory/node_modules"
|
||||
# ...and that the clone carries the AUTH FIX, not merely that it exists. om's
|
||||
# pre-flight hasUsableAuth() check silently disabled `recall` for ~8 weeks once
|
||||
# pi moved to request-time SigV4 signing and stopped exposing a static Bedrock
|
||||
# key; upstream fixed it in ce9fc98, adopted in v1.8.4. PI_OBSMEM_REF tracks
|
||||
# master, so an upstream revert or force-push would ship a dead `recall` with
|
||||
# the clone assertion above still green — the exact gap flagged as open in the
|
||||
# v1.8.5 changelog.
|
||||
#
|
||||
# Pin the markers to src/runtime.ts, the fix SITE, rather than grepping the
|
||||
# repo: two of these three strings also appear under tests/, so a repo-wide
|
||||
# grep stays green with runtime.ts itself reverted. That is a false green of the
|
||||
# same family as the old skill-snapshot canary.
|
||||
run "pi-observational-memory carries the ce9fc98 auth fix (recall stays alive)" '
|
||||
f=/opt/pi-observational-memory/src/runtime.ts
|
||||
test -f "$f" || { echo "fix site missing: $f" >&2; exit 1; }
|
||||
for m in availability_recheck providerCredentialConfigured hasConfiguredAuth; do
|
||||
grep -q "$m" "$f" || { echo "marker absent from runtime.ts: $m" >&2; exit 1; }
|
||||
done
|
||||
echo ok
|
||||
'
|
||||
# pi-atelier: deliberately NO node_modules assertion, unlike its siblings —
|
||||
# it declares zero runtime dependencies (only peerDeps, satisfied by the baked
|
||||
# pi) and has no build step, so Dockerfile.variant skips `npm install` for it.
|
||||
@@ -307,6 +354,20 @@ run_expect "manifest records pi-atelier" \
|
||||
"cat /etc/pi-devbox/build-manifest.json" '"pi-atelier"'
|
||||
run_expect "manifest records pi_version" \
|
||||
"cat /etc/pi-devbox/build-manifest.json" '"pi_version"'
|
||||
# mempalace CORE was absent from the manifest through v1.8.5: the toolkit SHA
|
||||
# was recorded but the palace version behind the MCP tools was not, so a palace
|
||||
# bug could not be correlated to an image version. Assert the field exists AND
|
||||
# equals the installed binary — recording it from ARG MEMPALACE_VERSION instead
|
||||
# would look identical here yet drift silently the first time an install
|
||||
# resolved to something other than the pin, which is the whole reason this file
|
||||
# is built from ground truth. `// empty` matters: jq -r prints the 4-char
|
||||
# string "null" for a JSON null, which would satisfy a naive -n test.
|
||||
run "manifest mempalace_version matches the installed core" '
|
||||
m=$(jq -r ".mempalace_version // empty" /etc/pi-devbox/build-manifest.json)
|
||||
b=$(mempalace --version 2>/dev/null | head -n1 | tr -d "\r"); b=${b##* }
|
||||
echo "manifest=[$m] installed=[$b]" >&2
|
||||
[ -n "$m" ] && [ "$m" = "$b" ]
|
||||
'
|
||||
# Every component must be a resolved commit (or null for pi-studio in the
|
||||
# non-studio variant) — 'unknown' means a clone silently failed to resolve.
|
||||
run "manifest has no unresolved ('unknown') components" \
|
||||
|
||||
Reference in New Issue
Block a user