diff --git a/plugins/doc-guardian/commands/doc-sync.md b/plugins/doc-guardian/commands/doc-sync.md index 5805a1f..5cae98d 100644 --- a/plugins/doc-guardian/commands/doc-sync.md +++ b/plugins/doc-guardian/commands/doc-sync.md @@ -52,7 +52,13 @@ Then proceed with the sync. - Single commit: `docs: sync documentation with code changes` - Include summary of what was updated in commit body -5. **Output** +5. **Clear Queue** + After successful sync, clear the queue file: + ```bash + echo "# Doc Guardian Queue - cleared after sync on $(date +%Y-%m-%d)" > .doc-guardian-queue + ``` + +6. **Output** ``` ## Documentation Sync Complete diff --git a/plugins/doc-guardian/hooks/notify.sh b/plugins/doc-guardian/hooks/notify.sh index 8511fb8..e4624be 100755 --- a/plugins/doc-guardian/hooks/notify.sh +++ b/plugins/doc-guardian/hooks/notify.sh @@ -2,6 +2,10 @@ # doc-guardian notification hook # Tracks documentation dependencies and queues updates # This is a command hook - guaranteed not to block workflow +# +# IMPORTANT: Output is purely informational - uses passive language +# to avoid triggering Claude to seek user confirmation. +# Run /doc-sync to process the queue when ready. # Read tool input from stdin (JSON with file_path) INPUT=$(cat) @@ -44,6 +48,30 @@ DEPENDENT_DOCS="${DOC_DEPS[$MODIFIED_TYPE]}" # Queue file for tracking pending updates QUEUE_FILE="${CLAUDE_PROJECT_ROOT:-.}/.doc-guardian-queue" +# Debounce: skip notification if same type was logged in last 5 seconds +# This prevents 4+ rapid notifications during batch edits +DEBOUNCE_SECONDS=5 +if [ -f "$QUEUE_FILE" ]; then + LAST_ENTRY=$(tail -1 "$QUEUE_FILE" 2>/dev/null || true) + LAST_TYPE=$(echo "$LAST_ENTRY" | cut -d'|' -f2 | tr -d ' ') + LAST_TIME=$(echo "$LAST_ENTRY" | cut -d'|' -f1 | tr -d ' ') + + if [ "$LAST_TYPE" = "$MODIFIED_TYPE" ] && [ -n "$LAST_TIME" ]; then + # Convert timestamps to seconds for comparison + LAST_EPOCH=$(date -d "$LAST_TIME" +%s 2>/dev/null || echo "0") + NOW_EPOCH=$(date +%s) + DIFF=$((NOW_EPOCH - LAST_EPOCH)) + + if [ "$DIFF" -lt "$DEBOUNCE_SECONDS" ]; then + # Still add to queue, but skip notification + { + echo "$(date +%Y-%m-%dT%H:%M:%S) | $MODIFIED_TYPE | $FILE_PATH | $DEPENDENT_DOCS" + } >> "$QUEUE_FILE" 2>/dev/null || true + exit 0 + fi + fi +fi + # Add to queue (create if doesn't exist, append if does) { echo "$(date +%Y-%m-%dT%H:%M:%S) | $MODIFIED_TYPE | $FILE_PATH | $DEPENDENT_DOCS" @@ -52,7 +80,8 @@ QUEUE_FILE="${CLAUDE_PROJECT_ROOT:-.}/.doc-guardian-queue" # Count pending updates PENDING_COUNT=$(wc -l < "$QUEUE_FILE" 2>/dev/null | tr -d ' ' || echo "1") -# Output notification with specific docs that need updating -echo "[doc-guardian] $MODIFIED_TYPE changed → update needed: $DEPENDENT_DOCS (${PENDING_COUNT} pending)" +# Output passive notification (no action implied) +# Uses "queued" instead of "update needed" to avoid triggering Claude to ask about it +echo "[doc-guardian] drift queued: $MODIFIED_TYPE → $DEPENDENT_DOCS ($PENDING_COUNT total)" exit 0 diff --git a/plugins/projman/hooks/startup-check.sh b/plugins/projman/hooks/startup-check.sh index a86fff7..5dde1a9 100755 --- a/plugins/projman/hooks/startup-check.sh +++ b/plugins/projman/hooks/startup-check.sh @@ -81,6 +81,29 @@ if [[ -f ".env" ]]; then fi fi +# ============================================================================ +# Check version consistency across files (early drift detection) +# ============================================================================ +# Versions must stay in sync across: README.md, marketplace.json, CHANGELOG.md +# Drift here causes confusion and release issues + +if [[ -f "README.md" && -f ".claude-plugin/marketplace.json" && -f "CHANGELOG.md" ]]; then + VERSION_README=$(grep -oE "^# .* - v[0-9]+\.[0-9]+\.[0-9]+" README.md 2>/dev/null | grep -oE "[0-9]+\.[0-9]+\.[0-9]+" || echo "") + # Extract metadata.version specifically (appears after "metadata" in marketplace.json) + VERSION_MARKETPLACE=$(sed -n '/"metadata"/,/}/p' .claude-plugin/marketplace.json 2>/dev/null | grep -oE '"version"[[:space:]]*:[[:space:]]*"[0-9]+\.[0-9]+\.[0-9]+"' | head -1 | grep -oE "[0-9]+\.[0-9]+\.[0-9]+" || echo "") + VERSION_CHANGELOG=$(grep -oE "^## \[[0-9]+\.[0-9]+\.[0-9]+\]" CHANGELOG.md 2>/dev/null | head -1 | grep -oE "[0-9]+\.[0-9]+\.[0-9]+" || echo "") + + if [[ -n "$VERSION_README" && -n "$VERSION_MARKETPLACE" && -n "$VERSION_CHANGELOG" ]]; then + if [[ "$VERSION_README" != "$VERSION_MARKETPLACE" ]] || [[ "$VERSION_README" != "$VERSION_CHANGELOG" ]]; then + echo "$PREFIX Version mismatch detected:" + echo "$PREFIX README.md: v$VERSION_README" + echo "$PREFIX marketplace.json: v$VERSION_MARKETPLACE" + echo "$PREFIX CHANGELOG.md: v$VERSION_CHANGELOG" + echo "$PREFIX Run /suggest-version to analyze and fix" + fi + fi +fi + # Check for CHANGELOG.md [Unreleased] content (version management) if [[ -f "CHANGELOG.md" ]]; then # Check if there's content under [Unreleased] that hasn't been released