Commit Graph

49 Commits

Author SHA1 Message Date
joakimp f7c34091b1 CI: preventative fix for PI_VERSION/OMOS_VERSION cache-hit silent regression
Mirrors the pi-devbox v0.75.5b fix (2026-05-23) onto the four-variant
pipeline here. The with-pi, omos, and omos-with-pi variants install
upstream npm packages whose *_VERSION build-args defaulted to 'latest'.
When the build-arg string is byte-identical across builds, the layer
hash is identical and the registry buildcache silently reuses the layer
from whatever upstream version was current when the cache was first
populated — same mechanism that shipped pi-devbox v0.74.0..v0.75.5 with
identical image bytes.

Currently masked here because OPENCODE_VERSION is a hard-coded ARG that
bumps every release; parent-chain cache invalidation flushes the
downstream pi/omos layers. Masking would fail on any vN.N.Nb opencode-
version-unchanged release that only bumps pi or omos. Filed last night
as parked followup; fixing preventatively now that #5 (AWS SSO inside
tor-ms22 container) cleared.

CHANGES

.gitea/workflows/docker-publish-split.yml — new resolve-versions job
running 'npm view @earendil-works/pi-coding-agent version' and
'npm view oh-my-opencode-slim version', exposing concrete strings as
job outputs. All six affected jobs (smoke-omos, smoke-with-pi,
smoke-omos-with-pi, build-variant-omos, build-variant-with-pi,
build-variant-omos-with-pi) now consume them as PI_VERSION /
OMOS_VERSION build-args. smoke-base / build-variant-base unaffected.

scripts/smoke-test.sh — new run_expect helper asserting an expected
substring in command output. The pi check uses EXPECTED_PI_VERSION;
the omos check uses EXPECTED_OMOS_VERSION against npm ls -g. Both env
vars are wired from resolve-versions outputs in the smoke jobs. Catches
this regression class on the next release, not four releases later.

Dockerfile.variant — comment blocks above OPENCODE_VERSION (source-
pinned, not subject to the bug), PI_VERSION (CI-resolved), and
OMOS_VERSION (CI-resolved) explaining the cache-hit footgun.

AGENTS.md — new convention bullet under 'Critical conventions' naming
the resolve-versions job + EXPECTED_*_VERSION wiring as the contract
to keep in lockstep when modifying variant build-args.

.gitea/README.md — Step 1 expanded to cover the parallel resolve-
versions job alongside base-decide; pipeline diagram updated.

CHANGELOG.md — Unreleased entry describing the fix, masking mechanism,
and audit footprint.

No image-content change expected on the next release vs what 'latest'
would have resolved to anyway. Purely makes the cache invalidate
correctly going forward.
2026-05-24 15:38:36 +00:00
joakimp 72d2c99885 docs: enrich v1.15.10 CHANGELOG with actual upstream release notes
The v1.15.10 release commit (80e57d7) said upstream releases ship
empty bodies — that was incorrect. I was checking sst/opencode which
is a fork; the canonical upstream this devbox tracks is
github.com/anomalyco/opencode (per user correction). Three of the
four versions (1.15.7, 1.15.9, 1.15.10) have rich release notes;
only 1.15.8 is empty.

Expanded the v1.15.10 CHANGELOG entry with per-version summaries:

- v1.15.7: Grok OAuth + device-code login, v2 session API safe-error
  responses with reference IDs, Codex OAuth refresh dedup, restored
  OpenAI OAuth + reasoning streams, friendly tool-schema errors,
  Grok PDF attachments, several TUI and desktop improvements.

- v1.15.8: empty release body (assumed internal/no user-visible).

- v1.15.9: redesigned diff viewer with file tree + enabled by default,
  MCP OAuth callbackPort and scope-in-clientMetadata, Vertex Anthropic
  multi-region endpoint fix, many 'show clearer error' improvements,
  native reasoning metadata preservation across turns, TUI worktree-
  copy shortcut, desktop titlebar tab navigation.

- v1.15.10: single fix — restored legacy production desktop flows
  for opening projects and starting sessions.

Doc-only commit on main. The v1.15.10 tag snapshot is unchanged
because CI is mid-flight against it (5 jobs running at the time of
this correction); cancelling and re-tagging would cost ~50 min of
CI re-run for changelog wording with no image-content effect.
The Hub description for v1.15.10 will reflect the thin tag-snapshot
CHANGELOG; main has the correct content for the next release and
for anyone reading current docs.
2026-05-23 19:19:19 +02:00
joakimp 80e57d732b Bump opencode 1.15.6 -> 1.15.10 + cut v1.15.10
Validate / validate-base (push) Waiting to run
Validate / validate-with-pi (push) Waiting to run
Validate / docs-check (push) Successful in 15s
Validate / base-change-warning (push) Successful in 59s
Validate / validate-omos (push) Successful in 4m33s
Validate / validate-omos-with-pi (push) Successful in 7m50s
Publish Docker Image / base-decide (push) Failing after 10m22s
Publish Docker Image / build-base (push) Has been cancelled
Publish Docker Image / smoke-base (push) Has been cancelled
Publish Docker Image / smoke-omos (push) Has been cancelled
Publish Docker Image / smoke-with-pi (push) Has been cancelled
Publish Docker Image / smoke-omos-with-pi (push) Has been cancelled
Publish Docker Image / build-variant-base (push) Has been cancelled
Publish Docker Image / build-variant-omos (push) Has been cancelled
Publish Docker Image / build-variant-with-pi (push) Has been cancelled
Publish Docker Image / build-variant-omos-with-pi (push) Has been cancelled
Publish Docker Image / promote-base-latest (push) Has been cancelled
Publish Docker Image / update-description (push) Has been cancelled
Four upstream patch releases over two days. Upstream releases ship
empty bodies and no CHANGELOG; the patch sequence (1.15.7-1.15.10)
is fixes only per typical sst/opencode cadence.

The with-pi and omos-with-pi variants will also implicitly bump
pi 0.75.4 -> 0.75.5 since PI_VERSION=latest resolves at build time.

omos-with-pi smoke threshold remains 3700 MB (set v1.15.4b 2026-05-18).
Four opencode patches plus one pi patch typically add only a few MB
across both, not expected to trip. If it does, recovery is the
well-worn letter-suffix pattern (v1.15.10b with threshold bump).

Cache hit expected on base-35ee5fe7861a since neither Dockerfile.base
nor rootfs/ have changed since v1.14.50b. Built on the same CI path
as v1.15.6 — pinned-crane install (T14), skip-promote-on-cache-hit
(T15), and update-description-always-on-base-success (v1.15.4b)
all expected to remain quiet on this cache-hit run.
2026-05-23 19:14:58 +02:00
joakimp 19f8c043bd Bump opencode 1.15.4 -> 1.15.6 + cut v1.15.6
Validate / docs-check (push) Successful in 14s
Validate / base-change-warning (push) Successful in 10s
Validate / validate-base (push) Successful in 3m33s
Validate / validate-omos-with-pi (push) Successful in 4m57s
Validate / validate-with-pi (push) Successful in 6m18s
Validate / validate-omos (push) Successful in 12m13s
Publish Docker Image / base-decide (push) Successful in 13s
Publish Docker Image / build-base (push) Has been skipped
Publish Docker Image / smoke-base (push) Successful in 3m27s
Publish Docker Image / smoke-omos (push) Successful in 4m29s
Publish Docker Image / smoke-with-pi (push) Successful in 6m13s
Publish Docker Image / smoke-omos-with-pi (push) Successful in 12m31s
Publish Docker Image / build-variant-base (push) Successful in 14m33s
Publish Docker Image / build-variant-omos (push) Successful in 19m38s
Publish Docker Image / build-variant-with-pi (push) Successful in 19m0s
Publish Docker Image / build-variant-omos-with-pi (push) Successful in 30m37s
Publish Docker Image / promote-base-latest (push) Has been skipped
Publish Docker Image / update-description (push) Successful in 9s
Two upstream patch releases since v1.15.4b. Plus this release picks up
two workflow improvements that landed on main between v1.15.4b and
now (b6e4d89 pycache/DS_Store filter in base-decide, 90e5a1f doc-drift
sweep clause in AGENTS.md). No image-content changes beyond the
version bump; cache hit expected on base-35ee5fe7861a since neither
Dockerfile.base nor rootfs/ have changed.

The with-pi and omos-with-pi variants will also implicitly bump pi
0.75.3 -> 0.75.4 because PI_VERSION=latest resolves at build time.
The omos-with-pi smoke threshold (3700 MB after the v1.15.4b bump)
should accommodate two opencode patch versions plus one pi patch
without recurrence of the trip; a future bump-bump pattern would
push it again.

First release on the new CI path that exercises:
- pinned crane install (T14, v1.15.3) - only fires on real base rebuild,
  cache-hit on base means it stays unexercised this run too
- skip promote-base-latest on cache-hit (T15, v1.15.4) - active
- update-description always-and-success-of-base wrap (v1.15.4b) -
  active, will run since base variant publishes
