@seanyao/roll 3.609.2 → 3.610.2
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/CHANGELOG.md +44 -1
- package/README.md +5 -6
- package/dist/roll.mjs +16146 -16186
- package/package.json +3 -2
- package/skills/README.md +14 -1
- package/skills/docs/skill-authoring.md +66 -0
- package/skills/reports/skill-audit-summary.md +53 -0
- package/skills/roll-.changelog/SKILL.md +25 -443
- package/skills/roll-.changelog/references/full-contract.md +462 -0
- package/skills/roll-.clarify/SKILL.md +6 -4
- package/skills/roll-.dream/SKILL.md +26 -353
- package/skills/roll-.dream/references/full-contract.md +365 -0
- package/skills/roll-.echo/SKILL.md +6 -4
- package/skills/roll-.qa/SKILL.md +25 -236
- package/skills/roll-.qa/references/full-contract.md +256 -0
- package/skills/roll-.review/SKILL.md +6 -2
- package/skills/roll-brief/SKILL.md +6 -8
- package/skills/roll-build/SKILL.md +28 -864
- package/skills/roll-build/references/full-contract.md +883 -0
- package/skills/roll-debug/SKILL.md +26 -585
- package/skills/roll-debug/references/full-contract.md +607 -0
- package/skills/roll-design/SKILL.md +28 -903
- package/skills/roll-design/references/full-contract.md +923 -0
- package/skills/roll-doc/SKILL.md +25 -574
- package/skills/roll-doc/references/full-contract.md +594 -0
- package/skills/roll-doctor/SKILL.md +21 -2
- package/skills/roll-fix/SKILL.md +28 -621
- package/skills/roll-fix/references/full-contract.md +640 -0
- package/skills/roll-idea/SKILL.md +6 -2
- package/skills/roll-loop/SKILL.md +27 -543
- package/skills/roll-loop/references/full-contract.md +555 -0
- package/skills/roll-notes/SKILL.md +6 -2
- package/skills/roll-onboard/SKILL.md +6 -2
- package/skills/roll-peer/SKILL.md +27 -316
- package/skills/roll-peer/references/full-contract.md +329 -0
- package/skills/roll-propose/SKILL.md +6 -8
- package/skills/roll-review-pr/SKILL.md +6 -2
- package/skills/roll-sentinel/SKILL.md +26 -344
- package/skills/roll-sentinel/references/full-contract.md +363 -0
- package/skills/roll-spar/SKILL.md +27 -269
- package/skills/roll-spar/references/full-contract.md +288 -0
- package/skills/route-cases/skills.json +235 -0
- package/skills/scripts/audit-skills.mjs +272 -0
- package/skills/scripts/test-audit-skills.mjs +39 -0
- package/skills/tests/fixtures/skill-audit/block-skill/SKILL.md +12 -0
- package/skills/tests/fixtures/skill-audit/minimal-skill/SKILL.md +8 -0
- package/skills/tests/fixtures/skill-audit/quoted-skill/SKILL.md +10 -0
- package/skills/tests/fixtures/skill-audit/route-cases.json +21 -0
- package/skills/tests/fixtures/skill-audit/spoke-skill/SKILL.md +12 -0
- package/skills/tests/fixtures/skill-audit/spoke-skill/references/runbook.md +3 -0
- package/bin/roll +0 -15361
- package/lib/backfill-pi-usage.py +0 -243
- package/lib/changelog_audit.py +0 -149
- package/lib/changelog_generate.py +0 -470
- package/lib/consistency_check.py +0 -409
- package/lib/context_feed_budget.sh +0 -194
- package/lib/github_sync.py +0 -876
- package/lib/i18n/slides.sh +0 -3
- package/lib/i18n/slides_build.sh +0 -38
- package/lib/i18n/slides_delete.sh +0 -19
- package/lib/i18n/slides_list.sh +0 -14
- package/lib/i18n/slides_logs.sh +0 -12
- package/lib/i18n/slides_new.sh +0 -15
- package/lib/i18n/slides_preview.sh +0 -14
- package/lib/i18n/slides_templates.sh +0 -7
- package/lib/i18n.sh +0 -211
- package/lib/loop-exit-summary.py +0 -393
- package/lib/loop-fmt.py +0 -589
- package/lib/loop_pick_agent.py +0 -316
- package/lib/loop_result_eval.py +0 -469
- package/lib/loop_unstick.py +0 -180
- package/lib/model_prices.py +0 -194
- package/lib/prices_fetcher.py +0 -534
- package/lib/roll-backlog.py +0 -225
- package/lib/roll-brief.py +0 -286
- package/lib/roll-help.py +0 -158
- package/lib/roll-home.py +0 -556
- package/lib/roll-init.py +0 -156
- package/lib/roll-loop-status.py +0 -1691
- package/lib/roll-loop-story.py +0 -191
- package/lib/roll-peer.py +0 -252
- package/lib/roll-setup.py +0 -102
- package/lib/roll-status.py +0 -367
- package/lib/roll_git.py +0 -41
- package/lib/roll_render.py +0 -414
- package/lib/slides/components/README.md +0 -123
- package/lib/slides/components/cards-2.html +0 -9
- package/lib/slides/components/cards-3.html +0 -9
- package/lib/slides/components/cards-4.html +0 -9
- package/lib/slides/components/compare.html +0 -22
- package/lib/slides/components/highlight.html +0 -9
- package/lib/slides/components/pipeline.html +0 -12
- package/lib/slides/components/plain.html +0 -7
- package/lib/slides/components/quote.html +0 -4
- package/lib/slides/components/timeline.html +0 -9
- package/lib/slides/templates/introduction-v3.html +0 -571
- package/lib/slides/templates/pitch.html +0 -0
- package/lib/slides-render.py +0 -778
- package/lib/slides-validate.py +0 -357
- package/lib/test_quality_gate.py +0 -143
- package/skills/roll-deck/SKILL.md +0 -296
- /package/skills/roll-debug/{injectable-bb.js → assets/injectable-bb.js} +0 -0
- /package/skills/roll-design/{ENGINEERING_CHECKLIST.md → references/engineering-checklist.md} +0 -0
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
# Full Contract Reference
|
|
2
|
+
|
|
3
|
+
This file preserves the detailed contract extracted from SKILL.md. Read it when the hub points here for exact workflow steps, templates, rubrics, or recovery branches.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Sentinel
|
|
8
|
+
|
|
9
|
+
**Smart Patrol Inspector** - Scheduled, randomized, cost-controlled patrol and acceptance checks for production systems.
|
|
10
|
+
|
|
11
|
+
## When Not to Use
|
|
12
|
+
|
|
13
|
+
- One-off debugging of a reported bug (use `$roll-debug`)
|
|
14
|
+
- Full-coverage regression testing (sentinel samples, does not cover)
|
|
15
|
+
- Dev/staging environment checks (use CI tests instead)
|
|
16
|
+
- Pre-commit self-review of diffs (use `$roll-.review`)
|
|
17
|
+
|
|
18
|
+
## Core Principle
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
22
|
+
│ Smart Patrol Logic │
|
|
23
|
+
├─────────────────────────────────────────────────────────────┤
|
|
24
|
+
│ │
|
|
25
|
+
│ Not full-coverage checks! Think of it like a security │
|
|
26
|
+
│ guard on patrol: │
|
|
27
|
+
│ │
|
|
28
|
+
│ 🕐 Scheduled Triggers - Auto-patrol on schedule │
|
|
29
|
+
│ └── "Patrol once every 6 hours" │
|
|
30
|
+
│ │
|
|
31
|
+
│ 🎲 Random Sampling - Different samples each time │
|
|
32
|
+
│ └── "Check Stories 1-10 this time, 50-60 next time" │
|
|
33
|
+
│ │
|
|
34
|
+
│ 💰 Cost Control - AI checks are expensive, use sparingly │
|
|
35
|
+
│ └── "Only check 10 each time, not all 100" │
|
|
36
|
+
│ │
|
|
37
|
+
│ 🎯 BACKLOG-Based - Validate against requirements │
|
|
38
|
+
│ └── "US-001 says login works, so verify login" │
|
|
39
|
+
│ │
|
|
40
|
+
└─────────────────────────────────────────────────────────────┘
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Patrol Strategy
|
|
44
|
+
|
|
45
|
+
### Sampling Logic
|
|
46
|
+
|
|
47
|
+
```javascript
|
|
48
|
+
// Sampling logic for each patrol
|
|
49
|
+
function selectSamples(backlog, strategy = 'smart') {
|
|
50
|
+
const completedStories = backlog.filter(s => s.status === '✅');
|
|
51
|
+
|
|
52
|
+
switch(strategy) {
|
|
53
|
+
case 'random':
|
|
54
|
+
// Fully random: randomly select N from all completed Stories
|
|
55
|
+
return shuffle(completedStories).slice(0, 10);
|
|
56
|
+
|
|
57
|
+
case 'weighted':
|
|
58
|
+
// Weighted random: prioritize recently modified and frequently used
|
|
59
|
+
return completedStories
|
|
60
|
+
.sort((a, b) => b.lastModified - a.lastModified)
|
|
61
|
+
.slice(0, 5) // 5 most recent
|
|
62
|
+
.concat(shuffle(completedStories).slice(0, 5)); // + 5 random
|
|
63
|
+
|
|
64
|
+
case 'coverage':
|
|
65
|
+
// Coverage sampling: ensure different modules are all covered
|
|
66
|
+
const byModule = groupBy(completedStories, 'module');
|
|
67
|
+
return Object.values(byModule).map(
|
|
68
|
+
stories => randomPick(stories)
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Cost Control
|
|
75
|
+
|
|
76
|
+
| Strategy | Sample Size | Frequency | Use Case |
|
|
77
|
+
|----------|-------------|-----------|----------|
|
|
78
|
+
| **Light** | 5 Stories | Once daily | Stable period |
|
|
79
|
+
| **Normal** | 10 Stories | Every 6 hours | General monitoring |
|
|
80
|
+
| **Intensive** | 20 Stories | Every hour | Post-release period |
|
|
81
|
+
| **Full** | All | Once weekly | Weekly patrol |
|
|
82
|
+
|
|
83
|
+
```yaml
|
|
84
|
+
# sentinel.config.yml
|
|
85
|
+
cost_control:
|
|
86
|
+
daily_budget: 100 # AI call budget
|
|
87
|
+
|
|
88
|
+
light_patrol:
|
|
89
|
+
samples: 5
|
|
90
|
+
schedule: "0 9 * * *" # Daily at 9am
|
|
91
|
+
|
|
92
|
+
normal_patrol:
|
|
93
|
+
samples: 10
|
|
94
|
+
schedule: "0 */6 * * *" # Every 6 hours
|
|
95
|
+
|
|
96
|
+
# Intensive patrol after deployment
|
|
97
|
+
post_deploy:
|
|
98
|
+
trigger: "after_deploy"
|
|
99
|
+
samples: 20
|
|
100
|
+
duration: "2h" # Lasts 2 hours
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Uncertainty Handling
|
|
104
|
+
|
|
105
|
+
```javascript
|
|
106
|
+
// Systems have uncertainty; a single check may be inaccurate.
|
|
107
|
+
// Use multiple random checks to increase confidence.
|
|
108
|
+
|
|
109
|
+
class UncertaintyHandler {
|
|
110
|
+
// Track check result history
|
|
111
|
+
history = new Map(); // storyId -> [check1, check2, ...]
|
|
112
|
+
|
|
113
|
+
// Determine if an issue is real
|
|
114
|
+
isRealIssue(storyId, currentResult) {
|
|
115
|
+
const pastResults = this.history.get(storyId) || [];
|
|
116
|
+
pastResults.push(currentResult);
|
|
117
|
+
|
|
118
|
+
// Only consider it a real issue if it fails 3 times consecutively
|
|
119
|
+
const recent3 = pastResults.slice(-3);
|
|
120
|
+
if (recent3.every(r => r.status === 'FAIL')) {
|
|
121
|
+
return true; // Real issue
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// If it fails occasionally, it may be intermittent; keep observing
|
|
125
|
+
if (recent3.filter(r => r.status === 'FAIL').length === 1) {
|
|
126
|
+
return false; // Likely intermittent, don't alert yet
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## When to Patrol
|
|
135
|
+
|
|
136
|
+
### Scheduled Patrols
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
# Daily patrol - randomly check a few each day
|
|
140
|
+
$roll-sentinel patrol --mode=normal
|
|
141
|
+
|
|
142
|
+
# Late-night patrol - full check during off-peak hours
|
|
143
|
+
$roll-sentinel patrol --mode=full --schedule="0 3 * * *"
|
|
144
|
+
|
|
145
|
+
# Weekend walkthrough - check the week's accumulation on Sunday
|
|
146
|
+
$roll-sentinel patrol --mode=weekly --schedule="0 10 * * 0"
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Event-Triggered
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
# Intensive patrol for 2 hours after deployment
|
|
153
|
+
$roll-sentinel patrol --mode=intensive --duration=2h --after-deploy
|
|
154
|
+
|
|
155
|
+
# Emergency check after an alert
|
|
156
|
+
$roll-sentinel patrol --mode=focus --target=US-XXX
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Patrol Report
|
|
160
|
+
|
|
161
|
+
```markdown
|
|
162
|
+
## 🛡️ Sentinel Patrol Report #247
|
|
163
|
+
**Time**: 2024-01-15 14:00 UTC
|
|
164
|
+
**Patrol ID**: patrol-20240115-1400
|
|
165
|
+
**Mode**: Normal (Random Sampling)
|
|
166
|
+
|
|
167
|
+
### 📊 Sampling Info
|
|
168
|
+
| Metric | Value |
|
|
169
|
+
|--------|-------|
|
|
170
|
+
| Total Stories | 150 |
|
|
171
|
+
| Sample Size | 10 |
|
|
172
|
+
| Sampling Rate | 6.7% |
|
|
173
|
+
| Cost Estimate | $0.07 |
|
|
174
|
+
|
|
175
|
+
### 🎲 Random Sample
|
|
176
|
+
| # | Story | Module | Last Checked | Result |
|
|
177
|
+
|---|-------|--------|--------------|--------|
|
|
178
|
+
| 1 | US-LOGIN-001 | Auth | 6h ago | ✅ |
|
|
179
|
+
| 2 | US-STORY-042 | Content | 12h ago | ✅ |
|
|
180
|
+
| 3 | US-AUDIO-015 | Player | 2h ago | 🟡* |
|
|
181
|
+
| 4 | US-SEARCH-003 | Search | 18h ago | ✅ |
|
|
182
|
+
| 5 | ... | ... | ... | ... |
|
|
183
|
+
|
|
184
|
+
\* US-AUDIO-015: Occasional playback stuttering (2nd occurrence, under observation)
|
|
185
|
+
|
|
186
|
+
### 🔴 Issues Found
|
|
187
|
+
None (no confirmed issues found in this sample)
|
|
188
|
+
|
|
189
|
+
### 📈 Patrol Statistics (7 days)
|
|
190
|
+
| Metric | Value |
|
|
191
|
+
|--------|-------|
|
|
192
|
+
| Total Patrols | 28 |
|
|
193
|
+
| Stories Checked | 280 |
|
|
194
|
+
| Issues Found | 3 |
|
|
195
|
+
| False Positives | 1 |
|
|
196
|
+
| Coverage | 85% of all stories |
|
|
197
|
+
|
|
198
|
+
### 💰 Cost Report
|
|
199
|
+
| Item | Usage |
|
|
200
|
+
|------|-------|
|
|
201
|
+
| AI Checks | 280 calls |
|
|
202
|
+
| Playwright Runs | 28 sessions |
|
|
203
|
+
| Total Cost | $2 |
|
|
204
|
+
| Budget Used | 15% of monthly |
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Smart Detection Logic
|
|
208
|
+
|
|
209
|
+
### Pattern 1: Intermittent vs Real Issue
|
|
210
|
+
|
|
211
|
+
```javascript
|
|
212
|
+
// Don't alert on the first failure; look at the trend
|
|
213
|
+
const checks = [
|
|
214
|
+
{ time: 'T-6h', status: 'PASS' },
|
|
215
|
+
{ time: 'T-12h', status: 'FAIL' }, // Intermittent?
|
|
216
|
+
{ time: 'T-18h', status: 'PASS' },
|
|
217
|
+
{ time: 'Now', status: 'FAIL' }, // Failed again!
|
|
218
|
+
];
|
|
219
|
+
|
|
220
|
+
// 2 consecutive failures → Create Issue
|
|
221
|
+
if (lastN(checks, 2).all(c => c.status === 'FAIL')) {
|
|
222
|
+
createBacklogItem('FIX-XXX');
|
|
223
|
+
}
|
|
224
|
+
// Occasional failure → Log for observation
|
|
225
|
+
else if (checks.filter(c => c.status === 'FAIL').length <= 1) {
|
|
226
|
+
logForObservation('Might be flaky, continue monitoring');
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Pattern 2: Hotspot Detection
|
|
231
|
+
|
|
232
|
+
```javascript
|
|
233
|
+
// Some Stories frequently show issues when sampled.
|
|
234
|
+
// Automatically increase their check frequency.
|
|
235
|
+
|
|
236
|
+
const hotSpots = analyzeHistory();
|
|
237
|
+
// hotSpots = [
|
|
238
|
+
// { story: 'US-AUDIO-015', failRate: 0.3 }, // 30% failure rate
|
|
239
|
+
// { story: 'US-SEARCH-003', failRate: 0.1 },
|
|
240
|
+
// ]
|
|
241
|
+
|
|
242
|
+
// Increase weight for hotspots
|
|
243
|
+
if (hotSpots.some(h => h.story === selectedStory)) {
|
|
244
|
+
// If it's a hotspot, even if not randomly selected, add extra check probability
|
|
245
|
+
if (Math.random() < 0.3) {
|
|
246
|
+
extraCheck(story);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## Cost Optimization
|
|
252
|
+
|
|
253
|
+
### Tiered Checking
|
|
254
|
+
|
|
255
|
+
```
|
|
256
|
+
Level 1: Lightweight Check (cheap)
|
|
257
|
+
└── HTTP ping / API health check
|
|
258
|
+
└── Cost: $0.001 per check
|
|
259
|
+
|
|
260
|
+
Level 2: Functional Check (moderate)
|
|
261
|
+
└── Playwright critical path
|
|
262
|
+
└── Cost: $0.01 per check
|
|
263
|
+
|
|
264
|
+
Level 3: AI Deep Check (expensive)
|
|
265
|
+
└── AI-powered content quality analysis
|
|
266
|
+
└── Cost: $0.07 per check
|
|
267
|
+
|
|
268
|
+
Strategy:
|
|
269
|
+
- Each patrol: 90% Level 1 + 10% Level 2
|
|
270
|
+
- Once weekly: Level 3 deep inspection
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Smart Batching
|
|
274
|
+
|
|
275
|
+
```javascript
|
|
276
|
+
// Batch checks to reduce cost.
|
|
277
|
+
// Instead of 10 separate checks, open one browser for all 10.
|
|
278
|
+
|
|
279
|
+
async function batchCheck(stories) {
|
|
280
|
+
const browser = await chromium.launch();
|
|
281
|
+
const context = await browser.newContext();
|
|
282
|
+
|
|
283
|
+
// Reuse browser session to check multiple Stories
|
|
284
|
+
for (const story of stories) {
|
|
285
|
+
const page = await context.newPage();
|
|
286
|
+
await checkStory(page, story);
|
|
287
|
+
await page.close();
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
await browser.close();
|
|
291
|
+
// Cost: 1 session for 10 checks
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
## Workflow: Find Issue → Backlog
|
|
296
|
+
|
|
297
|
+
```
|
|
298
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
299
|
+
│ Issue Discovery Workflow via Patrol │
|
|
300
|
+
├─────────────────────────────────────────────────────────────┤
|
|
301
|
+
│ │
|
|
302
|
+
│ 1. Sentinel Patrol (scheduled random sampling) │
|
|
303
|
+
│ └── Sample: US-AUDIO-015 │
|
|
304
|
+
│ │
|
|
305
|
+
│ 2. Check Result │
|
|
306
|
+
│ └── Status: FAIL (playback stuttering) │
|
|
307
|
+
│ │
|
|
308
|
+
│ 3. Uncertainty Check │
|
|
309
|
+
│ └── Check history: this is the 2nd failure │
|
|
310
|
+
│ └── 1st was 6h ago (possibly intermittent) │
|
|
311
|
+
│ └── Decision: continue observing, don't create Issue │
|
|
312
|
+
│ │
|
|
313
|
+
│ 4. Next Patrol │
|
|
314
|
+
│ └── US-AUDIO-015 sampled again (hotspot weighting) │
|
|
315
|
+
│ └── Status: FAIL (failed again!) │
|
|
316
|
+
│ └── Check history: 2 consecutive failures │
|
|
317
|
+
│ └── Decision: create FIX-AUDIO-015 │
|
|
318
|
+
│ │
|
|
319
|
+
│ 5. Create Backlog Item │
|
|
320
|
+
│ └── Add FIX-AUDIO-015 to .roll/backlog.md │
|
|
321
|
+
│ └── Status: 📋 Todo │
|
|
322
|
+
│ └── Awaiting human fix │
|
|
323
|
+
│ │
|
|
324
|
+
│ 6. Human Fix │
|
|
325
|
+
│ └── User: "Fix FIX-AUDIO-015" │
|
|
326
|
+
│ └── $roll-fix FIX-AUDIO-015 │
|
|
327
|
+
│ │
|
|
328
|
+
│ 7. Verification │
|
|
329
|
+
│ └── Next patrol will prioritize verifying this FIX │
|
|
330
|
+
│ └── Status: ✅ Fixed │
|
|
331
|
+
│ │
|
|
332
|
+
└─────────────────────────────────────────────────────────────┘
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
## Integration with Other Skills
|
|
336
|
+
|
|
337
|
+
```
|
|
338
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
339
|
+
│ Complete Monitoring System │
|
|
340
|
+
├─────────────────────────────────────────────────────────────┤
|
|
341
|
+
│ │
|
|
342
|
+
│ $roll-sentinel patrol Scheduled random patrol (main) │
|
|
343
|
+
│ ↓ │
|
|
344
|
+
│ Issue found? ──┬── Yes ──→ Create BACKLOG item │
|
|
345
|
+
│ │ Await $roll-fix │
|
|
346
|
+
│ │ │
|
|
347
|
+
│ └── No ──→ Continue patrolling │
|
|
348
|
+
│ │
|
|
349
|
+
│ $roll-debug On-demand deep diagnosis (aux) │
|
|
350
|
+
│ (When Sentinel finds an issue, manually trigger deep dive) │
|
|
351
|
+
│ │
|
|
352
|
+
│ $roll-build Post-fix regression verify │
|
|
353
|
+
│ │
|
|
354
|
+
└─────────────────────────────────────────────────────────────┘
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
## Best Practices
|
|
358
|
+
|
|
359
|
+
1. **Don't do full-coverage checks** - Expensive and unnecessary
|
|
360
|
+
2. **Random + Hotspots** - Balance coverage and cost
|
|
361
|
+
3. **Multi-check confirmation** - Avoid false positives from intermittent failures
|
|
362
|
+
4. **Budget control** - Set daily/monthly AI call limits
|
|
363
|
+
5. **Progressive intensity** - Light during stable periods, Intensive after releases
|
|
@@ -2,288 +2,46 @@
|
|
|
2
2
|
name: roll-spar
|
|
3
3
|
license: MIT
|
|
4
4
|
allowed-tools: "Read, Edit, Write, Bash, Agent, Skill"
|
|
5
|
-
description:
|
|
5
|
+
description: "Load when high-risk logic needs adversarial TDD with attacker tests and defender implementation, such as auth, payments, data integrity, or state machines."
|
|
6
6
|
---
|
|
7
|
+
# Roll Spar
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
This hub keeps the routing boundary, hard gates, and execution skeleton in the initial context. Load the heavier runbook only when the task actually needs the detailed contract.
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
## Load
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
Load when high-risk logic needs adversarial TDD with attacker tests and defender implementation, such as auth, payments, data integrity, or state machines.
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
- User explicitly requests `$roll-spar`
|
|
16
|
-
- Involves core business logic requiring higher quality assurance
|
|
15
|
+
## When Not to Use
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
-
|
|
20
|
-
- Involves money / payments / billing
|
|
21
|
-
- Involves data integrity (writes are irreversible)
|
|
22
|
-
- Complex state machines / concurrency logic
|
|
23
|
-
- Module has had previous bugs (BACKLOG has related FIX records)
|
|
17
|
+
- Routine QA planning; load roll-.qa.
|
|
18
|
+
- Ordinary peer review; load roll-peer.
|
|
24
19
|
|
|
25
|
-
|
|
26
|
-
- UI styling adjustments, copy changes
|
|
27
|
-
- Simple CRUD
|
|
28
|
-
- Configuration changes
|
|
29
|
-
- Small tasks not worth the overhead of two-agent collaboration
|
|
20
|
+
## Read On Demand
|
|
30
21
|
|
|
31
|
-
|
|
22
|
+
- Read [the full contract](references/full-contract.md) before executing the workflow end to end, recovering from failures, or checking exact output templates.
|
|
23
|
+
- Keep this hub in context for trigger boundaries and hard gates.
|
|
32
24
|
|
|
33
|
-
|
|
25
|
+
## Workflow Skeleton
|
|
34
26
|
|
|
35
|
-
|
|
27
|
+
1. Define the high-risk invariant.
|
|
28
|
+
2. Attacker writes breaking tests first.
|
|
29
|
+
3. Defender implements the minimal passing code.
|
|
30
|
+
4. Iterate until the invariant is defended.
|
|
31
|
+
5. Record adversarial evidence.
|
|
36
32
|
|
|
37
|
-
|
|
38
|
-
- Write the trickiest test cases possible
|
|
39
|
-
- Don't care about implementation difficulty — only care about "can the system handle this scenario"
|
|
40
|
-
- Write at least 1 RED test per round, can write multiple
|
|
33
|
+
## Hard Gates
|
|
41
34
|
|
|
42
|
-
|
|
35
|
+
- Keep attacker/defender roles separate.
|
|
36
|
+
- Use only when added cost matches risk.
|
|
43
37
|
|
|
44
|
-
|
|
38
|
+
## Gotchas
|
|
45
39
|
|
|
46
|
-
-
|
|
47
|
-
-
|
|
48
|
-
- Make all tests GREEN each round, then commit
|
|
49
|
-
- May refactor, but must stay GREEN
|
|
40
|
+
- Use spar only for high-risk logic where adversarial tests are worth the added cost.
|
|
41
|
+
- Attacker and defender roles must stay separate; do not let implementation assumptions weaken the breaking tests.
|
|
50
42
|
|
|
51
|
-
##
|
|
43
|
+
## Maintenance
|
|
52
44
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
▼
|
|
57
|
-
┌─────────────────────────────────────┐
|
|
58
|
-
│ 0. Setup │
|
|
59
|
-
│ - Define feature scope and AC │
|
|
60
|
-
│ - Create test file skeleton │
|
|
61
|
-
│ - Context brief for Attacker │
|
|
62
|
-
│ and Defender │
|
|
63
|
-
└─────────────┬───────────────────────┘
|
|
64
|
-
│
|
|
65
|
-
▼
|
|
66
|
-
┌─────────────────────────────────────┐
|
|
67
|
-
│ Spar Loop (repeat until converged) │
|
|
68
|
-
│ │
|
|
69
|
-
│ ┌───────────────────────────────┐ │
|
|
70
|
-
│ │ 🔴 Attacker Turn │ │
|
|
71
|
-
│ │ - Analyze current code/API │ │
|
|
72
|
-
│ │ - Write 1+ RED tests │ │
|
|
73
|
-
│ │ - State attack intent: │ │
|
|
74
|
-
│ │ "Test balance consistency│ │
|
|
75
|
-
│ │ during concurrent │ │
|
|
76
|
-
│ │ transfers" │ │
|
|
77
|
-
│ └──────────────┬────────────────┘ │
|
|
78
|
-
│ │ │
|
|
79
|
-
│ ▼ │
|
|
80
|
-
│ ┌───────────────────────────────┐ │
|
|
81
|
-
│ │ 🟢 Defender Turn │ │
|
|
82
|
-
│ │ - Read Attacker's tests │ │
|
|
83
|
-
│ │ - Write minimal code to │ │
|
|
84
|
-
│ │ make tests pass │ │
|
|
85
|
-
│ │ - Run all tests → GREEN │ │
|
|
86
|
-
│ │ - git commit │ │
|
|
87
|
-
│ └──────────────┬────────────────┘ │
|
|
88
|
-
│ │ │
|
|
89
|
-
│ ▼ │
|
|
90
|
-
│ ┌───────────────────────────────┐ │
|
|
91
|
-
│ │ 🔴 Attacker Turn (again) │ │
|
|
92
|
-
│ │ - Review Defender's impl │ │
|
|
93
|
-
│ │ - Find new weaknesses, │ │
|
|
94
|
-
│ │ write new RED tests │ │
|
|
95
|
-
│ │ - Or: "No new weaknesses │ │
|
|
96
|
-
│ │ found" │ │
|
|
97
|
-
│ └──────────────┬────────────────┘ │
|
|
98
|
-
│ │ │
|
|
99
|
-
│ ┌────────┴────────┐ │
|
|
100
|
-
│ │ │ │
|
|
101
|
-
│ Has new tests No new tests │
|
|
102
|
-
│ → Continue loop → Exit Spar │
|
|
103
|
-
│ │
|
|
104
|
-
└─────────────────────────────────────┘
|
|
105
|
-
│
|
|
106
|
-
▼
|
|
107
|
-
┌─────────────────────────────────────┐
|
|
108
|
-
│ Wrap-up │
|
|
109
|
-
│ - Attacker summarizes attack │
|
|
110
|
-
│ coverage │
|
|
111
|
-
│ - Defender summarizes defense │
|
|
112
|
-
│ strategy │
|
|
113
|
-
│ - Merged report │
|
|
114
|
-
│ - Continue normal roll-build │
|
|
115
|
-
│ flow │
|
|
116
|
-
│ (push → CI → deploy → verify) │
|
|
117
|
-
└─────────────────────────────────────┘
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
## Spar Convergence Conditions
|
|
121
|
-
|
|
122
|
-
Attacker declares completion when any of these are met:
|
|
123
|
-
- Cannot write a new RED test for 2 consecutive rounds
|
|
124
|
-
- Already covered: happy path + boundary values + invalid inputs + concurrency/race conditions + state consistency
|
|
125
|
-
- Reached the agreed maximum number of rounds (default: 5 rounds)
|
|
126
|
-
|
|
127
|
-
## Agent Context Brief
|
|
128
|
-
|
|
129
|
-
### Attacker Brief Template
|
|
130
|
-
|
|
131
|
-
```markdown
|
|
132
|
-
## Role: Attacker (Red Agent)
|
|
133
|
-
|
|
134
|
-
Your goal is to find weaknesses in this code.
|
|
135
|
-
|
|
136
|
-
### Feature Description
|
|
137
|
-
{Feature AC and interface definition}
|
|
138
|
-
|
|
139
|
-
### Current Implementation
|
|
140
|
-
{Defender's latest code, or "not yet implemented"}
|
|
141
|
-
|
|
142
|
-
### Existing Tests
|
|
143
|
-
{Currently existing test cases}
|
|
144
|
-
|
|
145
|
-
### Your Task
|
|
146
|
-
Write 1+ new test cases that make the current implementation fail (RED).
|
|
147
|
-
Directions to explore:
|
|
148
|
-
- Boundary values (0, -1, MAX_INT, empty string, null)
|
|
149
|
-
- Exception flows (network disconnect, timeout, duplicate requests)
|
|
150
|
-
- Concurrency (two requests arriving simultaneously)
|
|
151
|
-
- State consistency (is system state clean after mid-process failure)
|
|
152
|
-
|
|
153
|
-
### Output Format
|
|
154
|
-
For each test, state the attack intent:
|
|
155
|
-
"Attack: {scenario description} — expected system behavior: {expected behavior}"
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
### Defender Brief Template
|
|
159
|
-
|
|
160
|
-
```markdown
|
|
161
|
-
## Role: Defender (Green Agent)
|
|
162
|
-
|
|
163
|
-
Your goal is to make all tests pass with the simplest implementation.
|
|
164
|
-
|
|
165
|
-
### Feature Description
|
|
166
|
-
{Feature AC and interface definition}
|
|
167
|
-
|
|
168
|
-
### Current Code
|
|
169
|
-
{Your previously written code, or empty}
|
|
170
|
-
|
|
171
|
-
### New RED Tests
|
|
172
|
-
{Tests written by the Attacker this round}
|
|
173
|
-
|
|
174
|
-
### Your Task
|
|
175
|
-
Modify/add code to make all tests (including previous ones) pass.
|
|
176
|
-
Rules:
|
|
177
|
-
- Cannot modify tests written by the Attacker
|
|
178
|
-
- Aim for minimal changes
|
|
179
|
-
- Keep the code clear
|
|
180
|
-
- Commit after all tests are GREEN
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
## Status Report
|
|
184
|
-
|
|
185
|
-
Report to the user after each round:
|
|
186
|
-
|
|
187
|
-
```
|
|
188
|
-
⚔️ Spar Round {N}
|
|
189
|
-
|
|
190
|
-
🔴 Attacker:
|
|
191
|
-
Attack: {scenario 1} — {result}
|
|
192
|
-
Attack: {scenario 2} — {result}
|
|
193
|
-
|
|
194
|
-
🟢 Defender:
|
|
195
|
-
Defense strategy: {brief description of how it was defended}
|
|
196
|
-
Test status: {passed}/{total} ✅
|
|
197
|
-
|
|
198
|
-
📊 Cumulative: {total tests} tests, {total rounds} rounds
|
|
199
|
-
🔄 Next round: Attacker continues looking for weaknesses...
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
## Hard Rules
|
|
203
|
-
|
|
204
|
-
1. **Attacker does not write implementation code** — only writes tests and attack analysis
|
|
205
|
-
2. **Defender does not modify tests** — unless the test itself has a bug (must explain the reason)
|
|
206
|
-
3. **Must commit each round** — Defender commits immediately after making tests GREEN, keeping the repo clean
|
|
207
|
-
4. **Attack intent must be explained** — cannot just write tests without explaining "why this scenario matters"
|
|
208
|
-
5. **Maximum round limit** — default 5 rounds, prevents infinite loops
|
|
209
|
-
|
|
210
|
-
## Integration with roll-build
|
|
211
|
-
|
|
212
|
-
Spar replaces steps 4-5 in roll-build (Test Design + TCR Implementation):
|
|
213
|
-
|
|
214
|
-
```
|
|
215
|
-
roll-build normal flow:
|
|
216
|
-
1. Clarify Story
|
|
217
|
-
2. Split Actions
|
|
218
|
-
3. Define verification
|
|
219
|
-
──────────────────────
|
|
220
|
-
4. Test Design Review ← Spar replaces this step
|
|
221
|
-
5. TCR Implementation ← and this step
|
|
222
|
-
──────────────────────
|
|
223
|
-
6. Local CI check ← Back to normal flow
|
|
224
|
-
7. Quality Review
|
|
225
|
-
...
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
**Auto-switching from roll-build to Spar:**
|
|
229
|
-
|
|
230
|
-
When the agent assesses an Action as high-risk at step 3:
|
|
231
|
-
```
|
|
232
|
-
⚔️ High-risk Action detected: {description}
|
|
233
|
-
Risk factors: {auth/payment/data integrity/...}
|
|
234
|
-
Recommend enabling Spar mode — confirm? [Y/n]
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
After user confirms, enter Spar. Once complete, return to roll-build step 6 to continue.
|
|
238
|
-
|
|
239
|
-
## Example
|
|
240
|
-
|
|
241
|
-
```
|
|
242
|
-
User: "$roll-spar implement user balance transfer"
|
|
243
|
-
|
|
244
|
-
⚔️ Spar: User Balance Transfer
|
|
245
|
-
|
|
246
|
-
── Round 1 ──
|
|
247
|
-
|
|
248
|
-
🔴 Attacker:
|
|
249
|
-
Attack 1: Transfer amount is 0 — should reject
|
|
250
|
-
Attack 2: Transfer amount is negative — should reject
|
|
251
|
-
Attack 3: Transfer amount exceeds balance — should reject and keep balance unchanged
|
|
252
|
-
|
|
253
|
-
🟢 Defender:
|
|
254
|
-
Implementation: transfer(from, to, amount) basic validation
|
|
255
|
-
Tests: 3/3 ✅
|
|
256
|
-
commit: "tcr: transfer basic validation"
|
|
257
|
-
|
|
258
|
-
── Round 2 ──
|
|
259
|
-
|
|
260
|
-
🔴 Attacker:
|
|
261
|
-
Attack 4: Transfer to self — should reject
|
|
262
|
-
Attack 5: Two concurrent transfers whose total exceeds balance — only one should succeed
|
|
263
|
-
|
|
264
|
-
🟢 Defender:
|
|
265
|
-
Implementation: add self-transfer check + optimistic lock
|
|
266
|
-
Tests: 5/5 ✅
|
|
267
|
-
commit: "tcr: transfer self-check and concurrency lock"
|
|
268
|
-
|
|
269
|
-
── Round 3 ──
|
|
270
|
-
|
|
271
|
-
🔴 Attacker:
|
|
272
|
-
Attack 6: Database error mid-transfer — both balances should remain unchanged (atomicity)
|
|
273
|
-
Attack 7: Recipient account does not exist — should reject and keep sender's balance
|
|
274
|
-
|
|
275
|
-
🟢 Defender:
|
|
276
|
-
Implementation: database transaction wrapper + recipient existence check
|
|
277
|
-
Tests: 7/7 ✅
|
|
278
|
-
commit: "tcr: transfer atomicity and recipient validation"
|
|
279
|
-
|
|
280
|
-
── Round 4 ──
|
|
281
|
-
|
|
282
|
-
🔴 Attacker:
|
|
283
|
-
No new weaknesses found. Covered: input validation, self-transfer, concurrency, atomicity, related accounts.
|
|
284
|
-
|
|
285
|
-
⚔️ Spar Complete!
|
|
286
|
-
📊 4 rounds, 7 tests, 3 commits
|
|
287
|
-
🔴 Attack coverage: input boundaries + business rules + concurrency + atomicity
|
|
288
|
-
🟢 Defense strategy: upfront validation + optimistic lock + transactions
|
|
289
|
-
```
|
|
45
|
+
- Description changes require updates in `route-cases/skills.json`.
|
|
46
|
+
- New observed failures should add a gotcha and the matching positive or negative route case.
|
|
47
|
+
- Heavy examples, templates, recovery paths, and deterministic snippets belong in `references/`, `assets/`, or `scripts/`, not in this hub.
|