From d7fd21bdad65710a516ff1164aeb33f453667a06 Mon Sep 17 00:00:00 2001 From: shibachan1015 Date: Sat, 25 Jul 2026 11:27:35 +0900 Subject: [PATCH] Fix stat mtime read on GNU/Linux (SessionStart hook crash during compact) `stat -f %m FILE` is BSD/macOS syntax. On GNU/Linux, `-f` means `--file-system`, so the command fails on the bogus `%m` argument and prints filesystem info to *stdout*. Because only stderr is redirected (`2>/dev/null`), that output leaks into CONFIG_MTIME / METH_MTIME, and the following arithmetic aborts: session-orient.sh: line 146: File: "ops/config.yaml" This fires on every SessionStart:compact, so Linux users crash the hook whenever a session compacts. Fix: try the GNU form (`stat -c %Y`) first and fall back to BSD (`stat -f %m`). Works on both Linux and macOS. Applied to all three files using the pattern. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01XvXshgWoaTKx7jAFNeyv77 --- hooks/scripts/session-orient.sh | 4 ++-- skill-sources/rethink/SKILL.md | 4 ++-- skills/health/SKILL.md | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/hooks/scripts/session-orient.sh b/hooks/scripts/session-orient.sh index 05cd652c..76f6a8b1 100755 --- a/hooks/scripts/session-orient.sh +++ b/hooks/scripts/session-orient.sh @@ -139,10 +139,10 @@ fi # Methodology staleness check (Rule Zero) if [ -d ops/methodology ] && [ -f ops/config.yaml ]; then - CONFIG_MTIME=$(stat -f %m ops/config.yaml 2>/dev/null || stat -c %Y ops/config.yaml 2>/dev/null || echo 0) + CONFIG_MTIME=$(stat -c %Y ops/config.yaml 2>/dev/null || stat -f %m ops/config.yaml 2>/dev/null || echo 0) NEWEST_METH=$(ls -t ops/methodology/*.md 2>/dev/null | head -1) if [ -n "$NEWEST_METH" ]; then - METH_MTIME=$(stat -f %m "$NEWEST_METH" 2>/dev/null || stat -c %Y "$NEWEST_METH" 2>/dev/null || echo 0) + METH_MTIME=$(stat -c %Y "$NEWEST_METH" 2>/dev/null || stat -f %m "$NEWEST_METH" 2>/dev/null || echo 0) DAYS_STALE=$(( (CONFIG_MTIME - METH_MTIME) / 86400 )) if [ "$DAYS_STALE" -ge 30 ]; then echo "CONDITION: Methodology notes are ${DAYS_STALE}+ days behind config changes. Consider /rethink drift." diff --git a/skill-sources/rethink/SKILL.md b/skill-sources/rethink/SKILL.md index 76c4257d..8e44fc61 100644 --- a/skill-sources/rethink/SKILL.md +++ b/skill-sources/rethink/SKILL.md @@ -86,9 +86,9 @@ Read: ```bash # Compare config.yaml modification time vs newest methodology note -CONFIG_MTIME=$(stat -f %m ops/config.yaml 2>/dev/null || stat -c %Y ops/config.yaml 2>/dev/null || echo 0) +CONFIG_MTIME=$(stat -c %Y ops/config.yaml 2>/dev/null || stat -f %m ops/config.yaml 2>/dev/null || echo 0) NEWEST_METH=$(ls -t ops/methodology/*.md 2>/dev/null | head -1) -METH_MTIME=$(stat -f %m "$NEWEST_METH" 2>/dev/null || stat -c %Y "$NEWEST_METH" 2>/dev/null || echo 0) +METH_MTIME=$(stat -c %Y "$NEWEST_METH" 2>/dev/null || stat -f %m "$NEWEST_METH" 2>/dev/null || echo 0) ``` If `CONFIG_MTIME > METH_MTIME`: config has changed since methodology was last updated. Flag as staleness drift. diff --git a/skills/health/SKILL.md b/skills/health/SKILL.md index 7c72862b..aab81c72 100644 --- a/skills/health/SKILL.md +++ b/skills/health/SKILL.md @@ -407,7 +407,7 @@ for f in {vocabulary.notes}/*.md; do basename=$(basename "$f" .md) # Last modified (days ago) - mod_days=$(( ($(date +%s) - $(stat -f %m "$f" 2>/dev/null || stat -c %Y "$f" 2>/dev/null)) / 86400 )) + mod_days=$(( ($(date +%s) - $(stat -c %Y "$f" 2>/dev/null || stat -f %m "$f" 2>/dev/null)) / 86400 )) # Incoming link count incoming=$(rg -l "\[\[$basename\]\]" --glob '*.md' | grep -v "$f" | wc -l | tr -d ' ')