sequant 1.16.1 → 1.18.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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +14 -2
- package/README.md +2 -0
- package/dist/bin/cli.js +2 -1
- package/dist/marketplace/external_plugins/sequant/.claude-plugin/plugin.json +21 -0
- package/dist/marketplace/external_plugins/sequant/README.md +38 -0
- package/dist/marketplace/external_plugins/sequant/hooks/post-tool.sh +292 -0
- package/dist/marketplace/external_plugins/sequant/hooks/pre-tool.sh +463 -0
- package/dist/marketplace/external_plugins/sequant/skills/_shared/references/prompt-templates.md +350 -0
- package/dist/marketplace/external_plugins/sequant/skills/_shared/references/subagent-types.md +131 -0
- package/dist/marketplace/external_plugins/sequant/skills/assess/SKILL.md +474 -0
- package/dist/marketplace/external_plugins/sequant/skills/clean/SKILL.md +211 -0
- package/dist/marketplace/external_plugins/sequant/skills/docs/SKILL.md +337 -0
- package/dist/marketplace/external_plugins/sequant/skills/exec/SKILL.md +807 -0
- package/dist/marketplace/external_plugins/sequant/skills/fullsolve/SKILL.md +678 -0
- package/dist/marketplace/external_plugins/sequant/skills/improve/SKILL.md +668 -0
- package/dist/marketplace/external_plugins/sequant/skills/loop/SKILL.md +374 -0
- package/dist/marketplace/external_plugins/sequant/skills/qa/SKILL.md +570 -0
- package/dist/marketplace/external_plugins/sequant/skills/qa/references/code-quality-exemplars.md +107 -0
- package/dist/marketplace/external_plugins/sequant/skills/qa/references/code-review-checklist.md +65 -0
- package/dist/marketplace/external_plugins/sequant/skills/qa/references/quality-gates.md +179 -0
- package/dist/marketplace/external_plugins/sequant/skills/qa/references/semgrep-rules.md +207 -0
- package/dist/marketplace/external_plugins/sequant/skills/qa/references/testing-requirements.md +109 -0
- package/dist/marketplace/external_plugins/sequant/skills/qa/scripts/quality-checks.sh +622 -0
- package/dist/marketplace/external_plugins/sequant/skills/reflect/SKILL.md +175 -0
- package/dist/marketplace/external_plugins/sequant/skills/reflect/references/documentation-tiers.md +70 -0
- package/dist/marketplace/external_plugins/sequant/skills/reflect/references/phase-reflection.md +95 -0
- package/dist/marketplace/external_plugins/sequant/skills/security-review/SKILL.md +358 -0
- package/dist/marketplace/external_plugins/sequant/skills/security-review/references/security-checklists.md +432 -0
- package/dist/marketplace/external_plugins/sequant/skills/solve/SKILL.md +697 -0
- package/dist/marketplace/external_plugins/sequant/skills/spec/SKILL.md +754 -0
- package/dist/marketplace/external_plugins/sequant/skills/spec/references/parallel-groups.md +72 -0
- package/dist/marketplace/external_plugins/sequant/skills/spec/references/recommended-workflow.md +92 -0
- package/dist/marketplace/external_plugins/sequant/skills/spec/references/verification-criteria.md +104 -0
- package/dist/marketplace/external_plugins/sequant/skills/test/SKILL.md +600 -0
- package/dist/marketplace/external_plugins/sequant/skills/testgen/SKILL.md +576 -0
- package/dist/marketplace/external_plugins/sequant/skills/verify/SKILL.md +281 -0
- package/dist/src/commands/run.d.ts +13 -274
- package/dist/src/commands/run.js +43 -1958
- package/dist/src/commands/sync.js +3 -0
- package/dist/src/commands/update.js +3 -0
- package/dist/src/lib/plugin-version-sync.d.ts +2 -1
- package/dist/src/lib/plugin-version-sync.js +28 -7
- package/dist/src/lib/solve-comment-parser.d.ts +26 -0
- package/dist/src/lib/solve-comment-parser.js +63 -7
- package/dist/src/lib/upstream/assessment.js +6 -3
- package/dist/src/lib/upstream/relevance.d.ts +5 -0
- package/dist/src/lib/upstream/relevance.js +24 -0
- package/dist/src/lib/upstream/report.js +18 -46
- package/dist/src/lib/upstream/types.d.ts +2 -0
- package/dist/src/lib/workflow/batch-executor.d.ts +117 -0
- package/dist/src/lib/workflow/batch-executor.js +574 -0
- package/dist/src/lib/workflow/phase-executor.d.ts +40 -0
- package/dist/src/lib/workflow/phase-executor.js +381 -0
- package/dist/src/lib/workflow/phase-mapper.d.ts +65 -0
- package/dist/src/lib/workflow/phase-mapper.js +147 -0
- package/dist/src/lib/workflow/pr-operations.d.ts +86 -0
- package/dist/src/lib/workflow/pr-operations.js +326 -0
- package/dist/src/lib/workflow/pr-status.d.ts +49 -0
- package/dist/src/lib/workflow/pr-status.js +131 -0
- package/dist/src/lib/workflow/run-reflect.d.ts +32 -0
- package/dist/src/lib/workflow/run-reflect.js +191 -0
- package/dist/src/lib/workflow/run-summary.d.ts +36 -0
- package/dist/src/lib/workflow/run-summary.js +142 -0
- package/dist/src/lib/workflow/state-cleanup.d.ts +79 -0
- package/dist/src/lib/workflow/state-cleanup.js +250 -0
- package/dist/src/lib/workflow/state-rebuild.d.ts +38 -0
- package/dist/src/lib/workflow/state-rebuild.js +140 -0
- package/dist/src/lib/workflow/state-utils.d.ts +14 -162
- package/dist/src/lib/workflow/state-utils.js +10 -677
- package/dist/src/lib/workflow/worktree-discovery.d.ts +61 -0
- package/dist/src/lib/workflow/worktree-discovery.js +229 -0
- package/dist/src/lib/workflow/worktree-manager.d.ts +205 -0
- package/dist/src/lib/workflow/worktree-manager.js +918 -0
- package/package.json +4 -2
- package/templates/skills/exec/SKILL.md +2 -2
- package/templates/skills/fullsolve/SKILL.md +15 -5
- package/templates/skills/loop/SKILL.md +1 -1
- package/templates/skills/qa/SKILL.md +47 -7
- package/templates/skills/solve/SKILL.md +92 -6
- package/templates/skills/spec/SKILL.md +57 -4
- package/templates/skills/test/SKILL.md +10 -0
- package/templates/skills/testgen/SKILL.md +1 -1
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
{
|
|
11
11
|
"name": "sequant",
|
|
12
12
|
"description": "Structured workflow system for Claude Code - GitHub issue resolution with spec, exec, test, and QA phases. Includes 16 skills for planning, implementation, testing, code review, and quality assurance.",
|
|
13
|
-
"version": "1.
|
|
13
|
+
"version": "1.17.0",
|
|
14
14
|
"author": {
|
|
15
15
|
"name": "sequant-io",
|
|
16
16
|
"email": "hello@sequant.io"
|
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sequant",
|
|
3
3
|
"description": "Structured workflow system for Claude Code - GitHub issue resolution with spec, exec, test, and QA phases",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.18.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "sequant-io",
|
|
7
7
|
"email": "hello@sequant.io"
|
|
8
|
-
}
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/sequant-io/sequant",
|
|
10
|
+
"repository": "https://github.com/sequant-io/sequant",
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"keywords": [
|
|
13
|
+
"workflow",
|
|
14
|
+
"github",
|
|
15
|
+
"issues",
|
|
16
|
+
"quality",
|
|
17
|
+
"testing",
|
|
18
|
+
"code-review",
|
|
19
|
+
"automation"
|
|
20
|
+
]
|
|
9
21
|
}
|
package/README.md
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
Solve GitHub issues with structured phases and quality gates — from issue to merge-ready PR.
|
|
6
6
|
|
|
7
|
+
**[sequant.io](https://sequant.io)** — docs, guides, and getting started.
|
|
8
|
+
|
|
7
9
|
[](https://www.npmjs.com/package/sequant)
|
|
8
10
|
[](https://opensource.org/licenses/MIT)
|
|
9
11
|
|
package/dist/bin/cli.js
CHANGED
|
@@ -122,7 +122,7 @@ program
|
|
|
122
122
|
.description("Execute workflow for GitHub issues using Claude Agent SDK")
|
|
123
123
|
.argument("[issues...]", "Issue numbers to process")
|
|
124
124
|
.option("--phases <list>", "Phases to run (default: spec,exec,qa)")
|
|
125
|
-
.option("--sequential", "
|
|
125
|
+
.option("--sequential", "Stop on first issue failure (default: continue)")
|
|
126
126
|
.option("-d, --dry-run", "Preview without execution")
|
|
127
127
|
.option("-v, --verbose", "Verbose output with streaming")
|
|
128
128
|
.option("--timeout <seconds>", "Timeout per phase in seconds", parseInt)
|
|
@@ -145,6 +145,7 @@ program
|
|
|
145
145
|
.option("--no-rebase", "Skip pre-PR rebase onto origin/main (use when you want to handle rebasing manually)")
|
|
146
146
|
.option("--no-pr", "Skip PR creation after successful QA (manual PR workflow)")
|
|
147
147
|
.option("-f, --force", "Force re-execution of completed issues (bypass pre-flight state guard)")
|
|
148
|
+
.option("--reflect", "Analyze run results and suggest improvements")
|
|
148
149
|
.action(runCommand);
|
|
149
150
|
program
|
|
150
151
|
.command("merge")
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "sequant",
|
|
3
|
+
"description": "Structured workflow system for Claude Code - GitHub issue resolution with spec, exec, test, and QA phases",
|
|
4
|
+
"version": "1.17.0",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "sequant-io",
|
|
7
|
+
"email": "hello@sequant.io"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/sequant-io/sequant",
|
|
10
|
+
"repository": "https://github.com/sequant-io/sequant",
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"keywords": [
|
|
13
|
+
"workflow",
|
|
14
|
+
"github",
|
|
15
|
+
"issues",
|
|
16
|
+
"quality",
|
|
17
|
+
"testing",
|
|
18
|
+
"code-review",
|
|
19
|
+
"automation"
|
|
20
|
+
]
|
|
21
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Sequant
|
|
2
|
+
|
|
3
|
+
Structured workflow system for Claude Code — GitHub issue resolution with spec, exec, test, and QA phases.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
/plugin install sequant@claude-plugin-directory
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Or browse in `/plugin > Discover`.
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- **16 workflow skills** for planning, implementation, testing, and code review
|
|
16
|
+
- **Automated quality gates** with test and QA loops
|
|
17
|
+
- **GitHub integration** for issue tracking and PR creation
|
|
18
|
+
- **Multi-stack support** (Next.js, Python, Go, Rust, and more)
|
|
19
|
+
|
|
20
|
+
## Skills
|
|
21
|
+
|
|
22
|
+
| Skill | Purpose |
|
|
23
|
+
|-------|---------|
|
|
24
|
+
| `/spec` | Plan implementation and extract acceptance criteria |
|
|
25
|
+
| `/exec` | Implement changes in a feature worktree |
|
|
26
|
+
| `/test` | Browser-based UI testing |
|
|
27
|
+
| `/qa` | Code review and AC validation |
|
|
28
|
+
| `/fullsolve` | End-to-end issue resolution |
|
|
29
|
+
| `/solve` | Generate recommended workflow for issues |
|
|
30
|
+
|
|
31
|
+
## Documentation
|
|
32
|
+
|
|
33
|
+
- [Getting Started](https://github.com/sequant-io/sequant/tree/main/docs/getting-started)
|
|
34
|
+
- [Configuration](https://github.com/sequant-io/sequant/tree/main/docs/reference)
|
|
35
|
+
|
|
36
|
+
## License
|
|
37
|
+
|
|
38
|
+
MIT
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Post-tool hook for Claude Code
|
|
3
|
+
# - Timing instrumentation (END timestamp to pair with pre-tool START)
|
|
4
|
+
# - Auto-formatting for code quality
|
|
5
|
+
# - Quality observability (test/build failures, SQL queries)
|
|
6
|
+
# - Smart test running (P3): Runs related tests after file edits (opt-in)
|
|
7
|
+
# - Webhook notifications (P3): Notifies on issue close (opt-in)
|
|
8
|
+
# Runs AFTER each tool completes
|
|
9
|
+
|
|
10
|
+
# === ROLLBACK MECHANISM ===
|
|
11
|
+
# Set CLAUDE_HOOKS_DISABLED=true to bypass all hook logic
|
|
12
|
+
if [[ "${CLAUDE_HOOKS_DISABLED:-}" == "true" ]]; then
|
|
13
|
+
exit 0
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
# === READ INPUT FROM STDIN ===
|
|
17
|
+
# Claude Code passes tool data as JSON via stdin, not environment variables
|
|
18
|
+
INPUT_JSON=$(cat)
|
|
19
|
+
|
|
20
|
+
# Parse JSON using jq (preferred) or fallback to grep
|
|
21
|
+
if command -v jq &>/dev/null; then
|
|
22
|
+
TOOL_NAME=$(echo "$INPUT_JSON" | jq -r '.tool_name // empty')
|
|
23
|
+
# For Bash tool, extract .command from tool_input; for others, stringify the whole object
|
|
24
|
+
if [[ "$(echo "$INPUT_JSON" | jq -r '.tool_name // empty')" == "Bash" ]]; then
|
|
25
|
+
TOOL_INPUT=$(echo "$INPUT_JSON" | jq -r '.tool_input.command // empty')
|
|
26
|
+
else
|
|
27
|
+
TOOL_INPUT=$(echo "$INPUT_JSON" | jq -r '.tool_input | tostring // empty')
|
|
28
|
+
fi
|
|
29
|
+
TOOL_OUTPUT=$(echo "$INPUT_JSON" | jq -r '.tool_response | tostring // empty')
|
|
30
|
+
else
|
|
31
|
+
TOOL_NAME=$(echo "$INPUT_JSON" | grep -oE '"tool_name"\s*:\s*"[^"]+"' | head -1 | cut -d'"' -f4)
|
|
32
|
+
# For Bash tool, extract command from tool_input; for others, extract the whole object
|
|
33
|
+
if [[ "$TOOL_NAME" == "Bash" ]]; then
|
|
34
|
+
TOOL_INPUT=$(echo "$INPUT_JSON" | grep -oE '"command"\s*:\s*"[^"]+"' | head -1 | cut -d'"' -f4)
|
|
35
|
+
else
|
|
36
|
+
TOOL_INPUT=$(echo "$INPUT_JSON" | grep -oE '"tool_input"\s*:\s*\{[^}]+\}' | head -1)
|
|
37
|
+
fi
|
|
38
|
+
TOOL_OUTPUT=$(echo "$INPUT_JSON" | grep -oE '"tool_response"\s*:\s*\{[^}]+\}' | head -1)
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
TIMING_LOG="/tmp/claude-timing.log"
|
|
42
|
+
QUALITY_LOG="/tmp/claude-quality.log"
|
|
43
|
+
TESTS_LOG="/tmp/claude-tests.log"
|
|
44
|
+
PARALLEL_MARKER_PREFIX="/tmp/claude-parallel-"
|
|
45
|
+
|
|
46
|
+
# === AGENT ID DETECTION ===
|
|
47
|
+
# For parallel agents, detect group ID from marker files
|
|
48
|
+
# Format: /tmp/claude-parallel-<group-id>.marker
|
|
49
|
+
AGENT_ID=""
|
|
50
|
+
IS_PARALLEL_AGENT="false"
|
|
51
|
+
for marker in "${PARALLEL_MARKER_PREFIX}"*.marker; do
|
|
52
|
+
if [[ -f "$marker" ]]; then
|
|
53
|
+
# Extract group ID from marker filename
|
|
54
|
+
AGENT_ID=$(basename "$marker" | sed 's/claude-parallel-//' | sed 's/\.marker//')
|
|
55
|
+
IS_PARALLEL_AGENT="true"
|
|
56
|
+
break
|
|
57
|
+
fi
|
|
58
|
+
done
|
|
59
|
+
|
|
60
|
+
# === TIMING END ===
|
|
61
|
+
# Include agent ID in log format if available (AC-4)
|
|
62
|
+
if [[ -n "$AGENT_ID" ]]; then
|
|
63
|
+
echo "$(date +%s.%N) [$AGENT_ID] END $TOOL_NAME" >> "$TIMING_LOG"
|
|
64
|
+
else
|
|
65
|
+
echo "$(date +%s.%N) END $TOOL_NAME" >> "$TIMING_LOG"
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
# === LOG ROTATION FOR QUALITY LOG ===
|
|
69
|
+
# Rotate if over 1000 lines to prevent unbounded growth
|
|
70
|
+
if [[ -f "$QUALITY_LOG" ]]; then
|
|
71
|
+
LINE_COUNT=$(wc -l < "$QUALITY_LOG" 2>/dev/null || echo 0)
|
|
72
|
+
if [[ "$LINE_COUNT" -gt 1000 ]]; then
|
|
73
|
+
tail -500 "$QUALITY_LOG" > "${QUALITY_LOG}.tmp" && mv "${QUALITY_LOG}.tmp" "$QUALITY_LOG"
|
|
74
|
+
fi
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
# === LOG ROTATION FOR TESTS LOG ===
|
|
78
|
+
if [[ -f "$TESTS_LOG" ]]; then
|
|
79
|
+
LINE_COUNT=$(wc -l < "$TESTS_LOG" 2>/dev/null || echo 0)
|
|
80
|
+
if [[ "$LINE_COUNT" -gt 1000 ]]; then
|
|
81
|
+
tail -500 "$TESTS_LOG" > "${TESTS_LOG}.tmp" && mv "${TESTS_LOG}.tmp" "$TESTS_LOG"
|
|
82
|
+
fi
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
# === JSON PARSING HELPER ===
|
|
86
|
+
# Try jq first for reliable JSON parsing, fall back to grep for simpler systems
|
|
87
|
+
extract_file_path() {
|
|
88
|
+
local input="$1"
|
|
89
|
+
local path=""
|
|
90
|
+
|
|
91
|
+
if command -v jq &>/dev/null; then
|
|
92
|
+
path=$(echo "$input" | jq -r '.file_path // empty' 2>/dev/null)
|
|
93
|
+
fi
|
|
94
|
+
|
|
95
|
+
# Fallback to grep if jq fails or isn't available
|
|
96
|
+
if [[ -z "$path" ]]; then
|
|
97
|
+
path=$(echo "$input" | grep -oE '"file_path"\s*:\s*"[^"]+"' | head -1 | cut -d'"' -f4)
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
echo "$path"
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
# === SECURITY WARNING LOGGING (AC-3 for Issue #492) ===
|
|
104
|
+
# Log warnings (don't block) for dangerous patterns in edited/written files
|
|
105
|
+
# These are not blocking because there may be legitimate uses, but should be reviewed
|
|
106
|
+
check_security_patterns() {
|
|
107
|
+
local content="$1"
|
|
108
|
+
local file_path="$2"
|
|
109
|
+
local warnings=()
|
|
110
|
+
|
|
111
|
+
# dangerouslyDisableSandbox usage (Bash tool security bypass)
|
|
112
|
+
if echo "$content" | grep -qE 'dangerouslyDisableSandbox.*true'; then
|
|
113
|
+
warnings+=("dangerouslyDisableSandbox=true (Bash security bypass)")
|
|
114
|
+
fi
|
|
115
|
+
|
|
116
|
+
# eval() usage (dynamic code execution - XSS/injection risk)
|
|
117
|
+
if echo "$content" | grep -qE '\beval\s*\('; then
|
|
118
|
+
warnings+=("eval() usage (dynamic code execution)")
|
|
119
|
+
fi
|
|
120
|
+
|
|
121
|
+
# innerHTML assignment (XSS vulnerability without sanitization)
|
|
122
|
+
if echo "$content" | grep -qE '\.innerHTML\s*='; then
|
|
123
|
+
warnings+=("innerHTML assignment (potential XSS)")
|
|
124
|
+
fi
|
|
125
|
+
|
|
126
|
+
# SQL string concatenation (SQL injection risk)
|
|
127
|
+
# Look for patterns like: query + variable or `SELECT ... ${variable}`
|
|
128
|
+
if echo "$content" | grep -qE "(query|sql|SQL)\s*\+\s*|query\s*=.*\\\$\{"; then
|
|
129
|
+
warnings+=("SQL string concatenation (potential injection)")
|
|
130
|
+
fi
|
|
131
|
+
|
|
132
|
+
# Log any warnings found
|
|
133
|
+
for warning in "${warnings[@]}"; do
|
|
134
|
+
echo "$(date +%H:%M:%S) SECURITY_WARNING: $warning in $file_path" >> "$QUALITY_LOG"
|
|
135
|
+
done
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if [[ "${CLAUDE_HOOKS_SECURITY:-true}" != "false" ]]; then
|
|
139
|
+
if [[ "$TOOL_NAME" == "Edit" || "$TOOL_NAME" == "Write" ]]; then
|
|
140
|
+
FILE_PATH=$(extract_file_path "$TOOL_INPUT")
|
|
141
|
+
|
|
142
|
+
if [[ -n "$FILE_PATH" && -f "$FILE_PATH" ]]; then
|
|
143
|
+
# Only check TypeScript/JavaScript files for security patterns
|
|
144
|
+
if [[ "$FILE_PATH" =~ \.(ts|tsx|js|jsx)$ ]]; then
|
|
145
|
+
FILE_CONTENT=$(cat "$FILE_PATH" 2>/dev/null || true)
|
|
146
|
+
if [[ -n "$FILE_CONTENT" ]]; then
|
|
147
|
+
check_security_patterns "$FILE_CONTENT" "$FILE_PATH"
|
|
148
|
+
fi
|
|
149
|
+
fi
|
|
150
|
+
fi
|
|
151
|
+
fi
|
|
152
|
+
fi
|
|
153
|
+
|
|
154
|
+
# === AUTO-FORMAT ON FILE WRITE ===
|
|
155
|
+
# Skip auto-formatting for parallel agents (AC-5)
|
|
156
|
+
# Parent agent will format after the parallel group completes
|
|
157
|
+
if [[ "$IS_PARALLEL_AGENT" == "true" ]]; then
|
|
158
|
+
# Log that formatting was skipped for parallel agent
|
|
159
|
+
if [[ "$TOOL_NAME" == "Edit" || "$TOOL_NAME" == "Write" ]]; then
|
|
160
|
+
FILE_PATH=$(extract_file_path "$TOOL_INPUT")
|
|
161
|
+
if [[ -n "$FILE_PATH" ]]; then
|
|
162
|
+
echo "$(date +%H:%M:%S) SKIP_FORMAT (parallel): $FILE_PATH" >> "$QUALITY_LOG"
|
|
163
|
+
fi
|
|
164
|
+
fi
|
|
165
|
+
elif [[ "$TOOL_NAME" == "Edit" || "$TOOL_NAME" == "Write" ]]; then
|
|
166
|
+
FILE_PATH=$(extract_file_path "$TOOL_INPUT")
|
|
167
|
+
|
|
168
|
+
if [[ -n "$FILE_PATH" && -f "$FILE_PATH" ]]; then
|
|
169
|
+
# Auto-format TypeScript/JavaScript files (synchronous to avoid race conditions)
|
|
170
|
+
if [[ "$FILE_PATH" =~ \.(ts|tsx|js|jsx)$ ]]; then
|
|
171
|
+
if npx prettier --write "$FILE_PATH" 2>/dev/null; then
|
|
172
|
+
echo "$(date +%H:%M:%S) FORMATTED: $FILE_PATH" >> "$QUALITY_LOG"
|
|
173
|
+
fi
|
|
174
|
+
fi
|
|
175
|
+
|
|
176
|
+
# Auto-format JSON files (synchronous)
|
|
177
|
+
if [[ "$FILE_PATH" =~ \.json$ ]]; then
|
|
178
|
+
npx prettier --write "$FILE_PATH" 2>/dev/null
|
|
179
|
+
fi
|
|
180
|
+
fi
|
|
181
|
+
fi
|
|
182
|
+
|
|
183
|
+
# === TRACK GIT OPERATIONS ===
|
|
184
|
+
if [[ "$TOOL_NAME" == "Bash" ]]; then
|
|
185
|
+
if echo "$TOOL_INPUT" | grep -qE 'git (commit|push|pr create)'; then
|
|
186
|
+
# Truncate long git commands for readability
|
|
187
|
+
GIT_CMD=$(echo "$TOOL_INPUT" | head -c 200)
|
|
188
|
+
echo "$(date +%H:%M:%S) GIT: $GIT_CMD" >> "$QUALITY_LOG"
|
|
189
|
+
fi
|
|
190
|
+
fi
|
|
191
|
+
|
|
192
|
+
# === DETECT TEST FAILURES ===
|
|
193
|
+
# Supports: npm, bun, yarn, pnpm
|
|
194
|
+
if [[ "$TOOL_NAME" == "Bash" ]] && echo "$TOOL_INPUT" | grep -qE '(npm (test|run test)|bun (test|run test)|yarn (test|run test)|pnpm (test|run test))'; then
|
|
195
|
+
if echo "$TOOL_OUTPUT" | grep -qE '(FAIL|failed|Error:)'; then
|
|
196
|
+
echo "$(date +%H:%M:%S) TEST_FAILURE detected" >> "$QUALITY_LOG"
|
|
197
|
+
fi
|
|
198
|
+
fi
|
|
199
|
+
|
|
200
|
+
# === DETECT BUILD FAILURES ===
|
|
201
|
+
# Supports: npm, bun, yarn, pnpm
|
|
202
|
+
if [[ "$TOOL_NAME" == "Bash" ]] && echo "$TOOL_INPUT" | grep -qE '(npm run build|bun run build|yarn build|yarn run build|pnpm run build)'; then
|
|
203
|
+
if echo "$TOOL_OUTPUT" | grep -qE '(error TS|Build failed|Error:)'; then
|
|
204
|
+
echo "$(date +%H:%M:%S) BUILD_FAILURE detected" >> "$QUALITY_LOG"
|
|
205
|
+
fi
|
|
206
|
+
fi
|
|
207
|
+
|
|
208
|
+
# === SMART TEST RUNNING (P3) ===
|
|
209
|
+
# Opt-in: Set CLAUDE_HOOKS_SMART_TESTS=true to enable
|
|
210
|
+
# Runs related tests asynchronously after file edits
|
|
211
|
+
if [[ "${CLAUDE_HOOKS_SMART_TESTS:-}" == "true" ]]; then
|
|
212
|
+
if [[ "$TOOL_NAME" == "Edit" || "$TOOL_NAME" == "Write" ]]; then
|
|
213
|
+
FILE_PATH=$(extract_file_path "$TOOL_INPUT")
|
|
214
|
+
|
|
215
|
+
if [[ -n "$FILE_PATH" && "$FILE_PATH" =~ \.(ts|tsx)$ ]]; then
|
|
216
|
+
# Extract filename without extension (use -E for macOS sed compatibility)
|
|
217
|
+
FILENAME=$(basename "$FILE_PATH" | sed -E 's/\.(ts|tsx)$//')
|
|
218
|
+
|
|
219
|
+
# Find related test file in __tests__/ directory
|
|
220
|
+
# This project uses centralized tests, not co-located
|
|
221
|
+
PROJECT_ROOT="${FILE_PATH%%/lib/*}"
|
|
222
|
+
if [[ "$PROJECT_ROOT" == "$FILE_PATH" ]]; then
|
|
223
|
+
PROJECT_ROOT="${FILE_PATH%%/components/*}"
|
|
224
|
+
fi
|
|
225
|
+
if [[ "$PROJECT_ROOT" == "$FILE_PATH" ]]; then
|
|
226
|
+
PROJECT_ROOT="${FILE_PATH%%/app/*}"
|
|
227
|
+
fi
|
|
228
|
+
|
|
229
|
+
# Search for test files matching the source file name
|
|
230
|
+
TEST_FILE=""
|
|
231
|
+
if [[ -d "$PROJECT_ROOT/__tests__" ]]; then
|
|
232
|
+
# Try direct match first
|
|
233
|
+
if [[ -f "$PROJECT_ROOT/__tests__/${FILENAME}.test.ts" ]]; then
|
|
234
|
+
TEST_FILE="$PROJECT_ROOT/__tests__/${FILENAME}.test.ts"
|
|
235
|
+
elif [[ -f "$PROJECT_ROOT/__tests__/${FILENAME}.test.tsx" ]]; then
|
|
236
|
+
TEST_FILE="$PROJECT_ROOT/__tests__/${FILENAME}.test.tsx"
|
|
237
|
+
# Try integration tests
|
|
238
|
+
elif [[ -f "$PROJECT_ROOT/__tests__/integration/${FILENAME}.test.ts" ]]; then
|
|
239
|
+
TEST_FILE="$PROJECT_ROOT/__tests__/integration/${FILENAME}.test.ts"
|
|
240
|
+
elif [[ -f "$PROJECT_ROOT/__tests__/integration/${FILENAME}.test.tsx" ]]; then
|
|
241
|
+
TEST_FILE="$PROJECT_ROOT/__tests__/integration/${FILENAME}.test.tsx"
|
|
242
|
+
fi
|
|
243
|
+
fi
|
|
244
|
+
|
|
245
|
+
if [[ -n "$TEST_FILE" && -f "$TEST_FILE" ]]; then
|
|
246
|
+
echo "$(date +%H:%M:%S) SMART_TEST: Running $TEST_FILE for $FILE_PATH" >> "$TESTS_LOG"
|
|
247
|
+
|
|
248
|
+
# Run test asynchronously to avoid blocking
|
|
249
|
+
# Use timeout/gtimeout if available, otherwise run without timeout
|
|
250
|
+
(
|
|
251
|
+
cd "$PROJECT_ROOT" 2>/dev/null || exit
|
|
252
|
+
TIMEOUT_CMD=""
|
|
253
|
+
if command -v timeout &>/dev/null; then
|
|
254
|
+
TIMEOUT_CMD="timeout 30"
|
|
255
|
+
elif command -v gtimeout &>/dev/null; then
|
|
256
|
+
TIMEOUT_CMD="gtimeout 30"
|
|
257
|
+
fi
|
|
258
|
+
$TIMEOUT_CMD npm test -- --testPathPatterns="$(basename "$TEST_FILE")" --silent 2>&1 | head -20 >> "$TESTS_LOG"
|
|
259
|
+
if [[ ${PIPESTATUS[0]} -ne 0 ]]; then
|
|
260
|
+
echo "$(date +%H:%M:%S) SMART_TEST_RESULT: FAIL" >> "$TESTS_LOG"
|
|
261
|
+
else
|
|
262
|
+
echo "$(date +%H:%M:%S) SMART_TEST_RESULT: PASS" >> "$TESTS_LOG"
|
|
263
|
+
fi
|
|
264
|
+
) &
|
|
265
|
+
fi
|
|
266
|
+
fi
|
|
267
|
+
fi
|
|
268
|
+
fi
|
|
269
|
+
|
|
270
|
+
# === WEBHOOK NOTIFICATIONS (P3) ===
|
|
271
|
+
# Opt-in: Set CLAUDE_HOOKS_WEBHOOK_URL to enable
|
|
272
|
+
# Fires notification when issues are closed
|
|
273
|
+
if [[ -n "${CLAUDE_HOOKS_WEBHOOK_URL:-}" ]]; then
|
|
274
|
+
if [[ "$TOOL_NAME" == "Bash" ]] && echo "$TOOL_INPUT" | grep -qE 'gh issue close'; then
|
|
275
|
+
# Extract issue number
|
|
276
|
+
ISSUE_NUM=$(echo "$TOOL_INPUT" | grep -oE '#?[0-9]+' | head -1 | tr -d '#')
|
|
277
|
+
|
|
278
|
+
if [[ -n "$ISSUE_NUM" ]]; then
|
|
279
|
+
echo "$(date +%H:%M:%S) WEBHOOK: Notifying issue #$ISSUE_NUM closed" >> "$QUALITY_LOG"
|
|
280
|
+
|
|
281
|
+
# Fire-and-forget async curl (don't block on webhook failures)
|
|
282
|
+
(
|
|
283
|
+
curl -s -X POST "$CLAUDE_HOOKS_WEBHOOK_URL" \
|
|
284
|
+
-H 'Content-Type: application/json' \
|
|
285
|
+
-d "{\"text\":\"Issue #$ISSUE_NUM completed by Claude Code automation\"}" \
|
|
286
|
+
--max-time 5 2>/dev/null || true
|
|
287
|
+
) &
|
|
288
|
+
fi
|
|
289
|
+
fi
|
|
290
|
+
fi
|
|
291
|
+
|
|
292
|
+
exit 0
|