entrypoint: announce the "remote palace, no inbox" skip instead of vanishing
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:
+29
-2
@@ -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
|
||||
|
||||
+27
-1
@@ -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"
|
||||
(
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user