Development record
PATH entry written as a symlink to the plugin-root binary (no verified artefact in the cache) is fragile by abcd's own note, yet bare 'ahoy' reports zero gaps afterwards. Immediately after a plugin update the symlink still pointed at the superseded root e3696dc while the live root was eda67ccc, and install_mode read 'pinned'. Detection should surface this as a gap (entry points at a non-current plugin root / not an owned copy) rather than only in a one-time install note; better still, provision the cache during install so the owned copy is written first time.
PATH entry written as a symlink to the plugin-root binary (no verified artefact in the cache) is fragile by abcd's own note, yet bare 'ahoy' reports zero gaps afterwards. Immediately after a plugin update the symlink still pointed at the superseded root e3696dc while the live root was eda67ccc, and install_mode read 'pinned'. Detection should surface this as a gap (entry points at a non-current plugin root / not an owned copy) rather than only in a one-time install note; better still, provision the cache during install so the owned copy is written first time.
Relocated from another repository's ledger on 2026-09-15. It was captured by an
ahoy install onboarding session whose working directory was a teaching-materials
repository, so the finding landed where nothing could resolve or detect it: that
tree has no installer, no plugin root and no ~/.local/bin surface. The id,
the found_during stamp and the body are unchanged; only the ledger it sits in
has moved. The store resolved correctly — it wrote to the repository it was
standing in — and the reason nothing refused the write is recorded as
iss-2609120511058115.
Grounds
- declined: duplicate of iss-2609100506263330: the same PATH entry written as a symlink to the plugin-root binary on a cold cache, which a plugin update breaks; its evidence and its two asks are appended to the survivor, and its superseded-root detection half is answered on main by 177a407d (iss-2609161805447092)
Frontmatter
| id | iss-2609120447482506 |
|---|---|
| type | issue |
| lifecycle | wontfix |
| severity | major |
.abcd/work/issues/wontfix/iss-2609120447482506-path-entry-written-as-a-symlink-to-the.md
open on GitHub ↗ · commit history ↗
mentions4
- iss-2609100506263330`ahoy install` can report success while leaving a PATH entry that a later plugin update silently breaks, and the condition that decides which happens is invisible to the operator.
- iss-2609120450411702Upgrade path self-blocks across a plugin update: v0.7.1 wrote ~/.local/bin/abcd as a symlink into its own plugin root (e3696dc) with the note 're-run install from a session whose hooks have provisioned the cache to upgrade it to an owned copy'. After the plugin updated to v0.8.0 (eda67ccc), that re-run classified the symlink as symlink.foreign ('expected .../eda67ccc02eb/abcd'), unresolvable, 'ahoy refuses to clobber' — so the prescribed remedy is refused by its own predecessor's write, abcd on PATH stays at v0.7.1, and install_mode reads empty. Only a manual rm and a third install produced the owned copy. Fix: a symlink whose target is inside abcd's own plugin-cache directory (any root hash) is abcd's, not foreign — adopt and replace it; or have the first install never write the plugin-root symlink fallback at all, since it is guaranteed to go stale on the next update. Related: iss-2609120447482506.
- iss-2609120511058115Nine findings about abcd's own installer are sitting in a teaching-materials
- iss-2609161805447092abcd update calls a pinned install foreign when its symlink points into a superseded plugin-cache version. On this machine ~/.local/bin/abcd is the pin abcd ahoy install wrote on 2026-09-07: a symlink into the plugin cache directory of the v0.7.1 vintage (e3696dc524e3). After the plugin moved on, go run ./cmd/abcd update v0.9.0 --yes refused with 'the entry at ~/.local/bin/abcd is not something abcd owns, and abcd never clobbers a binary it does not own' and offered 'remove or rename the occupant' as the remedy. The link target is a published release binary (its digest is the darwin-arm64 line of v0.7.1's checksums.txt) inside abcd's own cache, so nothing about it is foreign: the classifier in internal/core/ahoy/update_target.go only admits a symlink into the CURRENT plugin root as owned, and a link into an older vintage falls through to foreign before the digest check the verb's help promises ever runs. The refusal's detail and remedy are both wrong for this shape; the right remedy is abcd ahoy install, which the owned-dangling case already names, and the honest detail is that the pin points at a superseded vintage. Found while finishing the v0.9.0 deploy on 2026-09-16.