entrypoint: link fleet pi extensions from the mounted config dir
pi auto-loads every .ts in ~/.pi/agent/extensions/, which lives in the devbox-pi-config volume. A baked extension only seeds a fresh volume once, and a hand-copied one is a per-device step that drifts — the same two problems link-pi-models.sh was added for on 2026-10-12, one level down. This is also the only path that reaches every host: four of them mount common/pi from docker-compose-repo, and three cannot be reached from a devbox to create a symlink by hand (measured: no ssh config entry, no name resolution, and this instance's ~/.ssh-local/config carries no jump alias — only gitea and the mempalace feed host are reachable). link-pi-extensions.sh links each TOP-LEVEL *.ts from the mounted fleet directory (default /opt/fleet-pi, the same directory that already carries models.json; PI_EXTENSIONS_SRC overrides, =off disables). A symlink, not a single-file bind mount, for the measured reason already documented for models.json: git pull replaces a file by rename, and a file mount then serves stale content. Never destructive — a real file of that name in ~/.pi/agent/extensions/ wins over the fleet copy. Nested *.ts are deliberately not linked: the directory is fleet pi config, not an extension tree. - scripts/test-link-pi-extensions.sh: 16 two-sided cases (the negative half is the contract), all passing, wired into lint.yml beside the models one. - smoke-test.sh and recreate-sanity-check.sh gained the matching in-image and on-device checks, each gated on the fleet directory actually holding *.ts so a device without a shared directory is not judged by them. - README: the shared directory can carry extensions, and the rules that apply. Also repairs a pre-existing release blocker, found while checking this change. check-doc-drift.sh failed on pristine HEAD (verified in a clean worktree): pi-extensions main moved 0d8e417 -> 4c1d28d without the SHA being named above the v1.11.2 heading, and docker-publish.yml's resolve-versions has needs: [lint-gate] — so the next tag could not have published. The CHANGELOG now names 4c1d28d and describes the two confirm-destructive commits from their diff (they stop the gate prompting on harmless redirects, and add tee/dd of= as write forms); node --test test/confirm-destructive.test.mjs at 4c1d28d: 2 pass, 0 fail. Local verification: lint-shell.sh (21 files, severity error), check-workflow-shell.sh, check-skill-floor.sh, check-dockerfile-directives.sh, check-doc-drift.sh, and both link-pi-*.sh contract suites all pass. actionlint and hadolint are not installed in a devbox, so those CI steps are unvalidated here; the smoke-test addition runs only inside the image at release time.
This commit is contained in:
+39
-1
@@ -23,10 +23,48 @@ base** rather than reusing `base-6f3b20266de1`.
|
||||
|
||||
| Component | Baked in v1.11.2 | Next build | Why |
|
||||
|---|---|---|---|
|
||||
| pi-extensions | `750b2a8` | **`0d8e417`** (or later: CI resolves `main` at build time) | the AWS SSO keeper prints clock times in 24-hour format whatever the locale (below) |
|
||||
| pi-extensions | `750b2a8` | **`4c1d28d`** (or later: CI resolves `main` at build time) | the `confirm-destructive` gate stops prompting on harmless redirects and catches `tee`/`dd of=` (below); picks up the AWS SSO keeper's 24-hour times too (below) |
|
||||
|
||||
### Added
|
||||
|
||||
- **Fleet pi extensions are linked in at every container start**
|
||||
(`rootfs/usr/local/lib/pi-devbox/link-pi-extensions.sh`, called from
|
||||
`entrypoint-user.sh` next to `link-pi-models.sh`). pi auto-loads every `.ts` in
|
||||
`~/.pi/agent/extensions/`, which lives in the `devbox-pi-config` volume: a baked
|
||||
extension would only seed a fresh volume once, and a hand-copied one is a
|
||||
per-device step that drifts — the two problems `link-pi-models.sh` was added
|
||||
for on 2026-10-12, one level down. The script links each **top-level** `*.ts`
|
||||
from the mounted fleet directory (default `/opt/fleet-pi`, the same directory
|
||||
that already carries `models.json`; `PI_EXTENSIONS_SRC` overrides, `=off`
|
||||
disables) and is never destructive: a real file of that name in
|
||||
`~/.pi/agent/extensions/` is left alone, so a user's own copy of an extension
|
||||
always wins over the fleet one. A symlink rather than a single-file bind mount
|
||||
because `git pull` replaces a file by rename (measured on Docker Desktop,
|
||||
2026-10-12), which is the documented reason `models.json` is shared this way.
|
||||
Nested `*.ts` are deliberately NOT linked — the directory is fleet pi config,
|
||||
not an extension tree. `scripts/test-link-pi-extensions.sh` covers the contract
|
||||
with 16 two-sided cases and runs in `lint.yml`; `smoke-test.sh` and
|
||||
`recreate-sanity-check.sh` gained the matching in-image and on-device checks.
|
||||
Motivated by the ERDC System One classifier extension: four hosts mount
|
||||
`common/pi` from `docker-compose-repo`, and three of them are not reachable
|
||||
from a devbox to create a symlink by hand.
|
||||
|
||||
### Fixed
|
||||
|
||||
- **`confirm-destructive` asked for approval on nearly every `2>/dev/null`**
|
||||
(pi-extensions `4c1d28d`, two commits on top of the `0d8e417` named below).
|
||||
Its "write to device" pattern was a bare `>\s*/dev/`, so redirecting a
|
||||
standard stream into the null device looked like a write to a block device —
|
||||
the extension's own comment cites 20 of 70 bash calls in one 2026-10-16
|
||||
session, and a gate that prompts that often trains the user to approve without
|
||||
reading. `/dev/null`, `stdout`, `stderr`, `tty`, `/dev/fd/*` and `/dev/shm` are
|
||||
now exempt, matched as whole names so `/dev/nullfoo` still prompts and a
|
||||
`/dev/shm` path containing `..` is not exempt. The same gate got harder to
|
||||
slip past: `tee` and `dd of=` (which writes from stdin and has no `if=`) are
|
||||
now write forms, and quoted device paths are recognised. Its suite covers the
|
||||
new cases — `node --test test/confirm-destructive.test.mjs` in
|
||||
pi-extensions `4c1d28d`: 2 tests, 2 pass, 0 fail (measured 2026-10-16).
|
||||
|
||||
- **The AWS SSO keeper showed 12-hour times under the image's default
|
||||
locale** (pi-extensions `0d8e417`). The status line (`AWS ✓ since …` /
|
||||
`until …`), `/aws-sso status`, the "session ended at" login notice and the
|
||||
|
||||
Reference in New Issue
Block a user