49a6534093ded9e0fdc3c889d205910bac5ad1c4
40 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
49a6534093 |
docs: write down the coordination channel the fleet already runs on
The logstream has carried cross-machine work since 2026-08-18 — patch handoff, review, a v1->v2 supersede — and nothing in this repo said it existed. That gap had a measurable cost this morning: another host addressed a retraction to pi@tor-ms22 by name and it was read only because the human said "read the logstream", while the agent was actively rebuilding the thing it warned about. Split by what each document is authoritative for, so there is one copy of each claim rather than three that drift: - README § Cross-machine agent coordination — what the CONTAINER needs. MEMPALACE_REMOTE_URL selects the shared palace; MEMPALACE_PI_DEVICE is what makes this machine reachable, because where every host is a thin client of one palace the stamped agent name is the only thing that distinguishes them. Stated as a rule with teeth: set both or neither, since a container missing the device var can read the log but is addressable by nobody. - AGENTS.md release checklist step 2 — the vendored-snapshot refresh, as a MECHANISM in the document a releasing agent actually reads, not a comment hoping to be noticed. It says the refresh costs a base rebuild, that skipping it is legitimate (every enrolled host reads its live clone), and that skipping it silently is not. - CHANGELOG — the three-way split itself, plus the measurement that shaped the ack contract: unfiltered, the mailbox returned 5 events, 4 of them finished broadcasts from eight days earlier; with status="open", exactly the 1 that needed an answer. Norms live in the skillset skill (82a8d3c, already live on every host that mounts the skillset — no rebuild) and mechanism in mempalace-toolkit's extensions/pi/README.md (e70bef2, which also documents the edge stamper that 553d8657 shipped undocumented). Deliberately NOT duplicated here. Consequence recorded rather than hidden: the skill edit lands in the skillset, so this repo's SKILLSET_SNAPSHOT_REF now honestly reports itself behind, and --check exits 1 with "has moved to 82a8d3c; the snapshot describes the older c04cd15". That message is also fixed in this commit — it previously blamed "the working tree" even when the tree was clean and only the ref had moved, which is the same defect class as a canary pinned to a phrase the release deleted: a message that names the wrong cause. Now distinguishes moved-HEAD from dirty-tree, verified against both plus the in-sync case. |
||
|
|
93f986e90e |
v1.8.6: adopt pi 0.84.3 + mempalace 3.8.0, close the v1.8.5 doc/observability gaps
Lint / hadolint (push) Successful in 9s
Publish Docker Image / resolve-versions (push) Successful in 15s
Publish Docker Image / base-decide (push) Successful in 8s
Lint / actionlint (push) Successful in 1m9s
Publish Docker Image / build-base (push) Successful in 41m23s
Publish Docker Image / smoke (push) Successful in 4m50s
Publish Docker Image / smoke-studio (push) Successful in 5m5s
Publish Docker Image / build-variant (push) Successful in 15m46s
Publish Docker Image / update-description (push) Successful in 7s
Publish Docker Image / promote-base-latest (push) Successful in 15s
Publish Docker Image / build-variant-studio (push) Successful in 19m59s
Three coupled pieces of work, all of which ride on the base rebuild that the
mempalace bump forces anyway.
DRIFT ADOPTED
- pi 0.84.2 -> 0.84.3. Its release notes carry a "Breaking Changes" line
(GoogleThinkingLevel -> GoogleApiThinkingLevel). Audited before adopting:
zero references across all four vendored companions (pi-fork,
pi-observational-memory, pi-atelier, pi-studio), so it is inert for us. The
reason to adopt is two skill-discovery fixes that land directly on v1.8.5's
vendored-skill work: nested Markdown skills inside grouping directories were
not discovered, and root README.md/AGENTS.md in skill dirs were reported as
broken skills.
- mempalace core 3.7.1 -> 3.8.0. Additive/reliability only. Its sync fix
(#2320/#2322) stops sync --apply deleting drawers whose source_file was
unreachable *at that moment* -- which does NOT relax the standing landmine
against sync on the shared palace, because that landmine is about paths
permanently absent from whichever host runs the sync. Different failure
shape; the caution stands.
DOCS -- three defects, one of them public
- DOCKER_HUB.md advertised "neovim (LazyVim defaults)". Nothing in the image
installs LazyVim; the only nvim config is a 19-line sysinit.vim. CI PATCHes
this file into the Docker Hub description on every release, so this was a
false claim published to the world. Removed.
- agent-browser + Playwright + Chromium is the single largest addition in the
image (~625 MB) and had zero mentions in README, DOCKER_HUB or THIRD_PARTY --
it was documented only to agents, in the AGENTS.md managed block. Now
documented to humans, including the Chromium licence dimension.
- typst and socat appeared in README prose but not in the "What's inside"
inventory. Added.
OBSERVABILITY -- the three gaps v1.8.5 listed as still open
- build-manifest.json now records mempalace core, read from the live binary
(ground truth, not the build ARG). Placed as a sibling of pi_version rather
than inside components{}, because pi-devbox-version renders that map through
[0:12] and would truncate a version string.
- smoke asserts the pi-observational-memory clone actually CONTAINS the ce9fc98
auth fix, pinned to src/runtime.ts. Deliberately not a repo-wide grep: two of
the three markers also live under tests/, so the repo-wide form stays green
with the fix site reverted. That is the third false-green of this exact family
in this repo (canary phrase in both snapshots; reconciler fixture using a
non-owned name; now this) -- pin containment checks to the fix site.
- smoke asserts the feeder's pi@<device> agent default behaviourally. The
earlier audit concluded this needed a --print-config added upstream; it does
not. AGENT is assigned before arg parsing, so `bash -x mempalace-pi-session
--help` observes the real resolution with no toolkit change. Two-sided:
device set => pi@<device>, unset => must not be pi@*.
- pi-devbox-version now prints a palace: line with the same live-vs-baked drift
detection pi already had. This matters more than it looks: mempalace is the
one component that is both client (here) and server (synlig), so skew between
them is a real failure mode. Degrades quietly on pre-v1.8.6 images.
Deferred deliberately: a native arm64 act_runner on tor-ms22 (the current
runner is on synlig, x86_64, so every arm64 layer ships QEMU-emulated).
Analysis and caveats filed to the palace rather than actioned here.
|
||
|
|
b5810654f6 |
skills: let the skillset own the skills it owns, and stop a dangling link from killing boot
Baked skill links won over the live skillset clone for all three vendored skills, so a pushed edit to skills/mempalace/SKILL.md was invisible in every container until the next image build -- measured on two hosts (live md5 129bcc4752 vs baked 5236024fef). Cause was ordering, not intent: the baked links are created early with a create-only-when-absent guard to close a smoke readiness race, and the skillset deploy runs last and treats them as foreign. The comment claimed the opposite of the behaviour. The fix is not "skillset always wins". Ownership is per-skill: pi-extensions is owned by its package repo and copied over the snapshot at build time, so the skillset's lagging duplicate must keep losing; pi-devbox-environment is authored here. Only mempalace is skillset-owned. devbox-skill-reconcile therefore runs after the deploy and repoints only the names in skills/skillset-owned.txt, replacing a link solely when it points into the baked tree, so a real directory or a link pointing elsewhere is never disturbed. Precedence is now user override -> live clone (owned names) -> baked snapshot, with the early links intact as the fallback so the readiness race stays closed. Reviewing that turned up a latent boot-abort in the pre-existing baked-link block: `[ ! -e "$link" ]` is TRUE for a dangling symlink, so once a link can point into /workspace/skillset, a vanished mount makes plain `ln -s` fail with "File exists" -- and under `set -euo pipefail` that aborts container start before `exec "$@"`. Reachable on `docker restart` or a host reboot, not on a recreate, since ~/.agents is not a volume on any host. Now `ln -sfn`, which heals the link back to the baked fallback. Smoke additions cover what let this ship: the stale-snapshot canary grepped a phrase present in BOTH the stale and fresh copies, so it passed throughout; it now pins the newest section. Link targets are asserted, not just `test -L`; the owned-list content is asserted both ways; and the reconciler's replace path -- which no CI container exercises, since none mounts a skillset -- is covered by fabricating one. A mutation test showed the obvious three assertions still pass with the "is this link ours?" guard deleted, so a discriminating case was added: an owned name whose link is a user override outside the baked tree. Also refreshes the mempalace snapshot to skillset 670f7f1 (without it the fix helps only hosts that mount skillset) and corrects README, which documented the old, wrong precedence in three places. Verified with 12 fixture cases plus 2 mutants: ownership respected against the real trees, user overrides preserved, relative/trailing-slash/CRLF/space/glob inputs handled, dangling link healed, read-only skills dir exits 0, idempotent. |
||
|
|
2ebf00d6d4 |
v1.8.4: the om fix lands upstream, pi-atelier v0.8.2, todo edit
Lint / hadolint (push) Successful in 9s
Lint / actionlint (push) Successful in 22s
Publish Docker Image / resolve-versions (push) Successful in 19s
Publish Docker Image / base-decide (push) Successful in 11s
Publish Docker Image / build-base (push) Successful in 42m16s
Publish Docker Image / smoke-studio (push) Successful in 5m0s
Publish Docker Image / smoke (push) Successful in 19m0s
Publish Docker Image / build-variant-studio (push) Successful in 17m38s
Publish Docker Image / build-variant (push) Successful in 28m36s
Publish Docker Image / update-description (push) Successful in 8s
Publish Docker Image / promote-base-latest (push) Successful in 10s
Headline: pi-observational-memory 37986b6 -> ce9fc98. The ambient-credential gate fix (6f694e6 + 699ccc7) was merged upstream as PR #52 on 2026-08-22, closing issue #51, so this release picks it up through the ordinary PI_OBSMEM_REF=master path with nothing carried locally. Every image up to and including v1.8.3 silently recorded zero observations on a Bedrock host using ambient AWS credentials; from this one on, /opt is the fix and the settings.json packages[] workaround should be deleted (verify against /etc/pi-devbox/build-manifest.json first). npm still ships the broken 3.0.4, which does not matter here because the image clones the ref instead. Pin bump: PI_ATELIER_REF / PI_ATELIER_VERSION v0.8.1 -> v0.8.2, audited per the floor note above the ARG. The only version in between is 0.8.2 itself and both its entries are Workspace-Pulse-internal (inspection coalescing and serialization; fresh inspection guaranteed at Turn end, retired sessions can no longer publish stale results). Nothing touches pi's private TUI renderer, which is the coupling behind the 0.6.0/0.7.0-under-pi-0.84 startup hang, and pi is unchanged at 0.84.2 - so the bump stays outside that risk class. Also baked by this build, no pin needed: pi-extensions 98eb07b -> 2022887 (the todo edit action), pi-fork 4a09af4 -> f1ff808, pi-studio 0.9.44 -> v0.9.48, mempalace-toolkit b609cf5 -> fd8b15f (docs only - the pi-session false-success guard was already baked in v1.8.3, confirmed by ancestry), aws-cli 2.36.24 -> 2.36.29 and the other *_VERSION=latest tools. README: the pin table also said mempalace 3.6.0, stale since v1.8.3 bumped it to 3.7.1. Fixed in passing. Unchanged and verified current: pi 0.84.2 (npm latest, published 2026-08-14), MEMPALACE_VERSION 3.7.1 (PyPI latest), pi-toolkit 0e1369e. |
||
|
|
29b62093f0 |
v1.8.0: bump pi 0.84.1 → 0.84.2 and pi-atelier v0.8.0 → v0.8.1, audited
Publish Docker Image / resolve-versions (push) Successful in 12s
Lint / actionlint (push) Successful in 23s
Publish Docker Image / base-decide (push) Successful in 8s
Lint / hadolint (push) Successful in 1m20s
Publish Docker Image / build-base (push) Successful in 41m34s
Publish Docker Image / smoke (push) Failing after 4m41s
Publish Docker Image / build-variant (push) Has been skipped
Publish Docker Image / promote-base-latest (push) Has been skipped
Publish Docker Image / update-description (push) Has been skipped
Publish Docker Image / smoke-studio (push) Failing after 8m22s
Publish Docker Image / build-variant-studio (push) Has been skipped
pi 0.84.2 closes the Amazon Bedrock tool-argument poison pill that v1.6.4 recorded as "Not fixed upstream". pi-ai 0.84.2 adds a recursive sanitizeBedrockDocument() and applies it at exactly the site that entry named (dist/api/bedrock-converse-stream.js, line 692 -> 704; upstream PR #7882): - toolUse: { ..., input: c.arguments }, + toolUse: { ..., input: sanitizeBedrockDocument(c.arguments) }, It strips object members whose key is the empty string, recursing through arrays and nested objects. It runs at request-build time, so it covers the live turn and a resume alike: a session already bricked by an empty-key tool argument now replays instead of dying on a Bedrock ValidationException. pi-session-repair is therefore no longer the recovery path on this image -- it stays useful for older images and for inspection, since the fix sanitises what is sent, not what was recorded. Bumping PI_VERSION is the ONLY way to get that fix: pi publishes an npm-shrinkwrap.json, so pi 0.84.1 pins pi-ai to exactly 0.84.1 even though its package.json range (^0.84.1) would admit 0.84.2. Transitive upstream fixes never leak into this image. pi-atelier v0.8.1 is the matching companion -- both sides changed fullscreen input handling within three days. Its only code change (src/split-pane.ts) stops atelier writing its own 1002h/1006h pair around a sidebar resize under pi's fullscreen renderer, which had been tearing down the mouse reporting pi itself enabled and leaving the wheel dead. Audited against the surfaces the pin policies name: - session .jsonl: identical migrateV1ToV2/migrateV2ToV3 ladder - node engine floor: unchanged >=22.19.0 (image ships 22.23.2) - atelier's three private couplings all intact in pi-tui 0.84.2 -- class TuiAltScreen extends TuiBase (detected by constructor NAME, so a rename would fail silently), inputListeners still `new Set()` at the same line 103, own render(width) descriptor still present - pi's mouse sequences byte-identical between 0.84.1 and 0.84.2 - atelier metadata unchanged: engines >=22.19.0, peerDeps >=0.80.7, zero runtime deps, so the "no npm install step" note holds Not proven by execution: CI smoke does not drive the TUI, and 0.84.2 adds a focused fullscreen search overlay that also participates in input handling. The pairing is reasoned from the diffs. Worth an alt+a plus a sidebar resize and wheel scroll in fullscreen on first use. |
||
|
|
ade58131d6 |
docs(readme): use mkdir -p instead of install -d for the peer's ~/.ssh
`install -d -m 700 ~/.ssh` was correct but wrong for the audience. This snippet gets pasted onto an arbitrary peer — a NAS, a router, a BSD box — and `install` is not in POSIX, so it is not guaranteed to be there. `mkdir -p` + `chmod` is POSIX, present everywhere, and self-evidently idempotent to a reader deciding whether it is safe to run on a machine that already has keys. Behaviour was checked rather than assumed, on both coreutils and BSD/macOS `install`: on an existing ~/.ssh it exits 0 and leaves authorized_keys intact in content and mode, but it also silently chmods the directory (755 -> 700). Desirable here, yet invisible in a doc — which is the second reason to prefer the explicit two-step form, and why the surrounding text now states outright that re-running is safe on an already-configured peer: mkdir -p is a no-op, the chmods only tighten, and appending never touches keys already listed. Verified the whole block end-to-end against a fresh HOME and one with a pre-existing 755 ~/.ssh and an older key: 700/600 in both cases, older key preserved, new line appended. |
||
|
|
ffd44ad9cf |
docs(readme): say where the authorized_keys line actually goes
Step 2 of "Giving the container its own key for a peer" showed a correctly narrowed authorized_keys line but never named the file it belongs in, and never said which account's — the only mention of authorized_keys was an aside 35 lines further down about revoking one key per machine. A reader following the steps had a public key, a line to construct, and nowhere to put it. Now explicit: append to ~/.ssh/authorized_keys of the account named as `User` in step 3, via a heredoc that shows `>>` rather than `>` (the truncation that revokes every other key on that account), with `install -d -m 700 ~/.ssh` and `chmod 600` so the file is created correctly the first time. Adds the three failure modes that make a good key look broken, none of which announce themselves on the client: the options prefix must be on the same physical line as the key (a wrapped paste is the usual culprit), `ssh-copy-id` cannot add that prefix at all so the line must be appended by hand, and sshd's StrictModes silently ignores authorized_keys when the home directory, ~/.ssh or the file is group- or world-writable — reporting it only in the peer's own log. |
||
|
|
43cd6e22f2 |
v1.7.0: bundle pi-atelier at a pinned tag; pin pi to an audited 0.84.1
Publish Docker Image / resolve-versions (push) Successful in 9s
Lint / actionlint (push) Successful in 15s
Lint / hadolint (push) Successful in 13s
Publish Docker Image / base-decide (push) Successful in 8s
Publish Docker Image / build-base (push) Successful in 41m22s
Publish Docker Image / smoke-studio (push) Successful in 5m16s
Publish Docker Image / smoke (push) Successful in 7m31s
Publish Docker Image / build-variant-studio (push) Successful in 18m31s
Publish Docker Image / build-variant (push) Successful in 27m18s
Publish Docker Image / promote-base-latest (push) Successful in 11s
Publish Docker Image / update-description (push) Successful in 12s
Two changes that belong together, because the first is what makes the second dangerous to get wrong. pi-atelier (TUI sidebar + status rail) is now vendored to /opt/pi-atelier at PI_ATELIER_REF=v0.8.0 and registered by entrypoint-user.sh — the pi-fork / pi-observational-memory / pi-studio pattern, deliberately NOT `pi install npm:pi-atelier`, which writes into ~/.pi/npm-global on the config volume where it shadows the image and pins nothing. Unlike its siblings it gets no `npm install`: atelier declares zero runtime deps (peerDeps only, satisfied by the baked pi) and has no build step, so pi loads its TypeScript straight from the checkout via package.json `pi.extensions`. pi is no longer resolved to npm `latest` at build time. The pin lives in Dockerfile.variant and CI reads it from there, so a local `docker build` and a CI release ship the same versions by construction. The pin is a CHECKPOINT, NOT A FREEZE: bumping stays a one-line change; what stops is *unreviewed* adoption of whatever shipped that morning, in the same build that then gets tagged and published. CI fails when a pin is not concrete or not actually published on npm, and warns — never adopts — when npm latest moves ahead, naming what to re-check. Why this pairing needed care: pi-atelier 0.6.0/0.7.0 wrap pi's PRIVATE TUI renderer, and under pi 0.84 that wrapper recurses — pi hangs at startup burning CPU with no error. Upstream fixed the recursion in 0.7.1 and restored the non-overlapping split in 0.7.2; 0.8.0 is additive on top. atelier's own peerDependencies still say >=0.80.7, which does not express that floor, so nothing in npm metadata could have warned us. The floor is therefore encoded as an executable rule — pi >= 0.84 => pi-atelier >= 0.7.1 — asserted in both smoke-test.sh (build time) and recreate-sanity-check.sh (after a real recreate), verified against a 4x4 version matrix. Existing volumes needed migration, not just vendoring: a hand-installed `npm:pi-atelier` entry is counted as already-registered by the entrypoint guard, so every existing volume would have kept its unpinned npm copy — and a 0.6.x copy next to pi 0.84 is exactly the startup hang. The entrypoint now drops that one exact string (settings.json.bak.atelier.<ts> backup, distinct prefix so it cannot clobber the template merge's backup in the same second) and lets the pinned /opt copy register. Tested against a real settings.json: only that entry removed, other packages and all keys intact, idempotent, and unparseable JSON leaves the file untouched. DEVBOX_ATELIER=0 opts out entirely — in the entrypoint rather than via `pi uninstall`, because this component's failure mode is "pi will not start", which cannot be repaired from inside pi. 0.84.1 was audited for this release, not merely adopted: theme/TUI changes are additive, the session format is unchanged (CURRENT_SESSION_VERSION = 3 in both 0.83.0 and 0.84.1 with an identical migrateV1ToV2/migrateV2ToV3 ladder, so existing transcripts are neither migrated nor at risk and pi-session-repair stays valid), and the Node engine floor is unmoved at >=22.19.0. CI resolves the atelier tag to its PEELED commit SHA — atelier uses annotated tags, so the unpeeled ref is a tag object, not a commit; pi-studio's lightweight tags never exposed that distinction. Also: docs for overriding the read-only ~/.ssh/config from the container — container-only keys in ~/.ssh-local, hardened authorized_keys, the fact that `from=` must allow the HOST's addresses because container egress is NAT'd through it, and the macOS-only-keyword trap (`UseKeychain` is fatal to Linux OpenSSH and takes out dssh/pi --ssh while the host keeps working). Corrects two claims in "Naming LAN peers": ssh-lan.conf is not ProxyJump-only, and first-time creation does need one restart because the Include is emitted only when the file already exists at start. |
||
|
|
fb49828826 |
base: add pi-devbox-version command + startup banner
Wraps /etc/pi-devbox/build-manifest.json (already written at docker-build time in Dockerfile.variant) into a human-readable summary instead of requiring users to know the manifest path and pipe it through jq themselves. - rootfs/usr/local/bin/pi-devbox-version: human (default) / --json / --quiet output modes. Also flags live drift — compares the baked pi_version against the actually-running `pi --version` and warns on mismatch rather than trusting the manifest blindly (same ground-truth philosophy as the manifest generation itself). Exits 1 with a short stderr notice on images built before the manifest existed, instead of failing silently. - entrypoint-user.sh: calls it as the very first line. CMD is `bash -l` with tty:true in compose, so this banner lands directly above the first prompt on container start — no separate motd/bashrc hook needed (deliberately not wired into .bash_aliases, which would reprint on every docker exec -it). - Dockerfile.base: COPY + chmod, same pattern as dot-watch/studio-expose. - scripts/smoke-test.sh: 4 new checks (binary present+executable, human output has release tag, --json round-trips the manifest, --quiet is a single line). - README.md / AGENTS.md / CHANGELOG.md updated. |
||
|
|
291ae5345e |
repo: add LICENSE, THIRD_PARTY.md, .dockerignore, hadolint lint, IDEAS backlog
Repo/CI hygiene batch (none base-affecting; image contents unchanged): - LICENSE: actual MIT file (repo previously declared MIT only in prose). - THIRD_PARTY.md: notes bundled software + licenses (pi/pi-fork/pi-obsmem/ pi-studio MIT, gosu Apache-2.0, Debian packages under their own terms). - .dockerignore: trims build context to what the Dockerfiles COPY (rootfs/ + entrypoint*.sh); keeps .git/docs/scripts/compose out. Verified it excludes none of the required COPY sources. - lint.yml: new hadolint job (pinned v2.14.0) lints both Dockerfiles; .hadolint.yaml grandfathers deliberate choices (DL3008/DL3016/DL4006/DL3003/ SC2086, mirroring the shellcheck excludes), fails on anything new at warning+. Verified hadolint exit 0 and the repo shell-guard passes with the new job. - IDEAS.md: parks deferred follow-ups (SHA-pin actions, trivy, buildx SBOM/ provenance, Makefile, renovate). - README/DOCKER_HUB License sections now link LICENSE + THIRD_PARTY.md. No tag. |
||
|
|
aaf1be0bcb |
base: readable Neovim colours out of the box (termguicolors + kitty-terminfo)
Lint workflows / actionlint (push) Successful in 22s
Vanilla Neovim fell back to a 256-colour palette over ssh/kitty and rendered strings/comments in a muddy, low-contrast colour. Fix, all base-affecting: - rootfs/etc/xdg/nvim/sysinit.vim: system vimrc enabling termguicolors. Loads for every user before any personal ~/.config/nvim; overridable per-user. - Dockerfile.base: install kitty-terminfo (TERM=xterm-kitty understood; lets Neovim auto-detect true colour) and set ENV COLORTERM=truecolor. - smoke-test.sh: assert xterm-kitty terminfo present and nvim tgc default on. - CHANGELOG (Unreleased/Added) + README editor note. No tag — lands on the next base-<hash> rebuild. |
||
|
|
3d46c6615e |
fix(base): default pandoc typst template font so PDF export works without -V mainfont
Lint workflows / actionlint (push) Successful in 21s
pandoc's bundled typst template defaults the document font to an empty tuple (font: ()), so a naked `pandoc --pdf-engine=typst` fails with "font fallback list must not be empty". Patch the template default to Libertinus Serif (typst's own bundled default) at build time so PDF export works out of the box. Document usage in README and note the fix in CHANGELOG (Unreleased). Base-affecting. |
||
|
|
67da05b99b |
feat(base): ship typst as lightweight pandoc PDF engine
Lint workflows / actionlint (push) Successful in 15s
pandoc has been in the base since v1.0.0 but only as a front-end; PDF export (studio_export_pdf / pandoc -o out.pdf) failed with 'xelatex not found' because no back-end engine was installed. Ship typst (~30 MB static Rust binary, no LaTeX) as the default engine via `pandoc --pdf-engine=typst`, chosen over a ~600 MB TeX Live install. texlive-xetex remains the higher-fidelity install-on-demand fallback. - Dockerfile.base: install typst (latest GitHub-release idiom, pin via TYPST_VERSION); add xz-utils (typst ships .tar.xz); bump BASE_REBUILD_DATE. Lands in base-<hash>. - smoke-test.sh: verify typst + a real pandoc --pdf-engine=typst render. - README/AGENTS/CHANGELOG: typst now shipped (supersedes the planned :latest-studio-tex variant). No tag pushed — CI build intentionally deferred. |
||
|
|
f19c35da32 |
docs: note lightweight PDF engine (typst) as preferred over full texlive
Lint workflows / actionlint (push) Successful in 36s
PDF export from Studio/pandoc still isn't shipped. Record the engine decision in the living docs (README + AGENTS): pandoc is in the image but has no PDF back-end, so export fails with 'xelatex not found'. Prefer a lightweight engine — typst (~30 MB static binary, 'pandoc --pdf-engine=typst') which is small enough it could ship in base rather than needing a separate ':latest-studio-tex' variant; texlive-xetex (~600 MB) kept as the higher-fidelity fallback. Also drop stale 'v1.3.0' pins (v1.3.0 already shipped without PDF) in favour of 'a future release'. CHANGELOG history left untouched. |
||
|
|
d73bf2e9d3 |
feat: optional shared/external MemPalace via MEMPALACE_REMOTE_URL
Lint workflows / actionlint (push) Successful in 21s
Wire the shared-palace option (implemented in mempalace-toolkit's mempalace.ts) into the container: - .env.example: document MEMPALACE_REMOTE_URL / MEMPALACE_REMOTE_TOKEN (env_file-only, per this repo's convention). - docker-compose.mempalace.yml: optional shared server (mempalace-mcp --transport http), loopback-bound by default. - docker-compose.yml: local-vs-external note on the palace-volume comment. - README + CHANGELOG (Unreleased). |
||
|
|
3a59e15563 |
feat: ship nano + micro (non-modal editors) alongside nvim
Lint workflows / actionlint (push) Successful in 13s
The image shipped only nvim (EDITOR=nvim), a modal vi-style editor. Not everyone is comfortable with vi keybindings, so add both a classic and a modern non-modal option: - nano (apt): ~2.8 MB installed; deps (libc6, libncursesw6, libtinfo6) already present via nvim/less/htop/tmux, so no extra packages pulled in. - micro: ~12 MB single static Go binary from GitHub releases (same pattern as bat/eza/zoxide). Desktop-style keys (Ctrl+S/Ctrl+Q), mouse, syntax highlighting. ARG MICRO_VERSION pins; defaults to latest. Combined ~15 MB (<0.5% of the ~3.2 GB image). EDITOR stays nvim; both new editors are opt-in (export EDITOR=micro | nano). Uses the canonical micro-editor/micro URL because the old zyedidia/micro org rename makes /releases/latest redirect to another /latest, defeating the tag-parsing latest-resolution idiom. Base-image change, so it lands on the next base-<hash> rebuild. Updates README tool table + EDITOR note, CHANGELOG (Unreleased/Added), and smoke-test.sh (nano + micro presence checks). |
||
|
|
c42b237d30 |
compose: deliver secrets via env_file only (drop environment: passthrough)
Removes GITEA_ACCESS_TOKEN / GITEA_HOST / GITHUB_PERSONAL_ACCESS_TOKEN from the compose environment: block. An environment: entry both overrides env_file AND is interpolated from the host shell, so a stale shell export (e.g. one auto-loaded by an opencode/dotenv hook) silently shadowed the users .env — an updated token never reached the container. Secrets now flow solely via env_file: .env; .env.example already documents every variable. - docker-compose.yml: drop the 3 passthrough lines + explanatory comment - README.md: sync the "basic shape" snippet - CHANGELOG.md: note under Unreleased (no tag bump / unpublished) |
||
|
|
7551947466 |
feat(skills): add mempalace proactive-load directive for containers
Baking the mempalace fallback skill fixed *availability*, but mempalace had no proactive-load directive anywhere (pi-toolkit's global AGENTS.md only points to pi-extensions), so a new container would still surface it only via description-matching — the same under-utilisation the pi-extensions directive was created to fix. Add a session-start pointer to the pi-devbox managed AGENTS.md block (pi-global-AGENTS.append.md): gated to pi-devbox containers and conditional on the MemPalace MCP tools being present. Memory continuity matters most in a frequently-recreated container — the palace is its only cross-recreate memory. - pi-global-AGENTS.append.md: '## Session start: load the mempalace skill'. - smoke-test: assert the pointer merges into the global AGENTS.md at build. - docs: VENDORED.md, README, CHANGELOG [Unreleased]. Now both skills are complete in pi-devbox: directive + skill file. pi-extensions = directive (pi-toolkit) + baked skill; mempalace = directive (this block) + baked skill. |
||
|
|
a7d6a7d235 |
feat(skills): bake pi-extensions + mempalace fallback skills
The pi-toolkit global AGENTS.md tells every pi session to read
~/.agents/skills/pi-extensions/SKILL.md at start (the fork/recall
under-utilisation fix), but that skill lived only in the private skillset
repo — so the pointer dangled in any container started without skillset
mounted. Bake fallbacks so the pointer always resolves.
- pi-extensions (Option 1 + Option 2, layered):
* Canonical skill promoted to the public pi-extensions package repo under
skill/ (separate commit there); co-located with the code it documents.
* rootfs/ carries a committed snapshot (the floor).
* Dockerfile.variant copies /opt/pi-extensions/skill/ over the snapshot
after the pinned clone, so a normal build ships the fresh package copy
(recorded via PI_EXTENSIONS_REF) and an old-ref/mirror build still ships
the snapshot. Helper evaluate-extension-usage.py travels with it.
- mempalace (Option 2 only): snapshot in rootfs/. Its consumer skill has no
public package home (mempalace-toolkit ships a different skill,
opencode-mempalace-bridge), so no build-time refresh.
- entrypoint links both (only-when-absent; mounted skillset still wins).
- smoke-test: build-time presence + package-match check + runtime symlink
assertions; readiness gate now waits on the last-linked skill.
- docs: skills/VENDORED.md (provenance + refresh), README, AGENTS.md,
CHANGELOG [Unreleased].
Note: shipped in the NEXT release; v1.2.0 (run 409) predates this.
|
||
|
|
2abfee141b |
feat: image-baked agent skills + pi-devbox-environment skill (v1.2.0)
Publish Docker Image / resolve-versions (push) Successful in 35s
Publish Docker Image / base-decide (push) Successful in 23s
Publish Docker Image / build-base (push) Successful in 41m32s
Publish Docker Image / smoke-studio (push) Failing after 4m5s
Publish Docker Image / build-variant-studio (push) Has been skipped
Publish Docker Image / smoke (push) Failing after 5m46s
Publish Docker Image / build-variant (push) Has been skipped
Publish Docker Image / update-description (push) Has been skipped
Publish Docker Image / promote-base-latest (push) Has been skipped
Ship skills inside the image (independent of any mounted skillset repo): - rootfs/usr/local/share/pi-devbox/skills/<name>/ symlinked into ~/.agents/skills/ by entrypoint-user.sh (foreign-link, survives volume recreate, never clobbers a skillset/user skill of the same name). - New pi-devbox-environment skill: persistence model, host/LAN SSH reachability, split-DNS mechanisms, interactive-vs-tool-shell alias gotcha, tmux 0-index, uv-first Python, pi-studio reachability. Agnostic to host OS / hostnames / domains / nameservers (discovered at runtime). - Dockerfile.variant appends pi-global-AGENTS.append.md onto pi-toolkit's pi-global-AGENTS.md (single global slot) so the skill is loaded proactively; gated on /usr/local/lib/pi-devbox/. Idempotent. - smoke-test: baked-skill + append-snippet + merged-marker presence and a runtime symlink assertion. - docs: README 'Agent skills' section, AGENTS.md layout, DOCKER_HUB.md; moved studio-tex roadmap to v1.3.0. pi 0.79.7 -> 0.79.10 (auto-resolved from npm latest at build). |
||
|
|
8de0fad776 |
docs(lan): document ssh-lan.conf for naming LAN peers
The host-owned, bind-mounted ~/.config/devbox-shell/ssh-lan.conf is the intended place to add `ProxyJump host` overrides for named LAN peers (so `pi --ssh <peer>` / `dssh <peer>` route through the host), but it was only documented in .env.example and the setup-lan-access.sh header — never in the README, where someone hitting "can't reach LAN peers" actually looks. - README: add a "Naming LAN peers" subsection under the macOS LAN-peers troubleshooting block, with a ProxyJump example and the read-only ~/.ssh caveat; add a pointer to it from the SSH and ControlMaster section. - setup-lan-access.sh: correct the INCLUDE_BLOCK comment that suggested adding ProxyJump to the read-only ~/.ssh/config; point at ssh-lan.conf instead. - CHANGELOG: note under Unreleased. Docs/comment only — no behavior change. |
||
|
|
9eff3f3c48 |
release: v1.1.6 — build provenance + reproducibility hardening; pi 0.79.7 → 0.79.8
Publish Docker Image / resolve-versions (push) Failing after 52s
Publish Docker Image / base-decide (push) Has been skipped
Publish Docker Image / build-base (push) Has been skipped
Publish Docker Image / smoke-studio (push) Has been skipped
Publish Docker Image / smoke (push) Has been skipped
Publish Docker Image / build-variant (push) Has been skipped
Publish Docker Image / build-variant-studio (push) Has been skipped
Publish Docker Image / promote-base-latest (push) Has been skipped
Publish Docker Image / update-description (push) Has been skipped
Adds OCI labels + /etc/pi-devbox/build-manifest.json so a published tag is self-describing and reconstructable after CI logs rotate (manifest is written from the actual checked-out HEAD of each /opt clone + live pi --version, not just the intended build-args). Hardens the build plumbing: - scripts/check-base-hash.sh guards the base-rebuild invariant: every floating ARG *_REF in Dockerfile.base must be folded into the base_tag hash, else a ref-only change silently fails to rebuild the base (v1.1.2-class staleness footgun). Runs in base-decide and locally. - resolve-versions now fails loud instead of falling back to a floating main/master on a transient API failure — validates each ref is a 40-hex SHA (and pi a real semver) and aborts the release otherwise. - The three gitea companions (pi-toolkit, pi-extensions, mempalace-toolkit) gained overridable *_REPO build-args (defaulting to the canonical gitea origin) so a relocated/forked build can repoint them without editing the Dockerfiles — matching the existing PI_FORK_REPO/PI_OBSMEM_REPO pattern. README documents the forked/relocated build-arg trick and how to read the labels + manifest. smoke-test asserts the manifest + labels. pi bumps 0.79.7 → 0.79.8 (auto-resolved at build). |
||
|
|
a0abacaafb |
fix(ssh): survive read-only ~/.ssh ControlPath; render sidecar on all host OSes
Publish Docker Image / smoke (push) Successful in 3m22s
Publish Docker Image / smoke-studio (push) Successful in 3m42s
Publish Docker Image / build-variant (push) Successful in 15m29s
Publish Docker Image / update-description (push) Successful in 11s
Publish Docker Image / build-variant-studio (push) Successful in 16m49s
Publish Docker Image / promote-base-latest (push) Successful in 14s
Publish Docker Image / resolve-versions (push) Successful in 8s
Publish Docker Image / base-decide (push) Successful in 8s
Publish Docker Image / build-base (push) Successful in 33m44s
Coordinated with the pi-extensions ssh-controlmaster fix (picked up at build via PI_EXTENSIONS_REF=main), this makes `pi --ssh <host>` and `dssh`/`dscp` robust to a user ~/.ssh/config whose per-host ControlPath points under the read-only ~/.ssh bind-mount (e.g. `ControlPath ~/.ssh/cm/%r@%h:%p`). A system default can never override a user's per-host value, so the fix lives in two layers. - setup-lan-access.sh: always render the writable ~/.ssh-local/config sidecar (Host * ControlPath redirect into ~/.ssh-local/cm + Include ~/.ssh/config) on EVERY host OS. Previously the script exited early (no-op) on native Linux, leaving dssh/dscp broken when ~/.ssh was read-only there too. The host-jump block, its key generation, and the authorize hints stay gated on VM-backed detection / DEVBOX_LAN_ACCESS=jump (new NEED_JUMP flag). - Dockerfile.base: document that the /etc/ssh drop-in default cannot override a user per-host ControlPath; cross-ref the two handling layers. - entrypoint-user.sh: correct the now-stale "no-op on native Linux" comment. - README.md / DOCKER_HUB.md: document read-only-~/.ssh ControlPath handling. CHANGELOG: v1.1.5 (Fixed + Changed + pi 0.79.6 -> 0.79.7 auto-resolved bump). |
||
|
|
52fe09d79d |
release: v1.1.2 — pi 0.79.3 → 0.79.4
Publish Docker Image / resolve-versions (push) Successful in 29s
Publish Docker Image / base-decide (push) Successful in 9s
Publish Docker Image / build-base (push) Successful in 43m23s
Publish Docker Image / smoke-studio (push) Successful in 3m52s
Publish Docker Image / smoke (push) Successful in 5m26s
Publish Docker Image / build-variant (push) Successful in 17m55s
Publish Docker Image / update-description (push) Successful in 7s
Publish Docker Image / promote-base-latest (push) Successful in 10s
Publish Docker Image / build-variant-studio (push) Successful in 25m38s
Patch release per AGENTS.md versioning scheme (pi version bump + smaller fixes). Cut Unreleased → v1.1.2 (2026-06-15): pi 0.79.3→0.79.4 (CI-auto-resolved), the mempalace-toolkit SHA-resolution build fix, recreate-sanity-check.sh maintainer tooling, and the AGENTS/README docs. Bumped the README sanity-check version example to 0.79.4. |
||
|
|
4ed6764323 |
Add runtime post-recreate sanity check (peer of smoke-test.sh)
scripts/recreate-sanity-check.sh verifies what is actually live in a recreated container — persisted volumes, pi runtime wiring (keybindings, extensions, mempalace.ts bridge, settings.json, fork/obsmem/studio registrations), /tmp/sshcm, skel defaults, /opt toolkits. smoke-test.sh runs at build time with --entrypoint="" and cannot see any of this. Variant (studio/plain) auto-detected via /opt/pi-studio. pi version is asserted only with --expected-version (built from 'latest', no Dockerfile pin to self-derive). Maintainer tooling, not baked into the image. Documented in README and CHANGELOG. |
||
|
|
ab5ff8ec56 |
feat: bundle dot-watch helper for live graphviz .dot -> PNG re-render in Studio
pi-studio renders Mermaid natively but has no DOT renderer. Its markdown preview displays local PNG/JPG/GIF/WEBP images, so dot-watch closes the loop for Graphviz: edit .dot -> auto-render <name>.png -> Studio refresh-from-disk shows the update. Uses mtime polling (no inotify dep). - rootfs/usr/local/bin/dot-watch: the helper (executable) - Dockerfile.base: COPY + chmod, following the studio-expose pattern - README.md: 'Graphviz diagrams in Studio' subsection - CHANGELOG.md: Unreleased entry graphviz was already in the base image; no new package. |
||
|
|
421558477d | docs(studio): add commented studio ports + STUDIO_EXPOSE to basic-shape compose | ||
|
|
b655faab9f | docs(studio): render network-hop figure as mermaid flowchart | ||
|
|
3b0335f34e | docs(studio): clarify studio-expose foreground + token, add remote/mosh end-to-end recipe | ||
|
|
9ebb0643c7 |
docs: fix drift — sync compose/volumes, studio coverage, mempalace link
Audit found README/AGENTS carried a stale compose/volume set that diverged from the shipped docker-compose.yml (DOCKER_HUB + compose + .env.example were already consistent — README was the outlier): - README compose block + 'Volumes and persistence' table: correct volume names (devbox-shell-history not -bash-history; devbox-uv at ~/.local/share/uv not devbox-uv-tools at /opt/uv-tools — the latter would SHADOW the baked mempalace install at UV_TOOL_DIR); add devbox-ssh-local + devbox-zoxide; mark devbox-palace/-chroma-cache optional; WORKSPACE_PATH/SSH_KEY_PATH (not HOST_WORKSPACE). - README quickstart: 'compose exec -u developer' (no USER in image; bare exec lands a root shell). - README: pi-studio now 'shipped' not 'planned'; build-pipeline + tag table cover -studio + smoke-studio/build-variant-studio. - AGENTS: backward-compat volume names corrected; repo-layout bullets cover pi-studio install + studio-expose + STUDIO_EXPOSE bridge. - DOCKER_HUB: MemPalace source link -> upstream MemPalace/mempalace (matches Dockerfile.base + CHANGELOG refs). Note: the shipped v1.0.0 CHANGELOG migration note still lists the old (incorrect) volume names; left as immutable released history. |
||
|
|
7d8ee4cea1 |
feat(studio): bundle studio-expose bridge + socat (opt-in STUDIO_EXPOSE)
pi-studio binds the container's 127.0.0.1, which a published Docker port can't reach. Add a robust, portable bridge rather than a doc-only one-liner: - Dockerfile.base: add socat (~1 MB, generally useful TCP relay). - rootfs/usr/local/bin/studio-expose: socat TCP relay listening on the container's egress IPv4 (not 0.0.0.0 — that would EADDRINUSE against Studio's loopback listener) forwarding to 127.0.0.1:PORT on the SAME port, so Studio's printed token URL works verbatim. Robust egress-IP detection (hostname -I, loopback-filtered; ip route get fallback), --help, port validation, foreground. - entrypoint-user.sh: opt-in STUDIO_EXPOSE=1 auto-starts the bridge in the background (studio variant only). Default OFF — Studio stays loopback-only (its secure default) unless explicitly opted in. - README: 'Using pi-studio' now documents host-networking (A) and the studio-expose/STUDIO_EXPOSE bridge (B) with a security note; ssh -L for remote, mosh caveat retained. - smoke-test: assert socat + studio-expose present (base-level). - CHANGELOG/AGENTS updated. No tag — stopping for review. |
||
|
|
a78e59fb5b |
feat(studio): add :latest-studio variant (PR-3)
Bundle pi-studio (omaclaren/pi-studio) as a new -studio image variant: browser prompt editor, KaTeX/Mermaid preview, tmux-backed literate REPLs, /studio command + studio_* agent tools. - Dockerfile.variant: INSTALL_STUDIO + PI_STUDIO_REPO/REF args; vendor pi-studio to /opt/pi-studio (no build step — prebuilt client in git; npm install --omit=dev for 3 prod deps). STUDIO_PORT=8765 advisory. - entrypoint-user.sh: register /opt/pi-studio via the existing pi install local-path loop (auto-skips in non-studio variant). - smoke-test.sh: auto-detected studio assertions (clone + prebuilt client + pi install registration). - CI: resolve PI_STUDIO_REF to a SHA; independent smoke-studio + build-variant-studio jobs that gate ONLY the -studio tags, so a studio failure never blocks the core :latest release. - README: 'Using pi-studio' section documenting the container access reality — pi-studio hard-binds 127.0.0.1 (index.ts .listen(port, '127.0.0.1'), no --host flag), so -p publish alone can't reach it. Documents host-networking and loopback-bridge paths, the remote ssh -L forward, and the mosh caveat (no port forwarding; run parallel ssh -L). - CHANGELOG/AGENTS/DOCKER_HUB updated. Will tag as v1.1.0 (minor). No tag created — stopping for review. |
||
|
|
c1154f1fa6 |
v1.0.0: decouple from opencode-devbox
Publish Docker Image / resolve-versions (push) Successful in 5s
Publish Docker Image / base-decide (push) Successful in 12s
Publish Docker Image / build-base (push) Successful in 45m47s
Publish Docker Image / smoke (push) Successful in 8m18s
Publish Docker Image / build-variant (push) Successful in 22m41s
Publish Docker Image / update-description (push) Failing after 9s
Publish Docker Image / promote-base-latest (push) Successful in 14s
Self-contained build chain — own Dockerfile.base + Dockerfile.variant
+ entrypoint scripts + rootfs + CI pipeline. Previously v0.79.0 and
earlier were thin re-brands of opencode-devbox's pi-only variant
(joakimp/pi-devbox:base-pi-only built by opencode-devbox CI).
Architectural changes:
- Replace 5-line Dockerfile shim with full base+variant pair.
- Adapt CI workflow from opencode-devbox/docker-publish-split.yml,
simplified to a single variant. Includes content-addressed base hash,
PI_VERSION concrete-resolution to defeat registry-buildcache footgun,
crane-based base-latest promotion, and the c6f9d11 smoke-test gate.
- pi-devbox releases no longer require rebuilding opencode-devbox first.
Base image additions:
- pandoc, graphviz, imagemagick, yq — broadly useful, ~260 MB total.
- tldr (tealdeer) — Rust port replaces Node tldr global, saves 135 MB.
- /etc/tmux.conf with base-index 0 + pane-base-index 0 — required for
the planned :latest-studio variant; pi-studio hard-codes :0.0 target.
Smoke test:
- New checks for pandoc, graphviz, imagemagick, yq, tldr, tmux config,
/tmp/sshcm directory.
- Image-size measurement now sums docker history layers (the prior
inspect --format='{{.Size}}' returned only the variant-unique layer
with the new base/variant split, understating by 2+ GB).
- Threshold 2850 → 3500 MB to absorb base additions + arch margin.
Image size:
- Local arm64 build: 3.20 GB. ~390 MB up from prior pi-only equivalent.
- Will tighten threshold once amd64 actuals settle in CI.
Pre-1.0 history preserved at tag pre-v1.0.0-decouple-backup.
Future work:
- v1.1.0: :latest-studio variant (adds pi-studio).
- v1.2.0: :latest-studio-tex variant (adds texlive-xetex for PDF).
- opencode-devbox v2.0.0 will retire INSTALL_PI / pi-only paths.
|
||
|
|
2e86e5a3f3 |
compose: persist LAN jump key (devbox-ssh-local volume) + docs
Persist ~/.ssh-local so the generated LAN-jump key survives container recreation; authorize it on the host once per machine. Adds the volume to the compose template and documents it in the README volumes table. LAN-access mechanism/script changes are inherited from base-pi-only (opencode-devbox). |
||
|
|
08bb0c520e |
docs: LAN-access ssh-lan.conf + DEVBOX_LAN_AUTOJUMP_PRIVATE (inherited from base)
setup-lan-access.sh fixes (Include scope, ControlPath) + ssh-lan.conf and RFC1918 autojump flow in via FROM base-pi-only. Documents the knob and new host-owned config. Tag v0.78.0c AFTER opencode-devbox v1.15.13d publishes the rebuilt base-pi-only, so it doesn't build on the stale base. |
||
|
|
03629cdac7 |
refactor: build FROM joakimp/pi-devbox:base-pi-only (Option B)
The pi-only building block now lives in this repo as the internal base-pi-only tag (produced by opencode-devbox CI from Dockerfile.variant, INSTALL_OPENCODE=false) instead of opencode-devbox:latest-pi-only — so an 'opencode-devbox' tag never ships without opencode. - Dockerfile: BASE_IMAGE default joakimp/opencode-devbox:latest-pi-only -> joakimp/pi-devbox:base-pi-only. - Updated README, AGENTS, DOCKER_HUB, docker-compose, CHANGELOG. - Single source of truth unchanged (opencode-devbox/Dockerfile.variant); publish ordering + EXPECTED_PI_VERSION smoke guard unchanged. |
||
|
|
1d1283f942 |
refactor: FROM opencode-devbox:latest-pi-only (lean, no opencode)
Re-point the re-brand at the new pi-only variant instead of with-pi, so pi-devbox stays a lean pi-focused image (no opencode) while the pi install logic still lives in one place upstream. This keeps pi-devbox meaningfully distinct from opencode-devbox:latest-with-pi. - Dockerfile: BASE_IMAGE default -> joakimp/opencode-devbox:latest-pi-only. - smoke-test.sh: size threshold 2900 -> 2750 MB (pi-only = with-pi minus opencode's ~145 MB binary). - Docs (README/AGENTS/DOCKER_HUB/CHANGELOG/docker-compose): drop the 'also contains opencode' notes; describe pi-only basis and the distinction from with-pi. Publish ordering unchanged: release opencode-devbox first so latest-pi-only carries the target pi version, then tag here (smoke asserts pi --version). |
||
|
|
c139be326f |
refactor: re-brand the opencode-devbox with-pi variant (single source of truth)
pi-devbox no longer installs pi itself. The Dockerfile is now a thin FROM joakimp/opencode-devbox:latest-with-pi (overridable via BASE_IMAGE), inheriting pi + pi-toolkit + pi-extensions + pi-fork (fork) + pi-observational-memory (recall) + the LAN-access helper + all base tooling from the single source of truth. Eliminates the install-logic duplication that drifted against opencode-devbox/Dockerfile.variant (decision #3). Consequences (documented in CHANGELOG/AGENTS): - The image now ALSO contains opencode (with-pi has INSTALL_OPENCODE=true). A leaner pi-only image would need a dedicated pi-only variant upstream. - Publish ordering: release opencode-devbox first so latest-with-pi carries the target pi version, THEN tag this repo. The smoke test asserts pi --version matches the tag (EXPECTED_PI_VERSION) and fails loudly if the base is stale — turning the version coupling into an enforced ordering guard. CI: drop PI_VERSION build-arg (Dockerfile installs nothing); keep tag->version resolution to feed the smoke base-freshness guard. Smoke adds fork/recall clone + node_modules + settings.json registration checks; size threshold 2200 -> 2900 MB (now tracks with-pi). Docs updated across README, AGENTS, DOCKER_HUB, .env.example, docker-compose. |
||
|
|
973c2efd5c |
Expand README + tweak DOCKER_HUB.md for users not cloning the repo
README rewrite: - Two quick-start paths: 'no git clone' (curl docker-compose.yml + .env.example) and 'with git clone' for hackers/forkers - New 'Authentication' section with subsections per provider (Anthropic, OpenAI, Gemini, AWS Bedrock static, AWS Bedrock SSO). AWS SSO path documents the ~/.aws bind-mount. - Persistent state expanded: 5-row volume table + optional volumes table. Annotated what survives what. - Configuration reference: full .env table. - Versioning, building from source (with build args table), troubleshooting FAQ, related projects, license. - 11 kB total — comprehensive but readable. DOCKER_HUB.md tweaks: - Quick-start now has a 'no git clone' path (curl two files), pointing users at the gitea README for the full setup guide. The git-clone path was overkill for the 90% case (just want to docker run). - Explicit link to gitea README at the end of the quick-start block. |
||
|
|
7b634605b7 |
Initial commit: pi-devbox v0.74.0
pi coding-agent container built on opencode-devbox:base-latest. Includes Dockerfile, docker-compose, CI workflow, smoke-test, README, CHANGELOG, AGENTS.md. |