sequant 2.7.0 → 2.8.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.
Files changed (59) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +9 -1
  4. package/dist/bin/cli.d.ts +1 -1
  5. package/dist/bin/cli.js +10 -1
  6. package/dist/bin/preflight.d.ts +21 -0
  7. package/dist/bin/preflight.js +45 -0
  8. package/dist/marketplace/external_plugins/sequant/.claude-plugin/plugin.json +1 -1
  9. package/dist/marketplace/external_plugins/sequant/skills/_shared/references/force-push.md +34 -0
  10. package/dist/marketplace/external_plugins/sequant/skills/assess/SKILL.md +24 -7
  11. package/dist/marketplace/external_plugins/sequant/skills/exec/SKILL.md +29 -0
  12. package/dist/marketplace/external_plugins/sequant/skills/loop/SKILL.md +100 -2
  13. package/dist/marketplace/external_plugins/sequant/skills/qa/SKILL.md +24 -0
  14. package/dist/marketplace/external_plugins/sequant/skills/qa/references/anti-pattern-detection.md +285 -0
  15. package/dist/marketplace/external_plugins/sequant/skills/qa/references/call-site-review.md +202 -0
  16. package/dist/marketplace/external_plugins/sequant/skills/qa/references/quality-gates.md +287 -0
  17. package/dist/marketplace/external_plugins/sequant/skills/qa/references/test-quality-checklist.md +272 -0
  18. package/dist/marketplace/external_plugins/sequant/skills/qa/references/testing-requirements.md +40 -0
  19. package/dist/marketplace/external_plugins/sequant/skills/qa/scripts/quality-checks.sh +95 -11
  20. package/dist/marketplace/external_plugins/sequant/skills/references/shared/framework-gotchas.md +186 -0
  21. package/dist/marketplace/external_plugins/sequant/skills/release/SKILL.md +661 -0
  22. package/dist/marketplace/external_plugins/sequant/skills/test/references/browser-testing-patterns.md +423 -0
  23. package/dist/marketplace/external_plugins/sequant/skills/upstream/SKILL.md +419 -0
  24. package/dist/src/lib/errors.d.ts +85 -0
  25. package/dist/src/lib/errors.js +111 -0
  26. package/dist/src/lib/version-check.d.ts +19 -0
  27. package/dist/src/lib/version-check.js +44 -0
  28. package/dist/src/lib/workflow/batch-executor.js +61 -6
  29. package/dist/src/lib/workflow/drivers/agent-driver.d.ts +17 -0
  30. package/dist/src/lib/workflow/drivers/claude-code.d.ts +22 -0
  31. package/dist/src/lib/workflow/drivers/claude-code.js +111 -7
  32. package/dist/src/lib/workflow/log-writer.d.ts +1 -1
  33. package/dist/src/lib/workflow/phase-executor.d.ts +18 -0
  34. package/dist/src/lib/workflow/phase-executor.js +76 -14
  35. package/dist/src/lib/workflow/run-log-schema.d.ts +3 -0
  36. package/dist/src/lib/workflow/run-log-schema.js +7 -0
  37. package/dist/src/lib/workflow/state-manager.d.ts +1 -0
  38. package/dist/src/lib/workflow/state-manager.js +6 -0
  39. package/dist/src/lib/workflow/state-schema.d.ts +3 -0
  40. package/dist/src/lib/workflow/state-schema.js +7 -0
  41. package/dist/src/lib/workflow/types.d.ts +17 -0
  42. package/dist/src/ui/tui/theme.d.ts +18 -4
  43. package/dist/src/ui/tui/theme.js +18 -4
  44. package/package.json +4 -3
  45. package/templates/skills/_shared/references/force-push.md +34 -0
  46. package/templates/skills/assess/SKILL.md +24 -7
  47. package/templates/skills/exec/SKILL.md +29 -0
  48. package/templates/skills/loop/SKILL.md +100 -2
  49. package/templates/skills/qa/SKILL.md +24 -0
  50. package/templates/skills/qa/references/anti-pattern-detection.md +285 -0
  51. package/templates/skills/qa/references/call-site-review.md +202 -0
  52. package/templates/skills/qa/references/quality-gates.md +287 -0
  53. package/templates/skills/qa/references/test-quality-checklist.md +272 -0
  54. package/templates/skills/qa/references/testing-requirements.md +40 -0
  55. package/templates/skills/qa/scripts/quality-checks.sh +95 -11
  56. package/templates/skills/references/shared/framework-gotchas.md +186 -0
  57. package/templates/skills/release/SKILL.md +661 -0
  58. package/templates/skills/test/references/browser-testing-patterns.md +423 -0
  59. package/templates/skills/upstream/SKILL.md +419 -0
