Fleet changelogs · dev.ecs0.net
rdmsm4x-changelog-20260915-2141-claude-md-symlink-sweep-retraction-DOC-20260915-01

rdmsm4x-changelog-20260915-2141-claude-md-symlink-sweep-retraction-DOC-20260915-01

2026-09-15 21:41:48 EDT · rdmsm4x · session_012cXdr2uPhnPS1cQfbt9pPQ

Retracted a false defect I reported two hours earlier, and replaced it with the verified rule. apps/bitROO/CLAUDE.md is a symlink, not a duplicated file. Net code/config change: one corrected section in ~/dev/CLAUDE.md. Nothing in apps/bitROO was touched.

Scope

What happened

The /init pass at 17:40 reported apps/bitROO/CLAUDE.md as a byte-identical copy of the 52 KB apps/CLAUDE.md baseline — a real failure class here (a copy stops inheriting fixes). I opened DOC-20260915-01 to replace it with a bitROO-specific file. While reading bitROO to write that file, git show HEAD:CLAUDE.md returned 12 bytes against a 51,935-byte working tree with git status clean. That contradiction did not resolve as an index bit (git ls-files -v = H, no assume-unchanged/skip-worktree), and the 12 bytes read ../CLAUDE.md — a symlink blob.

The actual state (correct)

ls -l apps/bitROO/CLAUDE.md
  lrwxr-xr-x  1 richh  staff  12 Aug 22 18:12  apps/bitROO/CLAUDE.md -> ../CLAUDE.md
git -C apps/bitROO ls-files -s CLAUDE.md
  120000 949a29f150579fed484035dc172f7cb692f655d6 0    CLAUDE.md      # 120000 = symlink
stat -f '%HT %z' apps/bitROO/CLAUDE.md
  Symbolic Link 12

This is the right pattern, not a defect: a symlink cannot drift, so bitROO inherits every future apps/CLAUDE.md fix automatically — exactly the property the ticket demanded. Acting on the ticket as written would have replaced a working symlink with a real file and created the divergence it warned about.

Why the original measurement lied — the generalisable trap

Three independent measurements all agreed, and all three followed the link:

  1. shasum -a 256 follows symlinks — it hashed the target, so the child "matched" its parent byte-for-byte. Identical hashes are not evidence of duplication.
  2. stat -f %i follows too (reporting the target inode), while links=1 came from the symlink itself. Two inodes, links=1 each, reads exactly like two independent files — which is how I affirmatively ruled out a hardlink and concluded "they will diverge".
  3. git show HEAD:<path> resolves from the REPO ROOT, not the cwd. Correct form is git show HEAD:./<path>. This briefly looked like an index anomaly and sent me to git ls-files -v.

The negative control is one character: find … -type f excludes symlinks; or ls -l / stat -f %HT on the candidate before trusting any hash. Same family as the fleet's recurring "check that measures the wrong thing" — every measurement returned rc=0 and a confident wrong answer.

Corrected full-tree sweep

Re-run with -type f:

Verification evidence

Adjacent observation — routed, not actioned

apps/bitROO/Package.swift declares platforms: [.macOS("26.7"), .iOS(.v17)]. The macOS floor is correct for Intel support, but the iOS floor is v17 against the fleet target of iOS 27.0 (lib/app-baseline/PLATFORM_TARGETS.md). Changing a deployment floor is bitROO's owner's call, not a documentation pass's — noted here only. bitROO's STATUS.md already records "No iOS target has been built".

Outstanding owner actions

None. No decision is pending on Rich.

No secrets, credentials, tokens, or signed URLs appear in this record.