fix(entrypoint,tests): register pi-fork — guard matched its own config block
The `pi install /opt/<pkg>` loop in entrypoint-user.sh guarded on a whole-file substring grep of ~/.pi/agent/settings.json. settings.example.json ships a top-level "pi-fork" CONFIG block (fork effort profiles, pi-toolkit adb6907, 2026-06-17), so `grep -q pi-fork settings.json` matched the config key itself and `pi install /opt/pi-fork` never ran — on fresh or preserved volumes. The `fork` tool has therefore been absent since v1.0.0. The non-destructive template merge runs earlier in the same startup than the install loop, so the mechanism that delivers new template keys to an old volume is what plants the string that defeats the guard. pi-observational- memory and pi-studio escaped only by luck: the template key is "observational-memory" (no pi- prefix) and there is no studio block. Guard now inspects the `packages` array via jq, with a grep fallback on the stored `.../opt/<name>"` path form, which a config key can never produce. Existing volumes self-heal on the next container start. Both test suites asserted the bug as green — smoke-test.sh:244 and recreate-sanity-check.sh:204 used the same whole-file grep, so "pi-fork registered (fork tool)" passed on every build and recreate while the tool was missing. Both now assert against packages[] with the entrypoint's predicate, labels say packages[], and the smoke readiness wait loop uses the array check plus `docker exec -u developer` + $HOME instead of a hard-coded /home/developer path. Evidence: zero `fork` tool calls across all 19 sessions on this volume; the v1.6.3 session that tuned pi-fork.deep to opus-5 was configuring a tool that never loaded.
This commit is contained in:
+29
-4
@@ -178,13 +178,38 @@ if command -v pi &>/dev/null; then
|
||||
# idempotent (no duplicate package entry on re-run), and stores a relative
|
||||
# path that resolves into the image-layer /opt so it survives volume
|
||||
# recreate. The tools/command register on the NEXT pi start (extensions
|
||||
# bind at startup). Guard on settings.json so we only install once per
|
||||
# volume. /opt/pi-studio is present only in the studio variant; the
|
||||
# `[ -d ]` test makes this a no-op everywhere else.
|
||||
# bind at startup) or on `/reload`. Guard on settings.json so we only
|
||||
# install once per volume. /opt/pi-studio is present only in the studio
|
||||
# variant; the `[ -d ]` test makes this a no-op everywhere else.
|
||||
#
|
||||
# The guard MUST inspect the `packages` ARRAY, not merely grep the whole
|
||||
# file for the package name. settings.example.json ships a top-level
|
||||
# "pi-fork" CONFIG block (the fork effort profiles, pi-toolkit adb6907,
|
||||
# 2026-06-17), so a whole-file substring grep matches on any settings.json
|
||||
# that was bootstrapped from — or template-merged with — that template.
|
||||
# Worse, the merge above runs FIRST, so it plants the matching string in the
|
||||
# same startup that the loop then reads: `pi install /opt/pi-fork` was
|
||||
# skipped forever and the `fork` tool never registered (v1.0.0 → v1.6.3).
|
||||
# Its siblings escaped only by luck — the template key is
|
||||
# "observational-memory" (no pi- prefix) and there is no studio block.
|
||||
# jq reads the array; the grep fallback matches the stored relative-path
|
||||
# form ("…/opt/<name>\""), which a config KEY can never produce.
|
||||
_pi_pkg_registered() {
|
||||
_pi_reg_settings="$HOME/.pi/agent/settings.json"
|
||||
[ -f "$_pi_reg_settings" ] || return 1
|
||||
if command -v jq >/dev/null 2>&1; then
|
||||
jq -e --arg n "$1" \
|
||||
'(.packages // []) | any((type == "string") and (. == "npm:" + $n or endswith("/" + $n)))' \
|
||||
"$_pi_reg_settings" >/dev/null 2>&1
|
||||
else
|
||||
grep -q "opt/$1\"" "$_pi_reg_settings"
|
||||
fi
|
||||
}
|
||||
|
||||
for _pkg in /opt/pi-fork /opt/pi-observational-memory /opt/pi-studio; do
|
||||
[ -d "$_pkg" ] || continue
|
||||
_name=$(basename "$_pkg")
|
||||
if ! grep -q "$_name" "$HOME/.pi/agent/settings.json" 2>/dev/null; then
|
||||
if ! _pi_pkg_registered "$_name"; then
|
||||
pi install "$_pkg" >/dev/null 2>&1 || \
|
||||
echo "WARN: pi install $_name failed (continuing)"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user