Skip to content
This repository was archived by the owner on Apr 11, 2026. It is now read-only.

Commit ddb796b

Browse files
committed
fix(hooks): address adversarial review findings in simplify-ignore
- Detect missing placeholders before expanding (prevents permanent data loss) - Keep original backup pristine (never overwrite with expanded version) - Require comment prefix for annotations (prevents false triggers in strings/docs) - Document disk-state limitation and missing-placeholder safety
1 parent 56777d0 commit ddb796b

2 files changed

Lines changed: 26 additions & 5 deletions

File tree

hooks/SIMPLIFY-IGNORE.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ Backups are in `.claude/.simplify-ignore-cache/` within your project directory.
8181
- **Suffix detection covers `*/` and `-->` only.** Non-standard template comment closers (ERB, Blade) may not work; use `#` or `//` instead.
8282
- **Fuzzy fallback on altered placeholders.** If the model changes a placeholder's reason text, the hook tries a hash-only match which may leave cosmetic debris.
8383
- **File renaming leaves placeholders.** Renamed files retain placeholders; originals are saved as `.recovered` on stop.
84+
- **Annotation must be in a comment.** Only lines with `//`, `/*`, `#`, or `<!--` before `simplify-ignore-start` are recognized. String literals or docs won't accidentally trigger.
85+
- **Disk state during session.** While active, protected files on disk contain placeholders between Read and Edit/Write events. External tools may see broken source during this window.
86+
- **Missing placeholder safety.** If a whole-file Write drops a `BLOCK_<hash>` placeholder, the hook restores from backup to prevent data loss.
8487

8588
## Requirements
8689

hooks/simplify-ignore.sh

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ filter_file() {
5151
local count=0 in_block=0 buf="" reason="" prefix="" suffix=""
5252

5353
while IFS= read -r line || [ -n "$line" ]; do
54-
# Detect start marker
54+
# Detect start marker (must be preceded by a comment prefix: //, /*, #, or <!--)
5555
if [ $in_block -eq 0 ]; then
56-
case "$line" in *simplify-ignore-start*)
56+
case "$line" in *//*simplify-ignore-start*|*'/*'*simplify-ignore-start*|*'#'*simplify-ignore-start*|*'<!--'*simplify-ignore-start*)
5757
in_block=1
5858
buf="$line"
5959
prefix="${line%%simplify-ignore-start*}"
@@ -181,6 +181,24 @@ if [ "$TOOL_NAME" = "Edit" ] || [ "$TOOL_NAME" = "Write" ]; then
181181
[ -f "$CACHE/${ID}.bak" ] || exit 0
182182
ls "$CACHE/${ID}".block.* >/dev/null 2>&1 || exit 0
183183

184+
# Check for missing placeholders BEFORE expanding — if a placeholder was dropped
185+
# by a whole-file Write, restore from the original backup to prevent data loss.
186+
MISSING_BLOCKS=0
187+
for bf in "$CACHE/${ID}".block.*; do
188+
[ -f "$bf" ] || continue
189+
h="${bf##*.}"
190+
if ! grep -q "BLOCK_${h}" "$FILE_PATH" 2>/dev/null; then
191+
MISSING_BLOCKS=$((MISSING_BLOCKS + 1))
192+
printf 'Warning: BLOCK_%s placeholder missing — restoring from backup\n' "$h" >&2
193+
fi
194+
done
195+
if [ "$MISSING_BLOCKS" -gt 0 ]; then
196+
# Restore original backup (contains unfiltered code), then re-filter
197+
cat "$CACHE/${ID}.bak" > "$FILE_PATH"
198+
printf 'Restored %s from backup (%d missing placeholder(s))\n' "$FILE_PATH" "$MISSING_BLOCKS" >&2
199+
exit 0
200+
fi
201+
184202
# Expand placeholders back to original blocks
185203
EXPANDED="$CACHE/${ID}.$$.expanded"
186204
rm -f "$EXPANDED"
@@ -219,10 +237,10 @@ if [ "$TOOL_NAME" = "Edit" ] || [ "$TOOL_NAME" = "Write" ]; then
219237
cat "$EXPANDED" > "$FILE_PATH"
220238
rm -f "$EXPANDED"
221239

222-
# Save expanded version as new backup (includes model's changes)
223-
cp "$FILE_PATH" "$CACHE/${ID}.bak"
240+
# DO NOT overwrite the original backup — keep it pristine for crash recovery.
241+
# The backup always contains the pre-filter original, never the expanded version.
224242

225-
# Re-filter in-place so file stays with placeholders on disk
243+
# Re-filter in-place so next Read sees placeholders
226244
FILTERED="$CACHE/${ID}.$$.tmp"
227245
rm -f "$FILTERED"
228246
if filter_file "$FILE_PATH" "$FILTERED" "$ID"; then

0 commit comments

Comments
 (0)