diff --git a/CHANGELOG.md b/CHANGELOG.md index 685ab0d..c506074 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,17 @@ Tags follow `v{opencode_version}[letter]` — bare tag for the first build on a --- +## v1.14.30b — 2026-04-30 + +**Bake mempalace-toolkit wrappers into the image.** + +- **Fix:** The scheduler templates in [mempalace-toolkit's `contrib/`](https://gitea.jordbo.se/joakimp/mempalace-toolkit/src/branch/main/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 `docker compose up --force-recreate`, because the only way to get them was a post-hoc `./install.sh --yes` 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. + - 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/`, and asserts both respond to `--help` before the layer succeeds. + - Gated by `ARG INSTALL_MEMPALACE_TOOLKIT=true` (defaults on, depends on `INSTALL_MEMPALACE=true`). + - Floated ref via `ARG MEMPALACE_TOOLKIT_REF=main` — override for reproducible builds once the toolkit starts tagging releases. +- **Tests:** Smoke test gains three toolkit assertions (`mempalace-session --help`, `mempalace-docs --help`, symlink target check). The resolved-versions preamble now logs the toolkit git short-SHA alongside the other floated components. +- **Docs:** README's MemPalace section gains a `Scheduled mining (mempalace-toolkit)` subsection covering the new wrappers and pointing at `contrib/` for scheduling. New build-args table entry for `INSTALL_MEMPALACE_TOOLKIT`. + ## v1.14.30 — 2026-04-30 Bump opencode to 1.14.30. diff --git a/DOCKER_HUB.md b/DOCKER_HUB.md index 6101560..fa4cd2e 100644 --- a/DOCKER_HUB.md +++ b/DOCKER_HUB.md @@ -449,6 +449,24 @@ mempalace wake-up Each workspace gets its own isolated "wing" — memories never leak between projects. +### Scheduled mining (mempalace-toolkit) + +The image bakes in [mempalace-toolkit](https://gitea.jordbo.se/joakimp/mempalace-toolkit), a small set of bash wrappers that pair with mempalace for two common routines: + +```bash +# Mine opencode session history (reads ~/.local/share/opencode/opencode.db, stages JSONL, mines into wing_conversations) +mempalace-session + +# Mine a project's docs into a dedicated wing +mempalace-docs /workspace/my-project +``` + +Both wrappers are idempotent and dedup-aware — re-running them on unchanged input is a cheap no-op. + +For weekly automated runs, the toolkit ships ready-to-use scheduler templates (systemd user timer, launchd user agent, cron) in its [`contrib/`](https://gitea.jordbo.se/joakimp/mempalace-toolkit/src/branch/main/contrib) directory. The `*-devbox` variants are designed for this container: host-side schedulers that `docker exec` into the running opencode-devbox. + +Disable the toolkit (keeps mempalace itself) with `--build-arg INSTALL_MEMPALACE_TOOLKIT=false`. Pin to a specific ref with `--build-arg MEMPALACE_TOOLKIT_REF=v0.3.0` once tagged releases exist. + ### Storage Two separate named volumes keep different data classes apart: diff --git a/Dockerfile b/Dockerfile index 3427be5..f5fc010 100644 --- a/Dockerfile +++ b/Dockerfile @@ -207,6 +207,31 @@ RUN if [ "${INSTALL_MEMPALACE}" = "true" ]; then \ /opt/uv-tools/mempalace/bin/python -c "import mempalace; print('mempalace', mempalace.__version__ if hasattr(mempalace, '__version__') else 'installed')" ; \ fi +# ── mempalace-toolkit — bash wrappers for session/docs mining ──────── +# Thin wrappers (`mempalace-session`, `mempalace-docs`) that delegate to +# the mempalace Python CLI for two common scheduled tasks: +# - mempalace-session: mines opencode's SQLite session history into +# the palace (wing_conversations). Referenced by contrib/ scheduler +# templates (systemd user timer, cron) in the toolkit repo. +# - mempalace-docs: mines project docs into a per-project wing. +# Repo source of truth: https://gitea.jordbo.se/joakimp/mempalace-toolkit +# +# Requires INSTALL_MEMPALACE=true (wrappers shell out to `mempalace`). +# Disable with --build-arg INSTALL_MEMPALACE_TOOLKIT=false if you don't +# use the scheduled-mining workflow. +ARG INSTALL_MEMPALACE_TOOLKIT=true +ARG MEMPALACE_TOOLKIT_REF=main +RUN if [ "${INSTALL_MEMPALACE}" = "true" ] && [ "${INSTALL_MEMPALACE_TOOLKIT}" = "true" ]; then \ + git clone --depth 1 --branch "${MEMPALACE_TOOLKIT_REF}" \ + https://gitea.jordbo.se/joakimp/mempalace-toolkit.git /opt/mempalace-toolkit && \ + ln -sf /opt/mempalace-toolkit/bin/mempalace-session /usr/local/bin/mempalace-session && \ + ln -sf /opt/mempalace-toolkit/bin/mempalace-docs /usr/local/bin/mempalace-docs && \ + chmod +x /opt/mempalace-toolkit/bin/mempalace-session /opt/mempalace-toolkit/bin/mempalace-docs && \ + mempalace-session --help >/dev/null && \ + mempalace-docs --help >/dev/null && \ + echo "mempalace-toolkit installed at $(cd /opt/mempalace-toolkit && git rev-parse --short HEAD)" ; \ + fi + # rustup — Rust toolchain manager # Installs the rustup-init binary only. Users bootstrap Rust with: # rustup-init -y && source ~/.cargo/env diff --git a/README.md b/README.md index ddd21ca..4fe05da 100644 --- a/README.md +++ b/README.md @@ -339,6 +339,7 @@ docker compose build --build-arg NVIM_VERSION=0.12.1 # pin to a specific versi |---|---|---| | `INSTALL_GO` | `false` | Go toolchain (resolves latest stable from go.dev when `GO_VERSION=latest`) | | `INSTALL_MEMPALACE` | `true` | [MemPalace](https://github.com/MemPalace/mempalace) local AI memory system (~300 MB — disable to shrink image if you don't need MCP memory) | +| `INSTALL_MEMPALACE_TOOLKIT` | `true` | [mempalace-toolkit](https://gitea.jordbo.se/joakimp/mempalace-toolkit) bash wrappers (`mempalace-session`, `mempalace-docs`). Cloned at build time from `MEMPALACE_TOOLKIT_REF` (default `main`). Requires `INSTALL_MEMPALACE=true`. | | `INSTALL_OMOS` | `false` | [oh-my-opencode-slim](https://github.com/alvinunreal/oh-my-opencode-slim) multi-agent orchestration (installs Bun and plugin) | | `OPENCODE_VERSION` | *(pinned per release)* | opencode npm version. Drives the image tag and is intentionally not floated. | | `NODE_VERSION` | `22` | Node.js major version. Pinned to protect against upstream breaking changes across majors. | @@ -502,6 +503,24 @@ mempalace wake-up Each workspace gets its own isolated "wing" — memories never leak between projects. +### Scheduled mining (mempalace-toolkit) + +The image bakes in [mempalace-toolkit](https://gitea.jordbo.se/joakimp/mempalace-toolkit), a small set of bash wrappers that pair with mempalace for two common routines: + +```bash +# Mine opencode session history (reads ~/.local/share/opencode/opencode.db, stages JSONL, mines into wing_conversations) +mempalace-session + +# Mine a project's docs into a dedicated wing +mempalace-docs /workspace/my-project +``` + +Both wrappers are idempotent and dedup-aware — re-running them on unchanged input is a cheap no-op. + +For weekly automated runs, the toolkit ships ready-to-use scheduler templates (systemd user timer, launchd user agent, cron) in its [`contrib/`](https://gitea.jordbo.se/joakimp/mempalace-toolkit/src/branch/main/contrib) directory. The `*-devbox` variants are designed for this container: host-side schedulers that `docker exec` into the running opencode-devbox. + +Disable the toolkit (keeps mempalace itself) with `--build-arg INSTALL_MEMPALACE_TOOLKIT=false`. Pin to a specific ref with `--build-arg MEMPALACE_TOOLKIT_REF=v0.3.0` once tagged releases exist. + ### Storage Two separate named volumes keep different data classes apart: diff --git a/scripts/smoke-test.sh b/scripts/smoke-test.sh index 9df094f..bba3046 100755 --- a/scripts/smoke-test.sh +++ b/scripts/smoke-test.sh @@ -71,6 +71,9 @@ docker run --rm --entrypoint="" "$IMAGE" sh -c ' if command -v mempalace >/dev/null 2>&1; then printf " %-15s %s\n" "mempalace" "$(mempalace --version 2>&1 | head -1 || echo installed)" fi + if command -v mempalace-session >/dev/null 2>&1 && [ -d /opt/mempalace-toolkit ]; then + printf " %-15s %s\n" "toolkit" "$(git -C /opt/mempalace-toolkit rev-parse --short HEAD 2>/dev/null || echo installed)" + fi ' echo echo "-- Core binaries --" @@ -104,6 +107,16 @@ else echo " - mempalace not installed (INSTALL_MEMPALACE=false)" fi +# mempalace-toolkit wrappers: present unless built with INSTALL_MEMPALACE_TOOLKIT=false +# Gated on mempalace presence — wrappers are useless without the CLI. +if docker run --rm --entrypoint="" "$IMAGE" sh -c "command -v mempalace && command -v mempalace-session" >/dev/null 2>&1; then + run "mempalace-session (toolkit)" "mempalace-session --help | head -1" + run "mempalace-docs (toolkit)" "mempalace-docs --help | head -1" + run "toolkit symlink target" "test -L /usr/local/bin/mempalace-session && readlink /usr/local/bin/mempalace-session" +elif docker run --rm --entrypoint="" "$IMAGE" sh -c "command -v mempalace" >/dev/null 2>&1; then + echo " - mempalace-toolkit not installed (INSTALL_MEMPALACE_TOOLKIT=false)" +fi + # bun: only in the omos variant if [ "$VARIANT" = "omos" ]; then run "bun (omos)" "bun --version"