Commit Graph

12 Commits

Author SHA1 Message Date
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 148f4bce8c AGENTS.md: expand doc-coupling rule with release-day checklist
Validate / docs-check (push) Successful in 14s
Validate / validate-base (push) Successful in 11m9s
Validate / validate-omos (push) Successful in 16m33s
Validate / validate-with-pi (push) Successful in 12m9s
Validate / validate-omos-with-pi (push) Successful in 16m41s
The previous 'Two docs to keep in sync' bullet only mentioned
README + DOCKER_HUB.md + .env.example. Today's session surfaced
two additional drift points the rule didn't cover:

- CHANGELOG.md still claimed 'Unreleased — will become v1.14.41b
  on release' even though the tag had been pushed and shipped
  (caught a full session later when user asked about doc drift).
- AGENTS.md itself carried stale 'four Docker Hub tags' /
  'four load:true jobs' from before the v1.14.41b CI matrix
  expansion to eight.

Replaced the bullet with a full 'Documentation coupling on release'
rule listing all four coupled docs (README, DOCKER_HUB.md,
CHANGELOG.md, AGENTS.md, plus .env.example) and an explicit
release-day checklist. Calls out the 25 kB Hub limit on
DOCKER_HUB.md as a hard constraint to keep in mind when adding
sections to README.
2026-05-08 21:35:23 +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 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
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
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
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 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
joakimp c851b4cc8d Clarify tag-letter convention: suffix is build ordinal, 'a' is never used
Publish Docker Image / build-omos (push) Successful in 43m57s
Publish Docker Image / build-base (push) Successful in 45m46s
Publish Docker Image / update-description (push) Successful in 16s
Previous phrasing treated the letter suffix as a plain alphabetical
sequence, which led to confusion about whether the first rebuild
should be 'a' or 'b'. Spell out the intent: the suffix is the build
ordinal, and the letter 'a' is reserved to mean '1st build' — which
always uses the bare tag (no letter). So letters start at 'b' for
the 2nd build, 'c' for the 3rd, and so on.

Examples for opencode version 1.14.20:
  1st build: v1.14.20
  2nd build: v1.14.20b
  3rd build: v1.14.20c
2026-04-21 23:58:12 +02:00
joakimp c05ec7503c Bump opencode to 1.14.20 and clarify versioning convention
Publish Docker Image / build-omos (push) Successful in 44m59s
Publish Docker Image / build-base (push) Successful in 45m10s
Publish Docker Image / update-description (push) Successful in 16s
Bump OPENCODE_VERSION ARG from 1.14.19 to 1.14.20 to track the new
upstream release on npm.

Clarify the tagging convention in AGENTS.md: the first build on a new
opencode version uses the bare 'v{opencode_version}' tag (no letter
suffix). Letter suffixes (a, b, c, ...) are reserved for container-
level rebuilds on the same opencode version (CVE fixes, doc changes,
entrypoint bugs). The previous wording implied a letter was always
required, which was never the actual behaviour.
2026-04-21 21:16:47 +02:00
joakimp 5ec47fdf4b Add AGENTS.md with project-specific guidance for opencode sessions 2026-04-14 19:28:26 +02:00