skill(pi-devbox-environment): resolve a skill symlink before editing it
~/.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/<name>` 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.
This commit is contained in:
@@ -75,6 +75,45 @@ Practical consequences:
|
|||||||
belongs under an image path like `/usr/local/...` or `/opt/...` and is linked
|
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.
|
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/<name> # always do this first
|
||||||
|
```
|
||||||
|
|
||||||
|
| Resolves to | Tier | Edit here |
|
||||||
|
|---|---|---|
|
||||||
|
| `/workspace/skillset/skills/<name>/` | host bind-mount | edit in place, commit in that repo |
|
||||||
|
| `/usr/local/share/pi-devbox/skills/<name>/` | **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)
|
## 2. Interactive shell vs. your tool shell (a real footgun)
|
||||||
|
|
||||||
The conveniences below are defined in `~/.bash_aliases` and **only exist in an
|
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.
|
- [ ] Assuming a hostname / domain / nameserver / host OS? → stop, detect it.
|
||||||
- [ ] "Resolves but won't connect"? → check route *and* DNS (§3 + §4).
|
- [ ] "Resolves but won't connect"? → check route *and* DNS (§3 + §4).
|
||||||
- [ ] `apt`/toolchain install? → tell the user it's ephemeral unless imaged.
|
- [ ] `apt`/toolchain install? → tell the user it's ephemeral unless imaged.
|
||||||
|
- [ ] Editing a skill? → `readlink -f ~/.agents/skills/<name>` first (§1).
|
||||||
- [ ] Touching tmux indexing? → don't (§5).
|
- [ ] Touching tmux indexing? → don't (§5).
|
||||||
|
|||||||
Reference in New Issue
Block a user