codingbuddy-rules 5.0.0 → 5.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.
Files changed (53) hide show
  1. package/.ai-rules/adapters/aider.md +374 -0
  2. package/.ai-rules/adapters/windsurf.md +395 -0
  3. package/.ai-rules/agents/accessibility-specialist.json +6 -0
  4. package/.ai-rules/agents/act-mode.json +6 -0
  5. package/.ai-rules/agents/agent-architect.json +6 -0
  6. package/.ai-rules/agents/ai-ml-engineer.json +6 -0
  7. package/.ai-rules/agents/architecture-specialist.json +6 -0
  8. package/.ai-rules/agents/auto-mode.json +6 -0
  9. package/.ai-rules/agents/backend-developer.json +6 -0
  10. package/.ai-rules/agents/code-quality-specialist.json +6 -0
  11. package/.ai-rules/agents/code-reviewer.json +25 -4
  12. package/.ai-rules/agents/data-engineer.json +6 -0
  13. package/.ai-rules/agents/data-scientist.json +6 -0
  14. package/.ai-rules/agents/devops-engineer.json +6 -0
  15. package/.ai-rules/agents/documentation-specialist.json +6 -0
  16. package/.ai-rules/agents/eval-mode.json +11 -1
  17. package/.ai-rules/agents/event-architecture-specialist.json +6 -0
  18. package/.ai-rules/agents/frontend-developer.json +6 -0
  19. package/.ai-rules/agents/i18n-specialist.json +6 -0
  20. package/.ai-rules/agents/integration-specialist.json +6 -0
  21. package/.ai-rules/agents/migration-specialist.json +6 -0
  22. package/.ai-rules/agents/mobile-developer.json +7 -10
  23. package/.ai-rules/agents/observability-specialist.json +6 -0
  24. package/.ai-rules/agents/parallel-orchestrator.json +6 -0
  25. package/.ai-rules/agents/performance-specialist.json +6 -0
  26. package/.ai-rules/agents/plan-mode.json +6 -0
  27. package/.ai-rules/agents/plan-reviewer.json +7 -4
  28. package/.ai-rules/agents/platform-engineer.json +6 -0
  29. package/.ai-rules/agents/security-engineer.json +6 -0
  30. package/.ai-rules/agents/security-specialist.json +6 -0
  31. package/.ai-rules/agents/seo-specialist.json +6 -0
  32. package/.ai-rules/agents/software-engineer.json +6 -0
  33. package/.ai-rules/agents/solution-architect.json +6 -0
  34. package/.ai-rules/agents/systems-developer.json +6 -0
  35. package/.ai-rules/agents/technical-planner.json +6 -0
  36. package/.ai-rules/agents/test-engineer.json +6 -0
  37. package/.ai-rules/agents/test-strategy-specialist.json +6 -0
  38. package/.ai-rules/agents/tooling-engineer.json +6 -0
  39. package/.ai-rules/agents/ui-ux-designer.json +6 -0
  40. package/.ai-rules/schemas/agent.schema.json +38 -0
  41. package/.ai-rules/skills/README.md +6 -0
  42. package/.ai-rules/skills/agent-design/examples/agent-template.json +1 -4
  43. package/.ai-rules/skills/mcp-builder/examples/tool-example.ts +8 -13
  44. package/.ai-rules/skills/onboard/SKILL.md +150 -0
  45. package/.ai-rules/skills/plan-to-issues/SKILL.md +318 -0
  46. package/.ai-rules/skills/retrospective/SKILL.md +192 -0
  47. package/.ai-rules/skills/ship/SKILL.md +242 -0
  48. package/.ai-rules/skills/skill-creator/assets/eval_review.html +539 -260
  49. package/bin/cli.js +11 -19
  50. package/lib/init/detect-stack.js +18 -4
  51. package/lib/init/prompt.js +2 -2
  52. package/lib/init/suggest-agent.js +13 -2
  53. package/package.json +1 -1
@@ -1,289 +1,568 @@
1
- <!DOCTYPE html>
1
+ <!doctype html>
2
2
  <html lang="en" data-theme="dark">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Eval Review — __SKILL_NAME_PLACEHOLDER__</title>
