diff --git a/CHANGELOG.md b/CHANGELOG.md index 1493574..b24f7a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,7 +38,8 @@ the events already are: pi's own lifecycle, plus container start. `agent_settled`, but a hard kill (`docker kill`, OOM, host reboot) runs no handler at all; this is the only trigger that can recover the previous life's transcripts. Skipped when a remote palace is configured without an inbox to - ship to, and skippable entirely with `MEMPALACE_FEED=0`. + ship to — **and the skip now says so** (see Changed) — and skippable entirely + with `MEMPALACE_FEED=0`. - **`MEMPALACE_PI_STAGE` no longer needs pinning here — the feeder's default was fixed upstream instead.** It used to stage under `~/.cache`, which is disposable in a container; the first cut of this change pinned the env var @@ -72,11 +73,37 @@ the events already are: pi's own lifecycle, plus container start. shipping vars `MEMPALACE_PI_SSH_TARGET`, `MEMPALACE_PI_REMOTE_PATH`, `MEMPALACE_PI_DEVICE`. +### Changed + +- **The "remote palace, no inbox" skip announces itself instead of vanishing** + (`entrypoint-user.sh`). When `MEMPALACE_REMOTE_URL` is set but + `MEMPALACE_PI_SSH_TARGET` is not, there is genuinely nothing the feeder can + ship to, so skipping is correct — but the branch was a bare `:`, and the skip + happens *before* the subshell that writes `~/.pi/agent/mempalace-catchup.log`. + A container in that state therefore contributed nothing to the palace and left + **no artifact at all**, not even an empty log, to explain why — indistinguish- + able from a healthy run that had nothing to file. Found while flipping the + first client onto the shared palace (2026-08-12), where it is the single most + likely way to end up quietly memory-less. The notice now goes to both the + container start output and that log path, names the two variables that fix it, + states that MCP tools still work (only *this* container's transcripts go + nowhere), and points at `MEMPALACE_FEED=0` for anyone who meant it. + Deliberately incapable of breaking startup: an unwritable `~/.pi` — root-owned + volume, a classic Docker accident — would make `mkdir -p` fail under `set -e` + and abort the whole entrypoint, so it degrades to stdout-only. That was a real + new risk, since this branch previously touched no filesystem whatsoever. + Covered by two smoke assertions against the entrypoint as shipped in the image + (the branch only runs at container start, so a `docker run` one-shot cannot + reach it). + ### Notes - The `Dockerfile.base` change moves the base hash, so this needs a base rebuild; the `~/.local/bin` self-heal exists so the feature does not have to - wait for one. + wait for one. The skip-notice change is in `entrypoint-user.sh`, which is + `COPY`d in `Dockerfile.base` too, so it rides the same rebuild — until then, + older images keep skipping silently and the two commands in the toolkit's + `phase-1-exposure-runbook.md` §3.7 are the way to tell. - Requires the matching `mempalace-toolkit` change (`--prepare` two-phase split, remote transport, and the auto-feed triggers in `extensions/pi/mempalace.ts`). The split exists because the palace is diff --git a/entrypoint-user.sh b/entrypoint-user.sh index 11d66b8..e546bb2 100755 --- a/entrypoint-user.sh +++ b/entrypoint-user.sh @@ -132,7 +132,33 @@ fi if [ "${MEMPALACE_FEED:-1}" != "0" ] && [ -n "$MEMPALACE_FEEDER" ]; then if [ -n "${MEMPALACE_REMOTE_URL:-}" ] && [ -z "${MEMPALACE_PI_SSH_TARGET:-}" ]; then - : # remote palace but no inbox configured — nothing we can ship to; skip quietly + # Remote palace, but no inbox to ship transcripts to — the feeder genuinely + # cannot do anything here, so skipping is right. Saying so is the point: + # this branch used to be a bare `:`, and the skip happens *before* the + # subshell below that writes mempalace-catchup.log, so a container in this + # state contributed nothing to the palace and left no artifact at all — not + # even an empty log — to explain why. That is indistinguishable from a + # healthy run that simply had nothing to file. `tee` puts the notice both in + # the container's start output (docker logs) and at the path anyone + # debugging "why is nothing from this container in the palace?" looks first. + # This is an entrypoint: a notice must never be able to stop a container + # from starting. An unwritable ~/.pi (root-owned volume — a classic Docker + # permission accident) makes `mkdir -p` fail, and under `set -e` that would + # abort startup entirely: a brand-new failure mode in precisely the branch + # that used to do nothing at all. Degrade to stdout-only instead. + _mp_log="$HOME/.pi/agent/mempalace-catchup.log" + mkdir -p "$HOME/.pi/agent" 2>/dev/null || _mp_log=/dev/null + { + echo "MemPalace catch-up skipped: remote palace with no transcript inbox." + echo " MEMPALACE_REMOTE_URL is set (${MEMPALACE_REMOTE_URL})" + echo " but MEMPALACE_PI_SSH_TARGET is not, so there is nowhere to ship this" + echo " container's staged sessions. MCP tools still read and write the shared" + echo " palace — but this container's own conversations are mined nowhere." + echo " Fix: set MEMPALACE_PI_SSH_TARGET (and MEMPALACE_PI_DEVICE) in .env," + echo " or unset MEMPALACE_REMOTE_URL to keep the palace local." + echo " Deliberate? MEMPALACE_FEED=0 turns the feed off and silences this." + } | tee "$_mp_log" 2>/dev/null || true + unset _mp_log else mkdir -p "$HOME/.pi/agent" ( diff --git a/scripts/smoke-test.sh b/scripts/smoke-test.sh index f22f542..1e32c17 100755 --- a/scripts/smoke-test.sh +++ b/scripts/smoke-test.sh @@ -144,6 +144,17 @@ run "pi transcript exporter rejects an abandoned session" ' out=$(mempalace-pi-session --dry-run --sessions-dir "$d/sessions" --stage "$d/stage" 2>&1) echo "$out" | grep -q "no sessions qualified" ' +# The remote-palace-without-inbox skip must ANNOUNCE itself, not vanish. This +# branch of entrypoint-user.sh runs at container start (not reachable from a +# `docker run` one-shot), so assert against the entrypoint that actually shipped +# in the image. Guards a silent regression back to the bare `:` no-op, which +# left a container contributing nothing to the palace with no artifact saying +# why — the log it would normally leave is written by the other branch. +run_expect "remote-palace-without-inbox skip is announced, not silent" \ + "grep -o 'MemPalace catch-up skipped' /usr/local/bin/entrypoint-user.sh | head -1" \ + "MemPalace catch-up skipped" +run "...and the skip notice names the variable that fixes it" \ + "grep -A6 'MemPalace catch-up skipped' /usr/local/bin/entrypoint-user.sh | grep -q 'MEMPALACE_PI_SSH_TARGET'" # v1.0.0 base additions — verify presence and basic functionality. run "pandoc" "pandoc --version" run "typst" "typst --version"