Compare commits
3 Commits
9c31c641d6
...
v1.16.2
| Author | SHA1 | Date | |
|---|---|---|---|
| 56e6a782e3 | |||
| 49d3e113ee | |||
| f1e879ca6c |
@@ -104,6 +104,7 @@ cd /tmp && npm pack @earendil-works/pi-coding-agent@0.75.5 && tar -xzf earendil-
|
|||||||
- **`actions/upload-artifact` and `actions/download-artifact` must stay at @v3 on Gitea.** v4+ uses a GitHub-Enterprise-specific Artifact API; runs fail with `GHESNotSupportedError`. If you need artifacts for a new reason (build logs, SBOMs, etc.), pin @v3 explicitly.
|
- **`actions/upload-artifact` and `actions/download-artifact` must stay at @v3 on Gitea.** v4+ uses a GitHub-Enterprise-specific Artifact API; runs fail with `GHESNotSupportedError`. If you need artifacts for a new reason (build logs, SBOMs, etc.), pin @v3 explicitly.
|
||||||
- **Step scripts run under `/bin/sh` (dash), not bash.** Avoid bash-isms like `${VAR//a/b}` parameter-pattern substitution; use POSIX alternatives (`tr`, `sed`) or declare `shell: bash` on the step.
|
- **Step scripts run under `/bin/sh` (dash), not bash.** Avoid bash-isms like `${VAR//a/b}` parameter-pattern substitution; use POSIX alternatives (`tr`, `sed`) or declare `shell: bash` on the step.
|
||||||
- **`BUILDKIT_PROGRESS=plain`** is set at workflow level on `docker-publish-split.yml` so arm64-under-QEMU builds log each layer line-by-line. The default collapsed progress UI hides which step is stalled, which made diagnosing earlier hangs expensive.
|
- **`BUILDKIT_PROGRESS=plain`** is set at workflow level on `docker-publish-split.yml` so arm64-under-QEMU builds log each layer line-by-line. The default collapsed progress UI hides which step is stalled, which made diagnosing earlier hangs expensive.
|
||||||
|
- **`STRICT_REGISTRATION` gates the fork/recall *registration* smoke assertions.** `smoke-test.sh`'s two pi-extension registration checks (that `pi-fork`/`pi-observational-memory` registered in `~/.pi/agent/settings.json`) depend on the *base* entrypoint running `pi install /opt/<pkg>`. `validate.yml` builds variants from the **published** `base-latest`, which lags the in-repo entrypoint until a release rebuilds the base — so those checks would false-negative there. They are therefore warn-only unless `STRICT_REGISTRATION=1`: `validate.yml` leaves it unset (warn), and `docker-publish-split.yml` (which builds the base fresh in the same run) sets `STRICT_REGISTRATION: "1"` on the three pi-bearing smoke jobs to enforce them. Build-time `/opt` + `node_modules` checks stay hard in both paths. If you touch the registration checks or the base-freshness model, keep this flag wiring in lockstep across both workflows.
|
||||||
|
|
||||||
## Testing changes
|
## Testing changes
|
||||||
|
|
||||||
|
|||||||
+78
-1
@@ -8,6 +8,75 @@ Tags follow `v{opencode_version}[letter]` — bare tag for the first build on a
|
|||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
_(no changes since v1.16.2)_
|
||||||
|
|
||||||
|
## v1.16.2 — 2026-06-08
|
||||||
|
|
||||||
|
First container build on the `opencode-ai@1.16.x` minor release (rolls up
|
||||||
|
`1.16.0` → `1.16.1` → `1.16.2`, all published 2026-06-05). Also picks up
|
||||||
|
**pi `0.78.1` → `0.79.0`** (resolved fresh by CI's `resolve-versions` job) in
|
||||||
|
the `with-pi`, `omos-with-pi`, and `pi-only` variants.
|
||||||
|
|
||||||
|
### Bumped: opencode-ai 1.15.13 → 1.16.2
|
||||||
|
|
||||||
|
`OPENCODE_VERSION` ARG in `Dockerfile.variant`. Highlights from the upstream
|
||||||
|
release (full notes: <https://github.com/anomalyco/opencode/releases>):
|
||||||
|
|
||||||
|
- **1.16.0** — ~38% faster startup (@StarpTech); managed workspace cloning that
|
||||||
|
keeps dirty/untracked files; move sessions between workspaces/directories;
|
||||||
|
proper OpenAI-via-Bedrock support; skill discovery + file-based agent loading;
|
||||||
|
`run --replay` for interactive session replay. Plus TUI/desktop polish and
|
||||||
|
numerous bugfixes (shell cancellation races, Windows path normalization, ACP
|
||||||
|
cancel/abort).
|
||||||
|
- **1.16.1** — internal/no user-visible notes (empty release body).
|
||||||
|
- **1.16.2** — reasoning summaries only run on supporting providers (avoids
|
||||||
|
GPT-5 request failures); edit operations refuse loose matches that could
|
||||||
|
overwrite the wrong code; Bedrock hang-before-first-token fix; diff-viewer
|
||||||
|
hunk navigation; subagents can be backgrounded; Snowflake Cortex provider.
|
||||||
|
|
||||||
|
### Picks up: pi 0.78.1 → 0.79.0
|
||||||
|
|
||||||
|
Resolved at build time for the pi-bearing variants. Headlines: project-trust
|
||||||
|
prompting for project-local settings/resources/instructions/packages (with
|
||||||
|
`--approve`/`--no-approve` and a `project_trust` extension event), cache-hit
|
||||||
|
rate in the interactive footer, richer SDK/RPC extension surfaces, plus a
|
||||||
|
stack of TUI and provider fixes. Full notes ship in the npm tarball's
|
||||||
|
`CHANGELOG.md`.
|
||||||
|
|
||||||
|
### Smoke size thresholds bumped +150 MB (preemptive)
|
||||||
|
|
||||||
|
Ahead of the combined minor opencode + pi bump, all opencode-bearing variant
|
||||||
|
thresholds in `scripts/smoke-test.sh` were raised: `base` 2600 → 2750,
|
||||||
|
`omos` 3300 → 3450, `with-pi` 2900 → 3050, `omos-with-pi` 3900 → 4050; and
|
||||||
|
`pi-only` 2750 → 2850 (+100, pi-only carries only the pi bump). Both `base`
|
||||||
|
(last 2506 MB) and `omos` (last 3206 MB) were on ~94 MB headroom, and a minor
|
||||||
|
opencode bump has tripped these ceilings before (v1.15.0 omos, v1.15.4
|
||||||
|
omos-with-pi), causing a partial publish + letter-suffix recovery cycle.
|
||||||
|
Restoring ~250 MB headroom avoids that. CI's smoke size print records actual
|
||||||
|
landed sizes — tighten later if they come in well under.
|
||||||
|
|
||||||
|
## v1.15.13e — 2026-06-04
|
||||||
|
|
||||||
|
Letter-suffix rebuild on opencode `1.15.13` (version unchanged). Picks up
|
||||||
|
**pi `0.78.1`** (resolved fresh by CI's `resolve-versions` job) plus the LAN-jump
|
||||||
|
key-persistence work, an entrypoint ownership fix for the new `devbox-ssh-local`
|
||||||
|
volume, a CI smoke false-negative fix, and documentation. Touches `entrypoint.sh`
|
||||||
|
and `setup-lan-access.sh` (both in the base hash), so `base-latest` /
|
||||||
|
`base-pi-only` advance and the fixes propagate to `pi-devbox`.
|
||||||
|
|
||||||
|
### Docs: per-host `ControlPath` overrides break `pi --ssh` (read-only `~/.ssh`)
|
||||||
|
|
||||||
|
Documented a gotcha in the README "Reaching your LAN" section: the bind-mounted
|
||||||
|
`~/.ssh/config` is read before the baked `Host *` default, and SSH uses the
|
||||||
|
first `ControlPath` it sees. A per-host block that sets `ControlPath` under
|
||||||
|
`~/.ssh/` (a common CGNAT-multiplexing pattern, e.g. `~/.ssh/cm/%r@%h:%p`) wins
|
||||||
|
but then fails inside the container because `~/.ssh` is mounted read-only — the
|
||||||
|
master socket can't bind. This silently breaks `pi --ssh <host>`: the SSH layer
|
||||||
|
fails and pi falls back to running its tools locally in the container. Fix is
|
||||||
|
host-side — drop the per-host `ControlPath` or repoint it at the writable
|
||||||
|
`/tmp/sshcm/%r@%h:%p` (works on both host and container, preserves multiplexing).
|
||||||
|
No image change; documentation only.
|
||||||
|
|
||||||
### Fixed: validate.yml false-negative on fork/recall registration checks
|
### Fixed: validate.yml false-negative on fork/recall registration checks
|
||||||
|
|
||||||
The push-to-main `validate.yml` builds variants FROM the published `base-latest`
|
The push-to-main `validate.yml` builds variants FROM the published `base-latest`
|
||||||
@@ -48,7 +117,15 @@ stayed root-owned while `setup-lan-access.sh` runs as `developer` — both its
|
|||||||
the persistence change. `entrypoint.sh` now chowns `~/.ssh-local` to the
|
the persistence change. `entrypoint.sh` now chowns `~/.ssh-local` to the
|
||||||
developer user alongside the other named-volume mount points.
|
developer user alongside the other named-volume mount points.
|
||||||
|
|
||||||
_(no other changes since v1.15.13d)_
|
### Docs: document the optional `~/.config/devbox-shell` mount in the compose template
|
||||||
|
|
||||||
|
`docker-compose.yml` now carries a commented-out `~/.config/devbox-shell` bind
|
||||||
|
mount with an explanatory note. It's the recommended home for host-owned shell
|
||||||
|
config: the image's `~/.bash_aliases` sources `~/.config/devbox-shell/bash_aliases`
|
||||||
|
if present, and `setup-lan-access.sh` reads `~/.config/devbox-shell/ssh-lan.conf`
|
||||||
|
for named-peer `ProxyJump host` overrides. A directory mount is preferred over
|
||||||
|
the single-file `~/.bash_aliases` mount because it survives editors' atomic-save.
|
||||||
|
Template comment only; no behavior change.
|
||||||
|
|
||||||
## v1.15.13d — 2026-06-04
|
## v1.15.13d — 2026-06-04
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -42,7 +42,7 @@ ARG USER_NAME=developer
|
|||||||
# edit, so the cache-hit class of bug that bit pi-devbox v0.74.0..
|
# edit, so the cache-hit class of bug that bit pi-devbox v0.74.0..
|
||||||
# v0.75.5 cannot apply here.
|
# v0.75.5 cannot apply here.
|
||||||
ARG INSTALL_OPENCODE=true
|
ARG INSTALL_OPENCODE=true
|
||||||
ARG OPENCODE_VERSION=1.15.13
|
ARG OPENCODE_VERSION=1.16.2
|
||||||
RUN if [ "${INSTALL_OPENCODE}" = "true" ]; then \
|
RUN if [ "${INSTALL_OPENCODE}" = "true" ]; then \
|
||||||
NPM_CONFIG_PREFIX=/usr npm install -g opencode-ai@${OPENCODE_VERSION} && \
|
NPM_CONFIG_PREFIX=/usr npm install -g opencode-ai@${OPENCODE_VERSION} && \
|
||||||
opencode --version ; \
|
opencode --version ; \
|
||||||
|
|||||||
@@ -187,6 +187,22 @@ Now `dssh my-nas` routes container → host → LAN peer, pulling HostName/User/
|
|||||||
|
|
||||||
> This ships the **mechanism** only — your specific target hosts are facts about *your* network (and a laptop roams between several), so they live in your own host-side config, never baked into the image. Set `DEVBOX_LAN_ACCESS=off` to disable, or `=jump` to force it (e.g. native Linux with `extra_hosts: ["host.docker.internal:host-gateway"]`).
|
> This ships the **mechanism** only — your specific target hosts are facts about *your* network (and a laptop roams between several), so they live in your own host-side config, never baked into the image. Set `DEVBOX_LAN_ACCESS=off` to disable, or `=jump` to force it (e.g. native Linux with `extra_hosts: ["host.docker.internal:host-gateway"]`).
|
||||||
|
|
||||||
|
#### Gotcha: per-host `ControlPath` and `pi --ssh`
|
||||||
|
|
||||||
|
The base image bakes a `Host *` default (`/etc/ssh/ssh_config.d/00-devbox-controlmaster.conf`) that points `ControlPath` at the writable, per-container `/tmp/sshcm/` (created mode-700 on every start by `entrypoint-user.sh`). Multiplexing therefore works out of the box. **But your bind-mounted `~/.ssh/config` is read first, and SSH uses the first value it sees** — so any per-host block that sets its own `ControlPath` under `~/.ssh/` (a common CGNAT-multiplexing pattern, e.g. `ControlPath ~/.ssh/cm/%r@%h:%p`) **wins, and then fails inside the container** because `~/.ssh` is mounted **read-only** — the master socket can't bind (`cannot bind … Read-only file system`).
|
||||||
|
|
||||||
|
This bites `pi --ssh <host>` especially: the SSH layer fails to establish the master and pi silently falls back to running its `read`/`write`/`edit`/`bash` tools **locally in the container** instead of on the remote (watch for the missing `SSH ⚡` in the status bar — and `hostname` returning the container ID).
|
||||||
|
|
||||||
|
**Fix (host-side, one line):** in your host's `~/.ssh/config`, either drop the per-host `ControlPath` (to inherit the writable baked default) or point it at a path that's writable inside the container too:
|
||||||
|
|
||||||
|
```sshconfig
|
||||||
|
Host my-remote
|
||||||
|
# was: ControlPath ~/.ssh/cm/%r@%h:%p ← read-only in the container
|
||||||
|
ControlPath /tmp/sshcm/%r@%h:%p # writable on both host and container
|
||||||
|
```
|
||||||
|
|
||||||
|
`/tmp/sshcm/` is also writable on the host (macOS/Linux), so native (non-container) `ssh`/`pi --ssh` from the host keeps working and CGNAT multiplexing is preserved (`ControlMaster`/`ControlPersist` unchanged — only the socket *directory* moves). Note SSH does not create the `ControlPath` parent dir; the container makes `/tmp/sshcm` every start, but on the host run `mkdir -p /tmp/sshcm` once if it doesn't already exist.
|
||||||
|
|
||||||
### Custom opencode config
|
### Custom opencode config
|
||||||
|
|
||||||
Opencode configuration is persisted automatically via the named volume `devbox-opencode-config`. This volume is mounted at `/home/developer/.config/opencode` by default — no host directory setup required. All changes to `opencode.jsonc`, skills, and (on the OMOS variant) `oh-my-opencode-slim.json` survive container recreation.
|
Opencode configuration is persisted automatically via the named volume `devbox-opencode-config`. This volume is mounted at `/home/developer/.config/opencode` by default — no host directory setup required. All changes to `opencode.jsonc`, skills, and (on the OMOS variant) `oh-my-opencode-slim.json` survive container recreation.
|
||||||
|
|||||||
+12
-5
@@ -392,13 +392,20 @@ echo " Uncompressed size: ${SIZE_MB} MB"
|
|||||||
# deliberately zero-headroom 2500 ceiling and skipping promote-base-latest.
|
# deliberately zero-headroom 2500 ceiling and skipping promote-base-latest.
|
||||||
# omos variant to ~3.1 GB. Functional smoke checks all pass; this is a
|
# omos variant to ~3.1 GB. Functional smoke checks all pass; this is a
|
||||||
# guardrail, not a performance limit.
|
# guardrail, not a performance limit.
|
||||||
THRESHOLD=2600
|
# v1.16.2: all thresholds bumped +150 MB preemptively ahead of the combined
|
||||||
[ "$VARIANT" = "omos" ] && THRESHOLD=3300
|
# opencode 1.15.13->1.16.2 (minor) + pi 0.78.1->0.79.0 (minor) bump. Both
|
||||||
[ "$VARIANT" = "with-pi" ] && THRESHOLD=2900
|
# base (2506/2600) and omos (3206/3300) were sitting on ~94 MB headroom and
|
||||||
[ "$VARIANT" = "omos-with-pi" ] && THRESHOLD=3900
|
# a minor opencode bump has tripped them before (v1.15.0 omos, v1.15.4
|
||||||
|
# omos-with-pi). Restoring ~250 MB headroom avoids a partial-publish +
|
||||||
|
# letter-suffix recovery cycle. CI's smoke size print + resolved-versions
|
||||||
|
# table records the actual landed sizes; tighten later if they come in low.
|
||||||
|
THRESHOLD=2750
|
||||||
|
[ "$VARIANT" = "omos" ] && THRESHOLD=3450
|
||||||
|
[ "$VARIANT" = "with-pi" ] && THRESHOLD=3050
|
||||||
|
[ "$VARIANT" = "omos-with-pi" ] && THRESHOLD=4050
|
||||||
# pi-only = with-pi minus opencode (its platform binary is ~145 MB), so it
|
# pi-only = with-pi minus opencode (its platform binary is ~145 MB), so it
|
||||||
# lands a bit under base. Threshold 2750 leaves the same headroom pattern.
|
# lands a bit under base. Threshold 2750 leaves the same headroom pattern.
|
||||||
[ "$VARIANT" = "pi-only" ] && THRESHOLD=2750
|
[ "$VARIANT" = "pi-only" ] && THRESHOLD=2850
|
||||||
if [ "$SIZE_MB" -gt "$THRESHOLD" ]; then
|
if [ "$SIZE_MB" -gt "$THRESHOLD" ]; then
|
||||||
fail "image size ${SIZE_MB} MB exceeds threshold ${THRESHOLD} MB for variant=$VARIANT"
|
fail "image size ${SIZE_MB} MB exceeds threshold ${THRESHOLD} MB for variant=$VARIANT"
|
||||||
else
|
else
|
||||||
|
|||||||
Reference in New Issue
Block a user