@hopla/claude-setup 1.17.1 → 2.1.1
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.
- package/.claude-plugin/marketplace.json +2 -1
- package/.claude-plugin/plugin.json +4 -3
- package/CHANGELOG.md +123 -0
- package/LICENSE +21 -0
- package/README.md +65 -39
- package/agents/system-reviewer.md +4 -4
- package/cli.js +288 -8
- package/commands/archive.md +137 -0
- package/commands/execute.md +1 -1
- package/commands/guides/ai-optimized-codebase.md +5 -1
- package/commands/guides/data-audit.md +4 -0
- package/commands/guides/hooks-reference.md +4 -0
- package/commands/guides/mcp-integration.md +6 -2
- package/commands/guides/remote-coding.md +5 -1
- package/commands/guides/review-checklist.md +4 -0
- package/commands/guides/scaling-beyond-engineering.md +4 -0
- package/commands/guides/validation-pyramid.md +5 -1
- package/commands/guides/write-skill.md +4 -0
- package/commands/init-project.md +38 -17
- package/commands/plan-feature.md +21 -3
- package/commands/system-review.md +11 -15
- package/commands/validate.md +1 -1
- package/hooks/prompt-route.js +244 -91
- package/hooks/session-prime.js +12 -4
- package/hooks/statusline.js +3 -5
- package/hooks/tsc-check.js +40 -3
- package/package.json +16 -6
- package/skills/brainstorm/SKILL.md +18 -2
- package/skills/code-review/SKILL.md +5 -0
- package/skills/code-review/checklist.md +1 -1
- package/skills/debug/SKILL.md +1 -1
- package/skills/execution-report/SKILL.md +1 -1
- package/skills/execution-report/report-structure.md +2 -2
- package/skills/git/commit.md +2 -2
- package/skills/git/pr.md +1 -1
- package/skills/hook-audit/SKILL.md +135 -0
- package/skills/hook-audit/checklist.md +210 -0
- package/skills/hook-audit/tests/fixtures/use-bad.ts.example +53 -0
- package/skills/hook-audit/tests/fixtures/use-good.ts.example +64 -0
- package/skills/hook-audit/tests/manual-test.sh +73 -0
- package/skills/performance/SKILL.md +1 -1
- package/skills/prime/SKILL.md +2 -2
- package/skills/refactoring/SKILL.md +1 -1
- package/skills/subagent-execution/SKILL.md +2 -2
- package/skills/verify/SKILL.md +1 -1
- package/skills/worktree/SKILL.md +2 -2
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// SYNTHETIC FIXTURE — clean hook that passes all 4 rules.
|
|
2
|
+
// Mirrors the well-formed consumer-project shape (e.g. useGradingDefinitions.ts).
|
|
3
|
+
|
|
4
|
+
import { useState, useRef, useMemo } from 'react';
|
|
5
|
+
|
|
6
|
+
// Rule D-1: cache + companion inFlight map. CLEAN.
|
|
7
|
+
const cache = new Map<string, BarResult>();
|
|
8
|
+
const inFlight = new Map<string, Promise<BarResult>>();
|
|
9
|
+
|
|
10
|
+
type BarResult = { ok: boolean; value: string };
|
|
11
|
+
|
|
12
|
+
export function useBarLookup(barId: string) {
|
|
13
|
+
const [data, setData] = useState<BarResult | null>(null);
|
|
14
|
+
const [loading, setLoading] = useState(false);
|
|
15
|
+
const currentBarRef = useRef<string>(barId);
|
|
16
|
+
|
|
17
|
+
async function load(id: string) {
|
|
18
|
+
setLoading(true);
|
|
19
|
+
currentBarRef.current = id;
|
|
20
|
+
try {
|
|
21
|
+
const cached = cache.get(id);
|
|
22
|
+
if (cached) {
|
|
23
|
+
setData(cached);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const inflight = inFlight.get(id);
|
|
27
|
+
const promise = inflight ?? fakeFetch(id).then((result) => {
|
|
28
|
+
cache.set(id, result);
|
|
29
|
+
inFlight.delete(id);
|
|
30
|
+
return result;
|
|
31
|
+
});
|
|
32
|
+
if (!inflight) inFlight.set(id, promise);
|
|
33
|
+
const result = await promise;
|
|
34
|
+
if (currentBarRef.current === id) {
|
|
35
|
+
setData(result);
|
|
36
|
+
}
|
|
37
|
+
} catch (error: any) {
|
|
38
|
+
// Rule E-1: anchored regex — precise. CLEAN.
|
|
39
|
+
if (/^(invalid )?bar( format)?\b/i.test(error.message)) {
|
|
40
|
+
setData({ ok: false, value: 'bar-error' });
|
|
41
|
+
}
|
|
42
|
+
} finally {
|
|
43
|
+
if (currentBarRef.current === id) {
|
|
44
|
+
setData((prev) => prev);
|
|
45
|
+
}
|
|
46
|
+
// Rule S-8: setLoading(false) OUTSIDE the stale-id guard. CLEAN.
|
|
47
|
+
setLoading(false);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Rule P-5: return wrapped in useMemo with full deps. CLEAN.
|
|
52
|
+
return useMemo(
|
|
53
|
+
() => ({
|
|
54
|
+
data,
|
|
55
|
+
loading,
|
|
56
|
+
load,
|
|
57
|
+
}),
|
|
58
|
+
[data, loading, load],
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function fakeFetch(id: string): Promise<BarResult> {
|
|
63
|
+
return { ok: true, value: id };
|
|
64
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# Manual sanity test for the hook-audit skill's detection layer.
|
|
4
|
+
#
|
|
5
|
+
# The skill itself is markdown — an agent (Claude) interprets it. This script
|
|
6
|
+
# cannot exercise the full agent flow. What it CAN do is verify that the
|
|
7
|
+
# grep-based detection commands from `checklist.md` produce the expected
|
|
8
|
+
# candidate matches against the bundled fixtures.
|
|
9
|
+
#
|
|
10
|
+
# Rules covered by this script:
|
|
11
|
+
# - E-1 (substring error matching) — exact match count
|
|
12
|
+
# - D-1 (cache + inFlight) — presence check
|
|
13
|
+
#
|
|
14
|
+
# Rules requiring agent-level structural verification (NOT covered here, by design):
|
|
15
|
+
# - P-5 (return-not-memoized) — needs hook-scope + useMemo-wrapper filter
|
|
16
|
+
# - S-8 (setLoading inside guard) — needs brace-balance / above-context filter
|
|
17
|
+
# Their grep stage is exercised below but only as a "candidates exist" assertion.
|
|
18
|
+
#
|
|
19
|
+
# Usage: bash skills/hook-audit/tests/manual-test.sh
|
|
20
|
+
# Exits 0 on success, 1 on the first failed assertion.
|
|
21
|
+
|
|
22
|
+
set -e
|
|
23
|
+
set -u
|
|
24
|
+
|
|
25
|
+
DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
26
|
+
BAD="$DIR/fixtures/use-bad.ts.example"
|
|
27
|
+
GOOD="$DIR/fixtures/use-good.ts.example"
|
|
28
|
+
PASS=0
|
|
29
|
+
FAIL=0
|
|
30
|
+
|
|
31
|
+
run() {
|
|
32
|
+
local label="$1"
|
|
33
|
+
local expected="$2"
|
|
34
|
+
local actual="$3"
|
|
35
|
+
if [ "$expected" = "$actual" ]; then
|
|
36
|
+
echo " ✓ $label"
|
|
37
|
+
PASS=$((PASS + 1))
|
|
38
|
+
else
|
|
39
|
+
echo " ✗ $label — expected '$expected', got '$actual'"
|
|
40
|
+
FAIL=$((FAIL + 1))
|
|
41
|
+
fi
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
count() {
|
|
45
|
+
# `grep -c` already outputs the match count (0 if none). Its exit code is
|
|
46
|
+
# 1 on no matches; the `|| true` keeps `set -e` happy without duplicating
|
|
47
|
+
# output via an explicit `echo 0` fallback.
|
|
48
|
+
grep -cE "$1" "$2" 2>/dev/null || true
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
echo "=== hook-audit detection sanity test ==="
|
|
52
|
+
echo
|
|
53
|
+
|
|
54
|
+
[ -f "$BAD" ] || { echo "Missing fixture: $BAD"; exit 1; }
|
|
55
|
+
[ -f "$GOOD" ] || { echo "Missing fixture: $GOOD"; exit 1; }
|
|
56
|
+
|
|
57
|
+
echo "BAD fixture ($BAD):"
|
|
58
|
+
run "P-5 — return literal candidate present" "yes" "$([ $(count 'return[[:space:]]*\{' "$BAD") -ge 1 ] && echo yes || echo no)"
|
|
59
|
+
run "S-8 — setLoading(false) candidate present" "yes" "$([ $(count 'setLoading\(false\)' "$BAD") -ge 1 ] && echo yes || echo no)"
|
|
60
|
+
run "E-1 — substring matcher detected exactly 1" "1" "$(count "\.message\??\.includes\([\"'][a-z]+[\"']\)" "$BAD")"
|
|
61
|
+
run "D-1 — module cache present" "yes" "$([ $(count '^const cache[[:space:]]*=[[:space:]]*new Map' "$BAD") -ge 1 ] && echo yes || echo no)"
|
|
62
|
+
run "D-1 — inFlight ABSENT" "yes" "$([ $(count '^const inFlight[[:space:]]*=[[:space:]]*new Map' "$BAD") -eq 0 ] && echo yes || echo no)"
|
|
63
|
+
|
|
64
|
+
echo
|
|
65
|
+
echo "GOOD fixture ($GOOD):"
|
|
66
|
+
run "E-1 — no substring matcher (count is 0)" "0" "$(count "\.message\??\.includes\([\"'][a-z]+[\"']\)" "$GOOD")"
|
|
67
|
+
run "D-1 — module cache present" "yes" "$([ $(count '^const cache[[:space:]]*=[[:space:]]*new Map' "$GOOD") -ge 1 ] && echo yes || echo no)"
|
|
68
|
+
run "D-1 — inFlight present" "yes" "$([ $(count '^const inFlight[[:space:]]*=[[:space:]]*new Map' "$GOOD") -ge 1 ] && echo yes || echo no)"
|
|
69
|
+
|
|
70
|
+
echo
|
|
71
|
+
echo "=== Summary: $PASS passed, $FAIL failed ==="
|
|
72
|
+
[ "$FAIL" -eq 0 ] || exit 1
|
|
73
|
+
echo "All hook-audit detection tests pass."
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: performance
|
|
3
|
-
description: "Measured performance optimization workflow. Use when the user says 'slow', 'optimize', 'performance', 'bottleneck', 'too slow', 'high memory', 'high CPU',
|
|
3
|
+
description: "Measured performance optimization workflow. Use when the user says 'slow', 'optimize', 'performance', 'bottleneck', 'too slow', 'high memory', 'high CPU', or when asking to make something faster. Do NOT use for correctness bugs or new features — use the debug or plan-feature skills instead."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
> 🌐 **Language:** All user-facing output must match the user's language. Code, paths, and commands stay in English.
|
package/skills/prime/SKILL.md
CHANGED
|
@@ -14,14 +14,14 @@ Use the Glob tool to list project files (up to 60):
|
|
|
14
14
|
- Pattern: `**/*` with head_limit: 60
|
|
15
15
|
|
|
16
16
|
Use the Glob tool to find key config files:
|
|
17
|
-
- `**/CLAUDE.md`
|
|
18
17
|
- `**/AGENTS.md`
|
|
18
|
+
- `**/CLAUDE.md`
|
|
19
19
|
- `**/README.md`
|
|
20
20
|
|
|
21
21
|
## Step 2: Read Key Files
|
|
22
22
|
|
|
23
23
|
Read in this order:
|
|
24
|
-
1. `
|
|
24
|
+
1. `AGENTS.md` or `CLAUDE.md` at project root (project-specific rules — AGENTS.md is canonical when both exist; CLAUDE.md may be a thin `@AGENTS.md` alias)
|
|
25
25
|
2. `README.md` (project overview)
|
|
26
26
|
3. `package.json` or `pyproject.toml` (dependencies and scripts)
|
|
27
27
|
|
|
@@ -23,7 +23,7 @@ If the answers reveal a missing test covering the target, **write the test first
|
|
|
23
23
|
|
|
24
24
|
## Step 2: Capture the Baseline
|
|
25
25
|
|
|
26
|
-
Run the project's validation commands from `
|
|
26
|
+
Run the project's validation commands from `AGENTS.md` (or `CLAUDE.md` as fallback, or use `/hopla:validate`). Record:
|
|
27
27
|
|
|
28
28
|
- Lint / format — current state
|
|
29
29
|
- Types — current state
|
|
@@ -19,7 +19,7 @@ Instead of executing all tasks in one conversation (where context degrades), dis
|
|
|
19
19
|
1. **Dispatch implementer agent** with:
|
|
20
20
|
- The specific task spec (not the full plan)
|
|
21
21
|
- Relevant file paths from the plan
|
|
22
|
-
- Project CLAUDE.md for conventions
|
|
22
|
+
- Project AGENTS.md (or CLAUDE.md as fallback) for conventions
|
|
23
23
|
- Clear success criteria
|
|
24
24
|
|
|
25
25
|
2. **Agent implements, tests, and reports** with status:
|
|
@@ -48,7 +48,7 @@ Implement this task from the plan:
|
|
|
48
48
|
**Tests**: [tests to write]
|
|
49
49
|
**Validation**: [command to verify]
|
|
50
50
|
|
|
51
|
-
Project conventions are in CLAUDE.md. Follow them strictly.
|
|
51
|
+
Project conventions are in AGENTS.md (or CLAUDE.md for legacy projects). Follow them strictly.
|
|
52
52
|
Report your status as DONE, DONE_WITH_CONCERNS, NEEDS_CONTEXT, or BLOCKED.
|
|
53
53
|
```
|
|
54
54
|
|
package/skills/verify/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: verify
|
|
3
|
-
description: "Verification gate that ensures all completion claims are backed by fresh evidence. Use when the agent is about to declare work as done, finished, complete, ready, or implemented. Also use when hearing '
|
|
3
|
+
description: "Verification gate that ensures all completion claims are backed by fresh evidence. Use when the agent is about to declare work as done, finished, complete, ready, or implemented. Also use when hearing 'done', 'finished', 'all tests pass', 'everything works', or any completion claim. Do NOT use for intermediate progress updates or partial task completion."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Verification Before Completion
|
package/skills/worktree/SKILL.md
CHANGED
|
@@ -44,7 +44,7 @@ Use `../git/flow-detection.md` (Steps 1–2) to resolve the base branch from the
|
|
|
44
44
|
Check in order:
|
|
45
45
|
|
|
46
46
|
1. Existing `.worktrees/` or `worktrees/` directory
|
|
47
|
-
2. `CLAUDE.md` preference (if configured)
|
|
47
|
+
2. `AGENTS.md` / `CLAUDE.md` preference (if configured)
|
|
48
48
|
3. Ask the user (default: `worktrees/<kebab-name>`)
|
|
49
49
|
|
|
50
50
|
### Step 3: Ensure the worktree directory is gitignored
|
|
@@ -91,7 +91,7 @@ If none match, skip.
|
|
|
91
91
|
|
|
92
92
|
### Step 6: Verify clean baseline (optional)
|
|
93
93
|
|
|
94
|
-
If `CLAUDE.md` or `package.json` defines a test command, run it once inside the worktree to confirm the baseline is green. If no test command is defined, skip.
|
|
94
|
+
If `AGENTS.md` / `CLAUDE.md` or `package.json` defines a test command, run it once inside the worktree to confirm the baseline is green. If no test command is defined, skip.
|
|
95
95
|
|
|
96
96
|
If tests fail **before any changes**, STOP and report — the baseline is broken.
|
|
97
97
|
|