From 8fc7df9f5cd379fa478e2ee9fd59388e07060e04 Mon Sep 17 00:00:00 2001 From: Yuichi Uemura Date: Sun, 5 Jul 2026 23:49:00 +0900 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20fix:=20replace=20mapfile=20with?= =?UTF-8?q?=20while-read=20for=20bash=203.2=20compat?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit macOS ships /bin/bash 3.2 by default and 3.2 does not have the mapfile builtin. precompact-transcript-backup.sh starts with `trap 'exit 0' ERR` for fail-open behavior, which silently swallowed the `mapfile: command not found` failure. The visible symptom was that ~/.claude/backups/transcripts/ grew without bound because the rotation step never actually ran. Rewrite the rotation as a POSIX `find | sort | tail | while IFS= read -r` loop so it behaves identically on bash 3 / 4 / 5. Also introduce a version bump policy in AGENTS.md (adapted from reviewable-html-workbench) and bump the plugin version 1.0.0 → 1.0.1 per that policy. Fixes #2 Reported and diagnosed by @fuuuuuuma. Co-Authored-By: Claude Opus 4.7 --- .claude-plugin/marketplace.json | 4 ++-- .claude-plugin/plugin.json | 2 +- AGENTS.md | 19 +++++++++++++++++++ hooks/precompact-transcript-backup.sh | 12 ++++++++---- 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index a418e1d..2c07975 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -5,13 +5,13 @@ }, "metadata": { "description": "Local marketplace for the compact-plus plugin.", - "version": "1.0.0" + "version": "1.0.1" }, "plugins": [ { "name": "compact-plus", "description": "Preserve Claude Code session state before and after context compaction.", - "version": "1.0.0", + "version": "1.0.1", "author": { "name": "u1" }, diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index a5048c4..0442495 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "compact-plus", - "version": "1.0.0", + "version": "1.0.1", "description": "Preserve Claude Code session state before and after context compaction.", "author": { "name": "u1" diff --git a/AGENTS.md b/AGENTS.md index cadf88b..d6308f4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -40,3 +40,22 @@ Claude Code context compaction. - Hooks must fail open and must not block compaction. - Do not write machine-specific absolute paths into git-tracked files. - Use `${CLAUDE_PLUGIN_ROOT}`, `${HOME}`, `${TMPDIR:-/tmp}`, and repository-relative paths. + +## Version bump policy + +Every commit must bump the plugin version, following semver. Commits without a +version bump are not allowed. Keep the following three slots in sync at the +same value — the `Check version consistency` step in `.github/workflows/test.yml` +enforces this and will fail CI on any mismatch: + +1. `.claude-plugin/plugin.json` (`version`) +2. `.claude-plugin/marketplace.json` (`metadata.version`) +3. `.claude-plugin/marketplace.json` (`plugins[0].version`) + +| Change type | Bump | Example | +|-------------|------|---------| +| Bug fix, display tweak, refactor, docs | patch (1.0.0 → 1.0.1) | Fix a silent hook failure, small README edit | +| New feature, new skill, extension of existing behavior | minor (1.0.0 → 1.1.0) | Add a new hook, extend the `/compact-plus` skill | +| Breaking change, incompatible skill / hook I/O change | major (1.0.0 → 2.0.0) | Incompatible shared-state file format change | + +When in doubt, prefer patch. diff --git a/hooks/precompact-transcript-backup.sh b/hooks/precompact-transcript-backup.sh index 5e0807c..86cc196 100755 --- a/hooks/precompact-transcript-backup.sh +++ b/hooks/precompact-transcript-backup.sh @@ -20,9 +20,13 @@ EPOCH=$(date +%s) DEST="$BACKUP_DIR/${EPOCH}-${SESSION_ID}.jsonl" cp "$TRANSCRIPT_PATH" "$DEST" 2>/dev/null || exit 0 -mapfile -t OLD_BACKUPS < <(find "$BACKUP_DIR" -maxdepth 1 -type f -name "*-${SESSION_ID}.jsonl" -print 2>/dev/null | sort -r | tail -n +21) -if [[ ${#OLD_BACKUPS[@]} -gt 0 ]]; then - rm -f "${OLD_BACKUPS[@]}" 2>/dev/null || true -fi +# mapfile is a bash 4+ builtin and stock macOS /bin/bash is 3.2, so use a +# POSIX while-read loop to prune old backups instead. +find "$BACKUP_DIR" -maxdepth 1 -type f -name "*-${SESSION_ID}.jsonl" -print 2>/dev/null \ + | sort -r \ + | tail -n +21 \ + | while IFS= read -r old; do + rm -f "$old" 2>/dev/null || true + done exit 0