The relink gate alone left three destructive sites open:
- link_claude_skill_dirs runs BEFORE relink on every ./setup and used
`ln -snf` (Linux replaces a user's real SKILL.md with a symlink into
gstack) or, on Windows, rm -rf + cp followed by a marker that made the
user's directory "ours" on the next flip. It and _install_alias_skill_md
now consult _claude_entry_is_ours first and skip loudly.
- cleanup_prefixed_claude_symlinks kept a bare name-match deletion and a
`*gstack*` substring match. Symlink arms use anchored `gstack/` segment
patterns; the Windows real-file arm proves provenance (marker,
byte-identity with our source, or the full two-line gen-skill-docs banner
within the first 40 lines, never a one-line substring another generator
could emit). cleanup_old_claude_symlinks uses the same banner rule.
- gstack-relink's fast path judged absolute targets before canonicalizing,
so `/x/gstack/../foreign/SKILL.md` counted as ours; dot-segment targets
now canonicalize first. Its banner rule matches setup's.
The `.gstack-owned` marker records the owning payload's realpath. Entries
skipped by setup or relink are listed in the final setup summary.
Chromium bootstrap refinements from the pre-landing review: an INT/TERM
trap kills the installer's process tree; the Windows npm chain no longer
masks an install failure; GSTACK_SKIP_PLAYWRIGHT=1 is reported as a choice
rather than a failure and sends no telemetry; the timeout knob is
normalized (0, 000, non-numeric, or more than nine digits fall back to the
600s default instead of killing on the first poll or never killing).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>