Repository navigation
Description
Summary
PR #3927 closed the absent-ancestor hole in the stub-home fence by adding may_be_within, whose first arm is a spelling fold that consults no locale. That fold covers CASE differences. It does not cover Unicode NORMALIZATION, and APFS and HFS+ fold normalization while NTFS and ext4 do not.
The comments shipped in #3927 disclose this accurately at plugins/review/skills/audit-enforceability/scripts/emit-stubs.sh:51-53 and :319-321: the fold is "coarser than the CASE fold of any filesystem this runs on ... it is not coarser than a Unicode NORMALIZATION fold, which APFS and HFS+ apply and NTFS does not". Disclosure is not closure, so this issue tracks the remaining hole.
The hole
fold_path maps ASCII letters to upper case and every run of anything else to a single placeholder. For a precomposed é (NFC, U+00E9) it yields one placeholder; for a decomposed e plus combining acute (NFD, U+0065 U+0301) it yields the ASCII E followed by a placeholder. Those are different strings, so the fold reports two directories.
On APFS and HFS+ they are one directory. When the ancestor does not yet exist, the -ef arm cannot settle the question either, because there is nothing on disk to compare device and inode against. That is precisely the condition #3925 described, so the original escape is reachable again on those filesystems: stubs land inside the declared --scan-dir at exit 0.
Reproduction, on macOS with a case-insensitive normalizing volume, both directories absent beforehand:
T=$(mktemp -d); M="$T/mem"; mkdir -p "$M"
S=plugins/review/skills/audit-enforceability
# NFC in one path, NFD in the other, same directory to the filesystem
bash $S/scripts/emit-stubs.sh \
--findings $S/evals/fixtures/findings-one-per-rung.md \
--classes $S/evals/fixtures/classification-one-per-rung.tsv \
--out "$M/réviews/feat-x" \
--scan-dir "$M/réviews/feat-x" \
--memory-root "$M"
with the two é characters written in opposite normalization forms.
This was NOT executed. Both hosts available during verification are byte-exact: NTFS folds none of the ten Unicode pairs tried, and ext4 folds nothing. The finding is derived from the fold's own definition plus the documented behaviour of APFS and HFS+, and the shipped comments now state the same thing. It is reported as unexecuted rather than as observed.
Why it matters here
The repository recognizes macOS as a target platform: scripts/check-shell-portability.sh:131. As with the original escape, the load-bearing exclusion still holds even when the fence is bypassed, because a stub declares type: enforceability-stub and the fix pass admits only type: review-findings. This is a defence-in-depth gap, not a live corruption of the fix pass, and it is unreachable through the skill's own home composition, where both homes derive from the same charset-sanitized slug and the fixed literals enforceability and reviews. It is reachable at ladder rungs 2 through 4, where a consumer supplies the two homes independently.
Acceptance criteria
- The fence refuses an NFC versus NFD spelling pair of the same directory when that directory does not exist, on a normalizing filesystem, at the same exit code it uses when the directory does exist.
- The fix does not introduce over-refusal on byte-exact filesystems: two genuinely distinct directories whose names differ only by normalization must still be usable on NTFS and ext4, where the filesystem itself treats them as distinct.
- A test case covers the normalization pair. If it cannot execute on the CI runners available, it is skipped with a stated reason naming the filesystem property it needs, in the same honest style as the existing case 16 skip, rather than silently omitted.
- The comments at
emit-stubs.sh:51-53and:319-321are updated to describe whatever the fix actually covers. -
plugins/reviewis bumped past its published version with a matching new changelog entry.
Context
Raised by the independent verifier that re-attacked PR #3927 and cleared it as SAFE TO MERGE. It is recorded as the one residual that verdict does not cover, and it is pre-existing relative to that PR: #3927 narrowed the hole from every filesystem to normalizing filesystems only, and disclosed the remainder rather than leaving it unstated.
Activity
docs: park stub-home Unicode NFC/NFD normalization gap (#3934) (#4964)
revert: remove seven merged out-of-scope park ledgers (#5044)
fix(review): NFC-normalize absent-tail fence only on folding volumes …
fix(review): report the unexecuted normalizing-volume arm in emit-stu…
kyle-sexton commentedon Sep 29, 2026
Audit note. This comes from the 2026-09-29 audit of the Cursor agent run.
Which change delivered this. PR #5043 (review 0.32.1: NFC fold plus volume probe in
emit-stubs.sh) delivered the fix. It usedRefs, because this issue had already been closed by park PR #4964 (Closes #3934, 2026-09-28 05:26Z; the park ledger was reverted by #5044). The closure event therefore points at the wrong PR.What the audit found. The park was an agent choice on a
needs-humanfix request with no owner comment. The fix landed about 70 minutes later. The issue stays closed as COMPLETED; the row is ratify, so it is not reopened.What is proven and what is not.
--check-normalization-fold.Follow-up. PR #5277 makes
skip_caseinemit-stubs.test.shname this gap and fixes stale comments.Optional owner check (macOS). On a macOS APFS host:
emit-stubs.shwith--out,--scan-dir, and--memory-rootset to those paths.needs-humanstays.kyle-sexton commentedon Sep 29, 2026
Acceptance check of #5043 (merged as
00ca004c4, review 0.32.1) against this issue, from the tree at origin/main on 2026-09-29. Decision: the issue stays closed as completed; it is not reopened and not re-labelled not planned. The closure event points at park PR #4964 (ledger reverted in #5044), but the change that answers the issue is #5043.emit-stubs.shputs the absent tail in NFC after a same-device probe says the volume folds normalization (APFS, HFS+). The string-level fold is asserted by--check-normalization-fold. The exit-3 refusal arm has never run on APFS or HFS+ because both CI hosts are byte-exact.emit-stubs.test.sh, withskip_casenaming the filesystem property. PR #5277 makes the skip text say the refusal arm is unexecuted and addsEMIT_STUBS_ASSUME_NORMALIZING=1so the refusal arm runs on a byte-exact runner (a test of the code path, not of a real volume).emit-stubs.sh:46-66and:370-378describe the probe-gated NFC step; PR #5277 corrects the comment that says nothing is created (the probe makes and removes a private directory) and documents the probe cleanup trap.plugins/review0.32.1 (#5043).Only criterion 1 has a gap, and it is a verification gap, not a code gap.
needs-humanstays for the optional macOS check: on an APFS host, run the reproduction from the issue body with two absent paths (one NFC, one NFD e-acute), expect exit 3 and no directories created, and report the exit code here. A non-3 exit is the condition to reopen.fix(review): close audit findings in base ladders, emit-stubs, securi…