Skip to content

Conversation

@ANcpLua
Copy link
Owner

@ANcpLua ANcpLua commented Jan 4, 2026

Summary

  • Fixed struggle-detector.sh hook failing with exit code 1 on every Stop event
  • Root cause: set -o pipefail + grep returning exit code 1 when no matches found
  • Added 2>/dev/null and || echo "0" fallback to all grep commands in pipelines

Changes

  • plugins/metacognitive-guard/hooks/scripts/struggle-detector.sh: Fixed 4 grep pipeline patterns
  • plugins/metacognitive-guard/.claude-plugin/plugin.json: Bumped version 0.2.3 → 0.2.4

Test plan

  • Script no longer shows "Stop says: Plugin hook... exited with code 1" error
  • Script correctly counts patterns when matches exist
  • Script returns 0 counts when no matches found

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Improved stability in pattern detection by ensuring the system handles edge cases gracefully when no matches are found.
  • Chores

    • Updated plugin version to 0.2.4.

✏️ Tip: You can customize this high-level summary in your review settings.

With `set -o pipefail`, grep returning exit code 1 (no matches) caused
the entire script to fail. Added `2>/dev/null` and `|| echo "0"` fallback
to all grep commands in pipelines.

Fixes: Stop hook showing error message on every response

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings January 4, 2026 20:16
@coderabbitai
Copy link

coderabbitai bot commented Jan 4, 2026

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

Updated plugin version from 0.2.3 to 0.2.4 and enhanced null-safety in the struggle-detector script by redirecting grep errors to /dev/null and adding default fallbacks (|| echo "0") for count computations across multiple signal detectors.

Changes

Cohort / File(s) Summary
Plugin Version Bump
plugins/metacognitive-guard/.claude-plugin/plugin.json
Version incremented from 0.2.3 to 0.2.4; no structural changes
Null-Safety Enhancements
plugins/metacognitive-guard/hooks/scripts/struggle-detector.sh
Added error redirection (2>/dev/null) and default fallbacks (|| echo "0") to count computations for HEDGING, EXCESSIVE QUESTIONS, APOLOLOGY, and WEASEL WORDS signal detectors to prevent failures on empty grep results

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/struggle-detector-pipefail

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 42cef00 and 5569c77.

📒 Files selected for processing (2)
  • plugins/metacognitive-guard/.claude-plugin/plugin.json
  • plugins/metacognitive-guard/hooks/scripts/struggle-detector.sh

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link

Summary of Changes

Hello @ANcpLua, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a critical issue in the metacognitive-guard plugin's struggle-detector.sh script, where grep commands within pipelines were causing the script to fail due to set -o pipefail when no matches were found. The changes ensure the script's robustness and correct execution by gracefully handling grep's exit code 1, thereby preventing erroneous 'Stop' event failures and improving the reliability of the metacognitive guard system.

Highlights

  • Fix for struggle-detector.sh hook: The struggle-detector.sh hook no longer fails with exit code 1 on 'Stop' events, resolving an issue where grep in pipelines would cause failures when no matches were found.
  • Robust grep handling: All grep commands within pipelines in struggle-detector.sh have been updated to include 2>/dev/null to suppress error output and || echo "0" to ensure a zero exit code and numeric output when no matches are found, preventing pipeline failures due to set -o pipefail.
  • Plugin version bump: The metacognitive-guard plugin version has been incremented from 0.2.3 to 0.2.4 in plugin.json.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@ANcpLua ANcpLua merged commit 2693970 into main Jan 4, 2026
15 of 16 checks passed
@ANcpLua ANcpLua deleted the fix/struggle-detector-pipefail branch January 4, 2026 20:16
Copy link

@claude claude bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review (Opus 4.5)

Verdict: ✅ APPROVED (Post-merge review)

Summary

This PR fixes a common bash scripting issue where set -o pipefail causes grep to return exit code 1 when no matches are found, which was causing the struggle-detector hook to fail on every Stop event.

Findings

⚠️ Medium Priority - CHANGELOG Not Updated

The CHANGELOG.md was not updated for this fix. Per repository conventions (CLAUDE.md section 4.7), every non-trivial change requires a CHANGELOG entry under [Unreleased].

Missing entry should be:

### Fixed
- **metacognitive-guard struggle-detector exit code 1 (YYYY-MM-DD):**
  - Fixed `set -o pipefail` + `grep` returning exit code 1 when no matches found
  - Added `2>/dev/null` and `|| echo "0"` fallback to all grep pipeline patterns
  - Version bump to 0.2.4

