refactor: consolidate plugin marketplace — remove duplicates, add repo-native plugins
Remove claude/qa/ and claude/ci/ plugins (replaced by go-build and go-devops repo-native plugins). Strip duplicate qa command from code plugin. Marketplace now references plugins at their source repos. Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
63cb1e31bb
commit
a607a49287
22 changed files with 19 additions and 1036 deletions
|
|
@ -9,14 +9,14 @@
|
|||
{
|
||||
"name": "code",
|
||||
"source": "./claude/code",
|
||||
"description": "Core development plugin - hooks, scripts, data collection skills",
|
||||
"version": "0.1.0"
|
||||
"description": "Core development hooks, auto-approve workflow, and research data collection",
|
||||
"version": "0.2.0"
|
||||
},
|
||||
{
|
||||
"name": "review",
|
||||
"source": "./claude/review",
|
||||
"description": "Code review automation - PR review, security checks",
|
||||
"version": "0.1.0"
|
||||
"version": "0.2.0"
|
||||
},
|
||||
{
|
||||
"name": "verify",
|
||||
|
|
@ -25,15 +25,21 @@
|
|||
"version": "0.1.0"
|
||||
},
|
||||
{
|
||||
"name": "qa",
|
||||
"source": "./claude/qa",
|
||||
"description": "Quality assurance - iterative fix loops, lint enforcement",
|
||||
"name": "core-php",
|
||||
"source": "forge.lthn.ai/core/php",
|
||||
"description": "PHP/Laravel development skills, API generation, and formatting",
|
||||
"version": "0.1.0"
|
||||
},
|
||||
{
|
||||
"name": "ci",
|
||||
"source": "./claude/ci",
|
||||
"description": "CI integration - GitHub Actions, test automation",
|
||||
"name": "go-build",
|
||||
"source": "forge.lthn.ai/core/go-build",
|
||||
"description": "Go QA pipeline, build tooling, and development skills",
|
||||
"version": "0.1.0"
|
||||
},
|
||||
{
|
||||
"name": "devops",
|
||||
"source": "forge.lthn.ai/core/go-devops",
|
||||
"description": "CI/CD, deployment, issue tracking, and Coolify integration",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"name": "ci",
|
||||
"description": "CI integration - GitHub Actions status, workflow management",
|
||||
"version": "0.1.0",
|
||||
"author": {
|
||||
"name": "Lethean"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
---
|
||||
name: ci
|
||||
description: Check CI status and manage workflows
|
||||
args: [status|run|logs|fix]
|
||||
---
|
||||
|
||||
# CI Integration
|
||||
|
||||
Check CI status and manage workflows using the `core` CLI (supports Forgejo and GitHub).
|
||||
|
||||
## Commands
|
||||
|
||||
### Status (default)
|
||||
```
|
||||
/ci:ci
|
||||
/ci:ci status
|
||||
```
|
||||
```bash
|
||||
core dev ci
|
||||
core dev ci --branch $(git branch --show-current)
|
||||
core dev ci --failed
|
||||
```
|
||||
|
||||
### List workflows
|
||||
```
|
||||
/ci:ci workflows
|
||||
```
|
||||
```bash
|
||||
core dev workflow list
|
||||
```
|
||||
|
||||
### Issues
|
||||
```
|
||||
/ci:ci issues
|
||||
```
|
||||
```bash
|
||||
core dev issues
|
||||
core dev issues --assignee @me
|
||||
```
|
||||
|
||||
### Reviews / PRs
|
||||
```
|
||||
/ci:ci reviews
|
||||
```
|
||||
```bash
|
||||
core dev reviews
|
||||
core dev reviews --all
|
||||
```
|
||||
|
||||
### Fix failing CI
|
||||
```
|
||||
/ci:ci fix
|
||||
```
|
||||
Analyse failing CI and suggest fixes. See `/ci:fix`.
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
---
|
||||
name: fix
|
||||
description: Analyse and fix failing CI
|
||||
---
|
||||
|
||||
# Fix CI
|
||||
|
||||
Analyse failing CI runs and suggest/apply fixes.
|
||||
|
||||
## Process
|
||||
|
||||
1. **Get failing runs**
|
||||
```bash
|
||||
core dev ci --failed
|
||||
```
|
||||
|
||||
2. **Analyse failure**
|
||||
- Parse error messages from CI output
|
||||
- Identify root cause
|
||||
- Check if local issue or CI-specific
|
||||
|
||||
3. **Reproduce locally**
|
||||
```bash
|
||||
core go test
|
||||
core go lint
|
||||
core go vet
|
||||
```
|
||||
|
||||
4. **Suggest fix**
|
||||
- Code changes if needed
|
||||
- CI config changes if needed
|
||||
|
||||
5. **Apply fix** (if approved)
|
||||
|
||||
## Common CI Failures
|
||||
|
||||
### Test Failures
|
||||
→ Run `core go test --run TestFoo`, fix the test, push
|
||||
|
||||
### Lint Failures
|
||||
→ Run `core go lint`, fix lint issues
|
||||
|
||||
### Build Failures
|
||||
→ Run `core build`, check imports, run `core go fmt`
|
||||
|
||||
### Dependency Issues
|
||||
→ Check go.mod, `core go fmt`, retry
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
---
|
||||
name: run
|
||||
description: Trigger a CI workflow run
|
||||
args: [workflow-name]
|
||||
---
|
||||
|
||||
# Run Workflow
|
||||
|
||||
Trigger a CI workflow or view available workflows.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
/ci:run # List available workflows
|
||||
/ci:run tests # Trigger specific workflow
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
# List available workflows
|
||||
core dev workflow list
|
||||
|
||||
# Sync workflows across repos
|
||||
core dev workflow sync
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Forgejo Actions uses `.forgejo/workflows/` or `.github/workflows/` (both supported)
|
||||
- Workflows are triggered automatically on push/PR/tag
|
||||
- Manual dispatch: use the Forgejo web UI at `forge.lthn.ai/{owner}/{repo}/actions`
|
||||
- Runner: `build-noc` on the noc server
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
---
|
||||
name: status
|
||||
description: Show CI status for current branch
|
||||
---
|
||||
|
||||
# CI Status
|
||||
|
||||
Show CI status for the current branch.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
/ci:status
|
||||
```
|
||||
|
||||
## Detection
|
||||
|
||||
Detect the CI provider from git remote, then use the appropriate method:
|
||||
|
||||
```bash
|
||||
REMOTE_URL=$(git remote get-url origin 2>/dev/null)
|
||||
```
|
||||
|
||||
### Forgejo (forge.lthn.ai)
|
||||
|
||||
```bash
|
||||
# Extract owner/repo from remote
|
||||
OWNER_REPO=$(git remote get-url origin 2>/dev/null | sed -E 's#.*forge\.lthn\.ai[:/]+([0-9]+/)?##; s#\.git$##')
|
||||
|
||||
# List recent workflow runs (requires FORGEJO_TOKEN or use web UI)
|
||||
curl -s "https://forge.lthn.ai/api/v1/repos/${OWNER_REPO}/actions/tasks?limit=10&state=running"
|
||||
|
||||
# Or just open the Actions page
|
||||
echo "https://forge.lthn.ai/${OWNER_REPO}/actions"
|
||||
```
|
||||
|
||||
### GitHub (fallback, requires gh CLI)
|
||||
|
||||
```bash
|
||||
core dev ci
|
||||
core dev ci --branch $(git branch --show-current)
|
||||
core dev ci --failed
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
Present results as a status table:
|
||||
|
||||
```markdown
|
||||
## CI Status: main
|
||||
|
||||
| Workflow | Status | When |
|
||||
|----------|--------|------|
|
||||
| Tests | pass | 5m ago |
|
||||
| Build | pass | 5m ago |
|
||||
|
||||
**All checks passing**
|
||||
```
|
||||
|
||||
If no API token available, output the web URL:
|
||||
```
|
||||
View CI status: https://forge.lthn.ai/{owner}/{repo}/actions
|
||||
```
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
---
|
||||
name: workflow
|
||||
description: Create or update CI workflow
|
||||
args: <workflow-type>
|
||||
---
|
||||
|
||||
# Workflow Generator
|
||||
|
||||
Create or update CI workflows. Forgejo Actions uses the same YAML format as GitHub Actions.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
/ci:workflow test
|
||||
/ci:workflow lint
|
||||
/ci:workflow release
|
||||
```
|
||||
|
||||
## List existing workflows
|
||||
|
||||
```bash
|
||||
core dev workflow list
|
||||
```
|
||||
|
||||
## Sync workflows across repos
|
||||
|
||||
```bash
|
||||
core dev workflow sync
|
||||
```
|
||||
|
||||
## Workflow directory
|
||||
|
||||
Forgejo supports both:
|
||||
- `.forgejo/workflows/` (preferred)
|
||||
- `.github/workflows/` (also works)
|
||||
|
||||
## Templates
|
||||
|
||||
### Go Test Workflow
|
||||
```yaml
|
||||
name: Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
- run: go test -v -race ./...
|
||||
```
|
||||
|
||||
### Go Release Workflow (core build)
|
||||
```yaml
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: ['v*']
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
- name: Build and release
|
||||
run: core build release --we-are-go-for-launch
|
||||
```
|
||||
|
||||
## Forgejo Notes
|
||||
|
||||
- Runner label: `ubuntu-latest` (maps to Forgejo runner labels)
|
||||
- Secrets: Set via repo Settings → Actions → Secrets
|
||||
- Runner: `build-noc` on the noc server
|
||||
- Web UI: `forge.lthn.ai/{owner}/{repo}/actions`
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"$schema": "https://claude.ai/schemas/hooks.json",
|
||||
"hooks": {
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "tool == \"Bash\" && tool_input.command matches \"^git push\"",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/post-push-ci.sh"
|
||||
}
|
||||
],
|
||||
"description": "Show CI status after push"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
#!/bin/bash
|
||||
# Detect CI provider from git remote
|
||||
# Outputs: "forgejo" or "github" or "unknown"
|
||||
# Also exports FORGE_API, FORGE_OWNER, FORGE_REPO
|
||||
|
||||
REMOTE_URL=$(git remote get-url origin 2>/dev/null)
|
||||
|
||||
if echo "$REMOTE_URL" | grep -q "forge.lthn.ai"; then
|
||||
echo "forgejo"
|
||||
# Extract owner/repo from SSH or HTTPS URL
|
||||
# SSH: ssh://git@forge.lthn.ai:2223/core/go.git
|
||||
# HTTPS: https://forge.lthn.ai/core/go.git
|
||||
OWNER_REPO=$(echo "$REMOTE_URL" | sed -E 's#.*forge\.lthn\.ai[:/]+([0-9]+/)?##; s#\.git$##')
|
||||
export FORGE_API="https://forge.lthn.ai/api/v1"
|
||||
export FORGE_OWNER=$(echo "$OWNER_REPO" | cut -d'/' -f1)
|
||||
export FORGE_REPO=$(echo "$OWNER_REPO" | cut -d'/' -f2)
|
||||
elif echo "$REMOTE_URL" | grep -qE "github\.com"; then
|
||||
echo "github"
|
||||
else
|
||||
echo "unknown"
|
||||
fi
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
#!/bin/bash
|
||||
# Show CI status hint after push
|
||||
|
||||
read -r input
|
||||
EXIT_CODE=$(echo "$input" | jq -r '.tool_response.exit_code // 0')
|
||||
|
||||
if [ "$EXIT_CODE" = "0" ]; then
|
||||
# Check if repo has workflows (Forgejo or GitHub)
|
||||
if [ -d ".forgejo/workflows" ] || [ -d ".github/workflows" ]; then
|
||||
cat << 'EOF'
|
||||
{
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "PostToolUse",
|
||||
"additionalContext": "Push successful. CI workflows will run shortly.\n\nRun `/ci:status` to check progress or `core dev ci` to view status."
|
||||
}
|
||||
}
|
||||
EOF
|
||||
else
|
||||
echo "$input"
|
||||
fi
|
||||
else
|
||||
echo "$input"
|
||||
fi
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "code",
|
||||
"description": "Advanced Claude Code plugin for Host UK monorepo - core CLI integration, data collection skills, and autonomous workflows",
|
||||
"version": "0.1.3",
|
||||
"description": "Core development hooks, auto-approve workflow, and cryptocurrency research data collection skills",
|
||||
"version": "0.2.0",
|
||||
"author": {
|
||||
"name": "Lethean",
|
||||
"email": "hello@host.uk.com"
|
||||
|
|
@ -10,11 +10,8 @@
|
|||
"repository": "https://forge.lthn.ai/core/agent.git",
|
||||
"license": "EUPL-1.2",
|
||||
"keywords": [
|
||||
"devops",
|
||||
"monorepo",
|
||||
"go",
|
||||
"php",
|
||||
"laravel",
|
||||
"hooks",
|
||||
"auto-approve",
|
||||
"data-collection",
|
||||
"cryptocurrency",
|
||||
"archive"
|
||||
|
|
|
|||
|
|
@ -1,155 +0,0 @@
|
|||
---
|
||||
name: qa
|
||||
description: Run QA checks and fix all issues iteratively
|
||||
hooks:
|
||||
PostToolUse:
|
||||
- matcher: "Bash"
|
||||
hooks:
|
||||
- type: command
|
||||
command: "${CLAUDE_PLUGIN_ROOT}/scripts/qa-filter.sh"
|
||||
Stop:
|
||||
- hooks:
|
||||
- type: command
|
||||
command: "${CLAUDE_PLUGIN_ROOT}/scripts/qa-verify.sh"
|
||||
once: true
|
||||
---
|
||||
|
||||
# QA Fix Loop
|
||||
|
||||
Run the full QA pipeline and fix all issues.
|
||||
|
||||
## Detection
|
||||
|
||||
First, detect the project type:
|
||||
- If `go.mod` exists → Go project → `core go qa`
|
||||
- If `composer.json` exists → PHP project → `core php qa`
|
||||
- If both exist → ask user or check current directory
|
||||
|
||||
## Process
|
||||
|
||||
1. **Run QA**: Execute `core go qa` or `core php qa`
|
||||
2. **Parse issues**: Extract failures from output (see format below)
|
||||
3. **Fix each issue**: Address one at a time, simplest first
|
||||
4. **Re-verify**: After fixes, re-run QA
|
||||
5. **Repeat**: Until all checks pass
|
||||
6. **Report**: Summary of what was fixed
|
||||
|
||||
## Issue Priority
|
||||
|
||||
Fix in this order (fastest feedback first):
|
||||
1. **fmt** - formatting issues (auto-fix with `core go fmt`)
|
||||
2. **lint** - static analysis (usually quick fixes)
|
||||
3. **test** - failing tests (may need more investigation)
|
||||
4. **build** - compilation errors (fix before tests can run)
|
||||
|
||||
## Output Parsing
|
||||
|
||||
### Go QA Output
|
||||
```
|
||||
=== FMT ===
|
||||
FAIL: pkg/api/handler.go needs formatting
|
||||
|
||||
=== LINT ===
|
||||
pkg/api/handler.go:42:15: undefined: ErrNotFound (typecheck)
|
||||
pkg/api/handler.go:87:2: ineffectual assignment to err (ineffassign)
|
||||
|
||||
=== TEST ===
|
||||
--- FAIL: TestCreateUser (0.02s)
|
||||
handler_test.go:45: expected 200, got 500
|
||||
FAIL
|
||||
|
||||
=== RESULT ===
|
||||
fmt: FAIL
|
||||
lint: FAIL (2 issues)
|
||||
test: FAIL (1 failed)
|
||||
```
|
||||
|
||||
### PHP QA Output
|
||||
```
|
||||
=== PINT ===
|
||||
FAIL: 2 files need formatting
|
||||
|
||||
=== STAN ===
|
||||
src/Http/Controller.php:42 - Undefined variable $user
|
||||
|
||||
=== TEST ===
|
||||
✗ CreateUserTest::testSuccess
|
||||
Expected status 200, got 500
|
||||
|
||||
=== RESULT ===
|
||||
pint: FAIL
|
||||
stan: FAIL (1 error)
|
||||
test: FAIL (1 failed)
|
||||
```
|
||||
|
||||
## Fixing Strategy
|
||||
|
||||
**Formatting (fmt/pint):**
|
||||
- Just run `core go fmt` or `core php fmt`
|
||||
- No code reading needed
|
||||
|
||||
**Lint errors:**
|
||||
- Read the specific file:line
|
||||
- Understand the error type
|
||||
- Make minimal fix
|
||||
|
||||
**Test failures:**
|
||||
- Read the test file to understand expectation
|
||||
- Read the implementation
|
||||
- Fix the root cause (not just the symptom)
|
||||
|
||||
**Build errors:**
|
||||
- Usually missing imports or typos
|
||||
- Fix before attempting other checks
|
||||
|
||||
## Stop Condition
|
||||
|
||||
Only stop when:
|
||||
- All QA checks pass, OR
|
||||
- User explicitly cancels, OR
|
||||
- Same error repeats 3 times (stuck - ask for help)
|
||||
|
||||
## Example Session
|
||||
|
||||
```
|
||||
Detecting project type... Found go.mod → Go project
|
||||
|
||||
Running: core go qa
|
||||
|
||||
## QA Issues
|
||||
|
||||
pkg/api/handler.go:42:15: undefined: ErrNotFound
|
||||
--- FAIL: TestCreateUser (0.02s)
|
||||
|
||||
**Summary:** lint: FAIL (1) | test: FAIL (1)
|
||||
|
||||
---
|
||||
|
||||
Fixing lint issue: undefined ErrNotFound
|
||||
Reading pkg/api/handler.go...
|
||||
Adding error variable definition.
|
||||
|
||||
Running: core go qa
|
||||
|
||||
## QA Issues
|
||||
|
||||
--- FAIL: TestCreateUser (0.02s)
|
||||
expected 200, got 404
|
||||
|
||||
**Summary:** lint: PASS | test: FAIL (1)
|
||||
|
||||
---
|
||||
|
||||
Fixing test issue: expected 200, got 404
|
||||
Reading test setup...
|
||||
Correcting test data.
|
||||
|
||||
Running: core go qa
|
||||
|
||||
✓ All checks passed!
|
||||
|
||||
**Summary:**
|
||||
- Fixed: undefined ErrNotFound (added error variable)
|
||||
- Fixed: TestCreateUser (corrected test setup)
|
||||
- 2 issues resolved, all checks passing
|
||||
```
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
#!/bin/bash
|
||||
# Filter QA output to show only actionable issues during /core:qa mode
|
||||
#
|
||||
# PostToolUse hook that processes QA command output and extracts
|
||||
# only the failures, hiding verbose success output.
|
||||
|
||||
read -r input
|
||||
COMMAND=$(echo "$input" | jq -r '.tool_input.command // empty')
|
||||
OUTPUT=$(echo "$input" | jq -r '.tool_response.stdout // .tool_response.output // empty')
|
||||
EXIT_CODE=$(echo "$input" | jq -r '.tool_response.exit_code // 0')
|
||||
|
||||
# Only process QA-related commands
|
||||
case "$COMMAND" in
|
||||
"core go qa"*|"core php qa"*|"core go test"*|"core php test"*|"core go lint"*|"core php stan"*)
|
||||
;;
|
||||
*)
|
||||
# Not a QA command, pass through unchanged
|
||||
echo "$input"
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
# Extract failures from output
|
||||
FAILURES=$(echo "$OUTPUT" | grep -E "^(FAIL|---\s*FAIL|✗|ERROR|undefined:|error:|panic:)" | head -20)
|
||||
SUMMARY=$(echo "$OUTPUT" | grep -E "^(fmt:|lint:|test:|pint:|stan:|=== RESULT ===)" | tail -5)
|
||||
|
||||
# Also grab specific error lines with file:line references
|
||||
FILE_ERRORS=$(echo "$OUTPUT" | grep -E "^[a-zA-Z0-9_/.-]+\.(go|php):[0-9]+:" | head -10)
|
||||
|
||||
if [ -z "$FAILURES" ] && [ "$EXIT_CODE" = "0" ]; then
|
||||
# All passed - show brief confirmation
|
||||
cat << 'EOF'
|
||||
{
|
||||
"suppressOutput": true,
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "PostToolUse",
|
||||
"additionalContext": "✓ QA passed"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
else
|
||||
# Combine failures and file errors
|
||||
ISSUES="$FAILURES"
|
||||
if [ -n "$FILE_ERRORS" ]; then
|
||||
ISSUES="$ISSUES
|
||||
$FILE_ERRORS"
|
||||
fi
|
||||
|
||||
# Escape for JSON
|
||||
ISSUES_ESCAPED=$(echo "$ISSUES" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g')
|
||||
SUMMARY_ESCAPED=$(echo "$SUMMARY" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/ | /g')
|
||||
|
||||
cat << EOF
|
||||
{
|
||||
"suppressOutput": true,
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "PostToolUse",
|
||||
"additionalContext": "## QA Issues\n\n\`\`\`\n$ISSUES_ESCAPED\n\`\`\`\n\n**Summary:** $SUMMARY_ESCAPED"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
#!/bin/bash
|
||||
# Verify QA passes before stopping during /core:qa mode
|
||||
#
|
||||
# Stop hook that runs QA checks and blocks if any failures exist.
|
||||
# Ensures Claude fixes all issues before completing the task.
|
||||
|
||||
read -r input
|
||||
STOP_ACTIVE=$(echo "$input" | jq -r '.stop_hook_active // false')
|
||||
|
||||
# Prevent infinite loop
|
||||
if [ "$STOP_ACTIVE" = "true" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Detect project type and run QA
|
||||
if [ -f "go.mod" ]; then
|
||||
PROJECT="go"
|
||||
RESULT=$(core go qa 2>&1) || true
|
||||
elif [ -f "composer.json" ]; then
|
||||
PROJECT="php"
|
||||
RESULT=$(core php qa 2>&1) || true
|
||||
else
|
||||
# Not a Go or PHP project, allow stop
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check if QA passed
|
||||
if echo "$RESULT" | grep -qE "FAIL|ERROR|✗|panic:|undefined:"; then
|
||||
# Extract top issues for context
|
||||
ISSUES=$(echo "$RESULT" | grep -E "^(FAIL|ERROR|✗|undefined:|panic:)|^[a-zA-Z0-9_/.-]+\.(go|php):[0-9]+:" | head -5)
|
||||
|
||||
# Escape for JSON
|
||||
ISSUES_ESCAPED=$(echo "$ISSUES" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g')
|
||||
|
||||
cat << EOF
|
||||
{
|
||||
"decision": "block",
|
||||
"reason": "QA still has issues:\n\n$ISSUES_ESCAPED\n\nPlease fix these before stopping."
|
||||
}
|
||||
EOF
|
||||
else
|
||||
# QA passed, allow stop
|
||||
exit 0
|
||||
fi
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"name": "qa",
|
||||
"description": "Quality assurance - iterative fix loops, lint enforcement, test coverage",
|
||||
"version": "0.1.0",
|
||||
"author": {
|
||||
"name": "Lethean"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
---
|
||||
name: check
|
||||
description: Run QA checks without fixing (report only)
|
||||
args: [--go|--php|--all]
|
||||
---
|
||||
|
||||
# QA Check
|
||||
|
||||
Run QA pipeline and report issues without fixing them.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
/qa:check # Auto-detect project type
|
||||
/qa:check --go # Force Go checks
|
||||
/qa:check --php # Force PHP checks
|
||||
/qa:check --all # Run both if applicable
|
||||
```
|
||||
|
||||
## Process
|
||||
|
||||
1. **Detect project type**
|
||||
2. **Run QA pipeline**
|
||||
3. **Parse and report issues**
|
||||
4. **Do NOT fix anything**
|
||||
|
||||
## Go Checks
|
||||
|
||||
```bash
|
||||
core go qa
|
||||
```
|
||||
|
||||
Runs:
|
||||
- `go fmt` - Formatting
|
||||
- `go vet` - Static analysis
|
||||
- `golangci-lint` - Linting
|
||||
- `go test` - Tests
|
||||
|
||||
## PHP Checks
|
||||
|
||||
```bash
|
||||
core php qa
|
||||
```
|
||||
|
||||
Runs:
|
||||
- `pint` - Formatting
|
||||
- `phpstan` - Static analysis
|
||||
- `pest` - Tests
|
||||
|
||||
## Output
|
||||
|
||||
```markdown
|
||||
## QA Report
|
||||
|
||||
**Project**: Go (go.mod detected)
|
||||
**Status**: 3 issues found
|
||||
|
||||
### Formatting
|
||||
✗ 2 files need formatting
|
||||
- pkg/api/handler.go
|
||||
- pkg/auth/token.go
|
||||
|
||||
### Linting
|
||||
✗ 1 issue
|
||||
- pkg/api/handler.go:42 - undefined: ErrNotFound
|
||||
|
||||
### Tests
|
||||
✓ All passing (47/47)
|
||||
|
||||
---
|
||||
**Summary**: fmt: FAIL | lint: FAIL | test: PASS
|
||||
|
||||
Run `/qa:qa` to fix these issues automatically.
|
||||
```
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
---
|
||||
name: fix
|
||||
description: Fix a specific QA issue
|
||||
args: <issue-description>
|
||||
---
|
||||
|
||||
# Fix Issue
|
||||
|
||||
Fix a specific issue from QA output.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
/qa:fix undefined: ErrNotFound in pkg/api/handler.go:42
|
||||
/qa:fix TestCreateUser failing - expected 200, got 500
|
||||
/qa:fix pkg/api/handler.go needs formatting
|
||||
```
|
||||
|
||||
## Process
|
||||
|
||||
1. **Parse the issue**: Extract file, line, error type
|
||||
2. **Read context**: Read the file around the error line
|
||||
3. **Understand**: Determine root cause
|
||||
4. **Fix**: Make minimal change to resolve
|
||||
5. **Verify**: Run relevant test/lint check
|
||||
|
||||
## Issue Types
|
||||
|
||||
### Undefined variable/type
|
||||
```
|
||||
undefined: ErrNotFound
|
||||
```
|
||||
→ Add missing import or define the variable
|
||||
|
||||
### Test failure
|
||||
```
|
||||
expected 200, got 500
|
||||
```
|
||||
→ Read test and implementation, fix logic
|
||||
|
||||
### Formatting
|
||||
```
|
||||
file needs formatting
|
||||
```
|
||||
→ Run `core go fmt` or `core php fmt`
|
||||
|
||||
### Lint warning
|
||||
```
|
||||
ineffectual assignment to err
|
||||
```
|
||||
→ Use the variable or remove assignment
|
||||
|
||||
### Type error
|
||||
```
|
||||
cannot use X as Y
|
||||
```
|
||||
→ Fix type conversion or function signature
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
---
|
||||
name: lint
|
||||
description: Run linter and fix issues
|
||||
args: [--check|--fix]
|
||||
---
|
||||
|
||||
# Lint
|
||||
|
||||
Run linter and optionally fix issues.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
/qa:lint # Run lint, report issues
|
||||
/qa:lint --check # Check only, no fixes
|
||||
/qa:lint --fix # Auto-fix where possible
|
||||
```
|
||||
|
||||
## Process
|
||||
|
||||
### Go
|
||||
```bash
|
||||
# Check
|
||||
core go lint
|
||||
|
||||
# Some issues can be auto-fixed
|
||||
golangci-lint run --fix
|
||||
```
|
||||
|
||||
### PHP
|
||||
```bash
|
||||
# Check
|
||||
core php stan
|
||||
|
||||
# PHPStan doesn't auto-fix, but can suggest fixes
|
||||
```
|
||||
|
||||
## Common Issues
|
||||
|
||||
### Go
|
||||
|
||||
| Issue | Fix |
|
||||
|-------|-----|
|
||||
| `undefined: X` | Add import or define variable |
|
||||
| `ineffectual assignment` | Use variable or remove |
|
||||
| `unused parameter` | Use `_` prefix or remove |
|
||||
| `error return value not checked` | Handle the error |
|
||||
|
||||
### PHP
|
||||
|
||||
| Issue | Fix |
|
||||
|-------|-----|
|
||||
| `Undefined variable` | Define or check existence |
|
||||
| `Parameter $x has no type` | Add type hint |
|
||||
| `Method has no return type` | Add return type |
|
||||
|
||||
## Output
|
||||
|
||||
```markdown
|
||||
## Lint Results
|
||||
|
||||
**Linter**: golangci-lint
|
||||
**Issues**: 3
|
||||
|
||||
### Errors
|
||||
1. **pkg/api/handler.go:42** - undefined: ErrNotFound
|
||||
→ Add `var ErrNotFound = errors.New("not found")`
|
||||
|
||||
2. **pkg/api/handler.go:87** - error return value not checked
|
||||
→ Handle error: `if err != nil { return err }`
|
||||
|
||||
### Warnings
|
||||
1. **pkg/api/handler.go:15** - unused parameter ctx
|
||||
→ Rename to `_` or use it
|
||||
|
||||
---
|
||||
Run `/qa:lint --fix` to auto-fix where possible.
|
||||
```
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
---
|
||||
name: qa
|
||||
description: Run full QA pipeline and fix all issues iteratively
|
||||
hooks:
|
||||
PostToolUse:
|
||||
- matcher: "Bash"
|
||||
hooks:
|
||||
- type: command
|
||||
command: "${CLAUDE_PLUGIN_ROOT}/scripts/qa-filter.sh"
|
||||
Stop:
|
||||
- hooks:
|
||||
- type: command
|
||||
command: "${CLAUDE_PLUGIN_ROOT}/scripts/qa-verify.sh"
|
||||
once: true
|
||||
---
|
||||
|
||||
# QA Fix Loop
|
||||
|
||||
Run the full QA pipeline and fix all issues until everything passes.
|
||||
|
||||
## Detection
|
||||
|
||||
First, detect the project type:
|
||||
- If `go.mod` exists → Go project → `core go qa`
|
||||
- If `composer.json` exists → PHP project → `core php qa`
|
||||
- If both exist → check current directory or ask
|
||||
|
||||
## Process
|
||||
|
||||
1. **Run QA**: Execute `core go qa` or `core php qa`
|
||||
2. **Parse issues**: Extract failures from output
|
||||
3. **Fix each issue**: Address one at a time, simplest first
|
||||
4. **Re-verify**: After fixes, re-run QA
|
||||
5. **Repeat**: Until all checks pass
|
||||
6. **Report**: Summary of what was fixed
|
||||
|
||||
## Issue Priority
|
||||
|
||||
Fix in this order (fastest feedback first):
|
||||
1. **fmt** - formatting (auto-fix with `core go fmt`)
|
||||
2. **lint** - static analysis (usually quick fixes)
|
||||
3. **test** - failing tests (may need investigation)
|
||||
4. **build** - compilation errors (fix before tests can run)
|
||||
|
||||
## Fixing Strategy
|
||||
|
||||
**Formatting (fmt/pint):**
|
||||
- Just run `core go fmt` or `core php fmt`
|
||||
- No code reading needed
|
||||
|
||||
**Lint errors:**
|
||||
- Read the specific file:line
|
||||
- Understand the error type
|
||||
- Make minimal fix
|
||||
|
||||
**Test failures:**
|
||||
- Read the test file to understand expectation
|
||||
- Read the implementation
|
||||
- Fix the root cause (not just the symptom)
|
||||
|
||||
## Stop Condition
|
||||
|
||||
Only stop when:
|
||||
- All QA checks pass, OR
|
||||
- User explicitly cancels, OR
|
||||
- Same error repeats 3 times (stuck - ask for help)
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"$schema": "https://claude.ai/schemas/hooks.json",
|
||||
"hooks": {
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "tool == \"Bash\" && tool_input.command matches \"^core (go|php) (qa|test|lint|stan)\"",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/qa-filter.sh"
|
||||
}
|
||||
],
|
||||
"description": "Filter QA output to show only actionable issues"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
#!/bin/bash
|
||||
# Filter QA output to show only actionable issues during /core:qa mode
|
||||
#
|
||||
# PostToolUse hook that processes QA command output and extracts
|
||||
# only the failures, hiding verbose success output.
|
||||
|
||||
read -r input
|
||||
COMMAND=$(echo "$input" | jq -r '.tool_input.command // empty')
|
||||
OUTPUT=$(echo "$input" | jq -r '.tool_response.stdout // .tool_response.output // empty')
|
||||
EXIT_CODE=$(echo "$input" | jq -r '.tool_response.exit_code // 0')
|
||||
|
||||
# Only process QA-related commands
|
||||
case "$COMMAND" in
|
||||
"core go qa"*|"core php qa"*|"core go test"*|"core php test"*|"core go lint"*|"core php stan"*)
|
||||
;;
|
||||
*)
|
||||
# Not a QA command, pass through unchanged
|
||||
echo "$input"
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
# Extract failures from output
|
||||
FAILURES=$(echo "$OUTPUT" | grep -E "^(FAIL|---\s*FAIL|✗|ERROR|undefined:|error:|panic:)" | head -20)
|
||||
SUMMARY=$(echo "$OUTPUT" | grep -E "^(fmt:|lint:|test:|pint:|stan:|=== RESULT ===)" | tail -5)
|
||||
|
||||
# Also grab specific error lines with file:line references
|
||||
FILE_ERRORS=$(echo "$OUTPUT" | grep -E "^[a-zA-Z0-9_/.-]+\.(go|php):[0-9]+:" | head -10)
|
||||
|
||||
if [ -z "$FAILURES" ] && [ "$EXIT_CODE" = "0" ]; then
|
||||
# All passed - show brief confirmation
|
||||
cat << 'EOF'
|
||||
{
|
||||
"suppressOutput": true,
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "PostToolUse",
|
||||
"additionalContext": "✓ QA passed"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
else
|
||||
# Combine failures and file errors
|
||||
ISSUES="$FAILURES"
|
||||
if [ -n "$FILE_ERRORS" ]; then
|
||||
ISSUES="$ISSUES
|
||||
$FILE_ERRORS"
|
||||
fi
|
||||
|
||||
# Escape for JSON
|
||||
ISSUES_ESCAPED=$(echo "$ISSUES" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g')
|
||||
SUMMARY_ESCAPED=$(echo "$SUMMARY" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/ | /g')
|
||||
|
||||
cat << EOF
|
||||
{
|
||||
"suppressOutput": true,
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "PostToolUse",
|
||||
"additionalContext": "## QA Issues\n\n\`\`\`\n$ISSUES_ESCAPED\n\`\`\`\n\n**Summary:** $SUMMARY_ESCAPED"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
#!/bin/bash
|
||||
# Verify QA passes before stopping during /core:qa mode
|
||||
#
|
||||
# Stop hook that runs QA checks and blocks if any failures exist.
|
||||
# Ensures Claude fixes all issues before completing the task.
|
||||
|
||||
read -r input
|
||||
STOP_ACTIVE=$(echo "$input" | jq -r '.stop_hook_active // false')
|
||||
|
||||
# Prevent infinite loop
|
||||
if [ "$STOP_ACTIVE" = "true" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Detect project type and run QA
|
||||
if [ -f "go.mod" ]; then
|
||||
PROJECT="go"
|
||||
RESULT=$(core go qa 2>&1) || true
|
||||
elif [ -f "composer.json" ]; then
|
||||
PROJECT="php"
|
||||
RESULT=$(core php qa 2>&1) || true
|
||||
else
|
||||
# Not a Go or PHP project, allow stop
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check if QA passed
|
||||
if echo "$RESULT" | grep -qE "FAIL|ERROR|✗|panic:|undefined:"; then
|
||||
# Extract top issues for context
|
||||
ISSUES=$(echo "$RESULT" | grep -E "^(FAIL|ERROR|✗|undefined:|panic:)|^[a-zA-Z0-9_/.-]+\.(go|php):[0-9]+:" | head -5)
|
||||
|
||||
# Escape for JSON
|
||||
ISSUES_ESCAPED=$(echo "$ISSUES" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g')
|
||||
|
||||
cat << EOF
|
||||
{
|
||||
"decision": "block",
|
||||
"reason": "QA still has issues:\n\n$ISSUES_ESCAPED\n\nPlease fix these before stopping."
|
||||
}
|
||||
EOF
|
||||
else
|
||||
# QA passed, allow stop
|
||||
exit 0
|
||||
fi
|
||||
Loading…
Add table
Reference in a new issue