@fro.bot/systematic 3.12.4 → 3.13.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.
@@ -0,0 +1,517 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "type": "object",
4
+ "properties": {
5
+ "schema_version": {
6
+ "type": "number",
7
+ "const": 1
8
+ },
9
+ "run_id": {
10
+ "type": "string",
11
+ "minLength": 1,
12
+ "maxLength": 64,
13
+ "pattern": "\\S"
14
+ },
15
+ "mode": {
16
+ "type": "string",
17
+ "enum": ["interactive", "autofix", "headless"]
18
+ },
19
+ "harness": {
20
+ "type": "string",
21
+ "enum": ["opencode", "pi", "claude-code"]
22
+ },
23
+ "run_status": {
24
+ "type": "string",
25
+ "enum": ["in_progress", "completed", "degraded", "abnormal"]
26
+ },
27
+ "verdict": {
28
+ "type": "string",
29
+ "minLength": 1,
30
+ "maxLength": 256,
31
+ "pattern": "\\S"
32
+ },
33
+ "dispatches": {
34
+ "maxItems": 64,
35
+ "type": "array",
36
+ "items": {
37
+ "type": "object",
38
+ "properties": {
39
+ "persona": {
40
+ "type": "string",
41
+ "minLength": 1,
42
+ "maxLength": 64,
43
+ "pattern": "\\S"
44
+ },
45
+ "dispatch_outcome": {
46
+ "type": "string",
47
+ "enum": ["findings", "empty", "malformed", "never_returned"]
48
+ },
49
+ "input_finding_count": {
50
+ "type": "integer",
51
+ "minimum": 0,
52
+ "maximum": 32
53
+ },
54
+ "rejection_reason": {
55
+ "type": "string",
56
+ "minLength": 1,
57
+ "maxLength": 2048,
58
+ "pattern": "\\S"
59
+ }
60
+ },
61
+ "required": ["persona", "dispatch_outcome", "input_finding_count"],
62
+ "additionalProperties": false
63
+ }
64
+ },
65
+ "input_findings": {
66
+ "maxItems": 2048,
67
+ "type": "array",
68
+ "items": {
69
+ "oneOf": [
70
+ {
71
+ "type": "object",
72
+ "properties": {
73
+ "record_type": {
74
+ "type": "string",
75
+ "const": "admitted"
76
+ },
77
+ "input_id": {
78
+ "type": "string",
79
+ "minLength": 1,
80
+ "maxLength": 128,
81
+ "pattern": "\\S"
82
+ },
83
+ "reviewer": {
84
+ "type": "string",
85
+ "minLength": 1,
86
+ "maxLength": 64,
87
+ "pattern": "\\S"
88
+ },
89
+ "confidence": {
90
+ "type": "number",
91
+ "minimum": 0,
92
+ "maximum": 1
93
+ },
94
+ "disposition": {
95
+ "type": "string",
96
+ "enum": ["surviving", "merged", "suppressed", "filtered"]
97
+ },
98
+ "reason": {
99
+ "type": "string",
100
+ "minLength": 1,
101
+ "maxLength": 2048,
102
+ "pattern": "\\S"
103
+ }
104
+ },
105
+ "required": [
106
+ "record_type",
107
+ "input_id",
108
+ "reviewer",
109
+ "confidence",
110
+ "disposition",
111
+ "reason"
112
+ ],
113
+ "additionalProperties": false
114
+ },
115
+ {
116
+ "type": "object",
117
+ "properties": {
118
+ "record_type": {
119
+ "type": "string",
120
+ "const": "rejected_summary"
121
+ },
122
+ "reviewer": {
123
+ "type": "string",
124
+ "minLength": 1,
125
+ "maxLength": 64,
126
+ "pattern": "\\S"
127
+ },
128
+ "dispatch_outcome": {
129
+ "type": "string",
130
+ "enum": ["findings", "empty", "malformed", "never_returned"]
131
+ },
132
+ "rejected_finding_count": {
133
+ "type": "integer",
134
+ "exclusiveMinimum": 0,
135
+ "maximum": 32
136
+ },
137
+ "rejected_severities": {
138
+ "maxItems": 32,
139
+ "type": "array",
140
+ "items": {
141
+ "type": "string",
142
+ "enum": ["P0", "P1", "P2", "P3", "unknown"]
143
+ }
144
+ },
145
+ "disposition": {
146
+ "type": "string",
147
+ "enum": ["rejected"]
148
+ },
149
+ "reason": {
150
+ "type": "string",
151
+ "minLength": 1,
152
+ "maxLength": 2048,
153
+ "pattern": "\\S"
154
+ }
155
+ },
156
+ "required": [
157
+ "record_type",
158
+ "reviewer",
159
+ "dispatch_outcome",
160
+ "rejected_finding_count",
161
+ "rejected_severities",
162
+ "disposition",
163
+ "reason"
164
+ ],
165
+ "additionalProperties": false
166
+ }
167
+ ]
168
+ }
169
+ },
170
+ "findings": {
171
+ "maxItems": 32,
172
+ "type": "array",
173
+ "items": {
174
+ "type": "object",
175
+ "properties": {
176
+ "title": {
177
+ "type": "string",
178
+ "minLength": 1,
179
+ "maxLength": 256,
180
+ "pattern": "\\S"
181
+ },
182
+ "severity": {
183
+ "type": "string",
184
+ "enum": ["P0", "P1", "P2", "P3"]
185
+ },
186
+ "file": {
187
+ "type": "string",
188
+ "minLength": 1,
189
+ "maxLength": 256,
190
+ "allOf": [
191
+ {
192
+ "type": "string",
193
+ "pattern": "\\S"
194
+ },
195
+ {
196
+ "type": "string",
197
+ "pattern": "^(?!\\/)(?![A-Za-z]:[\\\\/])(?!\\\\).+"
198
+ }
199
+ ]
200
+ },
201
+ "line": {
202
+ "type": "integer",
203
+ "exclusiveMinimum": 0,
204
+ "maximum": 9007199254740991
205
+ },
206
+ "why_it_matters": {
207
+ "type": "string",
208
+ "minLength": 1,
209
+ "maxLength": 2048,
210
+ "pattern": "\\S"
211
+ },
212
+ "autofix_class": {
213
+ "type": "string",
214
+ "enum": ["safe_auto", "gated_auto", "manual", "advisory"]
215
+ },
216
+ "owner": {
217
+ "type": "string",
218
+ "enum": ["review-fixer", "downstream-resolver", "human", "release"]
219
+ },
220
+ "requires_verification": {
221
+ "type": "boolean"
222
+ },
223
+ "confidence": {
224
+ "type": "number",
225
+ "minimum": 0,
226
+ "maximum": 1
227
+ },
228
+ "evidence": {
229
+ "minItems": 1,
230
+ "maxItems": 5,
231
+ "type": "array",
232
+ "items": {
233
+ "anyOf": [
234
+ {
235
+ "type": "string",
236
+ "minLength": 1,
237
+ "maxLength": 500,
238
+ "allOf": [
239
+ {
240
+ "type": "string",
241
+ "pattern": "\\S"
242
+ },
243
+ {
244
+ "type": "string",
245
+ "pattern": "^(?!\\/)(?![A-Za-z]:[\\\\/])(?!\\\\).+"
246
+ }
247
+ ]
248
+ },
249
+ {
250
+ "type": "object",
251
+ "properties": {
252
+ "overflow": {
253
+ "type": "boolean",
254
+ "const": true
255
+ },
256
+ "excerpt": {
257
+ "type": "string",
258
+ "minLength": 1,
259
+ "maxLength": 500,
260
+ "allOf": [
261
+ {
262
+ "type": "string",
263
+ "pattern": "\\S"
264
+ },
265
+ {
266
+ "type": "string",
267
+ "pattern": "^(?!\\/)(?![A-Za-z]:[\\\\/])(?!\\\\).+"
268
+ }
269
+ ]
270
+ }
271
+ },
272
+ "required": ["overflow", "excerpt"],
273
+ "additionalProperties": false
274
+ }
275
+ ]
276
+ }
277
+ },
278
+ "pre_existing": {
279
+ "type": "boolean"
280
+ },
281
+ "suggested_fix": {
282
+ "anyOf": [
283
+ {
284
+ "type": "string",
285
+ "maxLength": 2048
286
+ },
287
+ {
288
+ "type": "null"
289
+ }
290
+ ]
291
+ },
292
+ "validated": {
293
+ "type": "boolean"
294
+ },
295
+ "validation_reason": {
296
+ "type": "string",
297
+ "minLength": 1,
298
+ "maxLength": 2048,
299
+ "pattern": "\\S"
300
+ },
301
+ "input_finding_ids": {
302
+ "minItems": 1,
303
+ "maxItems": 32,
304
+ "type": "array",
305
+ "items": {
306
+ "type": "string",
307
+ "minLength": 1,
308
+ "maxLength": 128,
309
+ "pattern": "\\S"
310
+ }
311
+ },
312
+ "provenance": {
313
+ "type": "object",
314
+ "properties": {
315
+ "fingerprint": {
316
+ "type": "string",
317
+ "minLength": 1,
318
+ "maxLength": 512,
319
+ "pattern": "\\S"
320
+ },
321
+ "submitters": {
322
+ "maxItems": 64,
323
+ "type": "array",
324
+ "items": {
325
+ "type": "string",
326
+ "minLength": 1,
327
+ "maxLength": 64,
328
+ "pattern": "\\S"
329
+ }
330
+ },
331
+ "agreement_credit": {
332
+ "maxItems": 64,
333
+ "type": "array",
334
+ "items": {
335
+ "type": "string",
336
+ "minLength": 1,
337
+ "maxLength": 64,
338
+ "pattern": "\\S"
339
+ }
340
+ }
341
+ },
342
+ "required": ["fingerprint", "submitters", "agreement_credit"],
343
+ "additionalProperties": false
344
+ }
345
+ },
346
+ "required": [
347
+ "title",
348
+ "severity",
349
+ "file",
350
+ "line",
351
+ "why_it_matters",
352
+ "autofix_class",
353
+ "owner",
354
+ "requires_verification",
355
+ "confidence",
356
+ "evidence",
357
+ "pre_existing",
358
+ "input_finding_ids",
359
+ "provenance"
360
+ ],
361
+ "additionalProperties": false
362
+ }
363
+ },
364
+ "disposition_counts": {
365
+ "type": "object",
366
+ "properties": {
367
+ "surviving": {
368
+ "type": "integer",
369
+ "minimum": 0,
370
+ "maximum": 2048
371
+ },
372
+ "merged": {
373
+ "type": "integer",
374
+ "minimum": 0,
375
+ "maximum": 2048
376
+ },
377
+ "suppressed": {
378
+ "type": "integer",
379
+ "minimum": 0,
380
+ "maximum": 2048
381
+ },
382
+ "filtered": {
383
+ "type": "integer",
384
+ "minimum": 0,
385
+ "maximum": 2048
386
+ },
387
+ "rejected": {
388
+ "type": "integer",
389
+ "minimum": 0,
390
+ "maximum": 2048
391
+ }
392
+ },
393
+ "required": ["surviving", "merged", "suppressed", "filtered", "rejected"],
394
+ "additionalProperties": false
395
+ },
396
+ "applied_fixes": {
397
+ "maxItems": 32,
398
+ "type": "array",
399
+ "items": {
400
+ "type": "string",
401
+ "minLength": 1,
402
+ "maxLength": 2048,
403
+ "pattern": "\\S"
404
+ }
405
+ },
406
+ "residual_actionable_work": {
407
+ "maxItems": 32,
408
+ "type": "array",
409
+ "items": {
410
+ "type": "string",
411
+ "minLength": 1,
412
+ "maxLength": 2048,
413
+ "pattern": "\\S"
414
+ }
415
+ },
416
+ "advisory_outputs": {
417
+ "maxItems": 32,
418
+ "type": "array",
419
+ "items": {
420
+ "type": "string",
421
+ "minLength": 1,
422
+ "maxLength": 2048,
423
+ "pattern": "\\S"
424
+ }
425
+ },
426
+ "coverage": {
427
+ "type": "object",
428
+ "properties": {
429
+ "reviewers": {
430
+ "type": "integer",
431
+ "minimum": 0,
432
+ "maximum": 64
433
+ },
434
+ "validators": {
435
+ "type": "integer",
436
+ "minimum": 0,
437
+ "maximum": 64
438
+ },
439
+ "residual_risks": {
440
+ "maxItems": 64,
441
+ "type": "array",
442
+ "items": {
443
+ "type": "string",
444
+ "minLength": 1,
445
+ "maxLength": 2048,
446
+ "pattern": "\\S"
447
+ }
448
+ },
449
+ "testing_gaps": {
450
+ "maxItems": 64,
451
+ "type": "array",
452
+ "items": {
453
+ "type": "string",
454
+ "minLength": 1,
455
+ "maxLength": 2048,
456
+ "pattern": "\\S"
457
+ }
458
+ },
459
+ "failed_reviewers": {
460
+ "maxItems": 64,
461
+ "type": "array",
462
+ "items": {
463
+ "type": "string",
464
+ "minLength": 1,
465
+ "maxLength": 64,
466
+ "pattern": "\\S"
467
+ }
468
+ },
469
+ "validator_failures": {
470
+ "maxItems": 64,
471
+ "type": "array",
472
+ "items": {
473
+ "type": "string",
474
+ "minLength": 1,
475
+ "maxLength": 2048,
476
+ "pattern": "\\S"
477
+ }
478
+ },
479
+ "intent_uncertainty": {
480
+ "maxItems": 64,
481
+ "type": "array",
482
+ "items": {
483
+ "type": "string",
484
+ "minLength": 1,
485
+ "maxLength": 2048,
486
+ "pattern": "\\S"
487
+ }
488
+ }
489
+ },
490
+ "required": [
491
+ "residual_risks",
492
+ "testing_gaps",
493
+ "failed_reviewers",
494
+ "validator_failures",
495
+ "intent_uncertainty"
496
+ ],
497
+ "additionalProperties": false
498
+ }
499
+ },
500
+ "required": [
501
+ "schema_version",
502
+ "run_id",
503
+ "mode",
504
+ "harness",
505
+ "run_status",
506
+ "verdict",
507
+ "dispatches",
508
+ "input_findings",
509
+ "findings",
510
+ "disposition_counts",
511
+ "applied_fixes",
512
+ "residual_actionable_work",
513
+ "advisory_outputs",
514
+ "coverage"
515
+ ],
516
+ "additionalProperties": false
517
+ }
@@ -34,6 +34,7 @@ The artifact must preserve these distinctions:
34
34
  ```json
35
35
  {
36
36
  "run_id": "<run-id>",
37
+ "schema_version": 1,
37
38
  "mode": "<interactive | autofix | headless>",
38
39
  "harness": "<opencode | pi | claude-code>",
39
40
  "run_status": "<in_progress | completed | degraded | abnormal>",
@@ -180,6 +181,45 @@ detection`, or `malformed JSON`):
180
181
  `Rejected persona <name> return: field <JSON path> failed <reason>.` Never