@@ -0,0 +1,285 @@
1
+ # Anti-Pattern Detection
2
+
3
+ ## Purpose
4
+
5
+ Lightweight pattern-matching sanity checks to catch issues that experts would flag immediately. These checks complement code review by automating detection of common mistakes.
6
+
7
+ ## Part 1: New Dependency Audit
8
+
9
+ ### When to Run
10
+
11
+ Run dependency audit when `package.json` is modified:
12
+
13
+ ```bash
14
+ # Check if package.json was modified
15
+ pkg_modified=$(git diff main...HEAD --name-only | grep -E "^package\.json$" | head -1)
16
+ if [[ -n "$pkg_modified" ]]; then
17
+ echo "package.json modified - running dependency audit"
18
+ fi
19
+ ```
20
+
21
+ ### Detecting New Dependencies
22
+
23
+ ```bash
24
+ # Get new dependencies (added in this branch)
25
+ git diff main...HEAD -- package.json | grep '^\+.*":' | grep -v '^\+\+\+' | sed 's/.*"\([^"]*\)".*/\1/' | grep -v -E '^(@types/|version|name|description|scripts|devDependencies|dependencies|peerDependencies)$'
26
+ ```
27
+
28
+ ### Audit Criteria
29
+
30
+ | Flag | Threshold | Detection Method | Risk Level |
31
+ |------|-----------|------------------|------------|
32
+ | Low downloads | <1,000/week | `npm view <pkg> --json \| jq '.downloads'` | ⚠️ Medium |
33
+ | Stale | No updates 12+ months | `npm view <pkg> time.modified` | ⚠️ Medium |
34
+ | License risk | UNLICENSED, GPL in MIT project | `npm view <pkg> license` | ❌ High |
35
+ | Size concern | >100kb for utility | `npm view <pkg> dist.unpackedSize` | ⚠️ Low |
36
+ | Security advisory | Known vulnerabilities | `npm audit --json` | ❌ High |
37
+
38
+ ### Audit Commands
39
+
40
+ ```bash
41
+ # Get package metadata (run for each new dependency)
42
+ pkg="<package-name>"
43
+
44
+ # Weekly downloads (requires npm API)
45
+ downloads=$(curl -s "https://api.npmjs.org/downloads/point/last-week/$pkg" | jq '.downloads // 0')
46
+
47
+ # Last update date
48
+ last_update=$(npm view "$pkg" time.modified 2>/dev/null)
49
+
50
+ # License
51
+ license=$(npm view "$pkg" license 2>/dev/null)
52
+
53
+ # Unpacked size (in bytes)
54
+ size=$(npm view "$pkg" dist.unpackedSize 2>/dev/null)
55
+
56
+ # Security check (all dependencies)
57
+ npm audit --json 2>/dev/null | jq '.vulnerabilities | length'
58
+ ```
59
+
60
+ ### Output Format
61
+
62
+ ```markdown
63
+ ### Dependency Audit
64
+
65
+ | Package | Downloads/wk | Last Update | License | Size | Flags |
66
+ |---------|--------------|-------------|---------|------|-------|
67
+ | foo-pkg | 500 | 2023-01-15 | MIT | 45kb | ⚠️ Low downloads, ⚠️ Stale |
68
+ | bar-lib | 50,000 | 2024-12-01 | Apache-2.0 | 120kb | ⚠️ Size |
69
+
70
+ **Security Audit:** 0 vulnerabilities found
71
+
72
+ **Flagged Dependencies:**
73
+ 1. `foo-pkg` - Low downloads (<1,000/week) and stale (12+ months)
74
+ - **Risk:** Unmaintained packages may have unpatched vulnerabilities
75
+ - **Suggestion:** Consider alternative with active maintenance or vendor the code
76
+ ```
77
+
78
+ ### Verdict Impact
79
+
80
+ | Finding | Verdict Impact |
81
+ |---------|----------------|
82
+ | Low downloads only | Note in QA, no verdict change |
83
+ | Stale only | Note in QA, no verdict change |
84
+ | Security vulnerability (moderate+) | `AC_NOT_MET` (blocker) |
85
+ | License incompatibility | `AC_NOT_MET` (blocker) |
86
+ | Multiple flags on same package | `AC_MET_BUT_NOT_A_PLUS` |
87
+
88
+ ---
89
+
90
+ ## Part 2: Code Pattern Checks
91
+
92
+ ### Anti-Pattern Detection Matrix
93
+
94
+ | Category | Pattern | Detection | Suggestion | Risk |
95
+ |----------|---------|-----------|------------|------|
96
+ | **Performance** | N+1 query (`await` in loop) | `for.*await\|\.forEach.*await` | Use batch query or `Promise.all` | ⚠️ Medium |
97
+ | **Performance** | Unbounded loop | `while.*true\|for.*;;` without break limit | Add iteration limit | ⚠️ Medium |
98
+ | **Performance** | Sync file ops in async context | `fs\.readFileSync\|fs\.writeFileSync` | Use async fs methods | ⚠️ Low |
99
+ | **Error Handling** | Empty catch block | `catch.*\{\s*\}` | Log or rethrow | ⚠️ Medium |
100
+ | **Error Handling** | Swallowed error | `catch.*\{\s*//` | Handle or rethrow | ⚠️ Medium |
101
+ | **Error Handling** | Unhandled promise | `\.then\(.*\)[^.]` without `.catch` | Add `.catch()` or use try/catch | ⚠️ Medium |
102
+ | **Security** | Hardcoded secret | `(api[_-]?key\|secret\|password)\s*[:=]\s*['"][^'"]+['"]` | Use env variable | ❌ High |
103
+ | **Security** | SQL concatenation | `\+.*SELECT\|SELECT.*\+\|'.*\$\{.*\}.*SELECT` | Use parameterized query | ❌ High |
104
+ | **Security** | eval usage | `eval\(` | Remove eval, use safe alternative | ❌ High |
105
+ | **Security** | Server binds all interfaces | `.listen(port)` without explicit host | Bind to `127.0.0.1` for local-only servers | ❌ High |
106
+ | **Memory** | Uncleared interval | `setInterval\(` without corresponding `clearInterval` | Clear in cleanup | ⚠️ Medium |
107
+ | **Memory** | Uncleared timeout | `setTimeout\(` in component without cleanup | Clear in useEffect cleanup | ⚠️ Low |
108
+ | **A11y** | Image without alt | `<img[^>]*(?!alt=)[^>]*>` | Add descriptive alt | ⚠️ Low |
109
+ | **A11y** | Click handler without keyboard | `onClick=\{` without `onKeyDown` | Add keyboard handler | ⚠️ Low |
110
+
111
+ ### Detection Commands
112
+
113
+ ```bash
114
+ # Run on changed files only
115
+ changed_files=$(git diff main...HEAD --name-only | grep -E '\.(ts|tsx|js|jsx)$')
116
+
117
+ # N+1 query pattern (await in loop)
118
+ grep -n -E 'for\s*\([^)]*\)\s*\{[^}]*await|\.forEach\([^)]*async' $changed_files 2>/dev/null
119
+
120
+ # Empty catch block
121
+ grep -n -E 'catch\s*\([^)]*\)\s*\{\s*\}' $changed_files 2>/dev/null
122
+
123
+ # Hardcoded secrets (case insensitive)
124
+ grep -ni -E '(api[_-]?key|secret|password|token)\s*[:=]\s*['"'"'"][^'"'"'"]+['"'"'"]' $changed_files 2>/dev/null | grep -v -E '(\.env|example|test|mock|placeholder)'
125
+
126
+ # SQL concatenation
127
+ grep -n -E "(\+\s*['\"].*SELECT|SELECT.*['\"].*\+|\`.*\$\{.*\}.*SELECT)" $changed_files 2>/dev/null
128
+
129
+ # Server binding to all interfaces (0.0.0.0)
130
+ grep -n -E '\.listen\(\s*(port|[0-9]+)\s*[,)]' $changed_files 2>/dev/null | grep -v -E '127\.0\.0\.1|localhost'
131
+
132
+ # Uncleared intervals (check for setInterval without corresponding clear)
133
+ for f in $changed_files; do
134
+ intervals=$(grep -c 'setInterval(' "$f" 2>/dev/null || echo 0)
135
+ clears=$(grep -c 'clearInterval(' "$f" 2>/dev/null || echo 0)
136
+ if [[ $intervals -gt $clears ]]; then
137
+ echo "$f: $intervals setInterval calls, only $clears clearInterval calls"
138
+ fi
139
+ done
140
+ ```
141
+
142
+ ### Output Format
143
+
144
+ ```markdown
145
+ ### Code Pattern Analysis
146
+
147
+ | File:Line | Category | Pattern | Suggestion |
148
+ |-----------|----------|---------|------------|
149
+ | `src/api/users.ts:45` | Performance | N+1 query | Use `Promise.all` for batch fetching |
150
+ | `src/utils/config.ts:12` | Error Handling | Empty catch | Log error or rethrow |
151
+ | `src/components/List.tsx:89` | Memory | Uncleared interval | Add `clearInterval` in cleanup |
152
+
153
+ **Critical Issues:** 0
154
+ **Warnings:** 3
155
+
156
+ **Details:**
157
+
158
+ 1. **N+1 Query** at `src/api/users.ts:45`
159
+ ```typescript
160
+ // Current (N+1)
161
+ for (const id of userIds) {
162
+ await fetchUser(id); // Makes N requests
163
+ }
164
+
165
+ // Suggested
166
+ await Promise.all(userIds.map(id => fetchUser(id)));
167
+ // Or use batch endpoint
168
+ await fetchUsers(userIds);
169
+ ```
170
+
171
+ 2. **Empty Catch** at `src/utils/config.ts:12`
172
+ ```typescript
173
+ // Current
174
+ try { ... } catch (e) { }
175
+
176
+ // Suggested
177
+ try { ... } catch (e) {
178
+ console.error('Config load failed:', e);
179
+ // or rethrow: throw e;
180
+ }
181
+ ```
182
+ ```
183
+
184
+ ### Verdict Impact
185
+
186
+ | Finding | Verdict Impact |
187
+ |---------|----------------|
188
+ | Performance warnings | Note in QA, no verdict change |
189
+ | Empty catch blocks | `AC_MET_BUT_NOT_A_PLUS` |
190
+ | Security issues (secrets, SQL injection) | `AC_NOT_MET` (blocker) |
191
+ | Uncleared intervals/timeouts | `AC_MET_BUT_NOT_A_PLUS` |
192
+ | A11y issues | Note in QA, no verdict change |
193
+
194
+ ---
195
+
196
+ ## Part 3: Integration with QA Workflow
197
+
198
+ ### When to Run
199
+
200
+ 1. **Dependency Audit:** Only when `package.json` is modified
201
+ 2. **Code Pattern Checks:** Always run on changed `.ts/.tsx/.js/.jsx` files
202
+
203
+ ### Execution Order
204
+
205
+ ```
206
+ 1. Standard quality checks (type safety, deleted tests, scope)
207
+ 2. Dependency audit (if package.json modified)
208
+ 3. Code pattern checks
209
+ 4. Test quality review (if test files modified)
210
+ 5. Execution evidence (if scripts/CLI modified)
211
+ ```
212
+
213
+ ### Combined Output Section
214
+
215
+ ```markdown
216
+ ### Anti-Pattern Detection
217
+
218
+ #### Dependency Audit
219
+ [Include if package.json modified, otherwise: "N/A - No dependency changes"]
220
+
221
+ #### Code Patterns
222
+ [Always include for code changes]
223
+
224
+ **Summary:**
225
+ - Dependencies flagged: X
226
+ - Code patterns flagged: Y
227
+ - Critical issues: Z (blockers)
228
+ ```
229
+
230
+ ---
231
+
232
+ ## Appendix: Full Detection Script
233
+
234
+ For automation, this script can be run to check all patterns:
235
+
236
+ ```bash
237
+ #!/bin/bash
238
+ # anti-pattern-check.sh
239
+
240
+ set -e
241
+
242
+ echo "=== Anti-Pattern Detection ==="
243
+
244
+ # Get changed files
245
+ CHANGED_TS=$(git diff main...HEAD --name-only | grep -E '\.(ts|tsx|js|jsx)$' || true)
246
+ PKG_CHANGED=$(git diff main...HEAD --name-only | grep -E '^package\.json$' || true)
247
+
248
+ # 1. Dependency Audit
249
+ if [[ -n "$PKG_CHANGED" ]]; then
250
+ echo ""
251
+ echo "## Dependency Audit"
252
+ # Get new deps
253
+ NEW_DEPS=$(git diff main...HEAD -- package.json | grep '^\+.*":' | grep -v '^\+\+\+' | sed 's/.*"\([^"]*\)".*/\1/' | grep -v -E '^(@types/|version|name|description|scripts|devDependencies|dependencies|peerDependencies|engines|repository|author|license|bugs|homepage|main|module|types)$' || true)
254
+
255
+ if [[ -n "$NEW_DEPS" ]]; then
256
+ echo "New dependencies detected:"
257
+ for dep in $NEW_DEPS; do
258
+ echo " - $dep"
259
+ done
260
+ else
261
+ echo "No new dependencies added"
262
+ fi
263
+ fi
264
+
265
+ # 2. Code Pattern Checks
266
+ if [[ -n "$CHANGED_TS" ]]; then
267
+ echo ""
268
+ echo "## Code Pattern Checks"
269
+
270
+ echo ""
271
+ echo "### N+1 Queries (await in loop):"
272
+ grep -n -E 'for\s*\([^)]*\)\s*\{[^}]*await|\.forEach\([^)]*async' $CHANGED_TS 2>/dev/null || echo " None found"
273
+
274
+ echo ""
275
+ echo "### Empty Catch Blocks:"
276
+ grep -n -E 'catch\s*\([^)]*\)\s*\{\s*\}' $CHANGED_TS 2>/dev/null || echo " None found"
277
+
278
+ echo ""
279
+ echo "### Potential Hardcoded Secrets:"
280
+ grep -ni -E '(api[_-]?key|secret|password|token)\s*[:=]\s*['"'"'"][^'"'"'"]+['"'"'"]' $CHANGED_TS 2>/dev/null | grep -v -E '(\.env|example|test|mock|placeholder|process\.env)' || echo " None found"
281
+ fi
282
+
283
+ echo ""
284
+ echo "=== End Anti-Pattern Detection ==="
285
+ ```
@@ -0,0 +1,202 @@
1
+ # Call-Site Review Checklist
2
+
3
+ ## Purpose
4
+
5
+ When new exported functions are added, QA must review not just the function itself but **where** and **how** it's called. A function can be perfectly implemented but called incorrectly at the call site.
6
+
7
+ **Origin:** Issue #295 — `rebaseBeforePR()` had thorough unit tests but was called for every issue in a chain loop when the AC specified "only the final branch."
8
+
9
+ ## When to Apply
10
+
11
+ This review is **triggered** when new exported functions are detected in the diff:
12
+
13
+ ```bash
14
+ # Detect new exported functions (added lines only)
15
+ # Catches: export function foo, export async function foo,
16
+ # export const foo = () =>, export const foo = async () =>
17
+ git diff main...HEAD | grep -E '^\+export (async )?function \w+' | sed 's/^+//'
18
+ git diff main...HEAD | grep -E '^\+export const \w+ = (async )?\(' | sed 's/^+//'
19
+ ```
20
+
21
+ ## Review Steps
22
+
23
+ ### Step 1: Call-Site Inventory
24
+
25
+ For each new exported function, find where it's called using the Grep tool:
26
+
27
+ ```bash
28
+ # Find call sites for a function (exclude test files)
29
+ Grep(pattern="functionName\\(", glob="*.{ts,tsx}", output_mode="content")
30
+ # Then exclude results from .test. files and __tests__ directories
31
+ ```
32
+
33
+ ### Step 2: Condition Audit
34
+
35
+ For each call site, identify:
36
+
37
+ 1. **What conditions gate the call?**
38
+ - `if` statements, `&&` guards, ternaries
39
+ - Mode flags, feature flags, environment checks
40
+
41
+ 2. **Is it in a loop?**
42
+ - `for`, `while`, `forEach`, `.map()`, `.filter()`, etc.
43
+ - If yes: Should it run for every iteration or only specific ones?
44
+
45
+ 3. **Is it in an async context?**
46
+ - Is `await` used appropriately?
47
+ - Could it cause race conditions?
48
+
49
+ 4. **Error handling at call site?**
50
+ - Is the call wrapped in try/catch?
51
+ - What happens if the function throws?
52
+
53
+ **AC Constraint Matching:**
54
+
55
+ Compare call-site conditions against AC constraints:
56
+
57
+ | AC Constraint | Call Site Check |
58
+ |---------------|-----------------|
59
+ | "Only for X" | Is there a guard: `if (X)` before the call? |
60
+ | "When Y happens" | Is the call triggered by the Y event/condition? |
61
+ | "Not in Z mode" | Is there a guard: `if (!Z)` or similar? |
62
+ | "Final item only" | If in loop, is there an index check or break? |
63
+
64
+ ### Step 3: Loop Awareness
65
+
66
+ When a function is called inside a loop, answer:
67
+
68
+ 1. **Iteration scope:**
69
+ - Should it run for ALL iterations? → OK
70
+ - Should it run for FIRST/LAST only? → Check for index guard
71
+ - Should it run for SOME iterations? → Check for condition filter
72
+
73
+ 2. **Common patterns to verify:**
74
+
75
+ ```typescript
76
+ // LAST only - should have index check
77
+ for (let i = 0; i < items.length; i++) {
78
+ if (i === items.length - 1) {
79
+ newFunction(); // ✅ Guarded for last
80
+ }
81
+ }
82
+
83
+ // FIRST only - should have index check
84
+ items.forEach((item, index) => {
85
+ if (index === 0) {
86
+ newFunction(); // ✅ Guarded for first
87
+ }
88
+ });
89
+
90
+ // CONDITIONAL - should have filter
91
+ for (const item of items) {
92
+ if (item.shouldProcess) {
93
+ newFunction(item); // ✅ Conditionally called
94
+ }
95
+ }
96
+ ```
97
+
98
+ 3. **Red flags:**
99
+ - Function called unconditionally in loop when AC says "only once"
100
+ - No break/return after the call when AC implies single execution
101
+ - Missing mode/flag guard when AC specifies conditions
102
+
103
+ ### Step 4: Mode Sensitivity
104
+
105
+ If the function behaves differently based on mode flags:
106
+
107
+ 1. **Identify mode parameters:**
108
+ - Does the function accept `options` or `config`?
109
+ - Are there mode-specific code paths inside?
110
+
111
+ 2. **Verify at call site:**
112
+ - Is the mode passed correctly?
113
+ - Does the caller's context match the mode expected?
114
+
115
+ ## Output Format
116
+
117
+ ```markdown
118
+ ### Call-Site Review
119
+
120
+ **New exported functions detected:** N
121
+
122
+ | Function | Call Sites | Loop? | Conditions | AC Match |
123
+ |----------|-----------|-------|------------|----------|
124
+ | `newFunction()` | `file.ts:123` | No | `if (condition)` | ✅ Matches AC-2 |
125
+ | `anotherFunc()` | `run.ts:456` | Yes (forEach) | None | ⚠️ Missing guard (AC-3 says "final only") |
126
+ | `thirdFunc()` | Not called | - | - | ⚠️ Unused export |
127
+
128
+ **Findings:**
129
+ - `anotherFunc()` is called in a loop without iteration guard. AC-3 specifies "only for the final item."
130
+
131
+ **Recommendations:**
132
+ 1. Add index check: `if (index === items.length - 1)` before calling `anotherFunc()`
133
+ ```
134
+
135
+ ## Verdict Impact
136
+
137
+ | Finding | Verdict Impact |
138
+ |---------|----------------|
139
+ | All call sites match AC | No impact |
140
+ | Call site missing AC-required guard | `AC_NOT_MET` |
141
+ | Function not called anywhere | `AC_MET_BUT_NOT_A_PLUS` (dead export) |
142
+ | Call site in loop, AC unclear about iteration | `NEEDS_VERIFICATION` |
143
+
144
+ ## Examples
145
+
146
+ ### Example 1: Missing Chain Mode Guard (Issue #295)
147
+
148
+ **AC:** "Rebase only the final branch in a chain"
149
+
150
+ **Detection:**
151
+
152
+ ```bash
153
+ Grep(pattern="rebaseBeforePR\\(", glob="*.ts", output_mode="content")
154
+ # Output: src/run.ts:2977: await rebaseBeforePR(worktreePath)
155
+ ```
156
+
157
+ **Analysis:**
158
+
159
+ ```typescript
160
+ // Found in loop over all chain issues
161
+ for (const result of chainResults) {
162
+ if (result.success && result.worktreePath) {
163
+ await rebaseBeforePR(result.worktreePath); // ⚠️ Called for ALL
164
+ }
165
+ }
166
+ ```
167
+
168
+ **Finding:** No guard for "final only" — function called for every issue in chain.
169
+
170
+ **Fix:** Add final-issue check:
171
+
172
+ ```typescript
173
+ for (let i = 0; i < chainResults.length; i++) {
174
+ const result = chainResults[i];
175
+ const isFinal = i === chainResults.length - 1;
176
+ if (result.success && result.worktreePath && isFinal) {
177
+ await rebaseBeforePR(result.worktreePath); // ✅ Only final
178
+ }
179
+ }
180
+ ```
181
+
182
+ ### Example 2: Correct Guard Present
183
+
184
+ **AC:** "Send notification only when status is 'complete'"
185
+
186
+ **Detection:**
187
+
188
+ ```bash
189
+ Grep(pattern="sendNotification\\(", glob="*.ts", output_mode="content")
190
+ # Output: src/handlers.ts:89: sendNotification(user.email, message)
191
+ ```
192
+
193
+ **Analysis:**
194
+
195
+ ```typescript
196
+ // Found with proper guard
197
+ if (task.status === 'complete') {
198
+ sendNotification(user.email, message); // ✅ Guarded
199
+ }
200
+ ```
201
+
202
+ **Finding:** Call site condition matches AC constraint. No issues.