2026-05-21 00:09:15 +02:00
joakimp 8f2c9f5112 v1.15.4b: omos-with-pi threshold bump + update-description partial-publish fix
Validate / docs-check (push) Successful in 7s
Validate / base-change-warning (push) Successful in 20s
Validate / validate-base (push) Successful in 3m36s
Publish Docker Image / base-decide (push) Successful in 13s
Publish Docker Image / build-base (push) Has been skipped
Validate / validate-with-pi (push) Successful in 4m14s
Validate / validate-omos (push) Successful in 7m1s
Publish Docker Image / smoke-base (push) Successful in 3m37s
Publish Docker Image / smoke-omos (push) Successful in 4m39s
Publish Docker Image / smoke-omos-with-pi (push) Successful in 5m7s
Publish Docker Image / smoke-with-pi (push) Successful in 6m24s
Validate / validate-omos-with-pi (push) Successful in 15m59s
Publish Docker Image / build-variant-base (push) Successful in 14m12s
Publish Docker Image / build-variant-omos (push) Successful in 19m29s
Publish Docker Image / build-variant-with-pi (push) Successful in 23m7s
Publish Docker Image / build-variant-omos-with-pi (push) Successful in 26m16s
Publish Docker Image / promote-base-latest (push) Has been skipped
Publish Docker Image / update-description (push) Successful in 8s
Recovery for v1.15.4's partial publish (omos-with-pi exceeded 3500 MB
smoke threshold; other 3 variants published cleanly). Two changes:

1. omos-with-pi threshold 3500 -> 3700 MB. Compounded growth from
   opencode 1.15.0 -> 1.15.4 (4 patch versions) plus pi 0.74.0 -> 0.75.3
   (minor + 3 patches) summed in the omos-with-pi variant, just over
   the existing limit. Same pattern as prior threshold bumps (v1.14.31c,
   v1.15.0b). Restores ~150 MB headroom for routine apt-upgrade drift.

2. update-description workflow bug fix. Pre-existing latent bug exposed
   by v1.15.4's partial publish: update-description.needs includes all 4
   build-variant-* jobs, and gitea Actions' default behavior is
   'skipped need => skip dependent' \u2014 even when the job's own if:
   condition is satisfied. So when build-variant-omos-with-pi was
   skipped (because its smoke failed), update-description cascaded into
   a skip too, and Hub description didn't refresh on v1.15.4 despite
   3 variants publishing.

   Fix: wrap if: in always() + explicit success check on the base
   variant. Same fix applied to promote-base-latest preemptively (it
   has the same latent bug, currently masked by the cache-hit gate).

No image-side changes \u2014 cache hit on base-35ee5fe7861a.
2026-05-18 22:30:59 +02:00
joakimp 60eb49469e v1.15.4: bump opencode 1.15.3 -> 1.15.4
Publish Docker Image / base-decide (push) Successful in 14s
Validate / docs-check (push) Successful in 8s
Validate / base-change-warning (push) Successful in 7s
Validate / validate-base (push) Successful in 3m30s
Publish Docker Image / build-base (push) Has been skipped
Validate / validate-with-pi (push) Successful in 4m12s
Validate / validate-omos (push) Successful in 7m8s
Validate / validate-omos-with-pi (push) Successful in 5m7s
Publish Docker Image / smoke-omos (push) Successful in 4m23s
Publish Docker Image / smoke-base (push) Successful in 8m17s
Publish Docker Image / smoke-with-pi (push) Successful in 6m24s
Publish Docker Image / smoke-omos-with-pi (push) Failing after 11m14s
Publish Docker Image / build-variant-base (push) Successful in 14m38s
Publish Docker Image / build-variant-omos-with-pi (push) Has been skipped
Publish Docker Image / build-variant-omos (push) Successful in 19m40s
Publish Docker Image / build-variant-with-pi (push) Successful in 19m49s
Publish Docker Image / promote-base-latest (push) Has been skipped
Publish Docker Image / update-description (push) Has been skipped
Bundles with the CI hardening landed on main since v1.15.3 (T14/T15 in
the operator backlog):

- Pinned crane install in promote-base-latest (replaces flaky
  imjasonh/setup-crane@v0.4 that depends on api.github.com/releases/latest
  at runtime and periodically rate-limits)
- Skip promote-base-latest on cache-hit base builds (need_build='false')

These will be exercised on this release run \u2014 if the base hash hasn't
drifted since v1.15.3 (likely cache hit), promote-base-latest should
SKIP rather than RUN, and update-description picks up the new tag.
2026-05-18 21:51:15 +02:00
joakimp 18b9c9c549 CI: harden promote-base-latest (pinned crane + skip on cache-hit)
Validate / docs-check (push) Successful in 10s
Validate / base-change-warning (push) Successful in 16s
Validate / validate-with-pi (push) Successful in 4m10s
Validate / validate-omos (push) Successful in 4m34s
Validate / validate-base (push) Has been cancelled
Validate / validate-omos-with-pi (push) Has been cancelled
Two workflow-only changes for promote-base-latest, no image-side impact:

T14 \u2014 replace imjasonh/setup-crane@v0.4 with direct pinned crane install.
The action's bootstrap script calls api.github.com/.../releases/latest
at every run to discover the crane version. That call periodically
rate-limits and returns JSON without .tag_name, jq emits 'null', the
action then downloads .../releases/download/null/... \u2192 404 \u2192 'gzip:
unexpected end of file' \u2192 exit 2. We hit this on the v1.15.3 release
(2026-05-16) where it was cosmetic only \u2014 base-latest was already
correct from cache hit \u2014 but the red-X is annoying.

Replaced with curl + tar pinned to crane v0.21.6 (latest at time of
change). Same pattern as other GitHub-sourced binaries in the
Dockerfile layer (gosu, fzf, eza etc.); operator bumps CRANE_VERSION
deliberately when wanting updates.

T15 \u2014 gate promote-base-latest on need_build == 'true'. When the base
layer's content hash hasn't changed (cache hit on existing base-<hash>
from a prior run), base-latest already points at the correct digest.
The retag is a tautology, and any transient failure of it produces a
red-X for an operation that didn't need to happen. Skipping the job
entirely on cache-hit is correct and removes a whole class of cosmetic
failure. Manual workflow_dispatch with promote_latest=true still bypasses
the gate as an escape hatch (e.g., if base-latest got hand-deleted and
needs regeneration without rebuilding the base).

This will not trigger a CI publish run (main-branch commit, no tag).
2026-05-18 21:45:10 +02:00
joakimp ad4a12b3ab v1.15.3: bump opencode 1.15.0 -> 1.15.3
Validate / base-change-warning (push) Successful in 10s
Validate / docs-check (push) Successful in 17s
Validate / validate-omos (push) Successful in 4m29s
Validate / validate-with-pi (push) Successful in 4m17s
Validate / validate-omos-with-pi (push) Successful in 8m13s
Validate / validate-base (push) Successful in 8m48s
Publish Docker Image / base-decide (push) Successful in 12s
Publish Docker Image / promote-base-latest (push) Failing after 6s
Publish Docker Image / build-base (push) Has been cancelled
Publish Docker Image / smoke-base (push) Has been cancelled
Publish Docker Image / smoke-omos (push) Has been cancelled
Publish Docker Image / smoke-with-pi (push) Has been cancelled
Publish Docker Image / smoke-omos-with-pi (push) Has been cancelled
Publish Docker Image / build-variant-base (push) Has been cancelled
Publish Docker Image / build-variant-omos (push) Has been cancelled
Publish Docker Image / build-variant-with-pi (push) Has been cancelled
Publish Docker Image / build-variant-omos-with-pi (push) Has been cancelled
Publish Docker Image / update-description (push) Has been cancelled
2026-05-16 19:54:15 +02:00
joakimp d293ddc202 v1.15.0b: bump omos smoke threshold 3200->3300, omos-with-pi 3400->3500
Validate / base-change-warning (push) Successful in 9s
Validate / docs-check (push) Successful in 18s
Validate / validate-omos (push) Successful in 4m22s
Validate / validate-with-pi (push) Successful in 4m10s
Publish Docker Image / base-decide (push) Successful in 15s
Publish Docker Image / build-base (push) Has been skipped
Validate / validate-base (push) Successful in 5m20s
Publish Docker Image / smoke-base (push) Successful in 3m34s
Publish Docker Image / smoke-with-pi (push) Successful in 4m12s
Publish Docker Image / smoke-omos (push) Successful in 7m2s
Publish Docker Image / smoke-omos-with-pi (push) Successful in 4m58s
Validate / validate-omos-with-pi (push) Successful in 17m33s
Publish Docker Image / build-variant-base (push) Successful in 14m18s
Publish Docker Image / build-variant-with-pi (push) Successful in 19m22s
Publish Docker Image / build-variant-omos (push) Successful in 18m50s
Publish Docker Image / build-variant-omos-with-pi (push) Successful in 31m58s
Publish Docker Image / promote-base-latest (push) Has been skipped
Publish Docker Image / update-description (push) Has been skipped
opencode 1.15.0 grew the omos image to 3206 MB, 6 MB over the existing
3200 MB threshold, causing smoke-omos to fail and build-variant-omos
to be skipped in v1.15.0. Bump thresholds with ~100 MB headroom for
routine apt-get upgrade drift.

