Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion plugins/metacognitive-guard/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "metacognitive-guard",
"description": "Cognitive amplification stack: prevents hallucinations via epistemic hooks, competitive code review, fact-checking, and deep-thinking agents.",
"version": "0.2.3",
"version": "0.2.4",
"author": {
"name": "AncpLua",
"url": "https://github.com/ANcpLua"
Expand Down
14 changes: 7 additions & 7 deletions plugins/metacognitive-guard/hooks/scripts/struggle-detector.sh
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,15 @@ score=0

# 1. HEDGING LANGUAGE (uncertainty markers) - count each instance
HEDGE_COUNT=$(echo "$RESPONSE" | grep -oiE \
"I think|I believe|probably|might be|could be|I'm not sure|not certain|unclear|I assume|possibly|perhaps" \
| wc -l | tr -d ' ')
"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")
Comment on lines +46 to +47
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.
if [[ "$HEDGE_COUNT" -gt 3 ]]; then
signals+=("hedging:$HEDGE_COUNT instances of uncertain language")
score=$((score + HEDGE_COUNT * 2))
fi

# 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 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.
RESPONSE_LINES=$(echo "$RESPONSE" | wc -l | tr -d ' ')
if [[ "$QUESTION_COUNT" -gt 3 && "$RESPONSE_LINES" -lt 30 ]]; then
signals+=("deflecting:$QUESTION_COUNT questions in short response")
Expand All @@ -77,17 +77,17 @@ fi

# 5. APOLOGETIC PATTERNS (sign of prior failure) - count each instance
APOLOGY_COUNT=$(echo "$RESPONSE" | grep -oiE \
"sorry|apologize|my mistake|I was wrong|let me try again|I missed" \
| wc -l | tr -d ' ')
"sorry|apologize|my mistake|I was wrong|let me try again|I missed" 2>/dev/null \
| wc -l | tr -d ' ' || echo "0")
Comment on lines +80 to +81
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.
if [[ "$APOLOGY_COUNT" -gt 1 ]]; then
signals+=("apologetic:$APOLOGY_COUNT apologies")
score=$((score + APOLOGY_COUNT * 8))
fi

# 6. WEASEL WORDS (avoiding commitment) - count each instance
WEASEL_COUNT=$(echo "$RESPONSE" | grep -oiE \
"generally|typically|usually|in most cases|it depends|that said|to be fair" \
| wc -l | tr -d ' ')
"generally|typically|usually|in most cases|it depends|that said|to be fair" 2>/dev/null \
| wc -l | tr -d ' ' || echo "0")
Comment on lines +89 to +90
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.
if [[ "$WEASEL_COUNT" -gt 2 ]]; then
signals+=("weaseling:$WEASEL_COUNT non-committal phrases")
score=$((score + WEASEL_COUNT * 3))
Expand Down
Loading