@bendyline/gilde 0.1.71 → 0.1.72
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/authoring/tactical/books/apply-review-findings.json +2 -0
- package/data/craftbook-templates/ap/apply-review-findings/versions/1.0.3/craftbook.json +604 -0
- package/data/craftbook-templates/ap/apply-review-findings/versions/1.0.3/test.json +290 -0
- package/data/craftbook-templates/co/code-review/versions/1.0.2/craftbook.json +230 -0
- package/data/craftbook-templates/co/code-review/versions/1.0.2/test.json +252 -0
- package/data/craftbook-templates/co/content-accuracy-review/versions/1.1.0/craftbook.json +311 -0
- package/data/craftbook-templates/co/content-accuracy-review/versions/1.1.0/test.json +167 -0
- package/data/craftbook-templates/eb/ebook-compile/versions/1.1.0/craftbook.json +332 -0
- package/data/craftbook-templates/eb/ebook-compile/versions/1.1.0/test.json +111 -0
- package/data/craftbook-templates/fa/faq-from-docs/versions/1.1.0/craftbook.json +245 -0
- package/data/craftbook-templates/fa/faq-from-docs/versions/1.1.0/test.json +113 -0
- package/data/craftbook-templates/index.json +1 -1
- package/data/craftbook-templates/me/meeting-minutes/versions/1.1.0/craftbook.json +246 -0
- package/data/craftbook-templates/me/meeting-minutes/versions/1.1.0/test.json +113 -0
- package/data/craftbook-templates/me/meeting-notes-to-actions/versions/1.1.0/craftbook.json +245 -0
- package/data/craftbook-templates/me/meeting-notes-to-actions/versions/1.1.0/test.json +113 -0
- package/data/craftbook-templates/ni/nightly-fix-sweep/versions/1.0.2/craftbook.json +243 -0
- package/data/craftbook-templates/ni/nightly-fix-sweep/versions/1.0.2/test.json +120 -0
- package/data/craftbook-templates/po/powerpoint-deck/versions/1.7.12/craftbook.json +581 -0
- package/data/craftbook-templates/po/powerpoint-deck/versions/1.7.12/test.json +240 -0
- package/data/craftbook-templates/pr/press-release/versions/1.0.4/craftbook.json +281 -0
- package/data/craftbook-templates/pr/press-release/versions/1.0.4/test.json +356 -0
- package/data/craftbook-templates/st/standup-summary/versions/1.1.0/craftbook.json +249 -0
- package/data/craftbook-templates/st/standup-summary/versions/1.1.0/test.json +113 -0
- package/data/craftbook-templates/we/weekly-review/versions/1.0.4/craftbook.json +223 -0
- package/data/craftbook-templates/we/weekly-review/versions/1.0.4/test.json +110 -0
- package/package.json +1 -1
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"title": "Apply review findings with a reconciled ledger",
|
|
4
|
+
"objective": "The craftbook drives a real findings pass: three seeded review findings (unvalidated numeric input, a swallowed error, a misleading error message) read from an artifacts-drawer findings file, triaged against the current code, fixed at their actual sites, and verified per finding - with behavior probes proving each one genuinely closed and the neighborhood suite still green.",
|
|
5
|
+
"tags": [
|
|
6
|
+
"code",
|
|
7
|
+
"review-findings",
|
|
8
|
+
"bug-fix",
|
|
9
|
+
"tactical-fleet"
|
|
10
|
+
],
|
|
11
|
+
"prompt": "Use the Apply Review Findings craftbook: last week's code review left three findings in the artifacts drawer at reviews/findings.json. Triage them against the current code, fix what is real at the real sites, and account for every finding.",
|
|
12
|
+
"setup": {
|
|
13
|
+
"projectName": "Order Intake",
|
|
14
|
+
"about": "A tiny order-intake library (quantity parsing, config loading, discounts). Tests run with `npm run test` (node --test).",
|
|
15
|
+
"files": [
|
|
16
|
+
{
|
|
17
|
+
"path": "package.json",
|
|
18
|
+
"content": "{\n \"name\": \"intake\",\n \"private\": true,\n \"version\": \"1.0.0\",\n \"type\": \"module\",\n \"scripts\": {\n \"test\": \"node --test\"\n }\n}\n",
|
|
19
|
+
"modelInput": false
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"path": "src/quantity.js",
|
|
23
|
+
"content": "export function parseQuantity(raw) {\n return parseInt(raw, 10);\n}\n\nexport function clampQuantity(qty, max) {\n return Math.min(qty, max);\n}\n"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"path": "src/config.js",
|
|
27
|
+
"content": "import { readFileSync } from 'node:fs';\n\nexport function loadConfig(path) {\n try {\n return JSON.parse(readFileSync(path, 'utf8'));\n } catch (err) {\n return {};\n }\n}\n"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"path": "src/discount.js",
|
|
31
|
+
"content": "export function applyDiscount(total, percent) {\n if (percent < 0 || percent > 100) {\n throw new Error('quantity out of range');\n }\n return Math.round(total * (1 - percent / 100) * 100) / 100;\n}\n"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"path": "tests/intake.test.mjs",
|
|
35
|
+
"content": "import assert from 'node:assert/strict';\nimport { test } from 'node:test';\nimport { parseQuantity } from '../src/quantity.js';\nimport { applyDiscount } from '../src/discount.js';\nimport { loadConfig } from '../src/config.js';\n\ntest('parseQuantity reads plain integers', () => {\n assert.equal(parseQuantity('3'), 3);\n assert.equal(parseQuantity('12'), 12);\n});\n\ntest('applyDiscount takes a percentage off', () => {\n assert.equal(applyDiscount(100, 10), 90);\n assert.equal(applyDiscount(80, 0), 80);\n});\n\ntest('loadConfig falls back to defaults for a missing file', () => {\n assert.deepEqual(loadConfig('no-such-config.json'), {});\n});\n",
|
|
36
|
+
"modelInput": false
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"path": "reviews/findings.json",
|
|
40
|
+
"content": "[\n {\n \"id\": \"RV-1\",\n \"file\": \"src/quantity.js\",\n \"severity\": \"major\",\n \"title\": \"parseQuantity accepts invalid numeric input\",\n \"detail\": \"parseInt returns NaN for non-numeric input, and negative or zero values pass through unchecked, so downstream order math silently corrupts. parseQuantity must return only positive integers and throw a RangeError naming the rejected value for anything else.\",\n \"verify\": \"parseQuantity('abc'), parseQuantity('-2'), and parseQuantity('0') must throw; parseQuantity('3') must still return 3.\"\n },\n {\n \"id\": \"RV-2\",\n \"file\": \"src/config.js\",\n \"severity\": \"major\",\n \"title\": \"loadConfig swallows JSON syntax errors\",\n \"detail\": \"The catch returns {} for every failure, so a corrupt config file silently behaves like an empty one and a bad deploy ships. Only a missing file may fall back to {}; a parse failure must propagate to the caller.\",\n \"verify\": \"loadConfig on a file containing invalid JSON must throw; loadConfig on a missing path must still return {}.\"\n },\n {\n \"id\": \"RV-3\",\n \"file\": \"src/discount.js\",\n \"severity\": \"minor\",\n \"title\": \"applyDiscount raises a misleading error message\",\n \"detail\": \"An out-of-range percent raises 'quantity out of range', so support keeps chasing phantom quantity bugs. The message must describe the discount percent that was rejected.\",\n \"verify\": \"applyDiscount(100, 150) must throw with a message that mentions the discount or percent, not quantity.\"\n }\n]\n",
|
|
41
|
+
"surface": "artifact"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"path": "tests/verify-findings.mjs",
|
|
45
|
+
"content": "import assert from 'node:assert/strict';\nimport { execFileSync } from 'node:child_process';\nimport { rmSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { parseQuantity } from '../src/quantity.js';\nimport { loadConfig } from '../src/config.js';\nimport { applyDiscount } from '../src/discount.js';\n\nconst root = process.cwd();\n\n// RV-1: parseQuantity accepts only positive integers, and still parses them.\nassert.equal(parseQuantity('3'), 3, \"parseQuantity('3') must still return 3\");\nassert.equal(parseQuantity('12'), 12, \"parseQuantity('12') must still return 12\");\nassert.throws(() => parseQuantity('abc'), \"parseQuantity('abc') must throw\");\nassert.throws(() => parseQuantity('-2'), \"parseQuantity('-2') must throw\");\nassert.throws(() => parseQuantity('0'), \"parseQuantity('0') must throw\");\nconsole.log('FINDINGS_ORACLE rv1 closed');\n\n// RV-2: a corrupt config raises; a missing config still falls back to {}.\nconst corruptPath = join(root, '.oracle-corrupt-config.json');\nwriteFileSync(corruptPath, '{ not json');\nassert.throws(() => loadConfig(corruptPath), 'a corrupt config must raise, not vanish into defaults');\nrmSync(corruptPath, { force: true });\nassert.deepEqual(loadConfig(join(root, 'no-such-config.json')), {}, 'a missing config must still fall back to {}');\nconsole.log('FINDINGS_ORACLE rv2 closed');\n\n// RV-3: the out-of-range message describes the discount, not the quantity.\nlet threw = false;\nlet message = '';\ntry {\n applyDiscount(100, 150);\n} catch (err) {\n threw = true;\n message = String((err && err.message) || err);\n}\nassert.ok(threw, 'applyDiscount(100, 150) must throw');\nassert.match(message, /discount|percent/i, 'the error must describe the discount percent');\nassert.ok(!/quantity/i.test(message), 'the error must not blame quantity');\nassert.equal(applyDiscount(100, 10), 90, 'valid discounts must still work');\nassert.equal(applyDiscount(80, 0), 80, 'a zero discount must still be allowed');\nconsole.log('FINDINGS_ORACLE rv3 closed');\n\n// The neighborhood suite stays green after the findings pass.\nexecFileSync(process.execPath, ['--test'], { cwd: root, stdio: 'pipe', timeout: 30000 });\nconsole.log('FINDINGS_ORACLE suite green');\nconsole.log('FINDINGS_ORACLE done');\n",
|
|
46
|
+
"surface": "harness"
|
|
47
|
+
}
|
|
48
|
+
],
|
|
49
|
+
"craftbookParams": {
|
|
50
|
+
"findingsPath": "reviews/findings.json"
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"mocks": [],
|
|
54
|
+
"success": {
|
|
55
|
+
"summary": "All three seeded findings are genuinely closed at their real sites (validated quantity input, propagating config parse errors, an honest discount message), the neighborhood tests stay green, and the finding ids reconcile across triage, fix notes, and verification.",
|
|
56
|
+
"deliverables": [
|
|
57
|
+
{
|
|
58
|
+
"path": "{{task.dir}}/triage.md",
|
|
59
|
+
"kind": "markdown-notes",
|
|
60
|
+
"artifact": true,
|
|
61
|
+
"minBytes": 600,
|
|
62
|
+
"checks": [
|
|
63
|
+
{
|
|
64
|
+
"kind": "contains",
|
|
65
|
+
"file": "{{task.dir}}/triage.md",
|
|
66
|
+
"pattern": "^##\\s+Findings read[\\s\\S]*^##\\s+Will fix[\\s\\S]*^##\\s+Deferred[\\s\\S]*^##\\s+Clusters",
|
|
67
|
+
"flags": "im",
|
|
68
|
+
"label": "triage sections in order"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"kind": "contains",
|
|
72
|
+
"file": "{{task.dir}}/triage.md",
|
|
73
|
+
"pattern": "\\bRV-1\\b",
|
|
74
|
+
"label": "finding RV-1 triaged"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"kind": "contains",
|
|
78
|
+
"file": "{{task.dir}}/triage.md",
|
|
79
|
+
"pattern": "\\bRV-2\\b",
|
|
80
|
+
"label": "finding RV-2 triaged"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"kind": "contains",
|
|
84
|
+
"file": "{{task.dir}}/triage.md",
|
|
85
|
+
"pattern": "\\bRV-3\\b",
|
|
86
|
+
"label": "finding RV-3 triaged"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"kind": "citationsResolve",
|
|
90
|
+
"file": "{{task.dir}}/triage.md",
|
|
91
|
+
"minCitations": 2,
|
|
92
|
+
"artifact": true
|
|
93
|
+
}
|
|
94
|
+
]
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"path": "{{task.dir}}/fix-notes.md",
|
|
98
|
+
"kind": "markdown-notes",
|
|
99
|
+
"artifact": true,
|
|
100
|
+
"minBytes": 700,
|
|
101
|
+
"checks": [
|
|
102
|
+
{
|
|
103
|
+
"kind": "contains",
|
|
104
|
+
"file": "{{task.dir}}/fix-notes.md",
|
|
105
|
+
"pattern": "^##\\s+Problem[\\s\\S]*^##\\s+Change[\\s\\S]*^##\\s+Files touched[\\s\\S]*^##\\s+Per-finding disposition[\\s\\S]*^##\\s+Risk[\\s\\S]*^##\\s+How to verify",
|
|
106
|
+
"flags": "im",
|
|
107
|
+
"label": "fix-notes sections in order"
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"kind": "contains",
|
|
111
|
+
"file": "{{task.dir}}/fix-notes.md",
|
|
112
|
+
"pattern": "\\bRV-1\\b",
|
|
113
|
+
"label": "disposition for RV-1"
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"kind": "contains",
|
|
117
|
+
"file": "{{task.dir}}/fix-notes.md",
|
|
118
|
+
"pattern": "\\bRV-2\\b",
|
|
119
|
+
"label": "disposition for RV-2"
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"kind": "contains",
|
|
123
|
+
"file": "{{task.dir}}/fix-notes.md",
|
|
124
|
+
"pattern": "\\bRV-3\\b",
|
|
125
|
+
"label": "disposition for RV-3"
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"kind": "citationsResolve",
|
|
129
|
+
"file": "{{task.dir}}/fix-notes.md",
|
|
130
|
+
"minCitations": 2,
|
|
131
|
+
"artifact": true
|
|
132
|
+
}
|
|
133
|
+
]
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"path": "{{task.dir}}/validation.md",
|
|
137
|
+
"kind": "markdown-notes",
|
|
138
|
+
"artifact": true,
|
|
139
|
+
"minBytes": 450,
|
|
140
|
+
"checks": [
|
|
141
|
+
{
|
|
142
|
+
"kind": "contains",
|
|
143
|
+
"file": "{{task.dir}}/validation.md",
|
|
144
|
+
"pattern": "^##\\s+Per-finding verification[\\s\\S]*^##\\s+Result",
|
|
145
|
+
"flags": "im",
|
|
146
|
+
"label": "validation sections in order"
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"kind": "contains",
|
|
150
|
+
"file": "{{task.dir}}/validation.md",
|
|
151
|
+
"pattern": "\\bRV-1\\b",
|
|
152
|
+
"label": "verification for RV-1"
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
"kind": "contains",
|
|
156
|
+
"file": "{{task.dir}}/validation.md",
|
|
157
|
+
"pattern": "\\bRV-2\\b",
|
|
158
|
+
"label": "verification for RV-2"
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
"kind": "contains",
|
|
162
|
+
"file": "{{task.dir}}/validation.md",
|
|
163
|
+
"pattern": "\\bRV-3\\b",
|
|
164
|
+
"label": "verification for RV-3"
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
"kind": "citationsResolve",
|
|
168
|
+
"file": "{{task.dir}}/validation.md",
|
|
169
|
+
"minCitations": 2,
|
|
170
|
+
"artifact": true
|
|
171
|
+
}
|
|
172
|
+
]
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
"path": "{{task.dir}}/review.md",
|
|
176
|
+
"kind": "markdown-report",
|
|
177
|
+
"artifact": true,
|
|
178
|
+
"minBytes": 400,
|
|
179
|
+
"checks": [
|
|
180
|
+
{
|
|
181
|
+
"kind": "contains",
|
|
182
|
+
"file": "{{task.dir}}/review.md",
|
|
183
|
+
"pattern": "Verdict:\\s*(?:PASS|REVISE)",
|
|
184
|
+
"flags": "i",
|
|
185
|
+
"label": "explicit reviewer verdict"
|
|
186
|
+
}
|
|
187
|
+
]
|
|
188
|
+
}
|
|
189
|
+
],
|
|
190
|
+
"checks": [
|
|
191
|
+
{
|
|
192
|
+
"kind": "notContains",
|
|
193
|
+
"file": "src/discount.js",
|
|
194
|
+
"pattern": "quantity out of range",
|
|
195
|
+
"label": "the misleading discount message is gone (RV-3)"
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
"kind": "notContains",
|
|
199
|
+
"file": "src/config.js",
|
|
200
|
+
"pattern": "catch\\s*(?:\\([^)]*\\))?\\s*\\{\\s*return\\s*\\{\\s*\\}",
|
|
201
|
+
"label": "the blanket error swallow is gone (RV-2)"
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
"kind": "sourceParses",
|
|
205
|
+
"file": "src/quantity.js"
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
"kind": "sourceParses",
|
|
209
|
+
"file": "src/config.js"
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
"kind": "sourceParses",
|
|
213
|
+
"file": "src/discount.js"
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
"kind": "nodeRuns",
|
|
217
|
+
"file": "tests/intake.test.mjs",
|
|
218
|
+
"timeoutMs": 30000
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
"kind": "nodeScriptPasses",
|
|
222
|
+
"script": "tests/verify-findings.mjs",
|
|
223
|
+
"timeoutMs": 60000,
|
|
224
|
+
"requiredOutput": [
|
|
225
|
+
{
|
|
226
|
+
"pattern": "FINDINGS_ORACLE rv1 closed",
|
|
227
|
+
"label": "invalid quantities are rejected (RV-1)"
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
"pattern": "FINDINGS_ORACLE rv2 closed",
|
|
231
|
+
"label": "corrupt configs raise, missing configs default (RV-2)"
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
"pattern": "FINDINGS_ORACLE rv3 closed",
|
|
235
|
+
"label": "the discount error names the discount (RV-3)"
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
"pattern": "FINDINGS_ORACLE suite green",
|
|
239
|
+
"label": "the neighborhood suite stays green"
|
|
240
|
+
}
|
|
241
|
+
]
|
|
242
|
+
}
|
|
243
|
+
],
|
|
244
|
+
"taskNotes": {
|
|
245
|
+
"minBytes": 120,
|
|
246
|
+
"checks": [
|
|
247
|
+
{
|
|
248
|
+
"kind": "contains",
|
|
249
|
+
"file": "task-notes.md",
|
|
250
|
+
"pattern": "\\bDONE\\b[\\s\\S]*validation\\.md",
|
|
251
|
+
"flags": "i",
|
|
252
|
+
"label": "DONE note names the validation deliverable"
|
|
253
|
+
}
|
|
254
|
+
]
|
|
255
|
+
},
|
|
256
|
+
"taskGraph": {
|
|
257
|
+
"requireCraftbookTask": true,
|
|
258
|
+
"requireTerminalStep": true
|
|
259
|
+
},
|
|
260
|
+
"unchangedFixtures": [
|
|
261
|
+
"package.json",
|
|
262
|
+
"tests/intake.test.mjs"
|
|
263
|
+
]
|
|
264
|
+
},
|
|
265
|
+
"rubric": {
|
|
266
|
+
"artifact": {
|
|
267
|
+
"path": "{{task.dir}}/fix-notes.md",
|
|
268
|
+
"kind": "markdown"
|
|
269
|
+
},
|
|
270
|
+
"axes": [
|
|
271
|
+
{
|
|
272
|
+
"name": "Triage honesty",
|
|
273
|
+
"description": "Every finding is judged against the code as it stands, with a defensible category and no invented or dropped findings."
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
"name": "Real closure",
|
|
277
|
+
"description": "Each fix lands at the actual cited site and genuinely resolves what the finding describes - validation added, errors propagated, messages made truthful - with the smallest correct change."
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
"name": "Ledger discipline",
|
|
281
|
+
"description": "The same finding ids flow through triage, fix notes, and verification with consistent outcomes, and verification honestly separates what was run from what was only read."
|
|
282
|
+
}
|
|
283
|
+
]
|
|
284
|
+
},
|
|
285
|
+
"qualityFocus": [
|
|
286
|
+
"per-finding accountability",
|
|
287
|
+
"smallest correct change",
|
|
288
|
+
"honest verification"
|
|
289
|
+
]
|
|
290
|
+
}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "code-review",
|
|
3
|
+
"name": "Code Review",
|
|
4
|
+
"description": "Review one staged change set and deliver a gated report.\n\nThe change set is snapshotted ahead of time into the project artifacts drawer at `reviews/<reviewId>/`: `manifest.json` (kind, base/head, changed files, and — for branch reviews — the commit list) plus `changes.diff` (the unified diff). Three steps:\n\n1. **Scope** — read the snapshot, note the review kind and the themes to check\n2. **Report** — walk the diff and write `reviews/<reviewId>/report.md` (Summary, severity-ranked Findings table with file:line citations, Verdict)\n3. **Done** — stamp the verdict to task notes\n\nThe reviewer never modifies project source — the only deliverable is the report artifact. Reports must ground every finding in the actual diff; the completion gate checks structure, citations, and verdict consistency.",
|
|
5
|
+
"entryStepId": "scope",
|
|
6
|
+
"triggers": [
|
|
7
|
+
"review my uncommitted changes",
|
|
8
|
+
"review the working tree",
|
|
9
|
+
"review this branch against main",
|
|
10
|
+
"review the staged change set"
|
|
11
|
+
],
|
|
12
|
+
"command": "code-review",
|
|
13
|
+
"requirements": [
|
|
14
|
+
{
|
|
15
|
+
"kind": "github"
|
|
16
|
+
}
|
|
17
|
+
],
|
|
18
|
+
"paramSchema": {
|
|
19
|
+
"type": "object",
|
|
20
|
+
"properties": {
|
|
21
|
+
"reviewId": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"askUser": false,
|
|
24
|
+
"title": "Review id",
|
|
25
|
+
"description": "The staged snapshot folder under the project artifacts: reviews/<reviewId>/. Filled automatically when launched from the Review panel."
|
|
26
|
+
},
|
|
27
|
+
"focus": {
|
|
28
|
+
"type": "string",
|
|
29
|
+
"title": "Review focus",
|
|
30
|
+
"description": "Optional area to emphasize, e.g. security, performance, tests."
|
|
31
|
+
},
|
|
32
|
+
"intensity": {
|
|
33
|
+
"type": "string",
|
|
34
|
+
"title": "Intensity",
|
|
35
|
+
"enum": [
|
|
36
|
+
"low",
|
|
37
|
+
"medium",
|
|
38
|
+
"high"
|
|
39
|
+
],
|
|
40
|
+
"default": "medium",
|
|
41
|
+
"squisq": {
|
|
42
|
+
"control": "segmented"
|
|
43
|
+
},
|
|
44
|
+
"description": "How deep to go on the diff walk."
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"steps": [
|
|
49
|
+
{
|
|
50
|
+
"id": "scope",
|
|
51
|
+
"name": "Scope the change set",
|
|
52
|
+
"description": "Read the staged snapshot (manifest + diff) and write a scope note naming the review kind, the changed files, and the themes to check.",
|
|
53
|
+
"prompt": "**You are the reviewer for one snapshotted change set.** In this task you read code and write exactly ONE report artifact — never modify project source files.\n\n**Your first tool call this turn:** `read_artifact({ path: \"reviews/{{reviewId}}/manifest.json\" })`. If that path contains a literal `{{...}}` placeholder or is missing, call `list_artifacts({ path: \"reviews\" })` and use the newest review folder instead; if none exists, write a task note saying no review snapshot is staged and stop.\n\nThe manifest tells you the review kind (`commit` = unsaved work vs the last save; `pr` = this branch vs the default branch), the base/head, every changed file, and — for branch reviews — the commit list. Then read `reviews/{{reviewId}}/changes.diff` with `read_artifact` (use `head`/`lines` slices on a large diff; the manifest's `diffChars` tells you how big it is).\n\nWrite ONE scope note with `write_task_note`, starting with the line `## Scope`: the review kind, base and head from the manifest, each changed file with its change kind, and the 3-6 themes you will check — weighted by any focus and intensity named in your task description. Then call `advance_task_step`.",
|
|
54
|
+
"suggestedRole": "reviewer",
|
|
55
|
+
"gate": {
|
|
56
|
+
"at": "completion",
|
|
57
|
+
"scripts": [
|
|
58
|
+
{
|
|
59
|
+
"name": "checkTaskNoteContains",
|
|
60
|
+
"scope": "standard",
|
|
61
|
+
"inputs": {
|
|
62
|
+
"pattern": "##\\s*Scope"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
],
|
|
66
|
+
"onReject": "scope",
|
|
67
|
+
"maxAttempts": 3
|
|
68
|
+
},
|
|
69
|
+
"next": "report",
|
|
70
|
+
"toolPolicy": {
|
|
71
|
+
"disallowBuiltinToolsets": [
|
|
72
|
+
"ai-apps",
|
|
73
|
+
"archives",
|
|
74
|
+
"audio",
|
|
75
|
+
"browser-automation",
|
|
76
|
+
"code-execution",
|
|
77
|
+
"craftbooks",
|
|
78
|
+
"data-tables",
|
|
79
|
+
"entity-intel",
|
|
80
|
+
"image-intel",
|
|
81
|
+
"images",
|
|
82
|
+
"role-delegation",
|
|
83
|
+
"role-delegation-escalation",
|
|
84
|
+
"security-intel",
|
|
85
|
+
"team-management",
|
|
86
|
+
"videos",
|
|
87
|
+
"web",
|
|
88
|
+
"workspace-fs-write"
|
|
89
|
+
],
|
|
90
|
+
"outputMedium": "task-note"
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"id": "report",
|
|
95
|
+
"name": "Review and write the report",
|
|
96
|
+
"description": "Walk the diff hunk by hunk and write the complete review report artifact. Writing the report IS the advance — the completion gate checks structure, citations, and verdict consistency.",
|
|
97
|
+
"prompt": "Walk `reviews/{{reviewId}}/changes.diff` hunk by hunk and review for correctness, security, data-loss risk, error handling, tests, and clarity — weighted by the focus and intensity in your task description. Use `read_file` on workspace files when you need surrounding context. Only discuss files that appear in the change set. Cite every finding as `path:line` using paths exactly as they appear in the diff.\n\nThen write the complete report in ONE `write_artifact` call to `reviews/{{reviewId}}/report.md`, exactly this skeleton:\n\n```\n# Code Review — <one-line title>\nReview-ID: {{reviewId}}\n\n## Summary\n<2-6 sentences: what the change does, overall risk. If there are no findings, say \"No findings.\" here.>\n\n## Findings\n| # | Severity | File | Line | Finding | Recommendation |\n|---|----------|------|------|---------|----------------|\n<one row per finding; severities: critical, major, minor, nit. Keep the header row even when there are no findings.>\n\n## Verdict\nVerdict: approve\n<or> Verdict: request-changes\n<one sentence of rationale. Any critical or major finding means request-changes.>\n```\n\nDo not write any workspace file. If the gate rejects, fix exactly the gap it names and rewrite the whole artifact in one `write_artifact` call. When the report is written, call `advance_task_step` (writing the file may advance this step for you).",
|
|
98
|
+
"suggestedRole": "reviewer",
|
|
99
|
+
"advanceWhen": {
|
|
100
|
+
"file": "reviews/{{reviewId}}/report.md",
|
|
101
|
+
"minBytes": 400,
|
|
102
|
+
"artifact": true
|
|
103
|
+
},
|
|
104
|
+
"gate": {
|
|
105
|
+
"at": "completion",
|
|
106
|
+
"checks": [
|
|
107
|
+
{
|
|
108
|
+
"kind": "minBytes",
|
|
109
|
+
"file": "reviews/{{reviewId}}/report.md",
|
|
110
|
+
"bytes": 400,
|
|
111
|
+
"artifact": true
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"kind": "contains",
|
|
115
|
+
"file": "reviews/{{reviewId}}/report.md",
|
|
116
|
+
"pattern": "##\\s+Summary",
|
|
117
|
+
"label": "Summary section",
|
|
118
|
+
"artifact": true
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"kind": "contains",
|
|
122
|
+
"file": "reviews/{{reviewId}}/report.md",
|
|
123
|
+
"pattern": "##\\s+Findings",
|
|
124
|
+
"label": "Findings section",
|
|
125
|
+
"artifact": true
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"kind": "contains",
|
|
129
|
+
"file": "reviews/{{reviewId}}/report.md",
|
|
130
|
+
"pattern": "\\|\\s*Severity\\s*\\|",
|
|
131
|
+
"label": "findings table header",
|
|
132
|
+
"artifact": true
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"kind": "contains",
|
|
136
|
+
"file": "reviews/{{reviewId}}/report.md",
|
|
137
|
+
"pattern": "Verdict:\\s*(approve|request-changes)",
|
|
138
|
+
"label": "verdict line",
|
|
139
|
+
"artifact": true
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"kind": "tableShape",
|
|
143
|
+
"file": "reviews/{{reviewId}}/report.md",
|
|
144
|
+
"requiredColumns": [
|
|
145
|
+
"Severity",
|
|
146
|
+
"File",
|
|
147
|
+
"Finding"
|
|
148
|
+
],
|
|
149
|
+
"artifact": true
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"kind": "judge",
|
|
153
|
+
"file": "reviews/{{reviewId}}/report.md",
|
|
154
|
+
"rubric": "Findings are grounded in the actual diff hunks (no invented code or files), severities are proportionate to real impact, and the verdict follows from the findings table.",
|
|
155
|
+
"sourceFiles": [
|
|
156
|
+
"reviews/{{reviewId}}/changes.diff"
|
|
157
|
+
],
|
|
158
|
+
"advisory": true,
|
|
159
|
+
"artifact": true
|
|
160
|
+
}
|
|
161
|
+
],
|
|
162
|
+
"scripts": [
|
|
163
|
+
{
|
|
164
|
+
"name": "checkReviewReport",
|
|
165
|
+
"scope": "standard"
|
|
166
|
+
}
|
|
167
|
+
],
|
|
168
|
+
"onReject": "report",
|
|
169
|
+
"maxAttempts": 4
|
|
170
|
+
},
|
|
171
|
+
"next": "done",
|
|
172
|
+
"toolPolicy": {
|
|
173
|
+
"disallowBuiltinToolsets": [
|
|
174
|
+
"ai-apps",
|
|
175
|
+
"archives",
|
|
176
|
+
"audio",
|
|
177
|
+
"browser-automation",
|
|
178
|
+
"code-execution",
|
|
179
|
+
"craftbooks",
|
|
180
|
+
"data-tables",
|
|
181
|
+
"entity-intel",
|
|
182
|
+
"git",
|
|
183
|
+
"image-intel",
|
|
184
|
+
"images",
|
|
185
|
+
"role-delegation",
|
|
186
|
+
"role-delegation-escalation",
|
|
187
|
+
"team-management",
|
|
188
|
+
"videos",
|
|
189
|
+
"web",
|
|
190
|
+
"workspace-fs-write"
|
|
191
|
+
],
|
|
192
|
+
"outputMedium": "artifact"
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
"id": "done",
|
|
197
|
+
"name": "Deliver the verdict",
|
|
198
|
+
"description": "The report passed its gate. Stamp the verdict to task notes and point the user at the report.",
|
|
199
|
+
"prompt": "The report is written and passed its gate. Write one final task note with `write_task_note`: `Verdict: <approve|request-changes> — N findings (a critical, b major, c minor, d nit)` plus a one-paragraph summary. Tell the user the full report is in the project artifacts at `reviews/{{reviewId}}/report.md` (the Review panel renders it). Then call `advance_task_step` to complete the task.",
|
|
200
|
+
"suggestedRole": "reviewer",
|
|
201
|
+
"terminal": true,
|
|
202
|
+
"toolPolicy": {
|
|
203
|
+
"disallowBuiltinToolsets": [
|
|
204
|
+
"ai-apps",
|
|
205
|
+
"archives",
|
|
206
|
+
"artifacts",
|
|
207
|
+
"audio",
|
|
208
|
+
"browser-automation",
|
|
209
|
+
"code-execution",
|
|
210
|
+
"craftbooks",
|
|
211
|
+
"data-tables",
|
|
212
|
+
"entity-intel",
|
|
213
|
+
"git",
|
|
214
|
+
"image-intel",
|
|
215
|
+
"images",
|
|
216
|
+
"role-delegation",
|
|
217
|
+
"role-delegation-escalation",
|
|
218
|
+
"security-intel",
|
|
219
|
+
"team-management",
|
|
220
|
+
"videos",
|
|
221
|
+
"web",
|
|
222
|
+
"workspace-fs-write"
|
|
223
|
+
],
|
|
224
|
+
"outputMedium": "task-note"
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
],
|
|
228
|
+
"version": "1.0.2",
|
|
229
|
+
"releasedAt": "2026-09-24T20:00:00Z"
|
|
230
|
+
}
|