No image-side changes — pure smoke threshold update. v1.15.0b will hit
the base hash cache and run only the variant deltas.
2026-05-15 10:35:08 +02:00
joakimp 910378fe06 v1.15.0: opencode bump + git clone retry + pi-devbox sibling mention
Validate / docs-check (push) Successful in 11s
Validate / base-change-warning (push) Successful in 56s
Publish Docker Image / base-decide (push) Successful in 17s
Publish Docker Image / build-base (push) Has been skipped
Validate / validate-base (push) Successful in 3m23s
Publish Docker Image / smoke-base (push) Successful in 3m34s
Validate / validate-omos (push) Successful in 6m52s
Publish Docker Image / smoke-with-pi (push) Successful in 4m10s
Publish Docker Image / smoke-omos-with-pi (push) Successful in 4m58s
Validate / validate-omos-with-pi (push) Failing after 10m27s
Validate / validate-with-pi (push) Failing after 10m38s
Publish Docker Image / smoke-omos (push) Failing after 9m35s
Publish Docker Image / build-variant-omos (push) Has been skipped
Publish Docker Image / build-variant-base (push) Successful in 15m36s
Publish Docker Image / build-variant-with-pi (push) Successful in 16m52s
Publish Docker Image / build-variant-omos-with-pi (push) Successful in 22m5s
Publish Docker Image / promote-base-latest (push) Has been skipped
Publish Docker Image / update-description (push) Has been skipped
- Bump OPENCODE_VERSION 1.14.50 -> 1.15.0 in Dockerfile.variant.
- Wrap pi-toolkit/pi-extensions git clone in Dockerfile.variant in a
  5-attempt retry loop with linear backoff (matches pi-devbox pattern).
  gitea.jordbo.se occasionally returns transient HTTP 500s that
  previously broke with-pi/omos-with-pi variant builds.
- Add 'Sibling images' section to DOCKER_HUB.md mentioning
  joakimp/pi-devbox as the pi-only counterpart.
- CHANGELOG entry for v1.15.0 with full notes.
2026-05-15 09:56:01 +02:00
joakimp f06a70a3bc v1.14.50c: tag-only retag to recover v1.14.50b's missing variants
Publish Docker Image / base-decide (push) Successful in 1m12s
Publish Docker Image / build-base (push) Has been skipped
Publish Docker Image / smoke-omos (push) Successful in 4m39s
Publish Docker Image / smoke-with-pi (push) Successful in 7m22s
Publish Docker Image / smoke-base (push) Successful in 8m1s
Publish Docker Image / smoke-omos-with-pi (push) Successful in 10m56s
Publish Docker Image / build-variant-omos (push) Failing after 12m49s
Publish Docker Image / build-variant-with-pi (push) Successful in 17m0s
Publish Docker Image / build-variant-base (push) Successful in 17m33s
Publish Docker Image / build-variant-omos-with-pi (push) Successful in 26m46s
Publish Docker Image / promote-base-latest (push) Has been skipped
Publish Docker Image / update-description (push) Has been skipped
CHANGELOG entry for v1.14.50c with full postmortem on the v1.14.50/50b
runner-fleet incident (AVX shadowing + containerd race + Proxmox CPU
default + base-latest auto-promote gap). No container-side code changes
\u2014 the rebuild on the now-healthy fleet is sufficient.
2026-05-14 23:32:46 +02:00
joakimp 8359fef949 Force fresh base rebuild for v1.14.50b
Validate / validate-base (push) Failing after 17s
Validate / docs-check (push) Successful in 20s
Publish Docker Image / base-decide (push) Successful in 13s
Validate / validate-with-pi (push) Failing after 2m57s
Validate / validate-omos (push) Failing after 9m29s
Validate / validate-omos-with-pi (push) Failing after 14m25s
Publish Docker Image / build-base (push) Successful in 13m58s
Publish Docker Image / smoke-omos-with-pi (push) Failing after 27s
Publish Docker Image / build-variant-omos-with-pi (push) Has been skipped
Publish Docker Image / smoke-omos (push) Failing after 1m51s
Publish Docker Image / build-variant-omos (push) Has been skipped
Publish Docker Image / smoke-base (push) Successful in 9m1s
Publish Docker Image / smoke-with-pi (push) Successful in 11m52s
Publish Docker Image / build-variant-base (push) Successful in 17m50s
Publish Docker Image / build-variant-with-pi (push) Failing after 16m10s
Publish Docker Image / promote-base-latest (push) Has been skipped
Publish Docker Image / update-description (push) Has been skipped
Add BASE_REBUILD_DATE comment to Dockerfile.base to invalidate the
content hash and trigger a full base rebuild. Picks up ~5 days of
Debian trixie security updates since the previous base-bf9df274db7a
was built on 2026-05-09.

The comment also documents the pattern for future intentional
base-rebuilds without other code changes — recommended cadence is
once per release for security currency.

Required because v1.14.50 hash inputs were unchanged from v1.14.44,
hitting the existing base-bf9df274db7a cache and shipping stale apt
packages. v1.14.50 also failed mid-flight before promote-base-latest
could publish base-latest to Hub — pi-devbox and other downstream
images that FROM base-latest were blocked.
2026-05-14 20:17:37 +02:00
joakimp 07e07ec611 Bump opencode 1.14.44 -> 1.14.50; cut over to split-base pipeline
Validate / validate-omos-with-pi (push) Waiting to run
Validate / docs-check (push) Successful in 1m7s
Validate / validate-with-pi (push) Failing after 3m16s
Validate / validate-omos (push) Failing after 3m15s
Validate / validate-base (push) Failing after 6m31s
Publish Docker Image / base-decide (push) Failing after 11m59s
Publish Docker Image / build-base (push) Has been cancelled
Publish Docker Image / smoke-base (push) Has been cancelled
Publish Docker Image / smoke-omos (push) Has been cancelled
Publish Docker Image / smoke-with-pi (push) Has been cancelled
Publish Docker Image / smoke-omos-with-pi (push) Has been cancelled
Publish Docker Image / build-variant-base (push) Has been cancelled
Publish Docker Image / build-variant-omos (push) Has been cancelled
Publish Docker Image / build-variant-with-pi (push) Has been cancelled
Publish Docker Image / build-variant-omos-with-pi (push) Has been cancelled
Publish Docker Image / promote-base-latest (push) Has been cancelled
Publish Docker Image / update-description (push) Has been cancelled
- Bump OPENCODE_VERSION 1.14.44 -> 1.14.50 in Dockerfile.variant
- Cut over: docker-publish-split.yml now triggers on push: tags: v*
  (was workflow_dispatch only). RELEASE_TAG and PROMOTE_LATEST derived
  from github.ref_type/ref_name for tag-push; inputs still available
  for manual workflow_dispatch runs.
- Delete docker-publish.yml (retired, replaced by split-base pipeline)
- Delete Dockerfile (retired, replaced by Dockerfile.base + Dockerfile.variant)
- Update CHANGELOG: promote Unreleased -> v1.14.50
- Update AGENTS.md, .gitea/README.md, validate.yml: remove all references
  to the old single-Dockerfile pipeline and WIP migration plan
2026-05-14 19:39:45 +02:00
joakimp a3ff601bf0 Bump opencode 1.14.42 -> 1.14.44; close v1.14.42 omos-with-pi gap
Validate / docs-check (push) Successful in 18s
Validate / validate-base (push) Successful in 11m46s
Validate / validate-omos (push) Successful in 13m32s
Validate / validate-with-pi (push) Successful in 13m20s
Validate / validate-omos-with-pi (push) Successful in 19m23s
Publish Docker Image / smoke-base (push) Successful in 11m46s
Publish Docker Image / smoke-omos (push) Successful in 13m45s
Publish Docker Image / smoke-with-pi (push) Successful in 13m13s
Publish Docker Image / smoke-omos-with-pi (push) Successful in 15m47s
Publish Docker Image / build-base (push) Successful in 42m18s
Publish Docker Image / build-omos (push) Successful in 52m1s
Publish Docker Image / build-with-pi (push) Successful in 46m28s
Publish Docker Image / build-omos-with-pi (push) Successful in 54m36s
Publish Docker Image / update-description (push) Successful in 14s
opencode-ai 1.14.44 published 20:26 UTC (1.14.43 skipped upstream).
Bumping to 1.14.44 instead of re-running the failed v1.14.42 build
gives us the same 3h CI cost and picks up upstream bug fixes.

Closes the v1.14.42 omos-with-pi gap. The v1.14.42 tag's
build-omos-with-pi job failed during publish: oh-my-opencode-slim@1.0.7
had been published with a dependency on @opencode-ai/sdk@1.14.44, and
our build hit the npm registry within ~2 minutes of that SDK version
landing -- before the tarball had propagated across npm's CDN. The
manifest's dist-tags.latest pointed at 1.14.44 but a tarball fetch on
/-/sdk-1.14.44.tgz returned 404. Tarball is now fully fetchable.

Result on Docker Hub once v1.14.44 publishes:
  v1.14.42 / latest                        -> stable (3 of 4 variants)
  v1.14.42-omos / latest-omos              -> stable
  v1.14.42-with-pi / latest-with-pi        -> stable
  v1.14.42-omos-with-pi                    -> NEVER PUBLISHED (404 if pulled)
  latest-omos-with-pi                      -> still v1.14.41b until v1.14.44
  v1.14.44 / latest                        -> NEW (replaces latest)
  v1.14.44-omos / latest-omos              -> NEW
  v1.14.44-with-pi / latest-with-pi        -> NEW
  v1.14.44-omos-with-pi / latest-omos-with-pi -> NEW (closes the gap)