7
- <style>
8
- *,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
9
- :root{
10
- --bg:#0d1117;--surface:#161b22;--border:#30363d;--text:#e6edf3;--text-dim:#8b949e;
11
- --trigger:#238636;--trigger-bg:rgba(35,134,54,.15);
12
- --no-trigger:#da3633;--no-trigger-bg:rgba(218,54,51,.15);
13
- --accent:#58a6ff;--accent-hover:#79c0ff;
14
- --warn:#d29922;--radius:8px;--shadow:0 2px 8px rgba(0,0,0,.3);
15
- --font-mono:'SF Mono','Cascadia Code','Fira Code',monospace;
16
- --font-sans:-apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;
17
- }
18
- html{font-size:15px}
19
- body{background:var(--bg);color:var(--text);font-family:var(--font-sans);line-height:1.6;padding:2rem;max-width:1200px;margin:0 auto}
20
- h1{font-size:1.6rem;font-weight:700;margin-bottom:.25rem}
21
- .subtitle{color:var(--text-dim);margin-bottom:1.5rem;font-size:.9rem}
22
- .stats{display:flex;gap:1rem;margin-bottom:1.5rem;flex-wrap:wrap}
23
- .stat{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:.75rem 1.25rem;min-width:120px}
24
- .stat-label{font-size:.75rem;color:var(--text-dim);text-transform:uppercase;letter-spacing:.05em}
25
- .stat-value{font-size:1.4rem;font-weight:700;font-family:var(--font-mono)}
26
- .stat-trigger .stat-value{color:var(--trigger)}
27
- .stat-no-trigger .stat-value{color:var(--no-trigger)}
28
- .stat-total .stat-value{color:var(--accent)}
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Eval Review — __SKILL_NAME_PLACEHOLDER__</title>
7
+ <style>
8
+ *,
9
+ *::before,
10
+ *::after {
11
+ box-sizing: border-box;
12
+ margin: 0;
13
+ padding: 0;
14
+ }
15
+ :root {
16
+ --bg: #0d1117;
17
+ --surface: #161b22;
18
+ --border: #30363d;
19
+ --text: #e6edf3;
20
+ --text-dim: #8b949e;
21
+ --trigger: #238636;
22
+ --trigger-bg: rgba(35, 134, 54, 0.15);
23
+ --no-trigger: #da3633;
24
+ --no-trigger-bg: rgba(218, 54, 51, 0.15);
25
+ --accent: #58a6ff;
26
+ --accent-hover: #79c0ff;
27
+ --warn: #d29922;
28
+ --radius: 8px;
29
+ --shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
30
+ --font-mono: 'SF Mono', 'Cascadia Code', 'Fira Code', monospace;
31
+ --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
32
+ }
33
+ html {
34
+ font-size: 15px;
35
+ }
36
+ body {
37
+ background: var(--bg);
38
+ color: var(--text);
39
+ font-family: var(--font-sans);
40
+ line-height: 1.6;
41
+ padding: 2rem;
42
+ max-width: 1200px;
43
+ margin: 0 auto;
44
+ }
45
+ h1 {
46
+ font-size: 1.6rem;
47
+ font-weight: 700;
48
+ margin-bottom: 0.25rem;
49
+ }
50
+ .subtitle {
51
+ color: var(--text-dim);
52
+ margin-bottom: 1.5rem;
53
+ font-size: 0.9rem;
54
+ }
55
+ .stats {
56
+ display: flex;
57
+ gap: 1rem;
58
+ margin-bottom: 1.5rem;
59
+ flex-wrap: wrap;
60
+ }
61
+ .stat {
62
+ background: var(--surface);
63
+ border: 1px solid var(--border);
64
+ border-radius: var(--radius);
65
+ padding: 0.75rem 1.25rem;
66
+ min-width: 120px;
67
+ }
68
+ .stat-label {
69
+ font-size: 0.75rem;
70
+ color: var(--text-dim);
71
+ text-transform: uppercase;
72
+ letter-spacing: 0.05em;
73
+ }
74
+ .stat-value {
75
+ font-size: 1.4rem;
76
+ font-weight: 700;
77
+ font-family: var(--font-mono);
78
+ }
79
+ .stat-trigger .stat-value {
80
+ color: var(--trigger);
81
+ }
82
+ .stat-no-trigger .stat-value {
83
+ color: var(--no-trigger);
84
+ }
85
+ .stat-total .stat-value {
86
+ color: var(--accent);
87
+ }
29
88
 
