ocak 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +268 -0
- data/bin/ocak +7 -0
- data/lib/ocak/agent_generator.rb +171 -0
- data/lib/ocak/claude_runner.rb +169 -0
- data/lib/ocak/cli.rb +28 -0
- data/lib/ocak/commands/audit.rb +25 -0
- data/lib/ocak/commands/clean.rb +30 -0
- data/lib/ocak/commands/debt.rb +21 -0
- data/lib/ocak/commands/design.rb +34 -0
- data/lib/ocak/commands/init.rb +212 -0
- data/lib/ocak/commands/resume.rb +128 -0
- data/lib/ocak/commands/run.rb +60 -0
- data/lib/ocak/commands/status.rb +102 -0
- data/lib/ocak/config.rb +109 -0
- data/lib/ocak/issue_fetcher.rb +137 -0
- data/lib/ocak/logger.rb +192 -0
- data/lib/ocak/merge_manager.rb +158 -0
- data/lib/ocak/pipeline_runner.rb +389 -0
- data/lib/ocak/pipeline_state.rb +51 -0
- data/lib/ocak/planner.rb +68 -0
- data/lib/ocak/process_runner.rb +82 -0
- data/lib/ocak/stack_detector.rb +333 -0
- data/lib/ocak/stream_parser.rb +189 -0
- data/lib/ocak/templates/agents/auditor.md.erb +87 -0
- data/lib/ocak/templates/agents/documenter.md.erb +67 -0
- data/lib/ocak/templates/agents/implementer.md.erb +154 -0
- data/lib/ocak/templates/agents/merger.md.erb +97 -0
- data/lib/ocak/templates/agents/pipeline.md.erb +126 -0
- data/lib/ocak/templates/agents/planner.md.erb +86 -0
- data/lib/ocak/templates/agents/reviewer.md.erb +98 -0
- data/lib/ocak/templates/agents/security_reviewer.md.erb +112 -0
- data/lib/ocak/templates/gitignore_additions.txt +10 -0
- data/lib/ocak/templates/hooks/post_edit_lint.sh.erb +57 -0
- data/lib/ocak/templates/hooks/task_completed_test.sh.erb +34 -0
- data/lib/ocak/templates/ocak.yml.erb +99 -0
- data/lib/ocak/templates/skills/audit/SKILL.md.erb +132 -0
- data/lib/ocak/templates/skills/debt/SKILL.md.erb +128 -0
- data/lib/ocak/templates/skills/design/SKILL.md.erb +131 -0
- data/lib/ocak/templates/skills/scan_file/SKILL.md.erb +113 -0
- data/lib/ocak/verification.rb +83 -0
- data/lib/ocak/worktree_manager.rb +92 -0
- data/lib/ocak.rb +13 -0
- metadata +115 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# PostToolUse hook for Edit|Write — runs the appropriate linter/formatter on the changed file.
|
|
3
|
+
# Receives JSON on stdin with tool_input.file_path.
|
|
4
|
+
# Exits 0 always (non-blocking) — linting feedback is advisory.
|
|
5
|
+
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
|
|
8
|
+
INPUT=$(cat)
|
|
9
|
+
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
|
|
10
|
+
|
|
11
|
+
[ -z "$FILE" ] && exit 0
|
|
12
|
+
[ ! -f "$FILE" ] && exit 0
|
|
13
|
+
|
|
14
|
+
PROJECT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
|
|
15
|
+
|
|
16
|
+
<%- if language == "ruby" -%>
|
|
17
|
+
<%- if lint_command -%>
|
|
18
|
+
case "$FILE" in
|
|
19
|
+
*.rb)
|
|
20
|
+
cd "$PROJECT_DIR"
|
|
21
|
+
<%= lint_command %> "$FILE" > /dev/null 2>&1 || true
|
|
22
|
+
;;
|
|
23
|
+
esac
|
|
24
|
+
<%- end -%>
|
|
25
|
+
<%- elsif language == "typescript" || language == "javascript" -%>
|
|
26
|
+
case "$FILE" in
|
|
27
|
+
*.ts|*.tsx|*.js|*.jsx|*.json|*.css)
|
|
28
|
+
cd "$PROJECT_DIR"
|
|
29
|
+
<%- if lint_command -%>
|
|
30
|
+
<%= lint_command.sub(/ \./, "") %> "$FILE" > /dev/null 2>&1 || true
|
|
31
|
+
<%- end -%>
|
|
32
|
+
;;
|
|
33
|
+
esac
|
|
34
|
+
<%- elsif language == "python" -%>
|
|
35
|
+
case "$FILE" in
|
|
36
|
+
*.py)
|
|
37
|
+
cd "$PROJECT_DIR"
|
|
38
|
+
<%- if lint_command -%>
|
|
39
|
+
<%= lint_command.sub(/ \./, "") %> "$FILE" > /dev/null 2>&1 || true
|
|
40
|
+
<%- end -%>
|
|
41
|
+
<%- if format_command -%>
|
|
42
|
+
<%= format_command.sub(/ \./, "") %> "$FILE" > /dev/null 2>&1 || true
|
|
43
|
+
<%- end -%>
|
|
44
|
+
;;
|
|
45
|
+
esac
|
|
46
|
+
<%- elsif language == "rust" -%>
|
|
47
|
+
cd "$PROJECT_DIR"
|
|
48
|
+
cargo fmt > /dev/null 2>&1 || true
|
|
49
|
+
<%- elsif language == "go" -%>
|
|
50
|
+
case "$FILE" in
|
|
51
|
+
*.go)
|
|
52
|
+
gofmt -w "$FILE" > /dev/null 2>&1 || true
|
|
53
|
+
;;
|
|
54
|
+
esac
|
|
55
|
+
<%- end -%>
|
|
56
|
+
|
|
57
|
+
exit 0
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# TaskCompleted hook — runs the test suite for the project.
|
|
3
|
+
# Blocks completion (exit 2) if tests fail. Stderr goes to Claude as feedback.
|
|
4
|
+
|
|
5
|
+
set -uo pipefail
|
|
6
|
+
|
|
7
|
+
PROJECT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
|
|
8
|
+
cd "$PROJECT_DIR"
|
|
9
|
+
|
|
10
|
+
FAILURES=()
|
|
11
|
+
|
|
12
|
+
<%- if test_command -%>
|
|
13
|
+
# Run tests
|
|
14
|
+
if ! <%= test_command %> 2>&1; then
|
|
15
|
+
FAILURES+=("Tests failed: <%= test_command %>")
|
|
16
|
+
fi
|
|
17
|
+
<%- end -%>
|
|
18
|
+
|
|
19
|
+
<%- if lint_command && !lint_command.include?("--fix") && !lint_command.include?("--write") && !lint_command.include?("-A") -%>
|
|
20
|
+
# Run linter (check only, no auto-fix)
|
|
21
|
+
if ! <%= lint_command %> 2>&1; then
|
|
22
|
+
FAILURES+=("Lint failed: <%= lint_command %>")
|
|
23
|
+
fi
|
|
24
|
+
<%- end -%>
|
|
25
|
+
|
|
26
|
+
if [ ${#FAILURES[@]} -gt 0 ]; then
|
|
27
|
+
echo "Checks failed. Fix before completing:" >&2
|
|
28
|
+
for f in "${FAILURES[@]}"; do
|
|
29
|
+
echo " - $f" >&2
|
|
30
|
+
done
|
|
31
|
+
exit 2
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
exit 0
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Ocak pipeline configuration
|
|
2
|
+
# Generated by `ocak init` — customize as needed
|
|
3
|
+
|
|
4
|
+
# Auto-detected project stack
|
|
5
|
+
stack:
|
|
6
|
+
language: <%= language %>
|
|
7
|
+
<%- if framework -%>
|
|
8
|
+
framework: <%= framework %>
|
|
9
|
+
<%- end -%>
|
|
10
|
+
<%- if test_command -%>
|
|
11
|
+
test_command: "<%= test_command %>"
|
|
12
|
+
<%- end -%>
|
|
13
|
+
<%- if lint_command -%>
|
|
14
|
+
lint_command: "<%= lint_command %>"
|
|
15
|
+
<%- end -%>
|
|
16
|
+
<%- if setup_command -%>
|
|
17
|
+
setup_command: "<%= setup_command %>"
|
|
18
|
+
<%- end -%>
|
|
19
|
+
<%- if format_command -%>
|
|
20
|
+
format_command: "<%= format_command %>"
|
|
21
|
+
<%- end -%>
|
|
22
|
+
<%- unless security_commands.empty? -%>
|
|
23
|
+
security_commands:
|
|
24
|
+
<%- security_commands.each do |cmd| -%>
|
|
25
|
+
- "<%= cmd %>"
|
|
26
|
+
<%- end -%>
|
|
27
|
+
<%- end -%>
|
|
28
|
+
|
|
29
|
+
# Pipeline settings
|
|
30
|
+
pipeline:
|
|
31
|
+
max_parallel: 3
|
|
32
|
+
poll_interval: 60
|
|
33
|
+
worktree_dir: ".claude/worktrees"
|
|
34
|
+
log_dir: "logs/pipeline"
|
|
35
|
+
# cost_budget: 5.00 # Max USD per issue pipeline (uncomment to enable)
|
|
36
|
+
|
|
37
|
+
# Safety — controls which issues the pipeline will process
|
|
38
|
+
# Default (no config): only issues created by the current `gh` user
|
|
39
|
+
safety:
|
|
40
|
+
allowed_authors: [] # Empty = current gh user only. Add usernames to allow others.
|
|
41
|
+
# require_comment: "auto-ready" # Require this exact comment from an allowed author
|
|
42
|
+
max_issues_per_run: 5 # Circuit breaker: max issues processed per poll cycle
|
|
43
|
+
|
|
44
|
+
# GitHub label state machine
|
|
45
|
+
labels:
|
|
46
|
+
ready: "auto-ready"
|
|
47
|
+
in_progress: "in-progress"
|
|
48
|
+
completed: "completed"
|
|
49
|
+
failed: "pipeline-failed"
|
|
50
|
+
|
|
51
|
+
# Pipeline steps — customize by adding/removing/reordering
|
|
52
|
+
# Each step can optionally specify `model:` to override the default (haiku|sonnet|opus)
|
|
53
|
+
steps:
|
|
54
|
+
- agent: implementer
|
|
55
|
+
role: implement
|
|
56
|
+
- agent: reviewer
|
|
57
|
+
role: review
|
|
58
|
+
- agent: implementer
|
|
59
|
+
role: fix
|
|
60
|
+
condition: has_findings
|
|
61
|
+
- agent: reviewer
|
|
62
|
+
role: verify
|
|
63
|
+
condition: had_fixes
|
|
64
|
+
- agent: security_reviewer
|
|
65
|
+
role: security
|
|
66
|
+
- agent: implementer
|
|
67
|
+
role: fix
|
|
68
|
+
condition: has_findings
|
|
69
|
+
complexity: full # skipped for simple issues
|
|
70
|
+
- agent: documenter
|
|
71
|
+
role: document
|
|
72
|
+
complexity: full # skipped for simple issues
|
|
73
|
+
- agent: auditor
|
|
74
|
+
role: audit
|
|
75
|
+
complexity: full # skipped for simple issues
|
|
76
|
+
- agent: merger
|
|
77
|
+
role: merge
|
|
78
|
+
|
|
79
|
+
# Agent file paths — override to use custom agents
|
|
80
|
+
agents:
|
|
81
|
+
implementer: .claude/agents/implementer.md
|
|
82
|
+
reviewer: .claude/agents/reviewer.md
|
|
83
|
+
security_reviewer: .claude/agents/security-reviewer.md
|
|
84
|
+
documenter: .claude/agents/documenter.md
|
|
85
|
+
merger: .claude/agents/merger.md
|
|
86
|
+
pipeline: .claude/agents/pipeline.md
|
|
87
|
+
planner: .claude/agents/planner.md
|
|
88
|
+
auditor: .claude/agents/auditor.md
|
|
89
|
+
<%- if defined?(monorepo) && monorepo -%>
|
|
90
|
+
|
|
91
|
+
# Monorepo — detected packages/workspaces
|
|
92
|
+
# Configure per-package test/lint commands here if needed
|
|
93
|
+
monorepo:
|
|
94
|
+
detected: true
|
|
95
|
+
packages:
|
|
96
|
+
<%- packages.each do |pkg| -%>
|
|
97
|
+
- "<%= pkg %>"
|
|
98
|
+
<%- end -%>
|
|
99
|
+
<%- end -%>
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: audit
|
|
3
|
+
description: Comprehensive codebase audit — security, error handling, patterns, tests, data, dependencies
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# /audit — Codebase Audit
|
|
8
|
+
|
|
9
|
+
Run a comprehensive sweep of the codebase across multiple dimensions. Produces a prioritized report with actionable findings.
|
|
10
|
+
|
|
11
|
+
## Input
|
|
12
|
+
|
|
13
|
+
Optional scope argument: $ARGUMENTS
|
|
14
|
+
|
|
15
|
+
Supported scopes: `security`, `errors`, `patterns`, `tests`, `data`, `dependencies`, or empty for all.
|
|
16
|
+
|
|
17
|
+
## Process
|
|
18
|
+
|
|
19
|
+
### Phase 1: Orientation
|
|
20
|
+
|
|
21
|
+
1. Read CLAUDE.md for architecture and conventions
|
|
22
|
+
2. Map the project structure using Glob to understand directories and file organization
|
|
23
|
+
|
|
24
|
+
### Phase 2: Static Analysis Tools
|
|
25
|
+
|
|
26
|
+
Run all available tools and capture output. Do NOT stop if a tool fails.
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
<%- if lint_command -%>
|
|
30
|
+
<%= lint_command.sub(/ -A| --fix| --write/, "") %> 2>&1 || true
|
|
31
|
+
<%- end -%>
|
|
32
|
+
<%- security_commands.each do |cmd| -%>
|
|
33
|
+
<%= cmd %> 2>&1 || true
|
|
34
|
+
<%- end -%>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Phase 3: Manual Analysis
|
|
38
|
+
|
|
39
|
+
For each dimension below, perform targeted searches and reads. Only run dimensions matching $ARGUMENTS (or all if no argument).
|
|
40
|
+
|
|
41
|
+
#### Security (`security`)
|
|
42
|
+
|
|
43
|
+
Search for and evaluate:
|
|
44
|
+
- Auth gaps — endpoints or handlers missing authentication
|
|
45
|
+
- Unvalidated inputs — user data used without validation
|
|
46
|
+
- SQL/command injection — string interpolation in queries or shell commands
|
|
47
|
+
- Hardcoded secrets — passwords, API keys, tokens in source code
|
|
48
|
+
- Mass assignment — unfiltered parameters in create/update operations
|
|
49
|
+
|
|
50
|
+
#### Error Handling (`errors`)
|
|
51
|
+
|
|
52
|
+
- Bare rescue/catch blocks without specific types
|
|
53
|
+
- Swallowed exceptions (caught with no re-raise, logging, or handling)
|
|
54
|
+
- Inconsistent error response patterns
|
|
55
|
+
- Missing error handling in external calls (HTTP, database, file I/O)
|
|
56
|
+
|
|
57
|
+
#### Bad Patterns (`patterns`)
|
|
58
|
+
|
|
59
|
+
- God classes/modules (files > 200 lines)
|
|
60
|
+
- TODO/FIXME/HACK/XXX comments
|
|
61
|
+
- Dead code or commented-out code
|
|
62
|
+
- Code duplication
|
|
63
|
+
- Tight coupling between unrelated modules
|
|
64
|
+
|
|
65
|
+
#### Test Gaps (`tests`)
|
|
66
|
+
|
|
67
|
+
- Public methods/functions without corresponding tests
|
|
68
|
+
- Tests that don't assert anything meaningful
|
|
69
|
+
- Skipped or pending tests
|
|
70
|
+
- Missing edge case and error path tests
|
|
71
|
+
|
|
72
|
+
#### Data Issues (`data`)
|
|
73
|
+
|
|
74
|
+
- N+1 query candidates
|
|
75
|
+
- Missing database indexes
|
|
76
|
+
- Unbounded queries (no limit/pagination)
|
|
77
|
+
- Incorrect data types (e.g., float for money)
|
|
78
|
+
|
|
79
|
+
#### Dependencies (`dependencies`)
|
|
80
|
+
|
|
81
|
+
- Outdated packages with known vulnerabilities
|
|
82
|
+
- Unused dependencies
|
|
83
|
+
- Overly broad version constraints
|
|
84
|
+
|
|
85
|
+
### Phase 4: Report
|
|
86
|
+
|
|
87
|
+
Output findings grouped by severity. Every finding must have a specific file path and line number.
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
# Codebase Audit Report
|
|
91
|
+
|
|
92
|
+
**Scope**: [all | security | errors | patterns | tests | data | dependencies]
|
|
93
|
+
|
|
94
|
+
## Critical (fix immediately)
|
|
95
|
+
|
|
96
|
+
### [Finding title]
|
|
97
|
+
**File**: `path/to/file:42`
|
|
98
|
+
**Category**: [Security | Error Handling | Pattern | Test Gap | Data | Dependency]
|
|
99
|
+
**Issue**: [Specific description of what's wrong]
|
|
100
|
+
**Impact**: [What could go wrong]
|
|
101
|
+
**Fix**: [Exact steps to remediate]
|
|
102
|
+
|
|
103
|
+
## High (fix soon)
|
|
104
|
+
...
|
|
105
|
+
|
|
106
|
+
## Medium (should fix)
|
|
107
|
+
...
|
|
108
|
+
|
|
109
|
+
## Low (consider fixing)
|
|
110
|
+
...
|
|
111
|
+
|
|
112
|
+
## Summary
|
|
113
|
+
|
|
114
|
+
| Category | Critical | High | Medium | Low |
|
|
115
|
+
|----------|----------|------|--------|-----|
|
|
116
|
+
| Security | N | N | N | N |
|
|
117
|
+
| Error Handling | N | N | N | N |
|
|
118
|
+
| Patterns | N | N | N | N |
|
|
119
|
+
| Test Gaps | N | N | N | N |
|
|
120
|
+
| Data | N | N | N | N |
|
|
121
|
+
| Dependencies | N | N | N | N |
|
|
122
|
+
| **Total** | **N** | **N** | **N** | **N** |
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Phase 5: Issue Generation
|
|
126
|
+
|
|
127
|
+
After presenting the report, offer:
|
|
128
|
+
|
|
129
|
+
> I found N critical and N high findings. Want me to generate GitHub issues for them?
|
|
130
|
+
> Each issue will follow the /design format so they can be processed by the autonomous pipeline.
|
|
131
|
+
|
|
132
|
+
If the user accepts, generate issues using the /design format and offer to create them with `gh issue create --label "auto-ready"`.
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: debt
|
|
3
|
+
description: Technical debt tracker — TODOs, suppressed rules, skipped tests, churn hotspots
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# /debt — Technical Debt Tracker
|
|
8
|
+
|
|
9
|
+
Tracks and ranks technical debt across the codebase. Combines static markers (TODOs, suppressions), test gaps, and git churn to identify the riskiest areas.
|
|
10
|
+
|
|
11
|
+
## Process
|
|
12
|
+
|
|
13
|
+
### Phase 1: Collect Debt Markers
|
|
14
|
+
|
|
15
|
+
#### TODO/FIXME/HACK Comments
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
grep -rn "TODO\|FIXME\|HACK\|XXX\|OPTIMIZE\|REFACTOR" \
|
|
19
|
+
--include="*.<%= language == "ruby" ? "rb" : language == "python" ? "py" : language == "rust" ? "rs" : language == "go" ? "go" : "{ts,tsx,js,jsx}" %>" \
|
|
20
|
+
--exclude-dir=node_modules --exclude-dir=vendor --exclude-dir=.git --exclude-dir=target \
|
|
21
|
+
. 2>/dev/null || true
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
For each marker, read the surrounding context (3-5 lines) to understand what the debt is.
|
|
25
|
+
|
|
26
|
+
#### Suppressed Linter Rules
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
<%- if language == "ruby" -%>
|
|
30
|
+
grep -rn "rubocop:disable" --include="*.rb" . 2>/dev/null || true
|
|
31
|
+
<%- elsif language == "typescript" || language == "javascript" -%>
|
|
32
|
+
grep -rn "eslint-disable\|biome-ignore\|@ts-ignore\|@ts-expect-error\|@ts-nocheck" \
|
|
33
|
+
--include="*.ts" --include="*.tsx" --include="*.js" \
|
|
34
|
+
--exclude-dir=node_modules . 2>/dev/null || true
|
|
35
|
+
grep -rn "as any\|as unknown" --include="*.ts" --include="*.tsx" \
|
|
36
|
+
--exclude-dir=node_modules . 2>/dev/null || true
|
|
37
|
+
<%- elsif language == "python" -%>
|
|
38
|
+
grep -rn "# noqa\|# type: ignore\|# pylint: disable" --include="*.py" . 2>/dev/null || true
|
|
39
|
+
<%- elsif language == "rust" -%>
|
|
40
|
+
grep -rn "#\[allow(" --include="*.rs" . 2>/dev/null || true
|
|
41
|
+
<%- elsif language == "go" -%>
|
|
42
|
+
grep -rn "//nolint\|// nolint" --include="*.go" . 2>/dev/null || true
|
|
43
|
+
<%- end -%>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
#### Skipped/Pending Tests
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
<%- if language == "ruby" -%>
|
|
50
|
+
grep -rn "skip\b\|pending\b" --include="*_test.rb" --include="*_spec.rb" . 2>/dev/null || true
|
|
51
|
+
<%- elsif language == "typescript" || language == "javascript" -%>
|
|
52
|
+
grep -rn "it\.skip\|test\.skip\|describe\.skip\|xit\|xdescribe\|xtest\|\.todo(" \
|
|
53
|
+
--include="*.test.ts" --include="*.test.tsx" --include="*.test.js" --include="*.spec.ts" \
|
|
54
|
+
--exclude-dir=node_modules . 2>/dev/null || true
|
|
55
|
+
<%- elsif language == "python" -%>
|
|
56
|
+
grep -rn "@pytest.mark.skip\|@unittest.skip\|pytest.skip" --include="*.py" . 2>/dev/null || true
|
|
57
|
+
<%- elsif language == "rust" -%>
|
|
58
|
+
grep -rn "#\[ignore\]" --include="*.rs" . 2>/dev/null || true
|
|
59
|
+
<%- end -%>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Phase 2: Git Churn Analysis
|
|
63
|
+
|
|
64
|
+
Find files that change most frequently — high churn signals instability or ongoing debt.
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# Top 30 most frequently changed files in the last 6 months
|
|
68
|
+
git log --since="6 months ago" --name-only --pretty=format: | \
|
|
69
|
+
grep -v '^$' | sort | uniq -c | sort -rn | head -30
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Phase 3: Test Coverage Cross-Reference
|
|
73
|
+
|
|
74
|
+
For the top 20 highest-churn files, check if they have corresponding tests.
|
|
75
|
+
|
|
76
|
+
### Phase 4: Risk Scoring
|
|
77
|
+
|
|
78
|
+
Score each debt item on a 1-10 scale based on:
|
|
79
|
+
|
|
80
|
+
| Factor | Weight | Description |
|
|
81
|
+
|--------|--------|-------------|
|
|
82
|
+
| **Churn** | 3x | Files changed 10+ times in 6 months = high churn |
|
|
83
|
+
| **Test coverage** | 3x | No tests = maximum risk |
|
|
84
|
+
| **Suppressed rules** | 2x | Disabled lint/type checks = hidden issues |
|
|
85
|
+
| **Age** | 1x | Old TODOs (> 3 months) = likely forgotten |
|
|
86
|
+
| **Blast radius** | 1x | Shared code (base classes, lib) = wider impact |
|
|
87
|
+
|
|
88
|
+
### Phase 5: Output
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
# Technical Debt Report
|
|
92
|
+
|
|
93
|
+
**Total debt items**: N
|
|
94
|
+
|
|
95
|
+
## Risk-Ranked Debt
|
|
96
|
+
|
|
97
|
+
### 1. `path/to/file` — Risk: 9/10
|
|
98
|
+
**Churn**: N changes in 6 months
|
|
99
|
+
**Tests**: N tests (N public methods untested)
|
|
100
|
+
**Suppressions**: N
|
|
101
|
+
**Markers**: N TODOs, N HACKs
|
|
102
|
+
**Details**:
|
|
103
|
+
- Line 42: `TODO: description` (added date)
|
|
104
|
+
- Line 78: suppressed lint rule — reason
|
|
105
|
+
|
|
106
|
+
## Debt by Category
|
|
107
|
+
|
|
108
|
+
| Category | Count | Oldest |
|
|
109
|
+
|----------|-------|--------|
|
|
110
|
+
| TODO | N | [date] |
|
|
111
|
+
| FIXME | N | [date] |
|
|
112
|
+
| HACK | N | [date] |
|
|
113
|
+
| Suppressed rules | N | - |
|
|
114
|
+
| Skipped tests | N | - |
|
|
115
|
+
| Untested high-churn files | N | - |
|
|
116
|
+
|
|
117
|
+
## Churn Hotspots
|
|
118
|
+
Files with high churn and low test coverage:
|
|
119
|
+
- `path/to/file` — N changes, N tests
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Phase 6: Issue Generation
|
|
123
|
+
|
|
124
|
+
After presenting the report, offer:
|
|
125
|
+
|
|
126
|
+
> The top N items are high-risk debt. Want me to generate GitHub issues for them?
|
|
127
|
+
|
|
128
|
+
If accepted, generate one issue per high-risk item using the /design format with the `auto-ready` label.
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: design
|
|
3
|
+
description: Interactive issue design — researches the codebase and produces implementation-ready GitHub issues
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# /design — Issue Design Skill
|
|
8
|
+
|
|
9
|
+
You are helping the user design a GitHub issue that a Claude agent with ZERO prior context can pick up and implement completely. The issue must be specific enough that an implementer needs nothing beyond the issue body and CLAUDE.md.
|
|
10
|
+
|
|
11
|
+
## Input
|
|
12
|
+
|
|
13
|
+
The user's rough description is: $ARGUMENTS
|
|
14
|
+
|
|
15
|
+
If $ARGUMENTS is empty, ask what they want to build or fix.
|
|
16
|
+
|
|
17
|
+
## Process
|
|
18
|
+
|
|
19
|
+
### Phase 1: Research
|
|
20
|
+
|
|
21
|
+
Before asking any questions, silently research the codebase to understand what exists:
|
|
22
|
+
|
|
23
|
+
1. Read CLAUDE.md for conventions, patterns, and architecture
|
|
24
|
+
2. Use Glob and Grep to find files related to the user's description
|
|
25
|
+
3. Read the most relevant files to understand current behavior, patterns, and data models
|
|
26
|
+
4. Identify which areas of the codebase this touches
|
|
27
|
+
5. Find existing tests, controllers, services, and routes that are relevant
|
|
28
|
+
6. Check for similar patterns already implemented that the issue should follow
|
|
29
|
+
|
|
30
|
+
### Phase 2: Clarify
|
|
31
|
+
|
|
32
|
+
Ask the user 2-5 targeted questions. Focus on:
|
|
33
|
+
|
|
34
|
+
- **Intent**: What problem does this solve? Who benefits?
|
|
35
|
+
- **Scope**: What's the minimum viable version? What should be explicitly excluded?
|
|
36
|
+
- **Behavior**: What should happen in edge cases? What error states exist?
|
|
37
|
+
- **Priority**: Is this blocking other work?
|
|
38
|
+
|
|
39
|
+
Do NOT ask questions you can answer from the codebase. Do NOT ask generic questions — be specific based on what you found in Phase 1.
|
|
40
|
+
|
|
41
|
+
### Phase 3: Draft Issue
|
|
42
|
+
|
|
43
|
+
Write the issue in this exact format:
|
|
44
|
+
|
|
45
|
+
```markdown
|
|
46
|
+
## Context
|
|
47
|
+
|
|
48
|
+
[1-3 sentences: what part of the system this touches, why it matters, specific modules/files involved]
|
|
49
|
+
|
|
50
|
+
**Relevant files:**
|
|
51
|
+
- `path/to/file` — [what it does]
|
|
52
|
+
- [list ALL files the implementer will need to read or modify]
|
|
53
|
+
|
|
54
|
+
## Current Behavior
|
|
55
|
+
|
|
56
|
+
[What happens now, or "This feature does not exist yet." Be specific — include actual code behavior]
|
|
57
|
+
|
|
58
|
+
## Desired Behavior
|
|
59
|
+
|
|
60
|
+
[Exactly what should change. Use concrete examples:]
|
|
61
|
+
|
|
62
|
+
**Example 1:** When [specific input/action], the system should [specific output/behavior].
|
|
63
|
+
|
|
64
|
+
## Acceptance Criteria
|
|
65
|
+
|
|
66
|
+
- [ ] When [specific condition], then [specific observable result]
|
|
67
|
+
- [ ] When [edge case], then [specific handling]
|
|
68
|
+
- [ ] When [error condition], then [specific error response/behavior]
|
|
69
|
+
- [ ] [Each criterion must be independently testable]
|
|
70
|
+
|
|
71
|
+
## Implementation Guide
|
|
72
|
+
|
|
73
|
+
[Specific files to create/modify, with the approach:]
|
|
74
|
+
- Create `path/to/new_file` — [what it does, key methods]
|
|
75
|
+
- Modify `path/to/existing_file` — [what to add/change]
|
|
76
|
+
|
|
77
|
+
### Patterns to Follow
|
|
78
|
+
- Follow the pattern in `path/to/example` for [specific pattern]
|
|
79
|
+
- Match the structure in `path/to/reference` for [specific convention]
|
|
80
|
+
|
|
81
|
+
## Security Considerations
|
|
82
|
+
|
|
83
|
+
[One of:]
|
|
84
|
+
- N/A — no security surface
|
|
85
|
+
- Auth: [who can access this, what scoping is needed]
|
|
86
|
+
- Validation: [what input must be validated]
|
|
87
|
+
- Data exposure: [what sensitive data could leak]
|
|
88
|
+
|
|
89
|
+
## Test Requirements
|
|
90
|
+
|
|
91
|
+
- `path/to/test_file`: [specific test cases]
|
|
92
|
+
- Edge cases: [list specific edge cases to test]
|
|
93
|
+
- Error cases: [list specific error scenarios]
|
|
94
|
+
|
|
95
|
+
## Documentation
|
|
96
|
+
|
|
97
|
+
- [ ] [Specific doc updates needed, or "No documentation changes required"]
|
|
98
|
+
|
|
99
|
+
## Out of Scope
|
|
100
|
+
|
|
101
|
+
- [Thing that might seem related but is NOT part of this issue]
|
|
102
|
+
- [Another boundary — be explicit to prevent scope creep]
|
|
103
|
+
|
|
104
|
+
## Dependencies
|
|
105
|
+
|
|
106
|
+
- [Issue #N must be completed first because...], or
|
|
107
|
+
- None
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Phase 4: Review & Create
|
|
111
|
+
|
|
112
|
+
1. Show the draft to the user
|
|
113
|
+
2. Ask if anything needs adjustment
|
|
114
|
+
3. After approval, offer to create the issue:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
gh issue create \
|
|
118
|
+
--title "Brief imperative title (under 70 chars)" \
|
|
119
|
+
--body "..." \
|
|
120
|
+
--label "auto-ready"
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
If the user described multiple things, break them into separate issues.
|
|
124
|
+
|
|
125
|
+
## Writing Style
|
|
126
|
+
|
|
127
|
+
- Direct and specific — like a senior engineer writing for a contractor
|
|
128
|
+
- No vague language: never say "improve", "clean up", "refactor" without specifying exactly what changes
|
|
129
|
+
- Every file path must be real and verified against the codebase
|
|
130
|
+
- Every pattern reference must point to an actual existing file
|
|
131
|
+
- Acceptance criteria must be testable by running a specific command or request
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: scan-file
|
|
3
|
+
description: Deep single-file analysis — bugs, security, patterns, test coverage
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
argument-hint: <file-path>
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# /scan-file — Single File Analysis
|
|
9
|
+
|
|
10
|
+
Deep analysis of a single file and its dependency graph. Finds bugs, security issues, bad patterns, missing error handling, and test gaps.
|
|
11
|
+
|
|
12
|
+
## Input
|
|
13
|
+
|
|
14
|
+
File path: $ARGUMENTS
|
|
15
|
+
|
|
16
|
+
If $ARGUMENTS is empty, ask which file to scan.
|
|
17
|
+
|
|
18
|
+
## Process
|
|
19
|
+
|
|
20
|
+
### Phase 1: Read the Target File
|
|
21
|
+
|
|
22
|
+
1. Read the file specified by $ARGUMENTS in full
|
|
23
|
+
2. Identify the file's role based on its location and contents
|
|
24
|
+
|
|
25
|
+
### Phase 2: Read Dependencies
|
|
26
|
+
|
|
27
|
+
Find and read all files this file imports, requires, or inherits from (skip third-party packages).
|
|
28
|
+
|
|
29
|
+
### Phase 3: Find the Test File
|
|
30
|
+
|
|
31
|
+
Determine the corresponding test file based on project conventions. If the test file exists, read it. If it doesn't exist, note this as a finding.
|
|
32
|
+
|
|
33
|
+
### Phase 4: Analysis
|
|
34
|
+
|
|
35
|
+
Check every line for:
|
|
36
|
+
|
|
37
|
+
#### Bugs
|
|
38
|
+
- Off-by-one errors in loops or ranges
|
|
39
|
+
- Nil/null reference risks
|
|
40
|
+
- Race conditions in concurrent code
|
|
41
|
+
- Incorrect method signatures or wrong argument order
|
|
42
|
+
- Missing return values
|
|
43
|
+
|
|
44
|
+
#### Security
|
|
45
|
+
- SQL injection (string interpolation in queries)
|
|
46
|
+
- Command injection (system calls with user input)
|
|
47
|
+
- Path traversal (file operations with user-supplied paths)
|
|
48
|
+
- Missing authorization checks
|
|
49
|
+
- Information leakage in error messages
|
|
50
|
+
- Hardcoded secrets
|
|
51
|
+
|
|
52
|
+
#### Patterns
|
|
53
|
+
- Violations of project conventions (read CLAUDE.md for reference)
|
|
54
|
+
- Methods that are too long (> 20 lines)
|
|
55
|
+
- Classes with too many responsibilities
|
|
56
|
+
- Dead code (unreachable branches, unused variables)
|
|
57
|
+
|
|
58
|
+
#### Error Handling
|
|
59
|
+
- Bare rescue/catch without specific exception types
|
|
60
|
+
- Swallowed exceptions
|
|
61
|
+
- Missing error handling for external calls
|
|
62
|
+
- Inconsistent error response format
|
|
63
|
+
|
|
64
|
+
#### Edge Cases
|
|
65
|
+
- Empty collections (`.first` on possibly empty array)
|
|
66
|
+
- Zero/negative values in calculations
|
|
67
|
+
- Very large inputs (unbounded queries, no pagination)
|
|
68
|
+
- Concurrent access (race conditions)
|
|
69
|
+
|
|
70
|
+
#### Test Coverage
|
|
71
|
+
Compare the public interface of the target file against the test file:
|
|
72
|
+
- List every public method/exported function
|
|
73
|
+
- For each, check if the test file has a corresponding test
|
|
74
|
+
- Check if error paths are tested
|
|
75
|
+
- Check if edge cases are tested
|
|
76
|
+
|
|
77
|
+
### Phase 5: Output
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
# Scan: `path/to/file`
|
|
81
|
+
|
|
82
|
+
## Summary
|
|
83
|
+
[1-2 sentence overview]
|
|
84
|
+
|
|
85
|
+
## Findings
|
|
86
|
+
|
|
87
|
+
### Line N: [Title]
|
|
88
|
+
**Severity**: Critical / High / Medium / Low
|
|
89
|
+
**Category**: Bug / Security / Pattern / Error Handling / Edge Case
|
|
90
|
+
**Issue**: [What's wrong]
|
|
91
|
+
**Fix**: [Exact fix]
|
|
92
|
+
|
|
93
|
+
## Test Coverage
|
|
94
|
+
|
|
95
|
+
| Method/Function | Tested | Edge Cases | Error Path |
|
|
96
|
+
|----------------|--------|------------|------------|
|
|
97
|
+
| `method_name` | yes/no | yes/no | yes/no |
|
|
98
|
+
|
|
99
|
+
**Missing tests**:
|
|
100
|
+
- `method_name` with nil input
|
|
101
|
+
- [specific untested scenarios]
|
|
102
|
+
|
|
103
|
+
## Score: N/10
|
|
104
|
+
[Brief justification]
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Phase 6: Offer Actions
|
|
108
|
+
|
|
109
|
+
After presenting findings, offer:
|
|
110
|
+
|
|
111
|
+
1. **Fix issues** — "Want me to fix the issues I found?"
|
|
112
|
+
2. **Generate issue** — "Want me to create a GitHub issue for these findings?"
|
|
113
|
+
3. **Both** — Fix what's safe to fix inline, create an issue for the rest
|