CHANGELOG: v1.14.44 entry added with the propagation-race rationale,
v1.14.42 entry annotated with the known gap. Reverse-chrono preserved.
2026-05-09 22:33:16 +02:00
joakimp 6fde27c212 Document the build pipeline architecture in .gitea/README.md
Validate / docs-check (push) Successful in 16s
Validate / validate-base (push) Successful in 12m9s
Validate / validate-omos (push) Successful in 16m45s
Validate / validate-with-pi (push) Successful in 13m30s
Validate / validate-omos-with-pi (push) Successful in 15m15s
The split-base build architecture, the NPM_CONFIG_PREFIX gotcha, the
hash-driven base cache reuse mechanism, and the cutover plan from
docker-publish.yml to docker-publish-split.yml were previously
scattered across:
  - inline Dockerfile.base / Dockerfile.variant comments
  - CHANGELOG Unreleased entries
  - AGENTS.md mentions
  - docker-publish-split.yml header comment
  - my own session notes

Consolidate into .gitea/README.md as the canonical architectural doc.
Gitea (like GitHub) auto-renders this when navigating to .gitea/ in
the web UI, so anyone investigating 'why is CI shaped this way?'
finds it on the first click. Cross-referenced from AGENTS.md as the
first thing to read when touching CI.

Covers:
  - The two release pipelines and why both exist
  - Why split-base: cross-variant cache misses on layer-hash-divergence
  - The 6 phases of the split-base pipeline with an ASCII diagram
  - base-decide hash inputs and Docker Hub probe logic
  - NPM_CONFIG_PREFIX variant-override pattern (the volume-shadow trap)
  - Registry cache strategy (mode=max for cross-arch reuse)
  - Wall-clock estimates: version-bump vs base-touching releases
  - Validate workflow role
  - Runner expectations: catthehacker image, disk reclaim, concurrency,
    Gitea Actions @v4 artifact incompatibility
  - 4-step migration plan from docker-publish.yml to .split.yml
  - Cross-refs to related docs

