@fro.bot/systematic 3.18.3 → 3.18.4
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/HARNESSES.md +8 -4
- package/dist/ce-review-validator.d.ts +43 -2
- package/dist/cli.js +10 -16
- package/dist/lib/review-artifact-schema.d.ts +18 -1
- package/dist/lib/review-pipeline-contract.d.ts +1446 -0
- package/dist/lib/review-pipeline.d.ts +812 -0
- package/dist/lib/review-return-validator.d.ts +19 -0
- package/package.json +1 -1
- package/skills/ce-review/SKILL.md +54 -83
- package/skills/ce-review/references/pipeline-invocation.md +263 -0
- package/skills/ce-review/references/review-output-template.md +2 -1
- package/skills/ce-review/references/review-pipeline-schema.json +391 -0
- package/skills/ce-review/references/subagent-template.md +1 -1
- package/skills/ce-review/references/synthesis-artifact-contract.md +57 -68
- package/skills/ce-review/scripts/validate-review.mjs +3277 -58
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"title": "Code Review Pipeline Envelopes",
|
|
4
|
+
"description": "Structured output schemas for the model-authored envelopes of the ce:review synthesis pipeline (adjudication decisions, validator lifecycle results, and plan assessment). Helper-produced internal phase state (screen output, prepared state, merge output, finalize output) is intentionally excluded: it is TypeScript/Zod-only and never authored by a model.",
|
|
5
|
+
"definitions": {
|
|
6
|
+
"adjudicationEnvelope": {
|
|
7
|
+
"type": "object",
|
|
8
|
+
"properties": {
|
|
9
|
+
"decisions": {
|
|
10
|
+
"maxItems": 32,
|
|
11
|
+
"type": "array",
|
|
12
|
+
"items": {
|
|
13
|
+
"oneOf": [
|
|
14
|
+
{
|
|
15
|
+
"type": "object",
|
|
16
|
+
"properties": {
|
|
17
|
+
"decision_id": {
|
|
18
|
+
"type": "string",
|
|
19
|
+
"minLength": 1,
|
|
20
|
+
"maxLength": 128,
|
|
21
|
+
"pattern": "\\S"
|
|
22
|
+
},
|
|
23
|
+
"disposition": {
|
|
24
|
+
"type": "string",
|
|
25
|
+
"const": "merged"
|
|
26
|
+
},
|
|
27
|
+
"input_finding_ids": {
|
|
28
|
+
"minItems": 2,
|
|
29
|
+
"maxItems": 32,
|
|
30
|
+
"type": "array",
|
|
31
|
+
"items": {
|
|
32
|
+
"type": "string",
|
|
33
|
+
"minLength": 1,
|
|
34
|
+
"maxLength": 128,
|
|
35
|
+
"pattern": "\\S"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"title": {
|
|
39
|
+
"type": "string",
|
|
40
|
+
"minLength": 1,
|
|
41
|
+
"maxLength": 256,
|
|
42
|
+
"pattern": "\\S",
|
|
43
|
+
"description": "Short, specific issue title. 10 words or fewer."
|
|
44
|
+
},
|
|
45
|
+
"why_it_matters": {
|
|
46
|
+
"type": "string",
|
|
47
|
+
"minLength": 1,
|
|
48
|
+
"maxLength": 2048,
|
|
49
|
+
"pattern": "\\S",
|
|
50
|
+
"description": "Non-empty impact and failure mode -- not 'what is wrong' but 'what breaks'"
|
|
51
|
+
},
|
|
52
|
+
"evidence": {
|
|
53
|
+
"minItems": 1,
|
|
54
|
+
"maxItems": 5,
|
|
55
|
+
"type": "array",
|
|
56
|
+
"items": {
|
|
57
|
+
"anyOf": [
|
|
58
|
+
{
|
|
59
|
+
"type": "string",
|
|
60
|
+
"minLength": 1,
|
|
61
|
+
"maxLength": 500,
|
|
62
|
+
"allOf": [
|
|
63
|
+
{
|
|
64
|
+
"type": "string",
|
|
65
|
+
"pattern": "\\S"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"type": "string",
|
|
69
|
+
"pattern": "^(?!\\/)(?![A-Za-z]:[\\\\/])(?!\\\\).+"
|
|
70
|
+
}
|
|
71
|
+
],
|
|
72
|
+
"description": "Bounded code-grounded evidence; absolute POSIX, drive-letter, and UNC paths are rejected"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"type": "object",
|
|
76
|
+
"properties": {
|
|
77
|
+
"overflow": {
|
|
78
|
+
"type": "boolean",
|
|
79
|
+
"const": true,
|
|
80
|
+
"description": "Explicit marker that the complete evidence did not fit in one bounded entry"
|
|
81
|
+
},
|
|
82
|
+
"excerpt": {
|
|
83
|
+
"type": "string",
|
|
84
|
+
"minLength": 1,
|
|
85
|
+
"maxLength": 500,
|
|
86
|
+
"allOf": [
|
|
87
|
+
{
|
|
88
|
+
"type": "string",
|
|
89
|
+
"pattern": "\\S"
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"type": "string",
|
|
93
|
+
"pattern": "^(?!\\/)(?![A-Za-z]:[\\\\/])(?!\\\\).+"
|
|
94
|
+
}
|
|
95
|
+
],
|
|
96
|
+
"description": "Bounded excerpt retained when evidence must be shortened"
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
"required": ["overflow", "excerpt"],
|
|
100
|
+
"additionalProperties": false
|
|
101
|
+
}
|
|
102
|
+
]
|
|
103
|
+
},
|
|
104
|
+
"description": "Code-grounded evidence. At least 1 and at most 5 bounded entries; split evidence across entries or use an explicit overflow marker rather than silently truncating it."
|
|
105
|
+
},
|
|
106
|
+
"suggested_fix": {
|
|
107
|
+
"description": "Concrete minimal fix. Omit or null if no good fix is obvious -- a bad suggestion is worse than none.",
|
|
108
|
+
"anyOf": [
|
|
109
|
+
{
|
|
110
|
+
"type": "string",
|
|
111
|
+
"maxLength": 2048
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"type": "null"
|
|
115
|
+
}
|
|
116
|
+
]
|
|
117
|
+
},
|
|
118
|
+
"line": {
|
|
119
|
+
"type": "integer",
|
|
120
|
+
"exclusiveMinimum": 0,
|
|
121
|
+
"maximum": 9007199254740991,
|
|
122
|
+
"description": "Primary line number of the issue"
|
|
123
|
+
},
|
|
124
|
+
"disagreement_facts": {
|
|
125
|
+
"maxItems": 32,
|
|
126
|
+
"type": "array",
|
|
127
|
+
"items": {
|
|
128
|
+
"type": "string",
|
|
129
|
+
"minLength": 1,
|
|
130
|
+
"maxLength": 2048,
|
|
131
|
+
"pattern": "\\S"
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
"eligible_agreement_credit": {
|
|
135
|
+
"maxItems": 64,
|
|
136
|
+
"type": "array",
|
|
137
|
+
"items": {
|
|
138
|
+
"type": "string",
|
|
139
|
+
"minLength": 1,
|
|
140
|
+
"maxLength": 64,
|
|
141
|
+
"pattern": "\\S",
|
|
142
|
+
"description": "Persona name that produced this output (e.g., 'correctness', 'security')"
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
"proposed_route": {
|
|
146
|
+
"type": "object",
|
|
147
|
+
"properties": {
|
|
148
|
+
"autofix_class": {
|
|
149
|
+
"type": "string",
|
|
150
|
+
"enum": [
|
|
151
|
+
"safe_auto",
|
|
152
|
+
"gated_auto",
|
|
153
|
+
"manual",
|
|
154
|
+
"advisory"
|
|
155
|
+
],
|
|
156
|
+
"description": "Reviewer's conservative recommendation for how this issue should be handled after synthesis"
|
|
157
|
+
},
|
|
158
|
+
"owner": {
|
|
159
|
+
"type": "string",
|
|
160
|
+
"enum": [
|
|
161
|
+
"review-fixer",
|
|
162
|
+
"downstream-resolver",
|
|
163
|
+
"human",
|
|
164
|
+
"release"
|
|
165
|
+
],
|
|
166
|
+
"description": "Who should own the next action for this finding after synthesis"
|
|
167
|
+
},
|
|
168
|
+
"requires_verification": {
|
|
169
|
+
"type": "boolean",
|
|
170
|
+
"description": "Whether any fix for this finding must be re-verified with targeted tests or a follow-up review pass"
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
"required": [
|
|
174
|
+
"autofix_class",
|
|
175
|
+
"owner",
|
|
176
|
+
"requires_verification"
|
|
177
|
+
],
|
|
178
|
+
"additionalProperties": false
|
|
179
|
+
},
|
|
180
|
+
"route_narrowing_reason": {
|
|
181
|
+
"type": "string",
|
|
182
|
+
"minLength": 1,
|
|
183
|
+
"maxLength": 2048,
|
|
184
|
+
"pattern": "\\S"
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
"required": [
|
|
188
|
+
"decision_id",
|
|
189
|
+
"disposition",
|
|
190
|
+
"input_finding_ids",
|
|
191
|
+
"title",
|
|
192
|
+
"why_it_matters",
|
|
193
|
+
"evidence",
|
|
194
|
+
"line"
|
|
195
|
+
],
|
|
196
|
+
"additionalProperties": false
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
"type": "object",
|
|
200
|
+
"properties": {
|
|
201
|
+
"decision_id": {
|
|
202
|
+
"type": "string",
|
|
203
|
+
"minLength": 1,
|
|
204
|
+
"maxLength": 128,
|
|
205
|
+
"pattern": "\\S"
|
|
206
|
+
},
|
|
207
|
+
"disposition": {
|
|
208
|
+
"type": "string",
|
|
209
|
+
"const": "declined"
|
|
210
|
+
},
|
|
211
|
+
"input_finding_id": {
|
|
212
|
+
"type": "string",
|
|
213
|
+
"minLength": 1,
|
|
214
|
+
"maxLength": 128,
|
|
215
|
+
"pattern": "\\S"
|
|
216
|
+
},
|
|
217
|
+
"declined_reason": {
|
|
218
|
+
"type": "string",
|
|
219
|
+
"minLength": 1,
|
|
220
|
+
"maxLength": 2048,
|
|
221
|
+
"pattern": "\\S"
|
|
222
|
+
},
|
|
223
|
+
"disagreement_facts": {
|
|
224
|
+
"maxItems": 32,
|
|
225
|
+
"type": "array",
|
|
226
|
+
"items": {
|
|
227
|
+
"type": "string",
|
|
228
|
+
"minLength": 1,
|
|
229
|
+
"maxLength": 2048,
|
|
230
|
+
"pattern": "\\S"
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
"proposed_route": {
|
|
234
|
+
"type": "object",
|
|
235
|
+
"properties": {
|
|
236
|
+
"autofix_class": {
|
|
237
|
+
"type": "string",
|
|
238
|
+
"enum": [
|
|
239
|
+
"safe_auto",
|
|
240
|
+
"gated_auto",
|
|
241
|
+
"manual",
|
|
242
|
+
"advisory"
|
|
243
|
+
],
|
|
244
|
+
"description": "Reviewer's conservative recommendation for how this issue should be handled after synthesis"
|
|
245
|
+
},
|
|
246
|
+
"owner": {
|
|
247
|
+
"type": "string",
|
|
248
|
+
"enum": [
|
|
249
|
+
"review-fixer",
|
|
250
|
+
"downstream-resolver",
|
|
251
|
+
"human",
|
|
252
|
+
"release"
|
|
253
|
+
],
|
|
254
|
+
"description": "Who should own the next action for this finding after synthesis"
|
|
255
|
+
},
|
|
256
|
+
"requires_verification": {
|
|
257
|
+
"type": "boolean",
|
|
258
|
+
"description": "Whether any fix for this finding must be re-verified with targeted tests or a follow-up review pass"
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
"required": [
|
|
262
|
+
"autofix_class",
|
|
263
|
+
"owner",
|
|
264
|
+
"requires_verification"
|
|
265
|
+
],
|
|
266
|
+
"additionalProperties": false
|
|
267
|
+
},
|
|
268
|
+
"route_narrowing_reason": {
|
|
269
|
+
"type": "string",
|
|
270
|
+
"minLength": 1,
|
|
271
|
+
"maxLength": 2048,
|
|
272
|
+
"pattern": "\\S"
|
|
273
|
+
}
|
|
274
|
+
},
|
|
275
|
+
"required": [
|
|
276
|
+
"decision_id",
|
|
277
|
+
"disposition",
|
|
278
|
+
"input_finding_id",
|
|
279
|
+
"declined_reason"
|
|
280
|
+
],
|
|
281
|
+
"additionalProperties": false
|
|
282
|
+
}
|
|
283
|
+
]
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
},
|
|
287
|
+
"required": ["decisions"],
|
|
288
|
+
"additionalProperties": false
|
|
289
|
+
},
|
|
290
|
+
"validatorLifecycleResult": {
|
|
291
|
+
"oneOf": [
|
|
292
|
+
{
|
|
293
|
+
"type": "object",
|
|
294
|
+
"properties": {
|
|
295
|
+
"outcome": {
|
|
296
|
+
"type": "string",
|
|
297
|
+
"const": "true"
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
"required": ["outcome"],
|
|
301
|
+
"additionalProperties": false
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
"type": "object",
|
|
305
|
+
"properties": {
|
|
306
|
+
"outcome": {
|
|
307
|
+
"type": "string",
|
|
308
|
+
"const": "false"
|
|
309
|
+
},
|
|
310
|
+
"reason": {
|
|
311
|
+
"type": "string",
|
|
312
|
+
"minLength": 1,
|
|
313
|
+
"maxLength": 2048,
|
|
314
|
+
"pattern": "\\S"
|
|
315
|
+
}
|
|
316
|
+
},
|
|
317
|
+
"required": ["outcome", "reason"],
|
|
318
|
+
"additionalProperties": false
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
"type": "object",
|
|
322
|
+
"properties": {
|
|
323
|
+
"outcome": {
|
|
324
|
+
"type": "string",
|
|
325
|
+
"const": "failed"
|
|
326
|
+
},
|
|
327
|
+
"reason": {
|
|
328
|
+
"type": "string",
|
|
329
|
+
"minLength": 1,
|
|
330
|
+
"maxLength": 2048,
|
|
331
|
+
"pattern": "\\S"
|
|
332
|
+
}
|
|
333
|
+
},
|
|
334
|
+
"required": ["outcome", "reason"],
|
|
335
|
+
"additionalProperties": false
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
"type": "object",
|
|
339
|
+
"properties": {
|
|
340
|
+
"outcome": {
|
|
341
|
+
"type": "string",
|
|
342
|
+
"const": "unavailable"
|
|
343
|
+
},
|
|
344
|
+
"reason": {
|
|
345
|
+
"type": "string",
|
|
346
|
+
"minLength": 1,
|
|
347
|
+
"maxLength": 2048,
|
|
348
|
+
"pattern": "\\S"
|
|
349
|
+
}
|
|
350
|
+
},
|
|
351
|
+
"required": ["outcome", "reason"],
|
|
352
|
+
"additionalProperties": false
|
|
353
|
+
}
|
|
354
|
+
]
|
|
355
|
+
},
|
|
356
|
+
"planAssessmentEnvelope": {
|
|
357
|
+
"type": "object",
|
|
358
|
+
"properties": {
|
|
359
|
+
"verdict": {
|
|
360
|
+
"type": "string",
|
|
361
|
+
"minLength": 1,
|
|
362
|
+
"maxLength": 256,
|
|
363
|
+
"pattern": "\\S"
|
|
364
|
+
},
|
|
365
|
+
"results": {
|
|
366
|
+
"maxItems": 32,
|
|
367
|
+
"type": "array",
|
|
368
|
+
"items": {
|
|
369
|
+
"type": "object",
|
|
370
|
+
"properties": {
|
|
371
|
+
"kind": {
|
|
372
|
+
"type": "string",
|
|
373
|
+
"enum": ["explicit_unmet_requirement", "inferred_gap"]
|
|
374
|
+
},
|
|
375
|
+
"description": {
|
|
376
|
+
"type": "string",
|
|
377
|
+
"minLength": 1,
|
|
378
|
+
"maxLength": 2048,
|
|
379
|
+
"pattern": "\\S"
|
|
380
|
+
}
|
|
381
|
+
},
|
|
382
|
+
"required": ["kind", "description"],
|
|
383
|
+
"additionalProperties": false
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
},
|
|
387
|
+
"required": ["verdict", "results"],
|
|
388
|
+
"additionalProperties": false
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
@@ -52,7 +52,7 @@ Rules:
|
|
|
52
52
|
- You are a leaf reviewer inside an already-running systematic review workflow. Do not invoke systematic skills or agents unless this template explicitly instructs you to. Perform your analysis directly and return findings in the required output format only.
|
|
53
53
|
- Every returned finding MUST include at least one evidence item grounded in the actual code. Detail fields are part of the returned payload, not a second output.
|
|
54
54
|
- Evidence is bounded to at most 5 entries of at most 500 characters each. Split a longer trail across entries when it fits; otherwise retain a bounded `excerpt` with `{ "overflow": true, "excerpt": "..." }`. Never silently truncate evidence.
|
|
55
|
-
- Finding paths MUST be repository-relative. The schema rejects absolute paths
|
|
55
|
+
- Finding paths MUST be repository-relative. The schema rejects absolute paths. Do not reproduce credential literals (API keys, tokens, passwords) in a finding's title, evidence, or fix; a source-level environment-variable reference (`process.env.API_KEY`, `${SECRET_TOKEN}`, and similar) is valid evidence and should be cited as such.
|
|
56
56
|
- The parent adds `harness`, `dispatch_outcome`, and `disposition` after validating the return. Do not invent those parent-owned fields. The parent uses only the canonical values defined by the schema (`findings`, `empty`, `malformed`, `never_returned`, `validation_unavailable` and `surviving`, `merged`, `suppressed`, `filtered`, `rejected`).
|
|
57
57
|
- Set pre_existing to true ONLY for issues in unchanged code that are unrelated to this diff. If the diff makes the issue newly relevant, it is NOT pre-existing.
|
|
58
58
|
- You are operationally read-only. You may use non-mutating inspection commands, including read-oriented `git` / `gh` commands, to gather evidence. Do not write files, edit project files, change branches, commit, push, create PRs, or otherwise mutate the checkout or repository state.
|
|
@@ -28,11 +28,11 @@ reason. An unfinished `in_progress` artifact is evidence of an abnormal run,
|
|
|
28
28
|
not evidence of a clean run. Never infer a clean run from an absent artifact.
|
|
29
29
|
|
|
30
30
|
The artifact is parent-owned. Per-agent full-detail JSON files are written
|
|
31
|
-
only for findings admitted after the parent completes schema
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
only for findings admitted after the parent completes schema validation. A
|
|
32
|
+
finding rejected by schema validation is not persisted; other findings from
|
|
33
|
+
the same return may proceed. A payload rejected at top level, or a rejected,
|
|
34
|
+
never-returned, or validation-unavailable persona, does not produce a
|
|
35
|
+
per-agent file. If a later confidence or validation stage
|
|
36
36
|
changes an input disposition, the parent updates the record and synthesis
|
|
37
37
|
ledger before finalizing the artifact.
|
|
38
38
|
|
|
@@ -131,7 +131,7 @@ The artifact must preserve these distinctions:
|
|
|
131
131
|
When a rejected finding's severity is absent, malformed, or not a valid
|
|
132
132
|
severity value, record it as `unknown`. Severity is metadata; recording it
|
|
133
133
|
never includes the offending value. Do not enumerate rejected findings or
|
|
134
|
-
assign them input IDs. A finding-level
|
|
134
|
+
assign them input IDs. A finding-level schema rejection uses the same
|
|
135
135
|
summary entry while admitted findings from that return continue normally.
|
|
136
136
|
New writers must emit a rejected-summary row only for `findings` or
|
|
137
137
|
`malformed`. The schema_version 1 validator deliberately continues to accept a
|
|
@@ -183,8 +183,8 @@ is finalized; consumers can therefore tell whether the artifact describes the
|
|
|
183
183
|
current checkout.
|
|
184
184
|
|
|
185
185
|
Validation and persistence remain parent-side: no per-agent record or finding
|
|
186
|
-
is written or merged until that finding passes schema
|
|
187
|
-
|
|
186
|
+
is written or merged until that finding passes schema validation. Rejected
|
|
187
|
+
findings are recorded through the single rejected-payload
|
|
188
188
|
ledger summary; admitted findings from the same return remain eligible for
|
|
189
189
|
synthesis. Rejected or malformed persona returns do not fail the whole review;
|
|
190
190
|
the review degrades while conforming returns continue through synthesis. Only
|
|
@@ -193,37 +193,30 @@ required run artifact is run-fatal.
|
|
|
193
193
|
|
|
194
194
|
## Raw-return admission and validation availability
|
|
195
195
|
|
|
196
|
-
Before a persona return is parsed into fields,
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
<the persona's returned JSON payload, copied verbatim>
|
|
205
|
-
REVIEW_RETURN_A1B2C3D4
|
|
206
|
-
```
|
|
196
|
+
Before a persona return is parsed into fields, assessed for evidence,
|
|
197
|
+
synthesized, or persisted, the parent admits it with the packaged structural
|
|
198
|
+
validator's `screen` phase, which structurally admits the return and binds it
|
|
199
|
+
to the dispatched persona in one call, replacing the former separate
|
|
200
|
+
raw-return-admission and dispatch-identity-binding steps. The full envelope,
|
|
201
|
+
the invocation block, and the never-bypass rule are canonically defined in
|
|
202
|
+
[pipeline invocation: screen](./pipeline-invocation.md#screen); this section
|
|
203
|
+
states the resulting contract.
|
|
207
204
|
|
|
208
205
|
Before each invocation, choose a fresh delimiter for that exact raw payload from
|
|
209
206
|
a safe token alphabet (`A-Z`, `0-9`, `_`), verify the delimiter is absent as a
|
|
210
207
|
complete line in that exact payload, and never reuse a fixed delimiter. The
|
|
211
|
-
|
|
212
|
-
with a single-quoted heredoc opener (`<<'DELIM'`) and close it with a line
|
|
213
|
-
containing exactly that delimiter. The payload travels on stdin, never in argv;
|
|
214
|
-
never use unquoted interpolation or command substitution, and never write the
|
|
215
|
-
payload to a temp file.
|
|
208
|
+
payload travels on stdin, never in argv, command substitution, or a temp file.
|
|
216
209
|
|
|
217
|
-
The parent maps the result to `dispatch_outcome`, keeping lifecycle,
|
|
218
|
-
validity,
|
|
210
|
+
The parent maps the result to `dispatch_outcome`, keeping lifecycle,
|
|
211
|
+
structural validity, and evidence assessment separate:
|
|
219
212
|
|
|
220
213
|
- **exit 0** — structurally admitted. Parse the already structurally validated
|
|
221
|
-
JSON without logging the raw text
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
asserts that a finding's claims or cited evidence are true.
|
|
214
|
+
JSON without logging the raw text. Zero findings is `empty`; one or more
|
|
215
|
+
findings is `findings`. Admission is structural only: it never asserts that
|
|
216
|
+
a finding's claims or cited evidence are true.
|
|
225
217
|
- **exit 1** — `malformed`. Record bounded validator diagnostics only; do not
|
|
226
|
-
parse
|
|
218
|
+
parse or persist payload fields or values. This covers malformed JSON, a
|
|
219
|
+
schema violation, and a dispatch identity mismatch alike.
|
|
227
220
|
- **exit 2**, a missing or unreadable helper, or a launch failure — validation
|
|
228
221
|
unavailable. Withhold the return and report the exact unavailability and what
|
|
229
222
|
was withheld. Update that selected persona's preinitialized dispatch entry
|
|
@@ -236,14 +229,15 @@ validity, environment screening, and evidence assessment separate:
|
|
|
236
229
|
task-lifecycle fact for a task that did not return. Validation unavailable is
|
|
237
230
|
not malformed and is not never_returned.
|
|
238
231
|
|
|
239
|
-
**Dispatch identity binding
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
232
|
+
**Dispatch identity binding** is folded into `screen`: it confirms the
|
|
233
|
+
returned `reviewer` field matches the dispatched persona before it returns
|
|
234
|
+
`exit 0`. A return whose `reviewer` does not match the dispatched persona is
|
|
235
|
+
an identity mismatch: `screen` rejects the whole return as `dispatch_outcome:
|
|
236
|
+
"malformed"`, and the parent records only a bounded rejection reason naming
|
|
237
|
+
the expected persona, sets `run_status` to `degraded`, and does not admit,
|
|
238
|
+
persist, or synthesize its payload. The stdin-only, flag-scoped validator
|
|
239
|
+
cannot see dispatch context beyond `--reviewer`/`--harness`, so this
|
|
240
|
+
comparison is `screen`'s own responsibility, not a separate parent step.
|
|
247
241
|
|
|
248
242
|
`validation_unavailable` is an additive enum value: `schema_version` stays `1`,
|
|
249
243
|
existing v1 artifacts remain valid, and no new field or migration is introduced.
|
|
@@ -256,34 +250,29 @@ that is a different object and phase, and these fields are never repurposed for
|
|
|
256
250
|
raw-dispatch availability. These admission states are surfaced in the report's
|
|
257
251
|
Coverage, which reports the exact unavailability and what was withheld.
|
|
258
252
|
|
|
259
|
-
##
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
`
|
|
274
|
-
Entries containing an underscore are matched against the variable name as
|
|
275
|
-
written; the underscore is deliberate and prevents matching benign names that
|
|
276
|
-
merely contain the bare word. Values that satisfy neither condition are not
|
|
277
|
-
matched. A match is an exact or embedded match.
|
|
278
|
-
|
|
279
|
-
If the offending string is inside one finding, drop that finding and record it
|
|
280
|
-
through the rejected-payload summary entry; the remaining findings continue
|
|
281
|
-
through validation and synthesis. If the offending string is outside any
|
|
282
|
-
finding, reject the whole payload. Every rejection uses only the persona name,
|
|
283
|
-
JSON path, and a fixed reason (`schema validation`, `environment-value
|
|
284
|
-
detection`, or `malformed JSON`):
|
|
253
|
+
## Sensitive-evidence handling
|
|
254
|
+
|
|
255
|
+
Review artifacts may contain sensitive source-derived information. They are
|
|
256
|
+
not certified secret-free.
|
|
257
|
+
|
|
258
|
+
Reviewers must describe credential and secret-handling defects without
|
|
259
|
+
reproducing credential values. Cite repository-relative locations and
|
|
260
|
+
behavioral evidence instead of the value itself. An environment-variable
|
|
261
|
+
reference appearing in reviewed source (`process.env.API_KEY`,
|
|
262
|
+
`${SECRET_TOKEN}`, and similar) is valid evidence and is never rejected for
|
|
263
|
+
being a reference.
|
|
264
|
+
|
|
265
|
+
The parent must not deliberately log, cache, or write a raw return to a
|
|
266
|
+
temporary file. Diagnostics stay allowlisted to persona name, JSON path, and a
|
|
267
|
+
fixed reason (`schema validation` or `malformed JSON`):
|
|
285
268
|
`Rejected persona <name> return: field <JSON path> failed <reason>.` Never
|
|
286
|
-
|
|
269
|
+
exception text, raw validation-library issue objects, candidate values, or
|
|
270
|
+
variable names.
|
|
271
|
+
|
|
272
|
+
These are handling instructions that reduce accidental disclosure, not
|
|
273
|
+
technical containment. Real containment would require restricting reviewer
|
|
274
|
+
inputs and capabilities at the harness boundary, which this portable Node
|
|
275
|
+
helper does not provide.
|
|
287
276
|
|
|
288
277
|
## Artifact validation
|
|
289
278
|
|
|
@@ -387,8 +376,8 @@ it is blocking unless another persona covered the lost surface with validated
|
|
|
387
376
|
evidence. For this rule, a validated finding from another persona covers a
|
|
388
377
|
lost risk-critical surface if and only if the finding's `file` appears in the
|
|
389
378
|
lost persona's recorded `selection_surface`; validated evidence means at least
|
|
390
|
-
one finding from that other persona's return passed complete schema
|
|
391
|
-
|
|
379
|
+
one finding from that other persona's return passed complete schema
|
|
380
|
+
validation. A coverage note alone cannot satisfy this rule;
|
|
392
381
|
the verdict must reflect the missing risk-critical evidence.
|
|
393
382
|
|
|
394
383
|
Finding-level rejection is keyed by the severities in
|