⚠️ Medium Priority - Version Mismatch

.claude-plugin/marketplace.json still shows "version": "0.2.3" while plugins/metacognitive-guard/.claude-plugin/plugin.json was correctly bumped to 0.2.4.

Strengths

  1. Correct fix pattern: The 2>/dev/null || echo "0" pattern is the idiomatic way to handle grep no-match in pipefail mode
  2. Consistent application: All 4 grep pipeline patterns were fixed uniformly
  3. Version bump included: Plugin version was correctly incremented
  4. Good test plan: PR description shows thorough testing criteria

Technical Analysis

The fix correctly addresses that grep returns:

  • Exit 0: matches found
  • Exit 1: no matches found
  • Exit 2: error

With set -o pipefail, any non-zero exit in a pipeline causes the whole pipeline to fail. The fix:

  1. Redirects stderr to /dev/null (for any grep errors)
  2. Falls back to "0" if grep returns non-zero (no matches)

Follow-up Actions Needed

  1. Update .claude-plugin/marketplace.json version to 0.2.4
  2. Add CHANGELOG entry under [Unreleased] ### Fixed section

Autonomous review by Claude Opus 4.5 (Type A repo)

Copy link

@claude claude bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review (Opus 4.5)

Verdict: ✅ APPROVED (Post-merge review)

Summary

This PR fixes a common bash scripting issue where set -o pipefail causes grep to return exit code 1 when no matches are found, which was causing the struggle-detector hook to fail on every Stop event.

Findings

⚠️ Medium Priority - CHANGELOG Not Updated

The CHANGELOG.md was not updated for this fix. Per repository conventions (CLAUDE.md section 4.7), every non-trivial change requires a CHANGELOG entry under [Unreleased].

Missing entry should be:

### Fixed
- **metacognitive-guard struggle-detector exit code 1 (YYYY-MM-DD):**
  - Fixed `set -o pipefail` + `grep` returning exit code 1 when no matches found
  - Added `2>/dev/null` and `|| echo "0"` fallback to all grep pipeline patterns
  - Version bump to 0.2.4

⚠️ Medium Priority - Version Mismatch

.claude-plugin/marketplace.json still shows "version": "0.2.3" while plugins/metacognitive-guard/.claude-plugin/plugin.json was correctly bumped to 0.2.4.

Strengths

  1. Correct fix pattern: The 2>/dev/null || echo "0" pattern is the idiomatic way to handle grep no-match in pipefail mode
  2. Consistent application: All 4 grep pipeline patterns were fixed uniformly
  3. Version bump included: Plugin version was correctly incremented
  4. Good test plan: PR description shows thorough testing criteria

Technical Analysis

The fix correctly addresses that grep returns:

  • Exit 0: matches found
  • Exit 1: no matches found
  • Exit 2: error

With set -o pipefail, any non-zero exit in a pipeline causes the whole pipeline to fail. The fix:

  1. Redirects stderr to /dev/null (for any grep errors)
  2. Falls back to "0" if grep returns non-zero (no matches)

Follow-up Actions Needed

  1. Update .claude-plugin/marketplace.json version to 0.2.4
  2. Add CHANGELOG entry under [Unreleased] ### Fixed section

Autonomous review by Claude Opus 4.5 (Type A repo)

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request effectively fixes a bug where the struggle-detector.sh script would exit with an error when grep found no matches, due to set -o pipefail. The solution of appending || echo "0" to the failing pipelines correctly handles the grep exit code and ensures the script continues execution, defaulting to a count of 0. The version bump in plugin.json is also appropriate. I have one minor suggestion to improve the clarity and robustness of one of the grep commands.


# 2. EXCESSIVE QUESTIONS (avoiding action) - count each question mark
QUESTION_COUNT=$(echo "$RESPONSE" | grep -o '?' | wc -l | tr -d ' ')
QUESTION_COUNT=$(echo "$RESPONSE" | grep -o '?' 2>/dev/null | wc -l | tr -d ' ' || echo "0")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

low

Since you are searching for a literal character ?, it's safer, more explicit, and slightly more performant to use grep -F which treats the pattern as a fixed string. While grep -o '?' works here because it's in a basic regular expression context, ? is a special character in other regex flavors, and using -F clearly states the intent to match a literal string, avoiding any potential for misinterpretation.