30
- .toolbar{display:flex;gap:.5rem;margin-bottom:1.5rem;flex-wrap:wrap;align-items:center}
31
- .btn{background:var(--surface);color:var(--text);border:1px solid var(--border);border-radius:6px;padding:.45rem 1rem;cursor:pointer;font-size:.85rem;font-family:var(--font-sans);transition:border-color .15s,background .15s}
32
- .btn:hover{border-color:var(--accent);background:#1c2129}
33
- .btn-primary{background:var(--accent);color:#000;border-color:var(--accent);font-weight:600}
34
- .btn-primary:hover{background:var(--accent-hover)}
35
- .btn-danger{color:var(--no-trigger)}
36
- .btn-danger:hover{background:var(--no-trigger-bg);border-color:var(--no-trigger)}
37
- .filter-group{display:flex;gap:0}
38
- .filter-btn{border-radius:0;margin-left:-1px}
39
- .filter-btn:first-child{border-radius:6px 0 0 6px;margin-left:0}
40
- .filter-btn:last-child{border-radius:0 6px 6px 0}
41
- .filter-btn.active{background:var(--accent);color:#000;border-color:var(--accent)}
42
- .spacer{flex:1}
89
+ .toolbar {
90
+ display: flex;
91
+ gap: 0.5rem;
92
+ margin-bottom: 1.5rem;
93
+ flex-wrap: wrap;
94
+ align-items: center;
95
+ }
96
+ .btn {
97
+ background: var(--surface);
98
+ color: var(--text);
99
+ border: 1px solid var(--border);
100
+ border-radius: 6px;
101
+ padding: 0.45rem 1rem;
102
+ cursor: pointer;
103
+ font-size: 0.85rem;
104
+ font-family: var(--font-sans);
105
+ transition:
106
+ border-color 0.15s,
107
+ background 0.15s;
108
+ }
109
+ .btn:hover {
110
+ border-color: var(--accent);
111
+ background: #1c2129;
112
+ }
113
+ .btn-primary {
114
+ background: var(--accent);
115
+ color: #000;
116
+ border-color: var(--accent);
117
+ font-weight: 600;
118
+ }
119
+ .btn-primary:hover {
120
+ background: var(--accent-hover);
121
+ }
122
+ .btn-danger {
123
+ color: var(--no-trigger);
124
+ }
125
+ .btn-danger:hover {
126
+ background: var(--no-trigger-bg);
127
+ border-color: var(--no-trigger);
128
+ }
129
+ .filter-group {
130
+ display: flex;
131
+ gap: 0;
132
+ }
133
+ .filter-btn {
134
+ border-radius: 0;
135
+ margin-left: -1px;
136
+ }
137
+ .filter-btn:first-child {
138
+ border-radius: 6px 0 0 6px;
139
+ margin-left: 0;
140
+ }
141
+ .filter-btn:last-child {
142
+ border-radius: 0 6px 6px 0;
143
+ }
144
+ .filter-btn.active {
145
+ background: var(--accent);
146
+ color: #000;
147
+ border-color: var(--accent);
148
+ }
149
+ .spacer {
150
+ flex: 1;
151
+ }
43
152
 
44
- .cards{display:grid;gap:1rem}
45
- .card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:1.25rem;transition:border-color .15s;position:relative}
46
- .card:hover{border-color:var(--text-dim)}
47
- .card.trigger{border-left:3px solid var(--trigger)}
48
- .card.no-trigger{border-left:3px solid var(--no-trigger)}
49
- .card-header{display:flex;align-items:flex-start;justify-content:space-between;gap:1rem;margin-bottom:.75rem}
50
- .card-query{font-size:1rem;font-weight:500;flex:1}
51
- .card-badge{font-size:.7rem;font-weight:700;padding:.2rem .6rem;border-radius:4px;white-space:nowrap;text-transform:uppercase;letter-spacing:.04em}
52
- .badge-trigger{background:var(--trigger-bg);color:var(--trigger)}
53
- .badge-no-trigger{background:var(--no-trigger-bg);color:var(--no-trigger)}
54
- .card-meta{display:flex;gap:1rem;color:var(--text-dim);font-size:.8rem;margin-bottom:.5rem;flex-wrap:wrap}
55
- .card-meta span{display:flex;align-items:center;gap:.25rem}
56
- .card-reason{color:var(--text-dim);font-size:.85rem;margin-top:.5rem;padding-top:.5rem;border-top:1px solid var(--border)}
57
- .card-actions{display:flex;gap:.5rem;margin-top:.75rem;justify-content:flex-end}
58
- .card-actions .btn{padding:.3rem .75rem;font-size:.8rem}
153
+ .cards {
154
+ display: grid;
155
+ gap: 1rem;
156
+ }
157
+ .card {
158
+ background: var(--surface);
159
+ border: 1px solid var(--border);
160
+ border-radius: var(--radius);
161
+ padding: 1.25rem;
162
+ transition: border-color 0.15s;
163
+ position: relative;
164
+ }
165
+ .card:hover {
166
+ border-color: var(--text-dim);
167
+ }
168
+ .card.trigger {
169
+ border-left: 3px solid var(--trigger);
170
+ }
171
+ .card.no-trigger {
172
+ border-left: 3px solid var(--no-trigger);
173
+ }
174
+ .card-header {
175
+ display: flex;
176
+ align-items: flex-start;
177
+ justify-content: space-between;
178
+ gap: 1rem;
179
+ margin-bottom: 0.75rem;
180
+ }
181
+ .card-query {
182
+ font-size: 1rem;
183
+ font-weight: 500;
184
+ flex: 1;
185
+ }
186
+ .card-badge {
187
+ font-size: 0.7rem;
188
+ font-weight: 700;
189
+ padding: 0.2rem 0.6rem;
190
+ border-radius: 4px;
191
+ white-space: nowrap;
192
+ text-transform: uppercase;
193
+ letter-spacing: 0.04em;
194
+ }
195
+ .badge-trigger {
196
+ background: var(--trigger-bg);
197
+ color: var(--trigger);
198
+ }
199
+ .badge-no-trigger {
200
+ background: var(--no-trigger-bg);
201
+ color: var(--no-trigger);
202
+ }
203
+ .card-meta {
204
+ display: flex;
205
+ gap: 1rem;
206
+ color: var(--text-dim);
207
+ font-size: 0.8rem;
208
+ margin-bottom: 0.5rem;
209
+ flex-wrap: wrap;
210
+ }
211
+ .card-meta span {
212
+ display: flex;
213
+ align-items: center;
214
+ gap: 0.25rem;
215
+ }
216
+ .card-reason {
217
+ color: var(--text-dim);
218
+ font-size: 0.85rem;
219
+ margin-top: 0.5rem;
220
+ padding-top: 0.5rem;
221
+ border-top: 1px solid var(--border);
222
+ }
223
+ .card-actions {
224
+ display: flex;
225
+ gap: 0.5rem;
226
+ margin-top: 0.75rem;
227
+ justify-content: flex-end;
228
+ }
229
+ .card-actions .btn {
230
+ padding: 0.3rem 0.75rem;
231
+ font-size: 0.8rem;
232
+ }
59
233
 
60
- /* Modal */
61
- .modal-overlay{display:none;position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:100;align-items:center;justify-content:center}
62
- .modal-overlay.open{display:flex}
63
- .modal{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:1.5rem;width:90%;max-width:560px;box-shadow:var(--shadow)}
64
- .modal h2{font-size:1.1rem;margin-bottom:1rem}
65
- .form-group{margin-bottom:1rem}
66
- .form-group label{display:block;font-size:.85rem;color:var(--text-dim);margin-bottom:.3rem}
67
- .form-group input,.form-group textarea,.form-group select{width:100%;background:var(--bg);color:var(--text);border:1px solid var(--border);border-radius:6px;padding:.5rem .75rem;font-size:.9rem;font-family:var(--font-sans)}
68
- .form-group textarea{min-height:80px;resize:vertical}
69
- .form-group select{cursor:pointer}
70
- .modal-footer{display:flex;gap:.5rem;justify-content:flex-end;margin-top:1.25rem}
234
+ /* Modal */
235
+ .modal-overlay {
236
+ display: none;
237
+ position: fixed;
238
+ inset: 0;
239
+ background: rgba(0, 0, 0, 0.6);
240
+ z-index: 100;
241
+ align-items: center;
242
+ justify-content: center;
243
+ }
244
+ .modal-overlay.open {
245
+ display: flex;
246
+ }
247
+ .modal {
248
+ background: var(--surface);
249
+ border: 1px solid var(--border);
250
+ border-radius: var(--radius);
251
+ padding: 1.5rem;
252
+ width: 90%;
253
+ max-width: 560px;
254
+ box-shadow: var(--shadow);
255
+ }
256
+ .modal h2 {
257
+ font-size: 1.1rem;
258
+ margin-bottom: 1rem;
259
+ }
260
+ .form-group {
261
+ margin-bottom: 1rem;
262
+ }
263
+ .form-group label {
264
+ display: block;
265
+ font-size: 0.85rem;
266
+ color: var(--text-dim);
267
+ margin-bottom: 0.3rem;
268
+ }
269
+ .form-group input,
270
+ .form-group textarea,
271
+ .form-group select {
272
+ width: 100%;
273
+ background: var(--bg);
274
+ color: var(--text);
275
+ border: 1px solid var(--border);
276
+ border-radius: 6px;
277
+ padding: 0.5rem 0.75rem;
278
+ font-size: 0.9rem;
279
+ font-family: var(--font-sans);
280
+ }
281
+ .form-group textarea {
282
+ min-height: 80px;
283
+ resize: vertical;
284
+ }
285
+ .form-group select {
286
+ cursor: pointer;
287
+ }
288
+ .modal-footer {
289
+ display: flex;
290
+ gap: 0.5rem;
291
+ justify-content: flex-end;
292
+ margin-top: 1.25rem;
293
+ }
71
294
 
72
- .empty{text-align:center;padding:3rem;color:var(--text-dim)}
73
- .count-badge{font-size:.75rem;color:var(--text-dim);margin-left:.25rem}
74
- </style>
75
- </head>
76
- <body>
295
+ .empty {
296
+ text-align: center;
297
+ padding: 3rem;
298
+ color: var(--text-dim);
299
+ }
300
+ .count-badge {
301
+ font-size: 0.75rem;
302
+ color: var(--text-dim);
303
+ margin-left: 0.25rem;
304
+ }
305
+ </style>
306
+ </head>
307
+ <body>
308
+ <h1>Eval Review — <span id="skillName">__SKILL_NAME_PLACEHOLDER__</span></h1>
309
+ <p class="subtitle" id="skillDesc">__SKILL_DESCRIPTION_PLACEHOLDER__</p>
77
310
 
78
- <h1>Eval Review — <span id="skillName">__SKILL_NAME_PLACEHOLDER__</span></h1>
79
- <p class="subtitle" id="skillDesc">__SKILL_DESCRIPTION_PLACEHOLDER__</p>
311
+ <div class="stats" id="stats"></div>
80
312
 
81
- <div class="stats" id="stats"></div>
82
-
83
- <div class="toolbar">
84
- <div class="filter-group">
85
- <button class="btn filter-btn active" data-filter="all">All <span class="count-badge" id="countAll"></span></button>
86
- <button class="btn filter-btn" data-filter="trigger">Trigger <span class="count-badge" id="countTrigger"></span></button>
87
- <button class="btn filter-btn" data-filter="no-trigger">No Trigger <span class="count-badge" id="countNoTrigger"></span></button>
88
- </div>
89
- <span class="spacer"></span>
90
- <button class="btn" onclick="openModal('add')">+ Add Query</button>
91
- <button class="btn btn-primary" onclick="downloadJSON()">Download eval_set.json</button>
92
- </div>
313
+ <div class="toolbar">
314
+ <div class="filter-group">
315
+ <button class="btn filter-btn active" data-filter="all">
316
+ All <span class="count-badge" id="countAll"></span>
317
+ </button>
318
+ <button class="btn filter-btn" data-filter="trigger">
319
+ Trigger <span class="count-badge" id="countTrigger"></span>
320
+ </button>
321
+ <button class="btn filter-btn" data-filter="no-trigger">
322
+ No Trigger <span class="count-badge" id="countNoTrigger"></span>
323
+ </button>
324
+ </div>
325
+ <span class="spacer"></span>
326
+ <button class="btn" onclick="openModal('add')">+ Add Query</button>
327
+ <button class="btn btn-primary" onclick="downloadJSON()">Download eval_set.json</button>
328
+ </div>
93
329
 
94
- <div class="cards" id="cardContainer"></div>
330
+ <div class="cards" id="cardContainer"></div>
95
331
 
96
- <!-- Add/Edit Modal -->
97
- <div class="modal-overlay" id="modalOverlay">
98
- <div class="modal">
99
- <h2 id="modalTitle">Add Query</h2>
100
- <div class="form-group">
101
- <label for="inputQuery">User Query</label>
102
- <textarea id="inputQuery" placeholder="Enter user prompt / query..."></textarea>
103
- </div>
104
- <div class="form-group">
105
- <label for="inputTrigger">Should Trigger?</label>
106
- <select id="inputTrigger">
107
- <option value="true">Yes — should trigger this skill</option>
108
- <option value="false">No — should NOT trigger this skill</option>
109
- </select>
110
- </div>
111
- <div class="form-group">
112
- <label for="inputReason">Reason (optional)</label>
113
- <input type="text" id="inputReason" placeholder="Why this query should/shouldn't trigger">
114
- </div>
115
- <div class="form-group">
116
- <label for="inputCategory">Category (optional)</label>
117
- <input type="text" id="inputCategory" placeholder="e.g. happy-path, edge-case, adversarial">
118
- </div>
119
- <div class="modal-footer">
120
- <button class="btn" onclick="closeModal()">Cancel</button>
121
- <button class="btn btn-primary" onclick="saveEntry()">Save</button>
332
+ <!-- Add/Edit Modal -->
333
+ <div class="modal-overlay" id="modalOverlay">
334
+ <div class="modal">
335
+ <h2 id="modalTitle">Add Query</h2>
336
+ <div class="form-group">
337
+ <label for="inputQuery">User Query</label>
338
+ <textarea id="inputQuery" placeholder="Enter user prompt / query..."></textarea>
339
+ </div>
340
+ <div class="form-group">
341
+ <label for="inputTrigger">Should Trigger?</label>
342
+ <select id="inputTrigger">
343
+ <option value="true">Yes — should trigger this skill</option>
344
+ <option value="false">No — should NOT trigger this skill</option>
345
+ </select>
346
+ </div>
347
+ <div class="form-group">
348
+ <label for="inputReason">Reason (optional)</label>
349
+ <input
350
+ type="text"
351
+ id="inputReason"
352
+ placeholder="Why this query should/shouldn't trigger"
353
+ />
354
+ </div>
355
+ <div class="form-group">
356
+ <label for="inputCategory">Category (optional)</label>
357
+ <input
358
+ type="text"
359
+ id="inputCategory"
360
+ placeholder="e.g. happy-path, edge-case, adversarial"
361
+ />
362
+ </div>
363
+ <div class="modal-footer">
364
+ <button class="btn" onclick="closeModal()">Cancel</button>
365
+ <button class="btn btn-primary" onclick="saveEntry()">Save</button>
366
+ </div>
367
+ </div>
122
368
  </div>
123
- </div>
124
- </div>
125
369
 
126
- <script>
127
- (function(){
128
- "use strict";
370
+ <script>
371
+ (function () {
372
+ 'use strict';
129
373
 
130
- // --- Data ---
131
- var rawData = __EVAL_DATA_PLACEHOLDER__;
132
- var evalSet = Array.isArray(rawData) ? rawData : (rawData && rawData.queries ? rawData.queries : []);
133
- var currentFilter = "all";
134
- var editIndex = -1;
374
+ // --- Data ---
375
+ var rawData = __EVAL_DATA_PLACEHOLDER__;
376
+ var evalSet = Array.isArray(rawData)
377
+ ? rawData
378
+ : rawData && rawData.queries
379
+ ? rawData.queries
380
+ : [];
381
+ var currentFilter = 'all';
382
+ var editIndex = -1;
135
383
 
136
- // --- Render ---
137
- function render(){
138
- renderStats();
139
- renderCards();
140
- updateCounts();
141
- }
384
+ // --- Render ---
385
+ function render() {
386
+ renderStats();
387
+ renderCards();
388
+ updateCounts();
389
+ }
142
390
 
143
- function renderStats(){
144
- var total = evalSet.length;
145
- var triggers = evalSet.filter(function(q){return q.should_trigger;}).length;
146
- var noTriggers = total - triggers;
147
- document.getElementById("stats").innerHTML =
148
- '<div class="stat stat-total"><div class="stat-label">Total</div><div class="stat-value">'+total+'</div></div>'+
149
- '<div class="stat stat-trigger"><div class="stat-label">Should Trigger</div><div class="stat-value">'+triggers+'</div></div>'+
150
- '<div class="stat stat-no-trigger"><div class="stat-label">Should Not</div><div class="stat-value">'+noTriggers+'</div></div>';
151
- }
391
+ function renderStats() {
392
+ var total = evalSet.length;
393
+ var triggers = evalSet.filter(function (q) {
394
+ return q.should_trigger;
395
+ }).length;
396
+ var noTriggers = total - triggers;
397
+ document.getElementById('stats').innerHTML =
398
+ '<div class="stat stat-total"><div class="stat-label">Total</div><div class="stat-value">' +
399
+ total +
400
+ '</div></div>' +
401
+ '<div class="stat stat-trigger"><div class="stat-label">Should Trigger</div><div class="stat-value">' +
402
+ triggers +
403
+ '</div></div>' +
404
+ '<div class="stat stat-no-trigger"><div class="stat-label">Should Not</div><div class="stat-value">' +
405
+ noTriggers +
406
+ '</div></div>';
407
+ }
152
408
 
153
- function renderCards(){
154
- var container = document.getElementById("cardContainer");
155
- var filtered = evalSet.filter(function(q, i){
156
- q._index = i;
157
- if(currentFilter === "trigger") return q.should_trigger;
158
- if(currentFilter === "no-trigger") return !q.should_trigger;
159
- return true;
160
- });
409
+ function renderCards() {
410
+ var container = document.getElementById('cardContainer');
411
+ var filtered = evalSet.filter(function (q, i) {
412
+ q._index = i;
413
+ if (currentFilter === 'trigger') return q.should_trigger;
414
+ if (currentFilter === 'no-trigger') return !q.should_trigger;
415
+ return true;
416
+ });
161
417
 
162
- if(filtered.length === 0){
163
- container.innerHTML = '<div class="empty">No queries to display. Click "+ Add Query" to create one.</div>';
164
- return;
165
- }
418
+ if (filtered.length === 0) {
419
+ container.innerHTML =
420
+ '<div class="empty">No queries to display. Click "+ Add Query" to create one.</div>';
421
+ return;
422
+ }
166
423
 
167
- container.innerHTML = filtered.map(function(q){
168
- var cls = q.should_trigger ? "trigger" : "no-trigger";
169
- var badge = q.should_trigger
170
- ? '<span class="card-badge badge-trigger">Should Trigger</span>'
171
- : '<span class="card-badge badge-no-trigger">Should Not Trigger</span>';
172
- var meta = '';
173
- if(q.category) meta += '<span>Category: '+esc(q.category)+'</span>';
174
- if(q.confidence) meta += '<span>Confidence: '+q.confidence+'</span>';
175
- var reason = q.reason ? '<div class="card-reason">'+esc(q.reason)+'</div>' : '';
176
- return '<div class="card '+cls+'">'+
177
- '<div class="card-header"><div class="card-query">'+esc(q.query)+'</div>'+badge+'</div>'+
178
- (meta ? '<div class="card-meta">'+meta+'</div>' : '')+
179
- reason+
180
- '<div class="card-actions">'+
181
- '<button class="btn" onclick="openModal(\'edit\','+q._index+')">Edit</button>'+
182
- '<button class="btn btn-danger" onclick="deleteEntry('+q._index+')">Delete</button>'+
183
- '</div></div>';
184
- }).join("");
185
- }
424
+ container.innerHTML = filtered
425
+ .map(function (q) {
426
+ var cls = q.should_trigger ? 'trigger' : 'no-trigger';
427
+ var badge = q.should_trigger
428
+ ? '<span class="card-badge badge-trigger">Should Trigger</span>'
429
+ : '<span class="card-badge badge-no-trigger">Should Not Trigger</span>';
430
+ var meta = '';
431
+ if (q.category) meta += '<span>Category: ' + esc(q.category) + '</span>';
432
+ if (q.confidence) meta += '<span>Confidence: ' + q.confidence + '</span>';
433
+ var reason = q.reason ? '<div class="card-reason">' + esc(q.reason) + '</div>' : '';
434
+ return (
435
+ '<div class="card ' +
436
+ cls +
437
+ '">' +
438
+ '<div class="card-header"><div class="card-query">' +
439
+ esc(q.query) +
440
+ '</div>' +
441
+ badge +
442
+ '</div>' +
443
+ (meta ? '<div class="card-meta">' + meta + '</div>' : '') +
444
+ reason +
445
+ '<div class="card-actions">' +
446
+ '<button class="btn" onclick="openModal(\'edit\',' +
447
+ q._index +
448
+ ')">Edit</button>' +
449
+ '<button class="btn btn-danger" onclick="deleteEntry(' +
450
+ q._index +
451
+ ')">Delete</button>' +
452
+ '</div></div>'
453
+ );
454
+ })
455
+ .join('');
456
+ }
186
457
 
187
- function updateCounts(){
188
- var total = evalSet.length;
189
- var triggers = evalSet.filter(function(q){return q.should_trigger;}).length;
190
- document.getElementById("countAll").textContent = total;
191
- document.getElementById("countTrigger").textContent = triggers;
192
- document.getElementById("countNoTrigger").textContent = total - triggers;
193
- }
458
+ function updateCounts() {
459
+ var total = evalSet.length;
460
+ var triggers = evalSet.filter(function (q) {
461
+ return q.should_trigger;
462
+ }).length;
463
+ document.getElementById('countAll').textContent = total;
464
+ document.getElementById('countTrigger').textContent = triggers;
465
+ document.getElementById('countNoTrigger').textContent = total - triggers;
466
+ }
194
467
 
195
- function esc(s){
196
- if(!s) return "";
197
- var d = document.createElement("div");
198
- d.textContent = s;
199
- return d.innerHTML;
200
- }
468
+ function esc(s) {
469
+ if (!s) return '';
470
+ var d = document.createElement('div');
471
+ d.textContent = s;
472
+ return d.innerHTML;
473
+ }
201
474
 
202
- // --- Filters ---
203
- document.querySelectorAll(".filter-btn").forEach(function(btn){
204
- btn.addEventListener("click", function(){
205
- document.querySelectorAll(".filter-btn").forEach(function(b){b.classList.remove("active");});
206
- btn.classList.add("active");
207
- currentFilter = btn.getAttribute("data-filter");
208
- renderCards();
209
- });
210
- });
475
+ // --- Filters ---
476
+ document.querySelectorAll('.filter-btn').forEach(function (btn) {
477
+ btn.addEventListener('click', function () {
478
+ document.querySelectorAll('.filter-btn').forEach(function (b) {
479
+ b.classList.remove('active');
480
+ });
481
+ btn.classList.add('active');
482
+ currentFilter = btn.getAttribute('data-filter');
483
+ renderCards();
484
+ });
485
+ });
211
486
 
212
- // --- Modal ---
213
- window.openModal = function(mode, idx){
214
- editIndex = (mode === "edit") ? idx : -1;
215
- document.getElementById("modalTitle").textContent = mode === "edit" ? "Edit Query" : "Add Query";
216
- if(mode === "edit" && idx >= 0){
217
- var q = evalSet[idx];
218
- document.getElementById("inputQuery").value = q.query || "";
219
- document.getElementById("inputTrigger").value = q.should_trigger ? "true" : "false";
220
- document.getElementById("inputReason").value = q.reason || "";
221
- document.getElementById("inputCategory").value = q.category || "";
222
- } else {
223
- document.getElementById("inputQuery").value = "";
224
- document.getElementById("inputTrigger").value = "true";
225
- document.getElementById("inputReason").value = "";
226
- document.getElementById("inputCategory").value = "";
227
- }
228
- document.getElementById("modalOverlay").classList.add("open");
229
- document.getElementById("inputQuery").focus();
230
- };
487
+ // --- Modal ---
488
+ window.openModal = function (mode, idx) {
489
+ editIndex = mode === 'edit' ? idx : -1;
490
+ document.getElementById('modalTitle').textContent =
491
+ mode === 'edit' ? 'Edit Query' : 'Add Query';
492
+ if (mode === 'edit' && idx >= 0) {
493
+ var q = evalSet[idx];
494
+ document.getElementById('inputQuery').value = q.query || '';
495
+ document.getElementById('inputTrigger').value = q.should_trigger ? 'true' : 'false';
496
+ document.getElementById('inputReason').value = q.reason || '';
497
+ document.getElementById('inputCategory').value = q.category || '';
498
+ } else {
499
+ document.getElementById('inputQuery').value = '';
500
+ document.getElementById('inputTrigger').value = 'true';
501
+ document.getElementById('inputReason').value = '';
502
+ document.getElementById('inputCategory').value = '';
503
+ }
504
+ document.getElementById('modalOverlay').classList.add('open');
505
+ document.getElementById('inputQuery').focus();
506
+ };
231
507
 
232
- window.closeModal = function(){
233
- document.getElementById("modalOverlay").classList.remove("open");
234
- editIndex = -1;
235
- };
508
+ window.closeModal = function () {
509
+ document.getElementById('modalOverlay').classList.remove('open');
510
+ editIndex = -1;
511
+ };
236
512
 
237
- window.saveEntry = function(){
238
- var query = document.getElementById("inputQuery").value.trim();
239
- if(!query){ alert("Query is required."); return; }
240
- var entry = {
241
- query: query,
242
- should_trigger: document.getElementById("inputTrigger").value === "true"
243
- };
244
- var reason = document.getElementById("inputReason").value.trim();
245
- var category = document.getElementById("inputCategory").value.trim();
246
- if(reason) entry.reason = reason;
247
- if(category) entry.category = category;
513
+ window.saveEntry = function () {
514
+ var query = document.getElementById('inputQuery').value.trim();
515
+ if (!query) {
516
+ alert('Query is required.');
517
+ return;
518
+ }
519
+ var entry = {
520
+ query: query,
521
+ should_trigger: document.getElementById('inputTrigger').value === 'true',
522
+ };
523
+ var reason = document.getElementById('inputReason').value.trim();
524
+ var category = document.getElementById('inputCategory').value.trim();
525
+ if (reason) entry.reason = reason;
526
+ if (category) entry.category = category;
248
527
 
249
- if(editIndex >= 0){
250
- evalSet[editIndex] = entry;
251
- } else {
252
- evalSet.push(entry);
253
- }
254
- closeModal();
255
- render();
256
- };
528
+ if (editIndex >= 0) {
529
+ evalSet[editIndex] = entry;
530
+ } else {
531
+ evalSet.push(entry);
532
+ }
533
+ closeModal();
534
+ render();
535
+ };
257
536
 
258
- window.deleteEntry = function(idx){
259
- if(!confirm("Delete this query?")) return;
260
- evalSet.splice(idx, 1);
261
- render();
262
- };
537
+ window.deleteEntry = function (idx) {
538
+ if (!confirm('Delete this query?')) return;
539
+ evalSet.splice(idx, 1);
540
+ render();
541
+ };
263
542
 
264
- // --- Download ---
265
- window.downloadJSON = function(){
266
- var out = {
267
- skill_name: document.getElementById("skillName").textContent,
268
- description: document.getElementById("skillDesc").textContent,
269
- queries: evalSet
270
- };
271
- var blob = new Blob([JSON.stringify(out, null, 2)], {type:"application/json"});
272
- var a = document.createElement("a");
273
- a.href = URL.createObjectURL(blob);
274
- a.download = "eval_set.json";
275
- a.click();
276
- URL.revokeObjectURL(a.href);
277
- };
543
+ // --- Download ---
544
+ window.downloadJSON = function () {
545
+ var out = {
546
+ skill_name: document.getElementById('skillName').textContent,
547
+ description: document.getElementById('skillDesc').textContent,
548
+ queries: evalSet,
549
+ };
550
+ var blob = new Blob([JSON.stringify(out, null, 2)], { type: 'application/json' });
551
+ var a = document.createElement('a');
552
+ a.href = URL.createObjectURL(blob);
553
+ a.download = 'eval_set.json';
554
+ a.click();
555
+ URL.revokeObjectURL(a.href);
556
+ };
278
557
 
279
- // --- Keyboard ---
280
- document.addEventListener("keydown", function(e){
281
- if(e.key === "Escape") closeModal();
282
- });
558
+ // --- Keyboard ---
559
+ document.addEventListener('keydown', function (e) {
560
+ if (e.key === 'Escape') closeModal();
561
+ });
283
562
 
284
- // --- Init ---
285
- render();
286
- })();
287
- </script>
288
- </body>
563
+ // --- Init ---
564
+ render();
565
+ })();
566
+ </script>
567
+ </body>
289
568
  </html>