Does not duplicate AGENTS.md content; links to it for domain facts and
release-day checklist.
2026-05-09 19:28:03 +02:00
joakimp b30ffc83bd Bump opencode 1.14.41 -> 1.14.42
Validate / docs-check (push) Successful in 17s
Validate / validate-base (push) Has started running
Validate / validate-omos (push) Has been cancelled
Validate / validate-with-pi (push) Has been cancelled
Validate / validate-omos-with-pi (push) Has been cancelled
Publish Docker Image / smoke-base (push) Successful in 12m41s
Publish Docker Image / smoke-omos (push) Successful in 13m0s
Publish Docker Image / smoke-with-pi (push) Successful in 14m23s
Publish Docker Image / smoke-omos-with-pi (push) Successful in 15m48s
Publish Docker Image / build-base (push) Successful in 44m25s
Publish Docker Image / build-omos (push) Successful in 53m33s
Publish Docker Image / build-omos-with-pi (push) Failing after 17m9s
Publish Docker Image / build-with-pi (push) Successful in 46m17s
Publish Docker Image / update-description (push) Has been skipped
opencode-ai 1.14.42 was released; bump OPENCODE_VERSION default in
Dockerfile and Dockerfile.variant. Container changes accumulated since
v1.14.41b ride along with this tagged release: pi package rename to
@earendil-works/*, npm-prefix-on-volume fix, smoke-test query fix, Hub
doc rewrite, README/AGENTS docs catchup.

CHANGELOG promoted: Unreleased -> v1.14.42 (2026-05-09). The
split-base build pipeline note stays under a fresh Unreleased \u2014 it's
merged to main but not yet validated end-to-end via dispatch test, so
it does not ship with v1.14.42 (the production docker-publish.yml on
tag push is still authoritative).

Release contents:
- Bump: opencode 1.14.41 -> 1.14.42
- Rename: @mariozechner/pi-coding-agent -> @earendil-works/pi-coding-agent
- Fix: NPM_CONFIG_PREFIX on volume so 'pi install npm:<pkg>' as
  developer survives container recreate AND image rebuild
- Fix: smoke-test queries /usr prefix for npm ls -g check
- Docs: Hub doc rewrite (24997 -> 5529 bytes), README pi section
  catchup (6 -> 7 extensions, mcp-loader documented), AGENTS
  release-day checklist updates
2026-05-09 19:17:10 +02:00
joakimp 896380bb9c Rename @mariozechner/pi-coding-agent to @earendil-works/pi-coding-agent
Validate / docs-check (push) Successful in 16s
Validate / validate-base (push) Successful in 12m25s
Validate / validate-omos (push) Successful in 16m40s
Validate / validate-with-pi (push) Successful in 14m0s
Validate / validate-omos-with-pi (push) Successful in 18m18s
Pi moved to its new home at earendil-works on 2026-05-07
(https://pi.dev/news/2026/5/7/pi-has-a-new-home).

The old @mariozechner/pi-coding-agent npm package is deprecated with
the explicit message 'please use @earendil-works/pi-coding-agent
instead going forward', and the version stream has moved on (old
top-out 0.73.1; new currently 0.74.0). Anyone npm-installing the old
name today gets a deprecation warning + a stale binary, so this is
a non-optional migration before the next tagged release.

Sweep:
- Dockerfile (production single-Dockerfile path) and Dockerfile.variant
  (split-base path on main): npm install -g target updated.
- README, AGENTS, HUB_TEMPLATE: github.com/mariozechner/pi-coding-agent
  URL refs (which now 404) -> github.com/earendil-works/pi.
- DOCKER_HUB.md regenerated (5529 bytes, ~78% headroom).
- CHANGELOG Unreleased: rename entry added with migration context.

Brew install references (`brew install pi-coding-agent`) left as-is:
formula still works at 0.73.1 and a homebrew tap update is tracked
upstream at earendil-works/pi#2755.

Historical CHANGELOG entries: only github URL refs updated (the
package name was never spelled out in those entries; we're correcting
dead hyperlinks, not rewriting feature descriptions).
2026-05-09 17:58:07 +02:00
joakimp 4c27e6fd8a feat: split-base build pipeline (parallel, manual-trigger only)
Validate / docs-check (push) Successful in 15s
Validate / validate-base (push) Successful in 12m13s
Validate / validate-omos (push) Failing after 15m48s
Validate / validate-with-pi (push) Successful in 13m43s
Validate / validate-omos-with-pi (push) Has been cancelled
Two-Dockerfile split-base build alongside the existing single-Dockerfile
pipeline. Goal: cut CI wall clock from ~165-180min to ~30-40min on
typical version-bump-only releases by reusing a base image across the
four variants.

Files added:
- Dockerfile.base       variant-independent layers (apt, locales, AWS
                        CLI, Node.js, mempalace, gitea-mcp, user setup,
                        chromadb prewarm, ENVs, entrypoints).
- Dockerfile.variant    FROMs ${BASE_IMAGE} and adds opencode / pi /
                        omos / Go installs gated by INSTALL_* args.
                        Each npm install -g uses NPM_CONFIG_PREFIX=/usr
                        per-RUN to keep baked binaries off the volume-
                        shadowed ~/.pi/npm-global path inherited from
                        base.
- .gitea/workflows/docker-publish-split.yml
                        workflow_dispatch-only pipeline:
                        base-decide -> build-base (conditional) ->
                        smoke-* (4 parallel) -> build-variant-*
                        (4 parallel) -> promote-base-latest ->
                        update-description. Hash-driven base reuse:
                        if base-<sha> already exists on Docker Hub,
                        the build is skipped entirely. Inputs:
                        release_tag (test tag suffix, default
                        v0.0.0-split-test) and promote_latest
                        (default false; gates latest-* aliases and
                        Hub description update).

Files unchanged:
- Dockerfile, docker-publish.yml, validate.yml all left in place so
  the production tag-push pipeline keeps working untouched.

Migration plan (in CHANGELOG Unreleased):
1. workflow_dispatch test run with promote_latest=false; verify the
   four variant images smoke-pass and have plausible sizes.
2. Compare manifest digests against the same-version output from the
   production pipeline (independent test run on the same commit).
3. Once verified across 1-2 release cycles, swap docker-publish-split.yml
   to on: push: tags: v* and retire docker-publish.yml.

AGENTS.md and CHANGELOG.md updated with file roles and the migration
plan. Production pipeline behavior is bit-for-bit unchanged on this
branch.
2026-05-09 16:16:25 +02:00
joakimp b5da6a5cf8 README: pi 'What gets installed' section catchup
Was stale:
- Claimed 6 pi-extensions (actually 7 — mcp-loader was added in
  pi-extensions 141bf64 / 7eec49b / 37cc49e but the count was never
  propagated here).
- No mention of mcp-loader's dual-transport (local stdio + remote
  streamable-HTTP per MCP spec 2025-03-26) or the /mcp slash command.
- Mempalace bridge bullet didn't note that it coexists with mcp-loader
  rather than being replaced by it (don't list mempalace in mcp block).
- No explicit 'no MCP servers baked in' line, leaving readers to
  guess whether searxng/context7 ship by default.

Each extension now gets a one-line description; mcp-loader gets a
paragraph covering its capabilities and a link to the pi-extensions
AGENTS for transport detail. Added an opt-in note for MCP servers.
2026-05-09 15:54:48 +02:00
joakimp f86c4b18cf Rewrite DOCKER_HUB.md as a hand-maintained slim template
Validate / docs-check (push) Successful in 16s
Validate / validate-base (push) Successful in 11m16s
Validate / validate-omos (push) Failing after 18m33s
Validate / validate-with-pi (push) Successful in 13m46s
Validate / validate-omos-with-pi (push) Failing after 19m52s
The previous derive-from-README mechanism (split_sections, SECTION_RULES,
TRIM_SUBSECTIONS, REPLACEMENTS) generated a 24 997 byte Hub doc with
3 byte headroom against the 25 kB Hub limit. Every README addition
forced a 'trim something else first' exercise, and the resulting copy
was awkward (terse, repetitive linkbacks injected mid-section).

Replace with a single hand-maintained HUB_TEMPLATE constant. The Hub
doc is now intentionally slim (~5.5 kB, ~78 percent headroom) and
focuses on what Hub readers actually need: elevator pitch, image
variants, quick start, what's inside, auth, persistence, and link-outs
to the gitea README for depth.

Trade-off: when image-variants or quick-start change, update
HUB_TEMPLATE here too. That coupling is now explicit and local rather
than spread across SECTION_RULES + REPLACEMENTS + TRIM machinery,
and most README edits no longer require regenerating DOCKER_HUB.md
at all.

Generator simplified from 323 lines to 199 lines (270-line net
reduction across the script + DOCKER_HUB.md). README and Hub doc are
now independent surfaces.

CHANGELOG and AGENTS updated to reflect the new coupling. Release-day
checklist tightened: README -> regenerate DOCKER_HUB ONLY if
HUB_TEMPLATE changed -> promote CHANGELOG -> grep AGENTS -> commit
-> tag.
2026-05-09 15:49:43 +02:00
joakimp 9df126c7a9 Fix: developer-writable npm prefix for pi install
Validate / docs-check (push) Successful in 23s
Validate / validate-base (push) Has started running
Validate / validate-omos (push) Has started running
Validate / validate-with-pi (push) Has been cancelled
Validate / validate-omos-with-pi (push) Has been cancelled
NPM_CONFIG_PREFIX is now /home/developer/.pi/npm-global, with that
prefix's bin/ prepended to PATH. Without this, 'pi install npm:<pkg>'
(and any 'npm install -g') by the developer user would EACCES against
the system prefix (/usr).

The new prefix lives on the devbox-pi-config named volume, so:
  - User-installed pi packages (themes, skills, extensions) survive
    container recreate AND image rebuild, complementing pi's auto-
    restore from settings.json with one less cold-start step.
  - A user-driven 'npm install -g @mariozechner/pi-coding-agent' lands
    on the volume and wins over the baked pi via PATH order.

Build-time 'npm install -g' calls (opencode, pi, oh-my-opencode-slim)
are unaffected: the new ENVs are declared after those steps in the
Dockerfile, so the baked binaries still install to /usr at build time
and are not shadowed by the volume mount at runtime.

Verified end-to-end with a Bun-driven smoke test: as developer,
'npm install -g cowsay' inside the container succeeds, the binary
lands on PATH, and survives a fresh container against the same volume.

DOCKER_HUB.md regenerated (24997/25000 bytes, 3-byte headroom — was
138 before; future README additions to the persistence section need
to trim something else first).

Docs updated: Dockerfile inline comments, README persistence section,
AGENTS install contract, DOCKER_HUB persistence table, .env.example
notes, CHANGELOG Unreleased entry.
2026-05-09 15:41:33 +02:00
joakimp cc98722d84 docs: catch up CHANGELOG and AGENTS.md with v1.14.41b reality
Validate / docs-check (push) Has been cancelled
Validate / validate-base (push) Has been cancelled
Validate / validate-omos (push) Has been cancelled
Validate / validate-with-pi (push) Has been cancelled
Validate / validate-omos-with-pi (push) Has been cancelled
CHANGELOG drift:
- 'Unreleased' still claimed 'Will become v1.14.41b on release' even
  though the tag was cut and shipped today. Promoted to a proper
  '## v1.14.41b — 2026-05-08' release header (re-ordered above v1.14.41
  to keep reverse-chronological invariant).
- New 'Unreleased' entry records today's docs-only updates (commits
  8083cd1, d01cff3, this commit) which were patched to Docker Hub via
  the API rather than re-tagging.

AGENTS.md drift introduced by the v1.14.41b CI matrix expansion:
- 'CI produces four Docker Hub tags per release' → eight (one tag pair
  per build variant: base, omos, with-pi, omos-with-pi).
- 'all four `load: true` jobs (validate-base, validate-omos, smoke-base,
  smoke-omos)' → all eight (added validate-with-pi, validate-omos-with-pi,
  smoke-with-pi, smoke-omos-with-pi).

DOCKER_HUB.md unchanged (already in sync, regenerator confirms).
2026-05-08 21:32:11 +02:00
joakimp bf811f2170 Merge main (v1.14.41 bump) into feat/install-pi
# Conflicts:
#	CHANGELOG.md
2026-05-08 13:46:03 +02:00
joakimp c76b1e8aa3 Bump opencode to 1.14.41
Validate / docs-check (push) Successful in 1m4s
Validate / validate-base (push) Successful in 13m20s
Validate / validate-omos (push) Successful in 24m0s
Publish Docker Image / smoke-base (push) Successful in 12m13s
Publish Docker Image / smoke-omos (push) Successful in 16m34s
Publish Docker Image / build-base (push) Successful in 39m22s
Publish Docker Image / build-omos (push) Successful in 51m43s
Publish Docker Image / update-description (push) Successful in 14s
Restored formatter output handling for stdout/stderr-writing formatters;
warping a session to another workspace can now carry over uncommitted
file changes; restored custom provider setup in /connect; macOS Settings
menu entry; desktop local server split into a separate utility process;
ACP clients restore last model/mode/effort when loading sessions and can
close sessions cleanly.

No container-level changes.
2026-05-08 13:08:50 +02:00
joakimp 5006b01170 Pre-warm chromadb embedding model at build time
Mempalace's embedding function is chromadb's ONNXMiniLM_L6_V2, which
downloads ~80 MB of all-MiniLM-L6-v2 ONNX weights from chromadb's CDN
on first use. Without pre-warming this happened silently in the
entrypoint init step (output redirected to /dev/null) and stalled
first container start by multiple minutes on slow networks — the
symptom user reported as 'hangs at Initializing MemPalace for
workspace'.

Fix: invoke the embedding function once at build time as gosu
developer so the cache lands at the runtime user's
~/.cache/chroma/onnx_models/all-MiniLM-L6-v2/ with correct ownership
and survives container recreate (cache path is not on a named
volume, so it lives in the image layer).

Build-time cost: ~3-5 s to download. Runtime saving: minutes per
fresh container.

Image size: 2110 → 2277 MB for the with-pi variant. Still within
the 2700 MB smoke-test threshold.
2026-05-08 00:25:22 +02:00
joakimp f51e9f52a1 Add INSTALL_PI build arg for pi as second harness
Optional integration of pi-coding-agent alongside opencode in the same
container. Both harnesses share the mempalace install and palace path —
wing/diary entries are mutually visible.

Build:
  --build-arg INSTALL_PI=true              # opt-in
  --build-arg PI_VERSION=0.73.1            # pin a version (default: latest)
  --build-arg INSTALL_OPENCODE=false       # build pi-only image

Dockerfile:
  • New INSTALL_PI block: npm install -g @mariozechner/pi-coding-agent
    + git-clones pi-toolkit and pi-extensions to /opt/.
  • Existing opencode install gated behind new INSTALL_OPENCODE arg
    (default true; existing builds unaffected).
  • mkdir adds ~/.pi/agent/extensions for the named volume mount root.
  • CMD changed from ['opencode'] to ['bash', '-l']. compose run --rm
    devbox now drops to a login shell so users pick the harness; pass
    'opencode' or 'pi' explicitly to launch directly. compose exec
    workflows are unaffected (bypass entrypoint+CMD).

entrypoint.sh:
  • Adds ~/.pi to volume ownership loop.

entrypoint-user.sh:
  • New 'pi: deploy toolkit + extensions + mempalace bridge' block runs
    pi-toolkit/install.sh, pi-extensions/install.sh, settings.json
    template bootstrap, then symlinks the mempalace.ts bridge directly.
    Order: toolkit before extensions before bridge. mempalace-toolkit's
    full install.sh is intentionally NOT called (its install_skill
    would race with skillset auto-deploy --prune-stale).

docker-compose.yml:
  • New devbox-pi-config named volume mounted at /home/developer/.pi.
    Persists user toggles (/ext-disabled extensions) and settings.json
    edits across container recreate. Mirrors devbox-opencode-config
    pattern from v1.14.33.

scripts/smoke-test.sh:
  • New --variant with-pi (threshold 2700 MB) and --variant omos-with-pi
    (3400 MB).
  • Pi assertions gated on `command -v pi`: version, /opt/pi-toolkit
    clone HEAD, /opt/pi-extensions clone HEAD, deployed keybindings
    symlink, ≥4 extension symlinks, mempalace.ts bridge symlink,
    settings.json bootstrap.
  • Pi state assertions use docker exec from the host (not 'run'),
    since the container has no docker CLI.
  • opencode core test now gated on INSTALL_OPENCODE presence.

scripts/generate-dockerhub-md.py:
  • SECTION_RULES adds 'pi (alternative/complementary harness)': drop.
    Section stays in README; dropped from DOCKER_HUB.md to keep under
    the 25 kB Docker Hub limit.

Docs:
  • README adds full 'pi (alternative/complementary harness)' section.
  • AGENTS.md codifies pi install contract, deploy ordering, named
    volume rationale, and CMD change.
  • CHANGELOG.md gets an Unreleased entry.
  • .env.example documents new build args.
  • docker-compose.yml example args block updated.

Verification (local builds on arm64):
  • Default (INSTALL_PI=false): 1871 MB, all assertions pass — no
    regression.
  • INSTALL_PI=true: 2110 MB (within 2700 threshold), 37 assertions
    pass including pi version, all 7 extensions deployed (6 from
    pi-extensions + mempalace.ts bridge), settings.json bootstrap.

Not yet:
  • CI workflow updates to add -with-pi tag variants. Deferred until
    local path stabilizes through user testing.
  • pi-devbox separate repo for fully stripped pi-only image. Phase 2.
2026-05-07 23:58:37 +02:00
joakimp a208b073b0 Bump opencode to 1.14.40
Validate / docs-check (push) Successful in 1m5s
Validate / validate-base (push) Successful in 16m54s
Validate / validate-omos (push) Successful in 21m36s
Publish Docker Image / smoke-base (push) Successful in 11m17s
Publish Docker Image / smoke-omos (push) Successful in 14m52s
Publish Docker Image / build-base (push) Successful in 39m10s
Publish Docker Image / build-omos (push) Successful in 52m16s
Publish Docker Image / update-description (push) Successful in 14s
Rolls up upstream v1.14.34 through v1.14.40 (no v1.14.36 was published).
Highlights: .well-known/opencode remote config support; HTTP_PROXY honored
in desktop app; CORS/CSP fixes; warp-session-to-workspace feature; PTY
auth tickets; v2 session failure events; debug info CLI command. No
container-level changes.
2026-05-07 10:52:50 +02:00
joakimp 79b697dea0 Bump opencode to 1.14.33
Validate / docs-check (push) Successful in 1m16s
Validate / validate-base (push) Has started running
Validate / validate-omos (push) Has started running
Publish Docker Image / smoke-base (push) Has been cancelled
Publish Docker Image / smoke-omos (push) Has been cancelled
Publish Docker Image / build-base (push) Has been cancelled
Publish Docker Image / build-omos (push) Has been cancelled
Publish Docker Image / update-description (push) Has been cancelled
2026-05-03 10:31:17 +02:00
Joakim Persson 3e3abc8672 Update docs for named volume config, skillset auto-deploy, opencode.jsonc
Validate / docs-check (push) Successful in 15s
Validate / validate-base (push) Failing after 10m35s
Validate / validate-omos (push) Failing after 13m15s
- README: rewrite config/skills sections for named volume and auto-deploy,
  add Context7 MCP docs, update all opencode.json→opencode.jsonc refs,
  add SKILLSET_CONTAINER_PATH to env var table
- CHANGELOG: add v1.14.32b entry documenting breaking changes and features
- AGENTS.md: update file roles, add skillset and config volume conventions
- DOCKER_HUB.md: regenerated (drop Context7 and Shell defaults sections
  to stay within 25KB Docker Hub limit)
- generate-dockerhub-md.py: add Context7 (drop) and Shell defaults (drop)
  to SECTION_RULES
2026-05-02 23:00:41 +00:00
joakimp a6b0b59946 Bump opencode to 1.14.32
Validate / docs-check (push) Successful in 22s
Validate / validate-omos (push) Successful in 15m3s
Validate / validate-base (push) Successful in 16m13s
Publish Docker Image / smoke-base (push) Successful in 11m53s
Publish Docker Image / smoke-omos (push) Successful in 13m33s
Publish Docker Image / build-base (push) Successful in 42m37s
Publish Docker Image / build-omos (push) Successful in 47m20s
Publish Docker Image / update-description (push) Successful in 14s
2026-05-02 18:04:00 +02:00
Joakim Persson fc74a8f906 Collapse per-arch matrix back into single multi-arch push jobs
Validate / docs-check (push) Successful in 17s
Validate / validate-omos (push) Successful in 14m21s
Validate / validate-base (push) Successful in 14m50s
Publish Docker Image / smoke-base (push) Successful in 11m12s
Publish Docker Image / smoke-omos (push) Successful in 22m0s
Publish Docker Image / build-base (push) Successful in 42m25s
Publish Docker Image / build-omos (push) Failing after 1h16m24s
Publish Docker Image / update-description (push) Has been cancelled
v1.14.31c's matrix jobs failed on Upload digest with GHESNotSupportedError
— Gitea Actions doesn't support actions/upload-artifact@v4+.
Separately, build-omos arm64 hung silently for 12 min in Set-up job,
likely catthehacker pull contention between concurrent matrix children.

Rather than downgrade artifacts to @v3, collapse the matrix entirely.
docker/build-push-action@v7 with platforms: linux/amd64,linux/arm64
publishes a proper multi-arch manifest in one job, so the
artifact-passing and imagetools create merge dance only existed to
support a matrix split we no longer need.

The matrix was designed around load: true disk exhaustion (v1.14.30b),
but push-by-digest streams straight to the registry with fundamentally
different disk profile. Reclaim step gives enough headroom for the
combined amd64+arm64 push case.

Workflow: 7 jobs → 5. docker-publish.yml: 263 → ~110 lines of YAML.

Also:
- timeout-minutes: 90 on build jobs so hung builds fail explicitly
- BUILDKIT_PROGRESS=plain at workflow level for line-by-line arm64 logs
- AGENTS.md §CI quirks documents the Gitea-specific traps
  (upload-artifact@v3-only, dash-not-bash, build-push-action@v7
  multi-arch convention, reclaim requirement)
2026-05-01 12:28:34 +00:00
Joakim Persson 5a2d06340e Fix dash-incompatible slash substitution and bump omos size threshold
Validate / docs-check (push) Successful in 18s
Validate / validate-base (push) Successful in 15m44s
Validate / validate-omos (push) Successful in 15m21s
Publish Docker Image / smoke-base (push) Successful in 14m30s
Publish Docker Image / smoke-omos (push) Successful in 15m51s
Publish Docker Image / build-base (linux/amd64) (push) Failing after 10m58s
Publish Docker Image / build-omos (linux/amd64) (push) Failing after 15m9s
Publish Docker Image / build-omos (linux/arm64) (push) Failing after 11m57s
Publish Docker Image / build-base (linux/arm64) (push) Failing after 39m30s
Publish Docker Image / merge-base (push) Has been skipped
Publish Docker Image / merge-omos (push) Has been skipped
Publish Docker Image / update-description (push) Has been skipped
v1.14.31b made it through smoke-base and validate-base (reclaim worked),
but two narrow bugs blocked the rest:

1. 'Derive platform slug' in the per-arch matrix jobs used bash
   ${PLATFORM_PAIR//\//-} which dash (/bin/sh in the runner) can't
   parse — 'Bad substitution'. Rewrote with 'tr / -'.

2. smoke-omos image size 3107 MB tripped the 3000 MB guardrail. All
   functional checks pass; the mempalace-toolkit bake-in from v1.14.30b
   added ~100 MB and the threshold was stale. Bumped to 3200 MB.

No image-level changes.
2026-05-01 10:43:04 +00:00
Joakim Persson 23894bc19f Reclaim runner disk before load: true smoke builds
Validate / docs-check (push) Successful in 22s
Validate / validate-base (push) Successful in 18m10s
Validate / validate-omos (push) Failing after 25m54s
Publish Docker Image / smoke-base (push) Successful in 11m50s
Publish Docker Image / build-base (linux/amd64) (push) Failing after 38s
Publish Docker Image / build-base (linux/arm64) (push) Failing after 21s
Publish Docker Image / merge-base (push) Has been skipped
Publish Docker Image / smoke-omos (push) Failing after 19m18s
Publish Docker Image / build-omos (linux/amd64) (push) Has been skipped
Publish Docker Image / build-omos (linux/arm64) (push) Has been skipped
Publish Docker Image / merge-omos (push) Has been skipped
Publish Docker Image / update-description (push) Has been skipped
v1.14.31 publish and validate both hit 'No space left on device' on
single-arch amd64 smoke/validate builds. The image has crossed ~3 GB
and the runner's ~40 GB overlay starts ~70% full, so 'load: true'
peak disk (tarball + unpacked image + buildx cache) no longer fits.

Add a 'Reclaim runner disk' step to validate-base, validate-omos,
smoke-base, smoke-omos. Strips catthehacker-resident toolchains we
never use (hosted-tool-cache, dotnet, android, powershell, swift,
ghc, jvm, microsoft, chromium, boost), then runs 'docker system
prune -af --volumes' + 'docker builder prune -af' against the
runner's dockerd before setup-buildx-action. Expected reclaim is
6-12 GB depending on what's resident.

Deliberately NOT in the per-arch matrix build jobs — push-by-digest
doesn't need it and pruning in parallel jobs risks one job nuking
another's in-flight buildx cache. Also add workflow-level
concurrency on docker-publish.yml so concurrent tag pushes serialize
cleanly.
2026-05-01 09:34:52 +00:00
Joakim Persson f0918ba915 Bump opencode to 1.14.31 and split multi-arch publish across runners
Validate / docs-check (push) Successful in 26s
Publish Docker Image / smoke-base (push) Failing after 11m1s
Publish Docker Image / build-base (linux/amd64) (push) Has been skipped
Publish Docker Image / build-base (linux/arm64) (push) Has been skipped
Publish Docker Image / merge-base (push) Has been skipped
Validate / validate-base (push) Failing after 13m48s
Validate / validate-omos (push) Failing after 15m23s
Publish Docker Image / smoke-omos (push) Failing after 16m20s
Publish Docker Image / build-omos (linux/amd64) (push) Has been skipped
Publish Docker Image / build-omos (linux/arm64) (push) Has been skipped
Publish Docker Image / merge-omos (push) Has been skipped
Publish Docker Image / update-description (push) Has been skipped
The v1.14.30b publish failed on both variants with 'No space left on
device' — arm64 QEMU-emulated layers were stored alongside amd64 on the
same ~40 GB runner, and the mempalace-toolkit bake-in from v1.14.30b
tipped peak disk over the edge during the nodejs dpkg unpack and the
git-lfs layer export.

Refactor docker-publish.yml to the canonical push-by-digest +
manifest-merge pattern: smoke test (amd64) runs on its own runner, each
(variant x arch) push target runs on its own fresh runner with
outputs=type=image,push-by-digest=true,push=true (no local image
store), then a tiny merge job assembles the multi-arch manifest with
docker buildx imagetools create from digest artifacts. Per-runner disk
peak is roughly one-quarter of the old single-job peak. The four
Docker Hub tags per release are unchanged. As a bonus, amd64 and arm64
now build in parallel.

No image-level changes beyond the opencode bump.
2026-05-01 08:43:08 +00:00
Joakim Persson 1683650240 Bake mempalace-toolkit wrappers into the image
Validate / docs-check (push) Successful in 14s
Validate / validate-base (push) Successful in 14m44s
Validate / validate-omos (push) Successful in 17m51s
Publish Docker Image / build-omos (push) Failing after 25m7s
Publish Docker Image / build-base (push) Failing after 55m51s
Publish Docker Image / update-description (push) Has been skipped
The scheduler templates in mempalace-toolkit's contrib/ assume
mempalace-session is available inside the container, but the image
never actually installed it. Users following the *-devbox scheduler
docs would silently lose the wrappers on every container recreate,
because the only way to get them was a post-hoc install.sh inside
the container — which lives in the ephemeral layer. The host-side
systemd timer would then fire, docker exec in, and hit
"mempalace-session: command not found".

Caught during runtime validation on 2026-04-30: host-side systemd
unit ran cleanly at 16:15 today, then the container was rebuilt
and recreated, and the wrappers were gone. The rebuild produced
an image that the scheduler template's own documented precondition
did not hold for.

Fix: new Dockerfile block clones mempalace-toolkit at build time
(depth-1) to /opt/mempalace-toolkit/, symlinks bin/mempalace-session
and bin/mempalace-docs into /usr/local/bin/, asserts both respond
to --help before the layer succeeds. Gated by
INSTALL_MEMPALACE_TOOLKIT=true (defaults on, depends on
INSTALL_MEMPALACE=true). Floated ref via MEMPALACE_TOOLKIT_REF=main
for auto-picking-up toolkit updates; override for reproducible
builds once the toolkit starts tagging releases.

Smoke test gains three assertions (mempalace-session --help,
mempalace-docs --help, symlink target check). Resolved-versions
preamble logs the toolkit git short-SHA alongside the other
floated components, so CI logs always record what got baked in.

README gains a Scheduled mining (mempalace-toolkit) subsection
and a build-args row. DOCKER_HUB.md regenerated; sync-check passes.
2026-04-30 20:56:58 +00:00
joakimp 9d7c3e5ad8 Bump opencode to 1.14.30
Validate / docs-check (push) Successful in 1m51s
Validate / validate-base (push) Successful in 13m37s
Validate / validate-omos (push) Successful in 23m0s
Publish Docker Image / build-base (push) Successful in 54m42s
Publish Docker Image / build-omos (push) Successful in 1h25m20s
Publish Docker Image / update-description (push) Successful in 20s
2026-04-30 15:11:49 +02:00
joakimp 23bae2ab7d Use mempalace-mcp entry point directly, drop redundant wrapper
Validate / docs-check (push) Successful in 20s
Validate / validate-base (push) Successful in 11m32s
Validate / validate-omos (push) Successful in 15m18s
Publish Docker Image / build-base (push) Successful in 53m5s
Publish Docker Image / build-omos (push) Successful in 1h11m3s
Publish Docker Image / update-description (push) Successful in 15s
The mempalace Python package ships a 'mempalace-mcp' console entry
point; 'uv tool install' places it on PATH as a shim whose shebang
points at the isolated venv's Python. Our hand-rolled wrapper at
/usr/local/bin/mempalace-mcp-server was duplicating what uv installs
for free — one less file to maintain.

Fixes the MCP error users saw after the v1.14.28b → v1.14.29 upgrade
path: custom opencode.json files typically had the pre-v1.14.29
command ['python3', '-m', 'mempalace.mcp_server'] which worked with
the old pip install but fails silently after the uv-tool migration
because system python3 cannot import from the venv. Opencode surfaced
this as 'MCP error -32000: connection closed'.

- generate-config.py now emits ['mempalace-mcp'] and keys its detect
  on shutil.which('mempalace-mcp').
- Dockerfile drops 'COPY rootfs/usr/local/bin/' and the chmod of the
  wrapper. Build shrinks from 30 to 29 stages.
- rootfs/usr/local/bin/ removed entirely.
- Smoke test asserts /usr/local/bin/mempalace-mcp is executable and
  prints its symlink target.
- README's MemPalace section shows ['mempalace-mcp'] and explicitly
  warns against the old pattern with the observed failure mode.
- CHANGELOG adds a v1.14.29c entry.
2026-04-29 15:27:30 +02:00
joakimp e0b6c2082f Add apt-get upgrade to core packages layer
Validate / docs-check (push) Successful in 12s
Validate / validate-base (push) Successful in 12m18s
Validate / validate-omos (push) Successful in 17m2s
Publish Docker Image / build-base (push) Successful in 52m23s
Publish Docker Image / build-omos (push) Successful in 1h8m34s
Publish Docker Image / update-description (push) Successful in 17s
Pair 'apt-get upgrade -y --no-install-recommends' with the existing
update + install in the first RUN step. Picks up security/CVE fixes
that land in the Debian repos between base-image rebuilds. Same layer
as the install to avoid bloating history; combined with apt-get clean
and rm -rf /var/lib/apt/lists/* at the end so no index cache is kept.

Today this is a no-op (debian:trixie-slim is current: 0 upgraded).
Future-proofs against the lag between a CVE fix being published and
the next base-image rebuild.
2026-04-29 10:25:36 +02:00
joakimp 2c889b472e Add --retry to all Dockerfile curl invocations
Validate / docs-check (push) Successful in 18s
Validate / validate-omos (push) Has been cancelled
Validate / validate-base (push) Has been cancelled
Publish Docker Image / build-base (push) Has been cancelled
Publish Docker Image / build-omos (push) Has been cancelled
Publish Docker Image / update-description (push) Has been cancelled
The first v1.14.29b build attempt failed with an HTTP 502 from
GitHub's release CDN mid-download of zoxide. Single-shot curl had no
retry, so one transient 502 failed the entire OMOS build.

- curl --retry 5 --retry-delay 5 --retry-all-errors on every tool
  download (both -fsSL GETs and -sI HEAD redirect lookups).
- [ -n "$V" ] assertion after each version-resolution step, so a
  failed HEAD lookup fails fast with a clear message instead of
  producing an empty tag that then 404s on the download URL.
- Same hardening applied to the optional Go install block and the
  nodesource setup_22.x pipe.
2026-04-29 10:14:42 +02:00
joakimp 349bb633ff Fix OMOS bunx detection
Validate / docs-check (push) Successful in 1m13s
Validate / validate-omos (push) Successful in 15m30s
Validate / validate-base (push) Successful in 17m11s
Publish Docker Image / build-omos (push) Failing after 14m43s
Publish Docker Image / update-description (push) Has been cancelled
Publish Docker Image / build-base (push) Has been cancelled
entrypoint-user.sh gated OMOS auto-install on 'command -v bunx', but
neither upstream bun installer nor our Dockerfile creates a bunx
symlink — only the bun binary exists on PATH. The check always failed
on a fresh OMOS image, printing 'ENABLE_OMOS=true but bun is not
installed.' even though bun was right there. Latent until now because
the only exercised path had a persisted oh-my-opencode-slim.json from
a prior install.

Fixes:
- Gate on 'command -v bun' instead of bunx.
- Call 'bun x oh-my-opencode-slim@latest install ...' (bun x is the
  real subcommand that actually works with only the bun binary).
- Add 'ln -sf bun /usr/local/bin/bunx' in the Dockerfile OMOS block
  so interactive users can still type bunx by habit.
- Smoke test asserts the bunx symlink exists on the OMOS variant.

Also verify 'test -L /usr/local/bin/bunx' as a build-time sanity check.
Can't use 'bunx --help' for that — bun exits 1 on help output even
though it prints the usage correctly.
2026-04-29 09:01:23 +02:00
joakimp 3b3533d40b Bump opencode to 1.14.29
Validate / docs-check (push) Successful in 1m17s
Validate / validate-omos (push) Successful in 13m57s
Validate / validate-base (push) Successful in 16m39s
Publish Docker Image / build-base (push) Successful in 53m13s
Publish Docker Image / build-omos (push) Successful in 1h9m16s
Publish Docker Image / update-description (push) Successful in 13s
Also finalizes the CHANGELOG Unreleased section as v1.14.29 — 2026-04-28.
This is the first release to carry the infrastructure pass from the
preceding commit: floating upstream versions, uv-tool-installed
mempalace, sentinel-based chown optimization, and the new CI validate
workflow with smoke tests.
2026-04-28 23:28:53 +02:00
joakimp 113c9f0bb0 Infrastructure pass: CI smoke tests, floating versions, chown sentinel, generate-config script
Main changes:

- Extract opencode.json generation from entrypoint-user.sh into a
  standalone Python script (rootfs/usr/local/lib/opencode-devbox/
  generate-config.py). Preserves the never-overwrite-existing-config
  guarantee. Cuts entrypoint-user.sh from 176 to 97 lines.

- Install MemPalace via 'uv tool install' into an isolated venv at
  /opt/uv-tools/mempalace/ with a /usr/local/bin/mempalace-mcp-server
  wrapper, replacing the 'pip install --break-system-packages' escape
  hatch. The wrapper is what generate-config.py references in the
  auto-generated opencode.json. Also fix 'mempalace init' in
  entrypoint-user.sh to use --yes so first-start initialization isn't
  interactive (this used to hang or print prompts into the user's
  terminal). Gated by INSTALL_MEMPALACE build arg (default true) so
  users who don't need AI memory can shave ~300 MB.

- Sentinel-file pattern in entrypoint.sh volume-ownership loop: write
  .devbox-owner after a successful chown -R, skip the recursive walk
  on subsequent starts when the sentinel matches FINAL_UID:FINAL_GID.
  Cuts multi-second startup costs to milliseconds on large volumes
  (nvim plugins, palace data). UID changes still trigger a full chown.

- Float all GitHub/Gitea-hosted binary versions: gosu, fzf, git-lfs,
  neovim, bat, eza, zoxide, uv, gitea-mcp now default to 'latest' and
  resolve the newest upstream release at build time via the /releases/
  latest redirect. Go (go.dev JSON feed) and oh-my-opencode-slim (npm
  @latest) likewise. Intentional pins still in place: OPENCODE_VERSION,
  NODE_VERSION=22, DEBIAN_VERSION=trixie-slim. Each *_VERSION ARG
  accepts an explicit value to lock a specific version when needed.

- New scripts/smoke-test.sh verifies binary presence, opencode startup,
  entrypoint user drop, generate-config idempotency, bun's presence-
  per-variant, and image size against thresholds (2500 MB base, 3000
  MB OMOS). Prints resolved component versions as its first step so
  CI logs always record what got baked into a given image.

- New .gitea/workflows/validate.yml runs on push to main and PRs:
  single-arch amd64 build, smoke test, DOCKER_HUB.md sync check. Tag-
  triggered docker-publish.yml now smoke-tests each variant on amd64
  before the full multi-arch push.

- scripts/generate-dockerhub-md.py auto-generates DOCKER_HUB.md from
  README.md using explicit SECTION_RULES. --check mode fails CI when
  the committed file is out of sync. Enforces the 25 kB Docker Hub
  limit. Adding a new README section forces an explicit keep/drop/
  replace decision.

- Remove dead INSTALL_PYTHON build arg (was a no-op since mempalace
  added python3 unconditionally).
2026-04-28 23:28:43 +02:00
Joakim Persson 4efc4e8005 Remove dead INSTALL_PYTHON build arg
Python 3 has been unconditionally present since the Debian trixie
upgrade (e58962a, Apr 13) — python3 3.13 ships as a transitive
dependency of the trixie base image. python3-pip (e1029bb) and
python3-venv (3a7ec45) were later added to the base layer on Apr 23
so Mason could install Python-based LSPs (ruff, ansible-lint) into
venvs on nvim startup. MemPalace's pip install (b9c08c3) just
piggybacks on what was already there.

In other words, INSTALL_PYTHON=true has been a no-op reinstall of
already-installed packages for two weeks before MemPalace existed.
The flag is dead weight and the docs that advertise it as meaningful
are misleading. Remove it everywhere.

Users who want Python tooling should use the pre-installed uv/uvx.
2026-04-28 06:56:40 +00:00
joakimp ca44da71e1 Add official Gitea MCP server to base image
Publish Docker Image / build-base (push) Successful in 47m50s
Publish Docker Image / build-omos (push) Successful in 1h2m18s
Publish Docker Image / update-description (push) Successful in 14s
Install gitea-mcp v1.1.0 (Go binary from gitea.com/gitea/gitea-mcp)
using the same multi-arch pattern as gosu/fzf/bat. Provides 50+ MCP
tools for Gitea API — repos, issues, PRs, releases, branches, wiki,
and Actions.

Disabled by default in auto-generated opencode.json (requires
GITEA_ACCESS_TOKEN and GITEA_HOST to be useful). Users enable it by
setting those env vars in .env and flipping enabled to true in their
opencode.json.

Env vars forwarded into the container via docker-compose.yml and
docker-compose.shared.yml environment blocks. Same {env:VAR} pattern
as the GitHub MCP server.

Docs updated: README.md (new Gitea MCP section with setup steps),
DOCKER_HUB.md (tools list), CHANGELOG.md (v1.14.28b entry).
2026-04-27 22:28:15 +02:00
joakimp 8e605e87d4 Add chroma cache to entrypoint chown loop, finalize v1.14.28b changelog
Publish Docker Image / build-base (push) Has started running
Publish Docker Image / update-description (push) Has been cancelled
Publish Docker Image / build-omos (push) Has been cancelled
The ChromaDB embedding model cache at ~/.cache/chroma was missing
from the volume ownership-fix loop in entrypoint.sh. Without it,
the devbox-chroma-cache named volume would be root-owned on first
creation and mempalace search would fail with permission errors.

Update CHANGELOG.md from 'Unreleased' to v1.14.28b with the full
mempalace feature set (MCP auto-registration, two-volume split).
2026-04-27 21:45:16 +02:00
joakimp b9c08c3dbb Add MemPalace local-first AI memory system to base image
Install mempalace via pip in the Dockerfile. Provides 29 MCP tools
for semantic search over conversation history, knowledge graph
queries, agent diaries, and wing/room/drawer management. Everything
runs locally — no API keys, no data egress.

Integration:
- Dockerfile: pip install mempalace (with --break-system-packages
  for Debian trixie PEP 668 compliance)
- entrypoint-user.sh: auto-initializes palace for /workspace on
  first run (idempotent, skips if palace exists)
- entrypoint.sh: adds ~/.mempalace to the volume ownership-fix loop
- docker-compose.yml + shared: optional devbox-palace named volume
  at ~/.mempalace (commented out by default — user opts in)

Users configure MCP integration by adding a mempalace server entry
to their opencode.json. No wrapper plugin needed — the upstream
Python MCP server is used directly.

Docs updated: README.md (new MemPalace section with setup, MCP
config, usage examples, storage details), DOCKER_HUB.md (data
storage table + tools list), CHANGELOG.md (unreleased entry).
2026-04-27 19:25:38 +02:00
joakimp 45d7e02faf Bump opencode to 1.14.28
Publish Docker Image / build-omos (push) Successful in 47m20s
Publish Docker Image / build-base (push) Successful in 50m13s
Publish Docker Image / update-description (push) Successful in 20s
2026-04-27 18:50:57 +02:00
joakimp b648d83928 Bump opencode to 1.14.25
Publish Docker Image / build-base (push) Successful in 40m15s
Publish Docker Image / build-omos (push) Failing after 1h45m55s
Publish Docker Image / update-description (push) Has been skipped
2026-04-25 17:36:30 +02:00
joakimp f2f8a70dae Add CHANGELOG.md and link it from Docker Hub description
Generated from annotated git tag messages. Covers every release from
v1.4.2 (initial) through v1.14.22b. One-line summaries for simple
bumps, bullet-point detail for feature/fix releases.

DOCKER_HUB.md gains a Changelog link in the Source section so Docker
Hub users can find release history without navigating the git forge.
2026-04-23 21:13:31 +02:00