7 Commits

Author SHA1 Message Date
0d120bd041 Merge pull request 'feat: add plugin name prefixes to hooks and improve git-flow sync' (#105) from feat/hook-improvements-and-sync-prune into development 2026-01-22 21:14:32 +00:00
508832dae1 feat: add plugin name prefixes to hooks and improve git-flow sync
- Add [plugin-name] prefix to all hook messages for better identification
- Make doc-guardian hook notification-only (non-blocking)
- Add stale branch detection to /commit-sync with git fetch --prune
- Enhance /branch-cleanup to handle stale branches separately

Closes improvements for hook UX and git workflow

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 16:13:17 -05:00
0b23a02886 Merge pull request 'fix: add curl fallback to /debug-report when MCP tools unavailable' (#103) from fix/issue-100-debug-report-fallback into development
Reviewed-on: #103
2026-01-22 20:01:32 +00:00
71987ee537 fix: switch to development branch before adding issue comments
The MCP server's branch-aware security blocks write operations on
protected branches (main, fix/*, etc). After pushing a feature branch
and creating a PR, we must switch back to development before adding
comments to issues via MCP tools.
2026-01-22 14:28:01 -05:00
b7829dca05 fix: add curl fallback to /debug-report when MCP tools unavailable
When MCP tools are not available in a session (the very scenario
/debug-report is designed to diagnose), the command now falls back to:

1. Check for Gitea credentials at ~/.config/claude/gitea.env
2. Use curl + jq to create the issue via Gitea REST API
3. If no credentials, save report to local file for manual submission

Security measures:
- Uses mktemp -m 600 for restrictive file permissions
- Uses jq --rawfile for safe JSON construction (no command substitution)
- Proper cleanup of temporary files

Fixes #100

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 14:19:05 -05:00
9b0e9a69b1 Merge pull request 'development' (#102) from development into main
Reviewed-on: #102
2026-01-22 18:36:36 +00:00
620173eef6 Merge pull request 'Release: suggest_labels fix' (#96) from development into main 2026-01-22 15:54:28 +00:00
10 changed files with 185 additions and 32 deletions

View File

@@ -4,6 +4,26 @@ All notable changes to the Leo Claude Marketplace will be documented in this fil
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [3.1.1] - 2026-01-22
### Added
- **git-flow:** `/commit-sync` now prunes stale remote-tracking branches with `git fetch --prune`
- **git-flow:** `/commit-sync` detects and reports local branches with deleted upstreams
- **git-flow:** `/branch-cleanup` now handles stale branches (upstream gone) separately from merged branches
- **git-flow:** New `GIT_CLEANUP_STALE` environment variable for stale branch cleanup control
### Changed
- **All hooks:** Added `[plugin-name]` prefix to all hook messages for better identification
- `[projman]`, `[pr-review]`, `[code-sentinel]`, `[doc-guardian]` prefixes
- **doc-guardian:** Hook now notification-only (no file reads or blocking operations)
- Suggests running `/doc-sync` instead of performing inline checks
- Significantly reduces workflow interruption
### Fixed
- doc-guardian hook no longer stalls workflow with deep file analysis
---
## [3.1.0] - 2026-01-21 ## [3.1.0] - 2026-01-21
### Added ### Added

View File

@@ -1,4 +1,4 @@
# Leo Claude Marketplace - v3.1.0 # Leo Claude Marketplace - v3.1.1
A collection of Claude Code plugins for project management, infrastructure automation, and development workflows. A collection of Claude Code plugins for project management, infrastructure automation, and development workflows.

View File

@@ -6,7 +6,7 @@
"hooks": [ "hooks": [
{ {
"type": "prompt", "type": "prompt",
"prompt": "SECURITY CHECK - Before writing this code, scan for these patterns:\n\n**Critical (BLOCK if found):**\n- eval(), exec() with user input\n- SQL string concatenation (SQL injection)\n- shell=True with user input (command injection)\n- Hardcoded secrets (API keys, passwords, tokens)\n- Pickle/marshal deserialization of untrusted data\n- innerHTML/dangerouslySetInnerHTML with user content (XSS)\n\n**Warning (WARN but allow):**\n- subprocess without input validation\n- File operations without path sanitization\n- HTTP requests without timeout\n- Broad exception catches (except:)\n- Debug/print statements with sensitive data\n\n**Response:**\n- If CRITICAL found: STOP, explain the issue, suggest safe alternative\n- If WARNING found: Note it briefly, proceed with suggestion\n- If clean: Proceed silently (say nothing)\n\nDo NOT announce clean scans. Only speak if issues found." "prompt": "[code-sentinel] SECURITY CHECK - Before writing this code, scan for these patterns:\n\n**Critical (BLOCK if found):**\n- eval(), exec() with user input\n- SQL string concatenation (SQL injection)\n- shell=True with user input (command injection)\n- Hardcoded secrets (API keys, passwords, tokens)\n- Pickle/marshal deserialization of untrusted data\n- innerHTML/dangerouslySetInnerHTML with user content (XSS)\n\n**Warning (WARN but allow):**\n- subprocess without input validation\n- File operations without path sanitization\n- HTTP requests without timeout\n- Broad exception catches (except:)\n- Debug/print statements with sensitive data\n\n**Response:**\n- If CRITICAL found: STOP with '[code-sentinel] BLOCKED:', explain the issue, suggest safe alternative\n- If WARNING found: Note briefly with '[code-sentinel] WARNING:', proceed with suggestion\n- If clean: Proceed silently (say nothing)\n\nDo NOT announce clean scans. Only speak if issues found."
} }
] ]
} }

View File

@@ -6,7 +6,7 @@
"hooks": [ "hooks": [
{ {
"type": "prompt", "type": "prompt",
"prompt": "A file was just modified. Silently check if this change affects any documentation:\n\n1. If a code file changed: check if README, CLAUDE.md, docstrings, or API docs reference the modified functions/classes/configs\n2. If drift detected: briefly mention it to the user (e.g., 'Note: This change may require updating X documentation')\n3. Do NOT block the workflow - just inform\n\nDo NOT announce this check unless drift is found. Work silently." "prompt": "[doc-guardian] QUICK drift check (DO NOT block workflow):\n\n1. ONLY check if the modified file is referenced in README.md, CLAUDE.md, or API docs in the SAME directory\n2. Do NOT read files or perform deep analysis - just note potential drift based on file name/path\n3. If potential drift: output a single line like '[doc-guardian] Note: {filename} changed - may affect {doc}. Run /doc-sync to verify.'\n4. If no obvious drift: say nothing\n\nIMPORTANT: This is notification-only. Do NOT read documentation files, do NOT make changes, do NOT use any tools. Just a quick mental check based on the file path."
} }
] ]
} }

View File

@@ -1,12 +1,19 @@
# /branch-cleanup - Clean Merged Branches # /branch-cleanup - Clean Merged and Stale Branches
## Purpose ## Purpose
Remove branches that have been merged, both locally and optionally on remote. Remove branches that have been merged OR whose remote tracking branch no longer exists, both locally and optionally on remote.
## Behavior ## Behavior
### Step 1: Identify Merged Branches ### Step 1: Prune Remote Refs
```bash
# Remove stale remote-tracking references
git fetch --prune
```
### Step 2: Identify Branches for Cleanup
```bash ```bash
# Find merged local branches # Find merged local branches
@@ -14,19 +21,26 @@ git branch --merged <base-branch>
# Find merged remote branches # Find merged remote branches
git branch -r --merged <base-branch> git branch -r --merged <base-branch>
# Find local branches with deleted upstreams (stale)
git branch -vv | grep ': gone]'
``` ```
### Step 2: Present Findings ### Step 3: Present Findings
``` ```
Found 5 merged branches: Found branches for cleanup:
Local: Merged (safe to delete):
- feat/login-page (merged 3 days ago) - feat/login-page (merged 3 days ago)
- fix/typo-header (merged 1 week ago) - fix/typo-header (merged 1 week ago)
- chore/deps-update (merged 2 weeks ago) - chore/deps-update (merged 2 weeks ago)
Remote: Stale (remote deleted):
- feat/old-feature (upstream gone)
- fix/already-merged (upstream gone)
Remote (merged into base):
- origin/feat/login-page - origin/feat/login-page
- origin/fix/typo-header - origin/fix/typo-header
@@ -36,35 +50,40 @@ Protected (won't delete):
- staging - staging
Delete these branches? Delete these branches?
1. Delete all (local + remote) 1. Delete all (local merged + stale + remote)
2. Delete local only 2. Delete merged only (skip stale)
3. Let me pick which ones 3. Delete stale only (upstream gone)
4. Cancel 4. Let me pick which ones
5. Cancel
``` ```
### Step 3: Execute Cleanup ### Step 4: Execute Cleanup
```bash ```bash
# Delete local # Delete merged local branches
git branch -d <branch-name> git branch -d <branch-name>
# Delete remote # Delete stale local branches (force needed since no upstream)
git branch -D <stale-branch-name>
# Delete remote branches
git push origin --delete <branch-name> git push origin --delete <branch-name>
``` ```
### Step 4: Report ### Step 5: Report
``` ```
Cleanup complete: Cleanup complete:
Deleted local: 3 branches Deleted local (merged): 3 branches
Deleted local (stale): 2 branches
Deleted remote: 2 branches Deleted remote: 2 branches
Skipped: 0 branches Skipped: 0 branches
Remaining local branches: Remaining local branches:
- main - main
- development - development
- feat/current-work (not merged) - feat/current-work (not merged, has upstream)
``` ```
## Environment Variables ## Environment Variables
@@ -74,20 +93,24 @@ Remaining local branches:
| `GIT_DEFAULT_BASE` | `development` | Base branch for merge detection | | `GIT_DEFAULT_BASE` | `development` | Base branch for merge detection |
| `GIT_PROTECTED_BRANCHES` | `main,master,development,staging,production` | Never delete these | | `GIT_PROTECTED_BRANCHES` | `main,master,development,staging,production` | Never delete these |
| `GIT_AUTO_DELETE_REMOTE` | `false` | Auto-delete remote branches | | `GIT_AUTO_DELETE_REMOTE` | `false` | Auto-delete remote branches |
| `GIT_CLEANUP_STALE` | `true` | Include stale branches (upstream gone) in cleanup |
## Safety ## Safety
- Never deletes protected branches - Never deletes protected branches
- Warns about unmerged branches - Warns about unmerged branches that still have upstreams
- Confirms before deleting remote branches - Confirms before deleting remote branches
- Uses `-d` (safe delete) not `-D` (force delete) - Uses `-d` (safe delete) for merged branches
- Uses `-D` (force delete) only for stale branches with confirmation
- Stale branches are highlighted separately for review
## Output ## Output
On success: On success:
``` ```
Cleaned up: Cleaned up:
Local: 3 branches deleted Local (merged): 3 branches deleted
Local (stale): 2 branches deleted
Remote: 2 branches deleted Remote: 2 branches deleted
Repository is tidy! Repository is tidy!

View File

@@ -2,7 +2,7 @@
## Purpose ## Purpose
Full sync operation: commit local changes, push to remote, and sync with upstream/base branch. Full sync operation: commit local changes, push to remote, sync with upstream/base branch, and clean up stale remote-tracking branches.
## Behavior ## Behavior
@@ -19,8 +19,8 @@ Push committed changes to remote branch.
Pull latest from base branch and rebase/merge: Pull latest from base branch and rebase/merge:
```bash ```bash
# Fetch all # Fetch all with prune (removes stale remote-tracking refs)
git fetch --all git fetch --all --prune
# Rebase on base branch # Rebase on base branch
git rebase origin/<base-branch> git rebase origin/<base-branch>
@@ -29,7 +29,26 @@ git rebase origin/<base-branch>
git push --force-with-lease git push --force-with-lease
``` ```
### Step 4: Report Status ### Step 4: Detect Stale Local Branches
Check for local branches tracking deleted remotes:
```bash
# Find local branches with gone upstreams
git branch -vv | grep ': gone]'
```
If stale branches found, report them:
```
Stale local branches (remote deleted):
- feat/old-feature (was tracking origin/feat/old-feature)
- fix/merged-bugfix (was tracking origin/fix/merged-bugfix)
Run /branch-cleanup to remove these branches.
```
### Step 5: Report Status
``` ```
Sync complete: Sync complete:
@@ -40,6 +59,10 @@ Base: development @ xyz7890 (synced)
Your branch is up-to-date with development. Your branch is up-to-date with development.
No conflicts detected. No conflicts detected.
Cleanup:
Remote refs pruned: 2
Stale local branches: 2 (run /branch-cleanup to remove)
``` ```
## Environment Variables ## Environment Variables
@@ -48,6 +71,7 @@ No conflicts detected.
|----------|---------|-------------| |----------|---------|-------------|
| `GIT_DEFAULT_BASE` | `development` | Branch to sync with | | `GIT_DEFAULT_BASE` | `development` | Branch to sync with |
| `GIT_SYNC_STRATEGY` | `rebase` | How to incorporate upstream changes | | `GIT_SYNC_STRATEGY` | `rebase` | How to incorporate upstream changes |
| `GIT_AUTO_PRUNE` | `true` | Auto-prune stale remote refs on sync |
## Conflict Handling ## Conflict Handling
@@ -76,4 +100,5 @@ Pushed to: origin/feat/password-reset
Synced with: development (xyz7890) Synced with: development (xyz7890)
Status: Clean, up-to-date Status: Clean, up-to-date
Stale branches: None (or N found - run /branch-cleanup)
``` ```

View File

@@ -3,7 +3,7 @@
"SessionStart": [ "SessionStart": [
{ {
"type": "prompt", "type": "prompt",
"prompt": "Perform silent startup checks:\n\n1. Check if MCP venvs exist at the installed marketplace location. If the marketplace is installed but venvs are missing, warn the user to run setup.sh from that location.\n\n2. Check if the project git remote matches .env configuration (GITEA_ORG/GITEA_REPO). If mismatch, warn about /project-sync.\n\nStay silent if all checks pass or not applicable. Be quick and non-blocking." "prompt": "[pr-review] Perform silent startup checks:\n\n1. Check if MCP venvs exist at the installed marketplace location. If the marketplace is installed but venvs are missing, warn the user: '[pr-review] MCP venvs missing - run setup.sh from installed marketplace location'.\n\n2. Check if the project git remote matches .env configuration (GITEA_ORG/GITEA_REPO). If mismatch, warn: '[pr-review] Git remote mismatch - run /project-sync'.\n\nStay silent if all checks pass or not applicable. Be quick and non-blocking."
} }
] ]
} }

View File

@@ -184,6 +184,10 @@ Use this exact template:
### Step 6: Create Issue in Marketplace ### Step 6: Create Issue in Marketplace
**First, check if MCP tools are available.** Attempt to use an MCP tool. If you receive "tool not found", "not in function list", or similar error, the MCP server is not accessible in this session - use the curl fallback.
#### Option A: MCP Available (preferred)
``` ```
mcp__plugin_projman_gitea__create_issue( mcp__plugin_projman_gitea__create_issue(
repo=MARKETPLACE_REPO, repo=MARKETPLACE_REPO,
@@ -195,6 +199,81 @@ mcp__plugin_projman_gitea__create_issue(
If labels don't exist, create issue without labels. If labels don't exist, create issue without labels.
#### Option B: MCP Unavailable - Use curl Fallback
If MCP tools are not available (the very issue you may be diagnosing), use this fallback:
**1. Check for Gitea credentials:**
```bash
if [[ -f ~/.config/claude/gitea.env ]]; then
source ~/.config/claude/gitea.env
echo "Credentials found. API URL: $GITEA_API_URL"
else
echo "No credentials at ~/.config/claude/gitea.env"
fi
```
**2. If credentials exist, create issue via curl with proper JSON escaping:**
Create secure temp files and save content:
```bash
# Create temp files with restrictive permissions
DIAG_TITLE=$(mktemp -p /tmp -m 600 diag-title.XXXXXX)
DIAG_BODY=$(mktemp -p /tmp -m 600 diag-body.XXXXXX)
DIAG_PAYLOAD=$(mktemp -p /tmp -m 600 diag-payload.XXXXXX)
# Save title
echo "[Diagnostic] [summary of main failure]" > "$DIAG_TITLE"
# Save body (paste Step 5 content) - heredoc delimiter prevents shell expansion
cat > "$DIAG_BODY" << 'DIAGNOSTIC_EOF'
[Paste the full issue content from Step 5 here]
DIAGNOSTIC_EOF
```
Construct JSON safely using jq's --rawfile (avoids command substitution):
```bash
# Build JSON payload using jq with --rawfile for safe content handling
jq -n \
--rawfile title "$DIAG_TITLE" \
--rawfile body "$DIAG_BODY" \
'{title: ($title | rtrimstr("\n")), body: $body}' > "$DIAG_PAYLOAD"
# Create issue using the JSON file
curl -s -X POST "${GITEA_API_URL}/repos/${MARKETPLACE_REPO}/issues" \
-H "Authorization: token ${GITEA_API_TOKEN}" \
-H "Content-Type: application/json" \
-d @"$DIAG_PAYLOAD" | jq '.html_url // .'
# Secure cleanup
rm -f "$DIAG_TITLE" "$DIAG_BODY" "$DIAG_PAYLOAD"
```
**3. If no credentials found, save report locally:**
```bash
REPORT_FILE=$(mktemp -p /tmp -m 600 diagnostic-report-XXXXXX.md)
cat > "$REPORT_FILE" << 'DIAGNOSTIC_EOF'
[Paste the full issue content from Step 5 here]
DIAGNOSTIC_EOF
echo "Report saved to: $REPORT_FILE"
```
Then inform the user:
```
MCP tools are unavailable and no Gitea credentials found at ~/.config/claude/gitea.env.
Diagnostic report saved to: [REPORT_FILE]
To create the issue manually:
1. Configure credentials: See docs/CONFIGURATION.md
2. Or create issue directly at: http://gitea.hotserv.cloud/[MARKETPLACE_REPO]/issues/new
```
### Step 7: Report to User ### Step 7: Report to User
Display summary: Display summary:
@@ -258,5 +337,6 @@ and I can create a manual bug report.
- If not a git repo, ask user for the repository path - If not a git repo, ask user for the repository path
**MCP tools not available** **MCP tools not available**
- The projman plugin may not be properly installed - Use the curl fallback in Step 6, Option B
- Check if .mcp.json exists and is configured - Requires Gitea credentials at `~/.config/claude/gitea.env`
- If no credentials, report will be saved locally for manual submission

View File

@@ -312,7 +312,12 @@ git push -u origin fix/issue-[NUMBER]-[brief-description]
3. Create PR via API or MCP tools 3. Create PR via API or MCP tools
4. Add comment to original issue: 4. **Switch back to development branch** (required for MCP issue operations):
```bash
git checkout development
```
5. Add comment to original issue:
``` ```
mcp__plugin_projman_gitea__add_comment( mcp__plugin_projman_gitea__add_comment(
repo=REPO_NAME, repo=REPO_NAME,

View File

@@ -3,7 +3,7 @@
"SessionStart": [ "SessionStart": [
{ {
"type": "prompt", "type": "prompt",
"prompt": "Perform silent startup checks:\n\n1. Check if MCP venvs exist at the installed marketplace location. If the marketplace is installed but venvs are missing, warn the user to run setup.sh from that location.\n\n2. Check if the project git remote matches .env configuration (GITEA_ORG/GITEA_REPO). If mismatch, warn about /project-sync.\n\nStay silent if all checks pass or not applicable. Be quick and non-blocking." "prompt": "[projman] Perform silent startup checks:\n\n1. Check if MCP venvs exist at the installed marketplace location. If the marketplace is installed but venvs are missing, warn the user: '[projman] MCP venvs missing - run setup.sh from installed marketplace location'.\n\n2. Check if the project git remote matches .env configuration (GITEA_ORG/GITEA_REPO). If mismatch, warn: '[projman] Git remote mismatch - run /project-sync'.\n\nStay silent if all checks pass or not applicable. Be quick and non-blocking."
} }
] ]
} }