From 96963531fcf41f29af62641c941d1c39696bd1f4 Mon Sep 17 00:00:00 2001 From: lmiranda Date: Fri, 23 Jan 2026 12:36:00 -0500 Subject: [PATCH 1/4] fix(labels): add duplicate check before creating labels create_label_smart now checks if label already exists before creating. - Checks both org and repo labels - Handles format variations (Type/Bug vs Type: Bug) - Returns {skipped: true} if label already exists - Prevents duplicate label creation errors Co-Authored-By: Claude Opus 4.5 --- mcp-servers/gitea/mcp_server/tools/labels.py | 47 ++++++++++++++++---- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/mcp-servers/gitea/mcp_server/tools/labels.py b/mcp-servers/gitea/mcp_server/tools/labels.py index 3fb87a7..719519f 100644 --- a/mcp-servers/gitea/mcp_server/tools/labels.py +++ b/mcp-servers/gitea/mcp_server/tools/labels.py @@ -275,6 +275,7 @@ class LabelTools: ) -> Dict: """ Create a label at the appropriate level (org or repo) based on category. + Skips if label already exists (checks both org and repo levels). Organization labels: Agent, Complexity, Effort, Priority, Risk, Source, Type Repository labels: Component, Tech @@ -286,7 +287,7 @@ class LabelTools: repo: Repository in 'owner/repo' format Returns: - Created label dictionary with 'level' key indicating where it was created + Created label dictionary with 'level' key, or 'skipped' if already exists """ loop = asyncio.get_event_loop() @@ -294,6 +295,41 @@ class LabelTools: if not target_repo or '/' not in target_repo: raise ValueError("Use 'owner/repo' format (e.g. 'org/repo-name')") + owner = target_repo.split('/')[0] + is_org = await loop.run_in_executor( + None, + lambda: self.gitea.is_org_repo(target_repo) + ) + + # Fetch existing labels to check for duplicates + existing_labels = await self.get_labels(target_repo) + all_existing = existing_labels.get('organization', []) + existing_labels.get('repository', []) + existing_names = [label['name'].lower() for label in all_existing] + + # Normalize the new label name for comparison + name_normalized = name.lower() + + # Also check for format variations (Type/Bug vs Type: Bug) + name_variations = [name_normalized] + if '/' in name: + name_variations.append(name.replace('/', ': ').lower()) + name_variations.append(name.replace('/', ':').lower()) + elif ': ' in name: + name_variations.append(name.replace(': ', '/').lower()) + elif ':' in name: + name_variations.append(name.replace(':', '/').lower()) + + # Check if label already exists in any format + for variation in name_variations: + if variation in existing_names: + logger.info(f"Label '{name}' already exists (found as '{variation}'), skipping") + return { + 'name': name, + 'skipped': True, + 'reason': f"Label already exists", + 'level': 'existing' + } + # Parse category from label name category = None if '/' in name: @@ -301,13 +337,6 @@ class LabelTools: elif ':' in name: category = name.split(':')[0].strip().lower().rstrip('s') - # Determine level - owner = target_repo.split('/')[0] - is_org = await loop.run_in_executor( - None, - lambda: self.gitea.is_org_repo(target_repo) - ) - # If it's an org repo and the category is an org-level category, create at org level if is_org and category in self.ORG_LABEL_CATEGORIES: result = await loop.run_in_executor( @@ -315,6 +344,7 @@ class LabelTools: lambda: self.gitea.create_org_label(owner, name, color, description) ) result['level'] = 'organization' + result['skipped'] = False logger.info(f"Created organization label '{name}' in {owner}") else: # Create at repo level @@ -323,6 +353,7 @@ class LabelTools: lambda: self.gitea.create_label(name, color, description, target_repo) ) result['level'] = 'repository' + result['skipped'] = False logger.info(f"Created repository label '{name}' in {target_repo}") return result From b34304ed57b34a58df14620f7ccd00749b048263 Mon Sep 17 00:00:00 2001 From: lmiranda Date: Fri, 23 Jan 2026 12:41:33 -0500 Subject: [PATCH 2/4] fix: add cache clearing and hook verification scripts - post-update.sh now clears plugin cache automatically - verify-hooks.sh checks ALL locations for prompt hooks - Prevents cached old hooks from overriding fixed hooks Co-Authored-By: Claude Opus 4.5 --- scripts/post-update.sh | 5 +++++ scripts/verify-hooks.sh | 44 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100755 scripts/verify-hooks.sh diff --git a/scripts/post-update.sh b/scripts/post-update.sh index e8e9041..b93d8fc 100755 --- a/scripts/post-update.sh +++ b/scripts/post-update.sh @@ -78,3 +78,8 @@ main() { } main "$@" + +# Clear plugin cache to ensure fresh hooks are loaded +echo "Clearing plugin cache..." +rm -rf ~/.claude/plugins/cache/leo-claude-mktplace/ +echo "Cache cleared" diff --git a/scripts/verify-hooks.sh b/scripts/verify-hooks.sh new file mode 100755 index 0000000..bb6fff8 --- /dev/null +++ b/scripts/verify-hooks.sh @@ -0,0 +1,44 @@ +#!/bin/bash +# Verify all hooks are command type (not prompt) +# Run this after any plugin update + +echo "=== HOOK VERIFICATION ===" +echo "" + +FAILED=0 + +# Check ALL hooks.json files in .claude directory +for f in $(find ~/.claude -name "hooks.json" 2>/dev/null); do + if grep -q '"type": "prompt"' "$f" || grep -q '"type":"prompt"' "$f"; then + echo "❌ PROMPT HOOK FOUND: $f" + FAILED=1 + fi +done + +# Check cache specifically +if [ -d ~/.claude/plugins/cache/leo-claude-mktplace ]; then + echo "❌ CACHE EXISTS: ~/.claude/plugins/cache/leo-claude-mktplace" + echo " Run: rm -rf ~/.claude/plugins/cache/leo-claude-mktplace/" + FAILED=1 +fi + +# Verify installed hooks are command type +for plugin in doc-guardian code-sentinel projman pr-review project-hygiene; do + HOOK_FILE=~/.claude/plugins/marketplaces/leo-claude-mktplace/plugins/$plugin/hooks/hooks.json + if [ -f "$HOOK_FILE" ]; then + if grep -q '"type": "command"' "$HOOK_FILE" || grep -q '"type":"command"' "$HOOK_FILE"; then + echo "✓ $plugin: command type" + else + echo "❌ $plugin: NOT command type" + FAILED=1 + fi + fi +done + +echo "" +if [ $FAILED -eq 0 ]; then + echo "✓ All hooks verified OK" +else + echo "❌ ISSUES FOUND - fix before using" + exit 1 +fi From 0466b299a7b1aafd46b025f90c3e1d6b96ec98be Mon Sep 17 00:00:00 2001 From: lmiranda Date: Fri, 23 Jan 2026 12:44:27 -0500 Subject: [PATCH 3/4] fix: add mandatory behavior rules and verification - Add MANDATORY BEHAVIOR RULES to CLAUDE.md (read every session) - Rules: check everything, believe user, verify before saying done - post-update.sh now clears plugin cache - verify-hooks.sh checks all locations for prompt hooks These rules prevent wasted user time from AI overconfidence. Co-Authored-By: Claude Opus 4.5 --- CLAUDE.md | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index 3d9f720..d80ad4f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,6 +1,46 @@ # CLAUDE.md This file provides guidance to Claude Code when working with code in this repository. +## ⛔ MANDATORY BEHAVIOR RULES - READ FIRST + +**These rules are NON-NEGOTIABLE. Violating them wastes the user's time and money.** + +### 1. WHEN USER ASKS YOU TO CHECK SOMETHING - CHECK EVERYTHING +- Search ALL locations, not just where you think it is +- Check cache directories: `~/.claude/plugins/cache/` +- Check installed: `~/.claude/plugins/marketplaces/` +- Check source: `~/claude-plugins-work/` +- **NEVER say "no" or "that's not the issue" without exhaustive verification** + +### 2. WHEN USER SAYS SOMETHING IS WRONG - BELIEVE THEM +- The user knows their system better than you +- Investigate thoroughly before disagreeing +- If user suspects cache, CHECK THE CACHE +- If user suspects a file, READ THE FILE +- **Your confidence is often wrong. User's instincts are often right.** + +### 3. NEVER SAY "DONE" WITHOUT VERIFICATION +- Run the actual command/script to verify +- Show the output to the user +- Check ALL affected locations +- **"Done" means VERIFIED WORKING, not "I made changes"** + +### 4. SHOW EXACTLY WHAT USER ASKS FOR +- If user asks for messages, show the MESSAGES +- If user asks for code, show the CODE +- If user asks for output, show the OUTPUT +- **Don't interpret or summarize unless asked** + +### 5. AFTER PLUGIN UPDATES - ALWAYS CLEAR CACHE +```bash +rm -rf ~/.claude/plugins/cache/leo-claude-mktplace/ +./scripts/verify-hooks.sh +``` + +**FAILURE TO FOLLOW THESE RULES = WASTED USER TIME = UNACCEPTABLE** + +--- + ## Project Overview From 7a2966367d21fec79057d69cee41bac213688848 Mon Sep 17 00:00:00 2001 From: lmiranda Date: Fri, 23 Jan 2026 12:46:18 -0500 Subject: [PATCH 4/4] feat(claude-config-maintainer): auto-enforce mandatory behavior rules SessionStart hook checks if CLAUDE.md has mandatory rules. If missing, adds them automatically. Rules enforced: - Check everything when user asks - Believe user when they say something's wrong - Never say "done" without verification - Show exactly what user asks for Co-Authored-By: Claude Opus 4.5 --- .../hooks/enforce-rules.sh | 68 +++++++++++++++++++ .../claude-config-maintainer/hooks/hooks.json | 10 +++ 2 files changed, 78 insertions(+) create mode 100755 plugins/claude-config-maintainer/hooks/enforce-rules.sh create mode 100644 plugins/claude-config-maintainer/hooks/hooks.json diff --git a/plugins/claude-config-maintainer/hooks/enforce-rules.sh b/plugins/claude-config-maintainer/hooks/enforce-rules.sh new file mode 100755 index 0000000..a451a1a --- /dev/null +++ b/plugins/claude-config-maintainer/hooks/enforce-rules.sh @@ -0,0 +1,68 @@ +#!/bin/bash +# claude-config-maintainer: enforce mandatory behavior rules +# Checks if CLAUDE.md has the rules, adds them if missing + +PREFIX="[claude-config-maintainer]" + +# Find CLAUDE.md in current directory or parent +CLAUDE_MD="" +if [ -f "./CLAUDE.md" ]; then + CLAUDE_MD="./CLAUDE.md" +elif [ -f "../CLAUDE.md" ]; then + CLAUDE_MD="../CLAUDE.md" +fi + +# If no CLAUDE.md found, exit silently +if [ -z "$CLAUDE_MD" ]; then + exit 0 +fi + +# Check if mandatory rules exist +if grep -q "MANDATORY BEHAVIOR RULES" "$CLAUDE_MD" 2>/dev/null; then + # Rules exist, all good + exit 0 +fi + +# Rules missing - add them +RULES='## ⛔ MANDATORY BEHAVIOR RULES - READ FIRST + +**These rules are NON-NEGOTIABLE. Violating them wastes the user'\''s time and money.** + +### 1. WHEN USER ASKS YOU TO CHECK SOMETHING - CHECK EVERYTHING +- Search ALL locations, not just where you think it is +- Check cache directories: `~/.claude/plugins/cache/` +- Check installed: `~/.claude/plugins/marketplaces/` +- Check source directories +- **NEVER say "no" or "that'\''s not the issue" without exhaustive verification** + +### 2. WHEN USER SAYS SOMETHING IS WRONG - BELIEVE THEM +- The user knows their system better than you +- Investigate thoroughly before disagreeing +- **Your confidence is often wrong. User'\''s instincts are often right.** + +### 3. NEVER SAY "DONE" WITHOUT VERIFICATION +- Run the actual command/script to verify +- Show the output to the user +- **"Done" means VERIFIED WORKING, not "I made changes"** + +### 4. SHOW EXACTLY WHAT USER ASKS FOR +- If user asks for messages, show the MESSAGES +- If user asks for code, show the CODE +- **Do not interpret or summarize unless asked** + +**FAILURE TO FOLLOW THESE RULES = WASTED USER TIME = UNACCEPTABLE** + +--- + +' + +# Create temp file with rules + existing content +{ + head -1 "$CLAUDE_MD" + echo "" + echo "$RULES" + tail -n +2 "$CLAUDE_MD" +} > "${CLAUDE_MD}.tmp" + +mv "${CLAUDE_MD}.tmp" "$CLAUDE_MD" +echo "$PREFIX Added mandatory behavior rules to CLAUDE.md" diff --git a/plugins/claude-config-maintainer/hooks/hooks.json b/plugins/claude-config-maintainer/hooks/hooks.json new file mode 100644 index 0000000..d80c531 --- /dev/null +++ b/plugins/claude-config-maintainer/hooks/hooks.json @@ -0,0 +1,10 @@ +{ + "hooks": { + "SessionStart": [ + { + "type": "command", + "command": "${CLAUDE_PLUGIN_ROOT}/hooks/enforce-rules.sh" + } + ] + } +}