From 4d4abd9a9fa77943967bec113ac55d0d34bd9a8e Mon Sep 17 00:00:00 2001 From: Joakim Persson Date: Wed, 29 Jul 2026 19:37:59 +0200 Subject: [PATCH] skill(pi-devbox-environment): resolve a skill symlink before editing it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ~/.agents/skills/ lives in the ephemeral container layer and is rebuilt by entrypoint-user.sh on every start from two sources, so an edit made through the symlink may vanish on the next recreate. Adds to §1 (persistence tiers): - `readlink -f ~/.agents/skills/` as the first move, with a tier table: resolves under /workspace/skillset → edit in place; resolves under /usr/local/share/pi-devbox/skills → image layer, edit the canonical repo and `sudo cp` to activate for the running session. - Canonical owner per baked skill (pi-devbox-environment → this repo; pi-extensions → the package repo's skill/, plus this repo's floor snapshot; mempalace → the private skillset repo), pointing at VENDORED.md as authoritative. - The shadowing gotcha: image-baked links are created first and only when absent, and deploy-skills.sh --prune-stale leaves foreign links alone, so for a name present in BOTH sources the image copy wins and a skillset edit has no effect in the container. Documented with the live example found while writing this: the baked mempalace snapshot carries a Temporal grounding section (904fe85) that skillset at its snapshot point (8e8db64) lacks. - Checklist gets a matching line. Found while adding session findings to the pi-extensions skill (e73cb9f), where the same resolve-first step was what kept the edit out of the image layer. --- .../skills/pi-devbox-environment/SKILL.md | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/rootfs/usr/local/share/pi-devbox/skills/pi-devbox-environment/SKILL.md b/rootfs/usr/local/share/pi-devbox/skills/pi-devbox-environment/SKILL.md index 17400bd..b433541 100644 --- a/rootfs/usr/local/share/pi-devbox/skills/pi-devbox-environment/SKILL.md +++ b/rootfs/usr/local/share/pi-devbox/skills/pi-devbox-environment/SKILL.md @@ -75,6 +75,45 @@ Practical consequences: belongs under an image path like `/usr/local/...` or `/opt/...` and is linked in by the entrypoint — not dropped into a home directory that a volume covers. +### Editing a skill: resolve the symlink before you touch it + +`~/.agents/skills/` itself is in the **ephemeral container layer**, rebuilt by +`entrypoint-user.sh` on every start from two sources — so *where a skill really +lives* decides whether your edit survives: + +```sh +readlink -f ~/.agents/skills/ # always do this first +``` + +| Resolves to | Tier | Edit here | +|---|---|---| +| `/workspace/skillset/skills//` | host bind-mount | edit in place, commit in that repo | +| `/usr/local/share/pi-devbox/skills//` | **image layer** (root-owned, ephemeral) | edit the **canonical repo**, then `sudo cp` the file over the image path to activate it for the running session | + +Only three skills are image-baked, and each has a different owner (the table in +`/usr/local/share/pi-devbox/skills/VENDORED.md` is authoritative): + +| Baked skill | Canonical source to edit | +|---|---| +| `pi-devbox-environment` | `pi-devbox` repo → `rootfs/usr/local/share/pi-devbox/skills/pi-devbox-environment/` (authored there; this file) | +| `pi-extensions` | the `pi-extensions` **package** repo → `skill/`. `Dockerfile.variant` copies it over the vendored snapshot at build, so also refresh `pi-devbox`'s `rootfs/.../pi-extensions/` copy to keep the fallback floor from diverging | +| `mempalace` | the private `skillset` repo → `skills/mempalace/` (manual snapshot refresh per release) | + +**Editing through the symlink into `/usr/local/...` is silently lost on the next +recreate** — and worse, it diverges from the canonical repo that every *other* +consumer (host pi, opencode) reads. + +**Shadowing gotcha:** image-baked links are created **first** and only when the +name is absent, and the later `deploy-skills.sh --bootstrap --prune-stale` pass +treats them as foreign links and leaves them alone. So for a name present in +**both** the image and `skillset` — currently `mempalace` and `pi-extensions` — +**the image copy wins**, and a `skillset` edit to that skill has no effect in +the container. Verified 2026-07-29: the baked `mempalace` snapshot carries a +*Temporal grounding* section (`pi-devbox` `904fe85`) that the `skillset` copy at +its snapshot point (`8e8db64`) lacks — containers load the richer baked text +while `skillset` consumers get the older one. When you change one of those two, +decide deliberately which copy is canonical and sync the other. + ## 2. Interactive shell vs. your tool shell (a real footgun) The conveniences below are defined in `~/.bash_aliases` and **only exist in an @@ -220,4 +259,5 @@ hardcode. Details are in the `mempalace` skill. - [ ] Assuming a hostname / domain / nameserver / host OS? → stop, detect it. - [ ] "Resolves but won't connect"? → check route *and* DNS (§3 + §4). - [ ] `apt`/toolchain install? → tell the user it's ephemeral unless imaged. +- [ ] Editing a skill? → `readlink -f ~/.agents/skills/` first (§1). - [ ] Touching tmux indexing? → don't (§5).