entrypoint: announce the "remote palace, no inbox" skip instead of vanishing
Lint / hadolint (push) Successful in 8s
Lint / actionlint (push) Successful in 1m8s

When MEMPALACE_REMOTE_URL is set but MEMPALACE_PI_SSH_TARGET is not, the feeder
has nowhere to ship staged transcripts, so skipping is correct. The problem was
that the branch was a bare `:` AND the skip happens before the subshell that
writes ~/.pi/agent/mempalace-catchup.log -- so a container in that state
contributed nothing to the palace and left no artifact at all, not even an empty
log, to explain why. It is indistinguishable from a healthy run that had nothing
to file, which is the worst property a memory system can have: the failure looks
exactly like success.

Surfaced while flipping the first client onto the shared palace, where this is
the single most likely way to end up quietly memory-less -- the palace is the
only thing that survives a container recreate.

The notice goes to both the container start output (docker logs) and the log
path anyone debugging looks at first. It names both variables, says what still
works (MCP tools read/write the shared palace; only this container's own
conversations go nowhere), and points at MEMPALACE_FEED=0 for anyone who meant
it -- "HTTPS first, mining later" is a documented interim state, so the notice
has to be silenceable without being ignorable.

Guarded against becoming a startup failure. mkdir -p in a branch that previously
touched no filesystem is a new risk: an unwritable ~/.pi (root-owned volume, a
classic Docker accident) fails under set -e and would abort the entire
entrypoint. It now degrades to stdout-only. Verified all five paths by executing
the extracted block under `set -euo pipefail`: the trap prints and writes the
log; unwritable ~/.pi still exits 0 and still prints; MEMPALACE_FEED=0 stays
completely silent (no message, no file); and both normal-remote and local mode
still background the feeder with no notice.

Two smoke assertions guard against a regression to the silent no-op. They test
the entrypoint as shipped in the image rather than behaviour, because this branch
only runs at container start and a `docker run` one-shot cannot reach it.

entrypoint-user.sh is COPY'd in Dockerfile.base, so this rides the base rebuild
the Unreleased feeder work already needs.
This commit is contained in:
Joakim Persson
2026-08-13 16:30:55 +02:00
parent 7c00dd6001
commit cbd7cf5c67
3 changed files with 67 additions and 3 deletions
+27 -1
View File
@@ -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"
(