sequant 2.0.0 ā 2.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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +7 -6
- package/dist/bin/cli.js +2 -1
- package/dist/marketplace/external_plugins/sequant/.claude-plugin/plugin.json +1 -1
- package/dist/marketplace/external_plugins/sequant/.mcp.json +6 -0
- package/dist/marketplace/external_plugins/sequant/README.md +58 -8
- package/dist/marketplace/external_plugins/sequant/hooks/post-tool.sh +19 -8
- package/dist/marketplace/external_plugins/sequant/hooks/pre-tool.sh +36 -49
- package/dist/marketplace/external_plugins/sequant/skills/_shared/references/subagent-types.md +158 -48
- package/dist/marketplace/external_plugins/sequant/skills/assess/SKILL.md +354 -352
- package/dist/marketplace/external_plugins/sequant/skills/exec/SKILL.md +1155 -33
- package/dist/marketplace/external_plugins/sequant/skills/fullsolve/SKILL.md +35 -4
- package/dist/marketplace/external_plugins/sequant/skills/qa/SKILL.md +2157 -104
- package/dist/marketplace/external_plugins/sequant/skills/qa/scripts/quality-checks.sh +1 -1
- package/dist/marketplace/external_plugins/sequant/skills/setup/SKILL.md +386 -0
- package/dist/marketplace/external_plugins/sequant/skills/solve/SKILL.md +38 -664
- package/dist/marketplace/external_plugins/sequant/skills/spec/SKILL.md +505 -120
- package/dist/marketplace/external_plugins/sequant/skills/test/SKILL.md +246 -1
- package/dist/marketplace/external_plugins/sequant/skills/testgen/SKILL.md +138 -1
- package/dist/src/commands/dashboard.js +1 -1
- package/dist/src/commands/doctor.js +1 -1
- package/dist/src/commands/init.js +10 -10
- package/dist/src/commands/logs.js +1 -1
- package/dist/src/commands/run.js +49 -39
- package/dist/src/commands/state.js +3 -3
- package/dist/src/commands/status.js +5 -5
- package/dist/src/commands/sync.js +8 -8
- package/dist/src/commands/update.js +16 -16
- package/dist/src/lib/cli-ui.js +20 -19
- package/dist/src/lib/merge-check/index.js +2 -2
- package/dist/src/lib/settings.d.ts +8 -0
- package/dist/src/lib/settings.js +1 -0
- package/dist/src/lib/shutdown.js +1 -1
- package/dist/src/lib/templates.js +2 -0
- package/dist/src/lib/wizard.js +6 -4
- package/dist/src/lib/workflow/batch-executor.d.ts +9 -1
- package/dist/src/lib/workflow/batch-executor.js +39 -2
- package/dist/src/lib/workflow/log-writer.js +6 -6
- package/dist/src/lib/workflow/metrics-writer.js +5 -3
- package/dist/src/lib/workflow/phase-executor.d.ts +1 -1
- package/dist/src/lib/workflow/phase-executor.js +52 -22
- package/dist/src/lib/workflow/platforms/github.js +5 -1
- package/dist/src/lib/workflow/state-cleanup.js +1 -1
- package/dist/src/lib/workflow/state-manager.js +15 -13
- package/dist/src/lib/workflow/state-rebuild.js +2 -2
- package/dist/src/lib/workflow/types.d.ts +27 -0
- package/dist/src/lib/workflow/worktree-manager.js +40 -41
- package/dist/src/lib/worktree-isolation.d.ts +130 -0
- package/dist/src/lib/worktree-isolation.js +310 -0
- package/package.json +24 -14
- package/templates/agents/sequant-explorer.md +23 -0
- package/templates/agents/sequant-implementer.md +18 -0
- package/templates/agents/sequant-qa-checker.md +24 -0
- package/templates/agents/sequant-testgen.md +25 -0
- package/templates/scripts/cleanup-worktree.sh +18 -0
- package/templates/skills/_shared/references/subagent-types.md +158 -48
- package/templates/skills/exec/SKILL.md +72 -6
- package/templates/skills/qa/SKILL.md +8 -217
- package/templates/skills/spec/SKILL.md +446 -120
- package/templates/skills/testgen/SKILL.md +138 -1
|
@@ -42,10 +42,127 @@ The `/test` phase is invoked by `/fullsolve` based on issue labels:
|
|
|
42
42
|
2. **Execution Phase:** Run tests systematically with browser automation
|
|
43
43
|
3. **Reporting Phase:** Generate test results and GitHub comment
|
|
44
44
|
|
|
45
|
+
## Orchestration Context
|
|
46
|
+
|
|
47
|
+
When running as part of an orchestrated workflow (e.g., `sequant run` or `/fullsolve`), this skill receives environment variables that indicate the orchestration context:
|
|
48
|
+
|
|
49
|
+
| Environment Variable | Description | Example Value |
|
|
50
|
+
|---------------------|-------------|---------------|
|
|
51
|
+
| `SEQUANT_ORCHESTRATOR` | The orchestrator invoking this skill | `sequant-run` |
|
|
52
|
+
| `SEQUANT_PHASE` | Current phase in the workflow | `test` |
|
|
53
|
+
| `SEQUANT_ISSUE` | Issue number being processed | `123` |
|
|
54
|
+
| `SEQUANT_WORKTREE` | Path to the feature worktree | `/path/to/worktrees/feature/...` |
|
|
55
|
+
|
|
56
|
+
**Behavior when orchestrated (SEQUANT_ORCHESTRATOR is set):**
|
|
57
|
+
|
|
58
|
+
1. **Skip issue fetch** - Use `SEQUANT_ISSUE` directly, orchestrator has context
|
|
59
|
+
2. **Use provided worktree** - Work in `SEQUANT_WORKTREE` path
|
|
60
|
+
3. **Reduce GitHub comment frequency** - Defer progress updates to orchestrator
|
|
61
|
+
4. **Trust dev server status** - Orchestrator may have started it already
|
|
62
|
+
|
|
63
|
+
**Behavior when standalone (SEQUANT_ORCHESTRATOR is NOT set):**
|
|
64
|
+
|
|
65
|
+
- Fetch fresh issue context from GitHub
|
|
66
|
+
- Locate or prompt for worktree
|
|
67
|
+
- Post progress updates to GitHub
|
|
68
|
+
- Start dev server if needed
|
|
69
|
+
|
|
70
|
+
## Pre-flight: Stale Branch Detection
|
|
71
|
+
|
|
72
|
+
**Skip this section if `SEQUANT_ORCHESTRATOR` is set** - the orchestrator handles branch freshness checks.
|
|
73
|
+
|
|
74
|
+
**Purpose:** Detect when the feature branch is significantly behind main before running browser tests. Testing stale code is wasteful because:
|
|
75
|
+
- Test results may not apply to the merged state
|
|
76
|
+
- Features may have conflicts that need resolution first
|
|
77
|
+
- Time spent on testing is lost if rebase is required
|
|
78
|
+
|
|
79
|
+
**Detection:**
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# Ensure we have latest remote state
|
|
83
|
+
git fetch origin 2>/dev/null || true
|
|
84
|
+
|
|
85
|
+
# Count commits behind main
|
|
86
|
+
behind=$(git rev-list --count HEAD..origin/main 2>/dev/null || echo "0")
|
|
87
|
+
echo "Feature branch is $behind commits behind main"
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Threshold Configuration:**
|
|
91
|
+
|
|
92
|
+
The stale branch threshold is configurable in `.sequant/settings.json`:
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"run": {
|
|
97
|
+
"staleBranchThreshold": 5
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Default: 5 commits
|
|
103
|
+
|
|
104
|
+
**Behavior:**
|
|
105
|
+
|
|
106
|
+
| Commits Behind | Action |
|
|
107
|
+
|----------------|--------|
|
|
108
|
+
| 0 | ā
Proceed normally |
|
|
109
|
+
| 1 to threshold | ā ļø **Warning:** "Feature branch is N commits behind main. Consider rebasing before testing." |
|
|
110
|
+
| > threshold | ā **Block:** "STALE_BRANCH: Feature branch is N commits behind main (threshold: T). Rebase required before testing." |
|
|
111
|
+
|
|
112
|
+
**Implementation:**
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
# Read threshold from settings (default: 5)
|
|
116
|
+
threshold=$(jq -r '.run.staleBranchThreshold // 5' .sequant/settings.json 2>/dev/null || echo "5")
|
|
117
|
+
|
|
118
|
+
behind=$(git rev-list --count HEAD..origin/main 2>/dev/null || echo "0")
|
|
119
|
+
|
|
120
|
+
if [[ $behind -gt $threshold ]]; then
|
|
121
|
+
echo "ā STALE_BRANCH: Feature branch is $behind commits behind main (threshold: $threshold)"
|
|
122
|
+
echo " Rebase required before testing:"
|
|
123
|
+
echo " git fetch origin && git rebase origin/main"
|
|
124
|
+
# Exit with error - testing should not proceed
|
|
125
|
+
exit 1
|
|
126
|
+
elif [[ $behind -gt 0 ]]; then
|
|
127
|
+
echo "ā ļø Warning: Feature branch is $behind commits behind main."
|
|
128
|
+
echo " Consider rebasing before testing: git fetch origin && git rebase origin/main"
|
|
129
|
+
# Continue with warning
|
|
130
|
+
fi
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**Output Format:**
|
|
134
|
+
|
|
135
|
+
```markdown
|
|
136
|
+
### Stale Branch Check
|
|
137
|
+
|
|
138
|
+
| Check | Value |
|
|
139
|
+
|-------|-------|
|
|
140
|
+
| Commits behind main | N |
|
|
141
|
+
| Threshold | T |
|
|
142
|
+
| Status | ā
OK / ā ļø Warning / ā Blocked |
|
|
143
|
+
|
|
144
|
+
[Warning/blocking message if applicable]
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**Verdict Impact:**
|
|
148
|
+
|
|
149
|
+
| Status | Verdict Impact |
|
|
150
|
+
|--------|----------------|
|
|
151
|
+
| OK (0 behind) | No impact |
|
|
152
|
+
| Warning (1 to threshold) | Note in test output, recommend rebase |
|
|
153
|
+
| Blocked (> threshold) | **Cannot proceed** - rebase first |
|
|
154
|
+
|
|
45
155
|
## Phase 1: Setup
|
|
46
156
|
|
|
47
157
|
### 1.1 Fetch Issue Context
|
|
48
158
|
|
|
159
|
+
**If orchestrated (SEQUANT_ORCHESTRATOR is set):**
|
|
160
|
+
- Use `SEQUANT_ISSUE` for the issue number
|
|
161
|
+
- Skip fetching issue context (orchestrator has already done this)
|
|
162
|
+
- Parse any context passed in the orchestrator's prompt
|
|
163
|
+
|
|
164
|
+
**If standalone:**
|
|
165
|
+
|
|
49
166
|
```bash
|
|
50
167
|
gh issue view <issue-number> --json title,body,labels
|
|
51
168
|
gh issue view <issue-number> --comments
|
|
@@ -132,7 +249,99 @@ Wait for server ready before proceeding.
|
|
|
132
249
|
|
|
133
250
|
**Note:** If `{{DEV_URL}}` or `{{PM_RUN}}` are not replaced with actual values, the defaults are:
|
|
134
251
|
- DEV_URL: `http://localhost:3000` (Next.js), `http://localhost:4321` (Astro), `http://localhost:5173` (Vite-based)
|
|
135
|
-
- PM_RUN: `npm run` (or `bun run`, `yarn`, `pnpm run` based on lockfile)
|
|
252
|
+
- PM_RUN: `npm run` (or `bun run`, `yarn`, `pnpm run`, `poetry run`, `uv run`, `python -m` based on lockfile)
|
|
253
|
+
|
|
254
|
+
### 1.5 Test Coverage Analysis (REQUIRED)
|
|
255
|
+
|
|
256
|
+
**Purpose:** Warn when new/modified source files lack corresponding test files.
|
|
257
|
+
|
|
258
|
+
**Before executing tests**, analyze coverage for changed files:
|
|
259
|
+
|
|
260
|
+
1. **Get changed source files:**
|
|
261
|
+
```bash
|
|
262
|
+
# Get changed source files (excluding tests themselves)
|
|
263
|
+
changed=$(git diff main...HEAD --name-only | grep -E '\.(ts|tsx|js|jsx)$' | grep -v -E '\.test\.|\.spec\.|__tests__' || true)
|
|
264
|
+
echo "Changed source files:"
|
|
265
|
+
echo "$changed"
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
2. **Check for corresponding test files:**
|
|
269
|
+
```bash
|
|
270
|
+
# For each changed file, check if a test file exists
|
|
271
|
+
for file in $changed; do
|
|
272
|
+
base=$(basename "$file" | sed -E 's/\.(ts|tsx|js|jsx)$//')
|
|
273
|
+
dir=$(dirname "$file")
|
|
274
|
+
|
|
275
|
+
# Look for test files in common locations
|
|
276
|
+
test_found=false
|
|
277
|
+
|
|
278
|
+
# Check co-located test file
|
|
279
|
+
if ls "$dir/$base.test."* 2>/dev/null | grep -q .; then
|
|
280
|
+
test_found=true
|
|
281
|
+
fi
|
|
282
|
+
|
|
283
|
+
# Check __tests__ directory
|
|
284
|
+
if ls "$dir/__tests__/$base.test."* 2>/dev/null | grep -q .; then
|
|
285
|
+
test_found=true
|
|
286
|
+
fi
|
|
287
|
+
|
|
288
|
+
# Check root __tests__ with path structure
|
|
289
|
+
if ls "__tests__/${file%.ts*}.test."* 2>/dev/null | grep -q .; then
|
|
290
|
+
test_found=true
|
|
291
|
+
fi
|
|
292
|
+
|
|
293
|
+
if [ "$test_found" = false ]; then
|
|
294
|
+
echo "ā ļø NO TEST: $file"
|
|
295
|
+
fi
|
|
296
|
+
done
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
3. **Generate Coverage Warning Report:**
|
|
300
|
+
|
|
301
|
+
```markdown
|
|
302
|
+
### Test Coverage Analysis
|
|
303
|
+
|
|
304
|
+
| Source File | Has Test? | Notes |
|
|
305
|
+
|-------------|-----------|-------|
|
|
306
|
+
| `src/lib/feature.ts` | ā ļø No | New file, no test coverage |
|
|
307
|
+
| `src/lib/utils.ts` | ā
Yes | `src/lib/utils.test.ts` |
|
|
308
|
+
| `app/admin/page.tsx` | - | UI component (browser tested) |
|
|
309
|
+
|
|
310
|
+
**Coverage:** X/Y changed source files have corresponding tests
|
|
311
|
+
|
|
312
|
+
**Warning:** The following new/modified files lack test coverage:
|
|
313
|
+
- `src/lib/feature.ts` - Consider adding `src/lib/feature.test.ts`
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
4. **Coverage Tier Classification:**
|
|
317
|
+
|
|
318
|
+
| Tier | File Pattern | Coverage Recommendation |
|
|
319
|
+
|------|--------------|------------------------|
|
|
320
|
+
| **Critical** | `auth/*`, `payment/*`, `security/*`, `middleware/*` | ā ļø Flag prominently if missing |
|
|
321
|
+
| **Standard** | `lib/*`, `utils/*`, `api/*`, `server/*` | Note if missing |
|
|
322
|
+
| **UI/Browser** | `app/**/page.tsx`, `components/*` | Browser testing covers these |
|
|
323
|
+
| **Config/Types** | `*.config.*`, `types/*`, `*.d.ts` | No test required |
|
|
324
|
+
|
|
325
|
+
5. **Detection Heuristic for Critical Paths:**
|
|
326
|
+
```bash
|
|
327
|
+
# Flag critical path changes without tests
|
|
328
|
+
critical=$(echo "$changed" | grep -E 'auth|payment|security|middleware|server-action' || true)
|
|
329
|
+
if [[ -n "$critical" ]]; then
|
|
330
|
+
echo "ā ļø CRITICAL PATH CHANGES - test coverage strongly recommended:"
|
|
331
|
+
echo "$critical"
|
|
332
|
+
fi
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
6. **Behavior:**
|
|
336
|
+
- **Warning-only**: Does NOT block test execution
|
|
337
|
+
- Include coverage analysis in test results report
|
|
338
|
+
- Recommend adding tests for uncovered critical paths
|
|
339
|
+
- Note UI files are covered by browser testing (this skill)
|
|
340
|
+
|
|
341
|
+
**Why this matters:** Catching missing test coverage early:
|
|
342
|
+
- Prevents regressions from shipping untested code
|
|
343
|
+
- Ensures new logic has corresponding test validation
|
|
344
|
+
- Highlights critical paths that need extra scrutiny
|
|
136
345
|
|
|
137
346
|
## Decision Point: Feature Implemented or Not?
|
|
138
347
|
|
|
@@ -369,6 +578,13 @@ Create structured test results:
|
|
|
369
578
|
|
|
370
579
|
### 3.2 GitHub Comment
|
|
371
580
|
|
|
581
|
+
**If orchestrated (SEQUANT_ORCHESTRATOR is set):**
|
|
582
|
+
- Skip posting GitHub comment (orchestrator handles summary)
|
|
583
|
+
- Include test summary in output for orchestrator to capture
|
|
584
|
+
- Let orchestrator aggregate results across phases
|
|
585
|
+
|
|
586
|
+
**If standalone:**
|
|
587
|
+
|
|
372
588
|
Draft comment for Issue #<N>:
|
|
373
589
|
|
|
374
590
|
```markdown
|
|
@@ -436,6 +652,8 @@ If no explicit tests, use AC as test cases:
|
|
|
436
652
|
|
|
437
653
|
## Browser Testing Best Practices
|
|
438
654
|
|
|
655
|
+
**Reference:** See [Browser Testing Patterns](references/browser-testing-patterns.md) for comprehensive patterns including forms, modals, grids, async content, and troubleshooting.
|
|
656
|
+
|
|
439
657
|
### Snapshots vs. Screenshots
|
|
440
658
|
|
|
441
659
|
**Use `take_snapshot()` when:**
|
|
@@ -587,6 +805,33 @@ Both can be used together:
|
|
|
587
805
|
|
|
588
806
|
---
|
|
589
807
|
|
|
808
|
+
## State Tracking
|
|
809
|
+
|
|
810
|
+
**IMPORTANT:** Update workflow state when running standalone (not orchestrated).
|
|
811
|
+
|
|
812
|
+
### State Updates (Standalone Only)
|
|
813
|
+
|
|
814
|
+
When NOT orchestrated (`SEQUANT_ORCHESTRATOR` is not set):
|
|
815
|
+
|
|
816
|
+
**At skill start:**
|
|
817
|
+
```bash
|
|
818
|
+
npx tsx scripts/state/update.ts start <issue-number> test
|
|
819
|
+
```
|
|
820
|
+
|
|
821
|
+
**On successful completion:**
|
|
822
|
+
```bash
|
|
823
|
+
npx tsx scripts/state/update.ts complete <issue-number> test
|
|
824
|
+
```
|
|
825
|
+
|
|
826
|
+
**On failure:**
|
|
827
|
+
```bash
|
|
828
|
+
npx tsx scripts/state/update.ts fail <issue-number> test "X/Y tests failed"
|
|
829
|
+
```
|
|
830
|
+
|
|
831
|
+
**Why this matters:** State tracking enables dashboard visibility, resume capability, and workflow orchestration. Skills update state when standalone; orchestrators handle state when running workflows.
|
|
832
|
+
|
|
833
|
+
---
|
|
834
|
+
|
|
590
835
|
## Output Verification
|
|
591
836
|
|
|
592
837
|
**Before responding, verify your output includes ALL of these:**
|
|
@@ -17,7 +17,7 @@ allowed-tools:
|
|
|
17
17
|
- Bash(git worktree list:*)
|
|
18
18
|
- Bash(ls:*)
|
|
19
19
|
- Bash(mkdir:*)
|
|
20
|
-
-
|
|
20
|
+
- Agent(sequant-testgen)
|
|
21
21
|
---
|
|
22
22
|
|
|
23
23
|
# Test Generation Command
|
|
@@ -39,6 +39,116 @@ When invoked as `/testgen <issue-number>`, your job is to:
|
|
|
39
39
|
- `/testgen 123` - Generate test stubs for issue #123 based on /spec comment
|
|
40
40
|
- `/testgen` - Generate stubs for the most recently discussed issue in conversation
|
|
41
41
|
|
|
42
|
+
## Token Optimization with Haiku Sub-Agents
|
|
43
|
+
|
|
44
|
+
**Purpose:** Test stub generation is highly mechanical and benefits from using haiku sub-agents to minimize token cost.
|
|
45
|
+
|
|
46
|
+
**Pattern:** Use `Agent(subagent_type="sequant-testgen")` for:
|
|
47
|
+
1. Parsing verification criteria from /spec comments
|
|
48
|
+
2. Generating individual test stubs from templates
|
|
49
|
+
3. Writing test file content
|
|
50
|
+
|
|
51
|
+
**Benefits:**
|
|
52
|
+
- 90% token cost reduction for mechanical generation
|
|
53
|
+
- Faster execution for templated operations
|
|
54
|
+
- Main agent focuses on orchestration and decisions
|
|
55
|
+
|
|
56
|
+
### Sub-Agent Usage
|
|
57
|
+
|
|
58
|
+
**Step 1: Parse Verification Criteria (use haiku)**
|
|
59
|
+
|
|
60
|
+
```javascript
|
|
61
|
+
Agent(subagent_type="sequant-testgen", prompt=`
|
|
62
|
+
Parse the following /spec comment and extract verification criteria.
|
|
63
|
+
|
|
64
|
+
For each AC, extract:
|
|
65
|
+
- AC number and description
|
|
66
|
+
- Verification method (Unit Test, Integration Test, Browser Test, Manual Test)
|
|
67
|
+
- Test scenario (Given/When/Then)
|
|
68
|
+
- Integration points
|
|
69
|
+
- Assumptions to validate
|
|
70
|
+
|
|
71
|
+
Return as JSON:
|
|
72
|
+
{
|
|
73
|
+
"criteria": [
|
|
74
|
+
{
|
|
75
|
+
"acNumber": "AC-1",
|
|
76
|
+
"description": "...",
|
|
77
|
+
"verificationMethod": "Unit Test",
|
|
78
|
+
"scenario": { "given": "...", "when": "...", "then": "..." },
|
|
79
|
+
"integrationPoints": ["..."],
|
|
80
|
+
"assumptions": ["..."]
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/spec comment:
|
|
86
|
+
${specComment}
|
|
87
|
+
`)
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Step 2: Generate Test Stubs (use haiku for each AC)**
|
|
91
|
+
|
|
92
|
+
```javascript
|
|
93
|
+
// For each AC with Unit Test or Integration Test verification method
|
|
94
|
+
Agent(subagent_type="sequant-testgen", prompt=`
|
|
95
|
+
Generate a Jest test stub for the following verification criteria.
|
|
96
|
+
|
|
97
|
+
AC: ${ac.acNumber}: ${ac.description}
|
|
98
|
+
Verification Method: ${ac.verificationMethod}
|
|
99
|
+
Test Scenario:
|
|
100
|
+
- Given: ${ac.scenario.given}
|
|
101
|
+
- When: ${ac.scenario.when}
|
|
102
|
+
- Then: ${ac.scenario.then}
|
|
103
|
+
|
|
104
|
+
Use the template format:
|
|
105
|
+
- Include Given/When/Then as comments
|
|
106
|
+
- Add TODO markers where implementation is needed
|
|
107
|
+
- Include failure path stubs based on the action verb
|
|
108
|
+
- Use throw new Error('Test stub - implement this test')
|
|
109
|
+
|
|
110
|
+
Return ONLY the test code, no explanation.
|
|
111
|
+
`)
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**Step 3: Write Test Files (main agent)**
|
|
115
|
+
|
|
116
|
+
The main agent handles file operations to ensure proper coordination:
|
|
117
|
+
- Check if files exist (don't overwrite)
|
|
118
|
+
- Create directories if needed
|
|
119
|
+
- Write generated stubs to correct locations
|
|
120
|
+
|
|
121
|
+
### When to Use Sub-Agents vs Main Agent
|
|
122
|
+
|
|
123
|
+
| Task | Agent | Reasoning |
|
|
124
|
+
|------|-------|-----------|
|
|
125
|
+
| Parse /spec comment | haiku | Mechanical text extraction |
|
|
126
|
+
| Generate test stub code | haiku | Templated generation |
|
|
127
|
+
| Identify failure scenarios | haiku | Pattern matching |
|
|
128
|
+
| Decide file locations | main | Requires codebase context |
|
|
129
|
+
| Write files | main | File system coordination |
|
|
130
|
+
| Post GitHub comment | main | Session context needed |
|
|
131
|
+
|
|
132
|
+
### Parallel Sub-Agent Execution
|
|
133
|
+
|
|
134
|
+
When multiple ACs need test stubs, spawn haiku agents in parallel:
|
|
135
|
+
|
|
136
|
+
```javascript
|
|
137
|
+
// Spawn all stub generation agents in a single message
|
|
138
|
+
const stubPromises = criteria
|
|
139
|
+
.filter(ac => ac.verificationMethod === 'Unit Test' || ac.verificationMethod === 'Integration Test')
|
|
140
|
+
.map(ac => Agent(subagent_type="sequant-testgen", prompt=`Generate test stub for ${ac.acNumber}...`))
|
|
141
|
+
|
|
142
|
+
// Collect results
|
|
143
|
+
// Main agent writes all files
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**Cost savings example:**
|
|
147
|
+
- 5 AC items with Unit Test verification
|
|
148
|
+
- Without haiku: ~50K tokens (main agent generates all)
|
|
149
|
+
- With haiku: ~5K tokens (main orchestrates, haiku generates)
|
|
150
|
+
- Savings: ~90%
|
|
151
|
+
|
|
42
152
|
## Workflow
|
|
43
153
|
|
|
44
154
|
### Step 1: Read Verification Criteria from GitHub Issue
|
|
@@ -562,6 +672,33 @@ Generated with [Claude Code](https://claude.com/claude-code)
|
|
|
562
672
|
|
|
563
673
|
---
|
|
564
674
|
|
|
675
|
+
## State Tracking
|
|
676
|
+
|
|
677
|
+
**IMPORTANT:** Update workflow state when running standalone (not orchestrated).
|
|
678
|
+
|
|
679
|
+
### State Updates (Standalone Only)
|
|
680
|
+
|
|
681
|
+
When NOT orchestrated (`SEQUANT_ORCHESTRATOR` is not set):
|
|
682
|
+
|
|
683
|
+
**At skill start:**
|
|
684
|
+
```bash
|
|
685
|
+
npx tsx scripts/state/update.ts start <issue-number> testgen
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
**On successful completion:**
|
|
689
|
+
```bash
|
|
690
|
+
npx tsx scripts/state/update.ts complete <issue-number> testgen
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
**On failure:**
|
|
694
|
+
```bash
|
|
695
|
+
npx tsx scripts/state/update.ts fail <issue-number> testgen "Failed to generate test stubs"
|
|
696
|
+
```
|
|
697
|
+
|
|
698
|
+
**Note:** `/testgen` is an optional skill that generates test stubs. State tracking is informational - it doesn't block subsequent phases.
|
|
699
|
+
|
|
700
|
+
---
|
|
701
|
+
|
|
565
702
|
## Output Verification
|
|
566
703
|
|
|
567
704
|
**Before responding, verify your output includes ALL of these:**
|
|
@@ -19,7 +19,7 @@ export async function dashboardCommand(options = {}) {
|
|
|
19
19
|
const port = options.port ?? 3456;
|
|
20
20
|
const shouldOpen = !options.noOpen;
|
|
21
21
|
const verbose = options.verbose ?? false;
|
|
22
|
-
console.log(chalk.bold("\
|
|
22
|
+
console.log(chalk.bold("\nSequant Dashboard\n"));
|
|
23
23
|
try {
|
|
24
24
|
// Dynamic import to avoid loading dashboard code unless needed
|
|
25
25
|
const { startDashboard } = await import("../../dashboard/server.js");
|
|
@@ -82,7 +82,7 @@ export async function doctorCommand(options = {}) {
|
|
|
82
82
|
message: `Outdated: ${versionResult.currentVersion} ā ${versionResult.latestVersion} available`,
|
|
83
83
|
});
|
|
84
84
|
// Show remediation steps
|
|
85
|
-
console.log(chalk.yellow(`
|
|
85
|
+
console.log(chalk.yellow(` ! ${getVersionWarning(versionResult.currentVersion, versionResult.latestVersion, versionResult.isLocalInstall)}`));
|
|
86
86
|
console.log("");
|
|
87
87
|
}
|
|
88
88
|
else {
|
|
@@ -67,7 +67,7 @@ async function updateGitignore() {
|
|
|
67
67
|
* Log a default value being used in non-interactive mode
|
|
68
68
|
*/
|
|
69
69
|
function logDefault(label, value) {
|
|
70
|
-
console.log(chalk.blue(
|
|
70
|
+
console.log(chalk.blue(`${label}: ${value} (default)`));
|
|
71
71
|
}
|
|
72
72
|
export async function initCommand(options) {
|
|
73
73
|
// Show banner
|
|
@@ -106,14 +106,14 @@ export async function initCommand(options) {
|
|
|
106
106
|
if (wizardRemainingIssues.length > 0 ||
|
|
107
107
|
(options.skipSetup && warnings.length > 0)) {
|
|
108
108
|
if (wizardRemainingIssues.length > 0) {
|
|
109
|
-
console.log(chalk.yellow("
|
|
109
|
+
console.log(chalk.yellow("! Remaining setup issues:\n"));
|
|
110
110
|
for (const issue of wizardRemainingIssues) {
|
|
111
111
|
console.log(chalk.yellow(` ⢠${issue}`));
|
|
112
112
|
}
|
|
113
113
|
console.log();
|
|
114
114
|
}
|
|
115
115
|
else if (warnings.length > 0) {
|
|
116
|
-
console.log(chalk.yellow("
|
|
116
|
+
console.log(chalk.yellow("! Prerequisites:\n"));
|
|
117
117
|
for (const warning of warnings) {
|
|
118
118
|
console.log(chalk.yellow(` ⢠${warning}`));
|
|
119
119
|
}
|
|
@@ -126,7 +126,7 @@ export async function initCommand(options) {
|
|
|
126
126
|
// Check if already initialized
|
|
127
127
|
const configExists = await fileExists(".claude/settings.json");
|
|
128
128
|
if (configExists && !options.force) {
|
|
129
|
-
console.log(chalk.yellow("
|
|
129
|
+
console.log(chalk.yellow("! Sequant appears to be already initialized (.claude/settings.json exists)"));
|
|
130
130
|
console.log(chalk.gray(" Use --force to reinitialize\n"));
|
|
131
131
|
if (!skipPrompts) {
|
|
132
132
|
const { proceed } = await inquirer.prompt([
|
|
@@ -151,7 +151,7 @@ export async function initCommand(options) {
|
|
|
151
151
|
const allDetectedStacks = !skipPrompts ? await detectAllStacks() : [];
|
|
152
152
|
if (allDetectedStacks.length > 1 && !skipPrompts) {
|
|
153
153
|
// Multi-stack project detected - show checkbox selection
|
|
154
|
-
console.log(chalk.blue(`\
|
|
154
|
+
console.log(chalk.blue(`\nDetected ${allDetectedStacks.length} stacks in this project:`));
|
|
155
155
|
for (const ds of allDetectedStacks) {
|
|
156
156
|
const location = ds.path ? ` (${ds.path}/)` : " (root)";
|
|
157
157
|
console.log(chalk.gray(` ⢠${STACKS[ds.stack]?.displayName || ds.stack}${location}`));
|
|
@@ -258,7 +258,7 @@ export async function initCommand(options) {
|
|
|
258
258
|
// Detect package manager
|
|
259
259
|
const packageManager = await detectPackageManager();
|
|
260
260
|
if (packageManager) {
|
|
261
|
-
console.log(chalk.blue(
|
|
261
|
+
console.log(chalk.blue(`Package Manager: ${packageManager}`));
|
|
262
262
|
}
|
|
263
263
|
// Get stack config for default dev URL
|
|
264
264
|
const stackConfig = getStackConfig(stack);
|
|
@@ -381,14 +381,14 @@ export async function initCommand(options) {
|
|
|
381
381
|
// Some symlinks may have fallen back to copies
|
|
382
382
|
const fallbacks = symlinkResults.filter((r) => r.fallbackToCopy);
|
|
383
383
|
if (fallbacks.length > 0) {
|
|
384
|
-
console.log(chalk.yellow("
|
|
384
|
+
console.log(chalk.yellow("! Some scripts were copied instead of symlinked:"));
|
|
385
385
|
for (const fb of fallbacks) {
|
|
386
386
|
console.log(chalk.gray(` ${fb.path}: ${fb.reason}`));
|
|
387
387
|
}
|
|
388
388
|
}
|
|
389
389
|
const skipped = symlinkResults.filter((r) => r.skipped);
|
|
390
390
|
if (skipped.length > 0) {
|
|
391
|
-
console.log(chalk.yellow("
|
|
391
|
+
console.log(chalk.yellow("! Some scripts were skipped (existing files found):"));
|
|
392
392
|
for (const s of skipped) {
|
|
393
393
|
console.log(chalk.gray(` ${s.path}: ${s.reason}`));
|
|
394
394
|
}
|
|
@@ -444,7 +444,7 @@ export async function initCommand(options) {
|
|
|
444
444
|
for (const client of detectedClients) {
|
|
445
445
|
console.log(chalk.gray(` ⢠${client.name}`));
|
|
446
446
|
}
|
|
447
|
-
let addMcp
|
|
447
|
+
let addMcp;
|
|
448
448
|
if (skipPrompts) {
|
|
449
449
|
// --yes alone skips MCP config; --yes --mcp explicitly opts in
|
|
450
450
|
addMcp = !!options.mcp;
|
|
@@ -483,7 +483,7 @@ export async function initCommand(options) {
|
|
|
483
483
|
// Build prerequisites reminder if there were remaining issues from wizard or warnings
|
|
484
484
|
const hasRemainingIssues = wizardRemainingIssues.length > 0 || warnings.length > 0;
|
|
485
485
|
const prereqReminder = hasRemainingIssues
|
|
486
|
-
? `\n${chalk.yellow("
|
|
486
|
+
? `\n${chalk.yellow("! Remember to install missing dependencies before using issue workflows.")}\n${chalk.gray(" Run 'sequant doctor' to verify your setup.\n")}`
|
|
487
487
|
: "";
|
|
488
488
|
// Success message with boxed output
|
|
489
489
|
const nextStepsContent = `${chalk.bold("Next steps:")}
|
|
@@ -171,7 +171,7 @@ function filterLogs(logs, options) {
|
|
|
171
171
|
async function handleRotation(logDir, dryRun) {
|
|
172
172
|
const settings = await getSettings();
|
|
173
173
|
const stats = getLogStats(logDir, settings.run.rotation);
|
|
174
|
-
console.log(chalk.blue("\
|
|
174
|
+
console.log(chalk.blue("\nLog Rotation\n"));
|
|
175
175
|
console.log(chalk.gray(` Log directory: ${logDir}`));
|
|
176
176
|
console.log(chalk.gray(` Current: ${stats.fileCount} files, ${formatBytes(stats.totalSizeBytes)}`));
|
|
177
177
|
console.log(chalk.gray(` Thresholds: ${settings.run.rotation.maxFiles} files, ${settings.run.rotation.maxSizeMB} MB`));
|