181
182
  echo the matched value.
182
183
 
184
+ ## Artifact validation
185
+
186
+ The parent writes `schema_version: 1` into `review-summary.json` before
187
+ validating it. This ordering makes the artifact validatable at all: without
188
+ `schema_version`, the validator reports the legacy status (exit 3) rather than
189
+ a real validation result.
190
+
191
+ After writing `review-summary.json`, the parent runs
192
+ `systematic validate-review-artifact <path>` against it. A nonzero exit means
193
+ the run is not complete. The [executable schema](./review-summary-schema.json)
194
+ is generated from a Zod source and is the machine-checkable form of the shape
195
+ described here.
196
+
197
+ On validation failure, the parent repairs the artifact and re-runs the
198
+ validator. It does not report a verdict over an artifact that failed
199
+ validation, and it does not delete the artifact to escape the check. A failing
200
+ artifact is evidence and stays on disk; an absent artifact is never evidence
201
+ of a clean run.
202
+
203
+ This is enforcement by visible failure, not by containment. An agent that
204
+ never runs the command can still finalize an artifact, but produces no evidence
205
+ in either direction. That is why the command exists as an independently
206
+ runnable check rather than as a self-validation instruction, and why its result
207
+ belongs in the run record.
208
+
209
+ `mode:report-only` writes no artifact and therefore performs no validation.
210
+
211
+ ## Historical corpus exclusion
212
+
213
+ Artifacts without `schema_version` predate this contract, are excluded from
214
+ quantitative analysis, and no legacy reader will be written. The validator
215
+ backs this exclusion with its exit 3 legacy status rather than leaving it as
216
+ a prose-only decision. Across 26 run directories, 7 synthesis artifacts were
217
+ written under two different filenames (`review-summary.json` and
218
+ `summary.json`); no two shared a shape. A parser would need seven special
219
+ cases to recover data that still could not answer cross-reviewer agreement
220
+ questions, because 19 of the 26 runs had no synthesis artifact to reconcile
221
+ against at all.
222
+
183
223
  ## Risk-aware degraded verdict
184
224
 
185
225
  The risk-critical surfaces are `security`, `data-migrations`, `api-contract`,