Suggested change
QUESTION_COUNT=$(echo "$RESPONSE" | grep -o '?' 2>/dev/null | wc -l | tr -d ' ' || echo "0")
QUESTION_COUNT=$(echo "$RESPONSE" | grep -Fo '?' 2>/dev/null | wc -l | tr -d ' ' || echo "0")

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR attempts to fix a bug where struggle-detector.sh exits with code 1 when grep finds no matches in pipelines, caused by the combination of set -o pipefail and grep's exit code 1 behavior. The fix adds 2>/dev/null error suppression and || echo "0" fallback to four grep patterns, and bumps the plugin version from 0.2.3 to 0.2.4.

Critical Issue Found: The fix does not correctly address the root cause. The || echo "0" fallback is placed at the end of the entire pipeline, but with set -o pipefail, the pipeline fails as soon as grep exits with code 1, before the fallback can execute.

Key Changes

  • Modified 4 grep patterns in struggle-detector.sh to add 2>/dev/null and || echo "0"
  • Bumped plugin version to 0.2.4

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
plugins/metacognitive-guard/hooks/scripts/struggle-detector.sh Added error suppression and fallback patterns to 4 grep commands (lines 46-47, 54, 80-81, 89-90), but the fallback placement is incorrect
plugins/metacognitive-guard/.claude-plugin/plugin.json Version bump from 0.2.3 to 0.2.4 for the bug fix

Comment on lines +46 to +47
"I think|I believe|probably|might be|could be|I'm not sure|not certain|unclear|I assume|possibly|perhaps" 2>/dev/null \
| wc -l | tr -d ' ' || echo "0")
Copy link

Copilot AI Jan 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fallback pattern || echo "0" is placed after tr -d ' ', but the pipe chain already includes wc -l which should always succeed and return a numeric value (even "0" when grep finds nothing). The issue is that grep exits with code 1 when no matches are found, causing the pipeline to fail due to set -o pipefail.

The correct fix should place the fallback immediately after the grep command, before the wc -l:

grep -oiE "..." 2>/dev/null || echo "" | wc -l | tr -d ' '

Or wrap just the grep in a subshell with the fallback:

(grep -oiE "..." 2>/dev/null || true) | wc -l | tr -d ' '

The current placement of || echo "0" after the entire pipeline means it will only execute if the final command (tr) fails, which is not the intended behavior.

Copilot uses AI. Check for mistakes.

# 2. EXCESSIVE QUESTIONS (avoiding action) - count each question mark
QUESTION_COUNT=$(echo "$RESPONSE" | grep -o '?' | wc -l | tr -d ' ')
QUESTION_COUNT=$(echo "$RESPONSE" | grep -o '?' 2>/dev/null | wc -l | tr -d ' ' || echo "0")
Copy link

Copilot AI Jan 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as lines 46-47: The fallback pattern || echo "0" is incorrectly placed after the entire pipeline. With set -o pipefail, when grep exits with code 1 (no matches), the entire pipeline fails before reaching || echo "0".

The fallback should be placed immediately after grep, or grep should be wrapped with || true:

grep -o '?' 2>/dev/null || echo "" | wc -l | tr -d ' '

Or:

(grep -o '?' 2>/dev/null || true) | wc -l | tr -d ' '

Copilot uses AI. Check for mistakes.
Comment on lines +80 to +81
"sorry|apologize|my mistake|I was wrong|let me try again|I missed" 2>/dev/null \
| wc -l | tr -d ' ' || echo "0")
Copy link

Copilot AI Jan 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as previous grep patterns: The fallback || echo "0" is placed after the entire pipeline and won't execute when grep exits with code 1 due to set -o pipefail.

The fallback should be placed immediately after grep:

grep -oiE "..." 2>/dev/null || echo "" | wc -l | tr -d ' '

Or:

(grep -oiE "..." 2>/dev/null || true) | wc -l | tr -d ' '

Copilot uses AI. Check for mistakes.
Comment on lines +89 to +90
"generally|typically|usually|in most cases|it depends|that said|to be fair" 2>/dev/null \
| wc -l | tr -d ' ' || echo "0")
Copy link

Copilot AI Jan 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as previous grep patterns: The fallback || echo "0" is placed after the entire pipeline and won't execute when grep exits with code 1 due to set -o pipefail.

The fallback should be placed immediately after grep:

grep -oiE "..." 2>/dev/null || echo "" | wc -l | tr -d ' '

Or:

(grep -oiE "..." 2>/dev/null || true) | wc -l | tr -d ' '

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants