@fro.bot/systematic 3.9.1 → 3.10.1

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.
@@ -1,134 +1,338 @@
1
1
  {
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
3
  "title": "Code Review Findings",
4
- "description": "Structured output schema for code review sub-agents",
5
- "type": "object",
6
- "required": ["reviewer", "findings", "residual_risks", "testing_gaps"],
7
- "properties": {
8
- "reviewer": {
4
+ "description": "Structured output schemas for code review sub-agent returns and parent-persisted records",
5
+ "$ref": "#/definitions/parentRecord",
6
+ "definitions": {
7
+ "dispatchOutcome": {
9
8
  "type": "string",
10
- "description": "Persona name that produced this output (e.g., 'correctness', 'security')"
9
+ "enum": ["findings", "empty", "malformed", "never_returned"],
10
+ "description": "What a persona returned: findings, empty, malformed, or never returned"
11
11
  },
12
- "findings": {
13
- "type": "array",
14
- "description": "List of code review findings. Empty array if no issues found.",
15
- "items": {
16
- "type": "object",
17
- "required": [
18
- "title",
19
- "severity",
20
- "file",
21
- "line",
22
- "why_it_matters",
23
- "autofix_class",
24
- "owner",
25
- "requires_verification",
26
- "confidence",
27
- "evidence",
28
- "pre_existing"
29
- ],
30
- "properties": {
31
- "title": {
32
- "type": "string",
33
- "description": "Short, specific issue title. 10 words or fewer.",
34
- "maxLength": 100
35
- },
36
- "severity": {
37
- "type": "string",
38
- "enum": ["P0", "P1", "P2", "P3"],
39
- "description": "Issue severity level"
40
- },
41
- "file": {
42
- "type": "string",
43
- "description": "Relative file path from repository root"
44
- },
45
- "line": {
46
- "type": "integer",
47
- "description": "Primary line number of the issue",
48
- "minimum": 1
49
- },
50
- "why_it_matters": {
51
- "type": "string",
52
- "description": "Impact and failure mode -- not 'what is wrong' but 'what breaks'"
53
- },
54
- "autofix_class": {
12
+ "disposition": {
13
+ "type": "string",
14
+ "enum": ["surviving", "merged", "suppressed", "filtered", "rejected"],
15
+ "description": "What happened to an input finding: surviving, merged, suppressed, filtered, or rejected"
16
+ },
17
+ "harness": {
18
+ "type": "string",
19
+ "enum": ["opencode", "pi", "claude-code"],
20
+ "description": "Harness that produced the artifact; populated by the parent orchestrator"
21
+ },
22
+ "repoRelativePath": {
23
+ "type": "string",
24
+ "minLength": 1,
25
+ "maxLength": 256,
26
+ "pattern": "^(?!/)(?![A-Za-z]:[\\\\/])(?!\\\\).+",
27
+ "description": "Relative file path from repository root; absolute POSIX, drive-letter, and UNC paths are rejected"
28
+ },
29
+ "boundedEvidenceString": {
30
+ "type": "string",
31
+ "minLength": 1,
32
+ "maxLength": 500,
33
+ "pattern": "^(?!/)(?![A-Za-z]:[\\\\/])(?!\\\\).+",
34
+ "description": "Bounded code-grounded evidence; absolute POSIX, drive-letter, and UNC paths are rejected"
35
+ },
36
+ "overflowExcerpt": {
37
+ "type": "string",
38
+ "minLength": 1,
39
+ "maxLength": 500,
40
+ "pattern": "^(?!/)(?![A-Za-z]:[\\\\/])(?!\\\\).+",
41
+ "description": "Bounded excerpt retained when evidence must be shortened"
42
+ },
43
+ "overflowEvidence": {
44
+ "type": "object",
45
+ "required": ["overflow", "excerpt"],
46
+ "properties": {
47
+ "overflow": {
48
+ "const": true,
49
+ "description": "Explicit marker that the complete evidence did not fit in one bounded entry"
50
+ },
51
+ "excerpt": {
52
+ "$ref": "#/definitions/overflowExcerpt"
53
+ }
54
+ },
55
+ "additionalProperties": false
56
+ },
57
+ "findingProperties": {
58
+ "type": "object",
59
+ "properties": {
60
+ "title": {
61
+ "type": "string",
62
+ "minLength": 1,
63
+ "maxLength": 256,
64
+ "pattern": "\\S",
65
+ "description": "Short, specific issue title. 10 words or fewer."
66
+ },
67
+ "severity": {
68
+ "type": "string",
69
+ "enum": ["P0", "P1", "P2", "P3"],
70
+ "description": "Issue severity level"
71
+ },
72
+ "file": {
73
+ "$ref": "#/definitions/repoRelativePath"
74
+ },
75
+ "line": {
76
+ "type": "integer",
77
+ "minimum": 1,
78
+ "description": "Primary line number of the issue"
79
+ },
80
+ "why_it_matters": {
81
+ "type": "string",
82
+ "minLength": 1,
83
+ "maxLength": 2048,
84
+ "pattern": "\\S",
85
+ "description": "Non-empty impact and failure mode -- not 'what is wrong' but 'what breaks'"
86
+ },
87
+ "autofix_class": {
88
+ "type": "string",
89
+ "enum": ["safe_auto", "gated_auto", "manual", "advisory"],
90
+ "description": "Reviewer's conservative recommendation for how this issue should be handled after synthesis"
91
+ },
92
+ "owner": {
93
+ "type": "string",
94
+ "enum": ["review-fixer", "downstream-resolver", "human", "release"],
95
+ "description": "Who should own the next action for this finding after synthesis"
96
+ },
97
+ "requires_verification": {
98
+ "type": "boolean",
99
+ "description": "Whether any fix for this finding must be re-verified with targeted tests or a follow-up review pass"
100
+ },
101
+ "suggested_fix": {
102
+ "type": ["string", "null"],
103
+ "maxLength": 2048,
104
+ "description": "Concrete minimal fix. Omit or null if no good fix is obvious -- a bad suggestion is worse than none."
105
+ },
106
+ "confidence": {
107
+ "type": "number",
108
+ "minimum": 0.0,
109
+ "maximum": 1.0,
110
+ "description": "Reviewer confidence in this finding, calibrated per persona"
111
+ },
112
+ "evidence": {
113
+ "type": "array",
114
+ "minItems": 1,
115
+ "maxItems": 5,
116
+ "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.",
117
+ "items": {
118
+ "oneOf": [
119
+ {
120
+ "$ref": "#/definitions/boundedEvidenceString"
121
+ },
122
+ {
123
+ "$ref": "#/definitions/overflowEvidence"
124
+ }
125
+ ]
126
+ }
127
+ },
128
+ "disposition": {
129
+ "$ref": "#/definitions/disposition"
130
+ },
131
+ "pre_existing": {
132
+ "type": "boolean",
133
+ "description": "True if this issue exists in unchanged code unrelated to the current diff"
134
+ }
135
+ }
136
+ },
137
+ "artifactProperties": {
138
+ "type": "object",
139
+ "properties": {
140
+ "reviewer": {
141
+ "type": "string",
142
+ "minLength": 1,
143
+ "maxLength": 64,
144
+ "pattern": "\\S",
145
+ "description": "Persona name that produced this output (e.g., 'correctness', 'security')"
146
+ },
147
+ "harness": {
148
+ "$ref": "#/definitions/harness"
149
+ },
150
+ "dispatch_outcome": {
151
+ "$ref": "#/definitions/dispatchOutcome"
152
+ },
153
+ "findings": {
154
+ "type": "array",
155
+ "maxItems": 32,
156
+ "description": "List of code review findings. Empty array if no issues found."
157
+ },
158
+ "residual_risks": {
159
+ "type": "array",
160
+ "maxItems": 64,
161
+ "description": "Risks the reviewer noticed but could not confirm as findings",
162
+ "items": {
55
163
  "type": "string",
56
- "enum": ["safe_auto", "gated_auto", "manual", "advisory"],
57
- "description": "Reviewer's conservative recommendation for how this issue should be handled after synthesis"
58
- },
59
- "owner": {
164
+ "maxLength": 1024
165
+ }
166
+ },
167
+ "testing_gaps": {
168
+ "type": "array",
169
+ "maxItems": 64,
170
+ "description": "Missing test coverage the reviewer identified",
171
+ "items": {
60
172
  "type": "string",
61
- "enum": ["review-fixer", "downstream-resolver", "human", "release"],
62
- "description": "Who should own the next action for this finding after synthesis"
63
- },
64
- "requires_verification": {
65
- "type": "boolean",
66
- "description": "Whether any fix for this finding must be re-verified with targeted tests or a follow-up review pass"
67
- },
68
- "suggested_fix": {
69
- "type": ["string", "null"],
70
- "description": "Concrete minimal fix. Omit or null if no good fix is obvious -- a bad suggestion is worse than none."
71
- },
72
- "confidence": {
73
- "type": "number",
74
- "description": "Reviewer confidence in this finding, calibrated per persona",
75
- "minimum": 0.0,
76
- "maximum": 1.0
77
- },
78
- "evidence": {
79
- "type": "array",
80
- "description": "Code-grounded evidence: snippets, line references, or pattern descriptions. At least 1 item.",
81
- "items": { "type": "string" },
82
- "minItems": 1
83
- },
84
- "pre_existing": {
85
- "type": "boolean",
86
- "description": "True if this issue exists in unchanged code unrelated to the current diff"
173
+ "maxLength": 1024
87
174
  }
88
175
  }
89
176
  }
90
177
  },
91
- "residual_risks": {
92
- "type": "array",
93
- "description": "Risks the reviewer noticed but could not confirm as findings",
94
- "items": { "type": "string" }
95
- },
96
- "testing_gaps": {
97
- "type": "array",
98
- "description": "Missing test coverage the reviewer identified",
99
- "items": { "type": "string" }
100
- }
101
- },
102
-
103
- "_meta": {
104
- "confidence_thresholds": {
105
- "suppress": "Below 0.60 -- do not report. Finding is speculative noise. Exception: P0 findings at 0.50+ may be reported.",
106
- "flag": "0.60-0.69 -- include only when the issue is clearly actionable with concrete evidence.",
107
- "confident": "0.70-0.84 -- real and important. Report with full evidence.",
108
- "certain": "0.85-1.00 -- verifiable from the code alone. Report."
109
- },
110
- "severity_definitions": {
111
- "P0": "Critical breakage, exploitable vulnerability, data loss/corruption. Must fix before merge.",
112
- "P1": "High-impact defect likely hit in normal usage, breaking contract. Should fix.",
113
- "P2": "Moderate issue with meaningful downside (edge case, perf regression, maintainability trap). Fix if straightforward.",
114
- "P3": "Low-impact, narrow scope, minor improvement. User's discretion."
178
+ "subAgentFinding": {
179
+ "type": "object",
180
+ "required": [
181
+ "title",
182
+ "severity",
183
+ "file",
184
+ "line",
185
+ "why_it_matters",
186
+ "autofix_class",
187
+ "owner",
188
+ "requires_verification",
189
+ "confidence",
190
+ "evidence",
191
+ "pre_existing"
192
+ ],
193
+ "properties": {
194
+ "title": { "$ref": "#/definitions/findingProperties/properties/title" },
195
+ "severity": {
196
+ "$ref": "#/definitions/findingProperties/properties/severity"
197
+ },
198
+ "file": { "$ref": "#/definitions/findingProperties/properties/file" },
199
+ "line": { "$ref": "#/definitions/findingProperties/properties/line" },
200
+ "why_it_matters": {
201
+ "$ref": "#/definitions/findingProperties/properties/why_it_matters"
202
+ },
203
+ "autofix_class": {
204
+ "$ref": "#/definitions/findingProperties/properties/autofix_class"
205
+ },
206
+ "owner": { "$ref": "#/definitions/findingProperties/properties/owner" },
207
+ "requires_verification": {
208
+ "$ref": "#/definitions/findingProperties/properties/requires_verification"
209
+ },
210
+ "suggested_fix": {
211
+ "$ref": "#/definitions/findingProperties/properties/suggested_fix"
212
+ },
213
+ "confidence": {
214
+ "$ref": "#/definitions/findingProperties/properties/confidence"
215
+ },
216
+ "evidence": {
217
+ "$ref": "#/definitions/findingProperties/properties/evidence"
218
+ },
219
+ "pre_existing": {
220
+ "$ref": "#/definitions/findingProperties/properties/pre_existing"
221
+ }
222
+ },
223
+ "additionalProperties": false
115
224
  },
116
- "autofix_classes": {
117
- "safe_auto": "Local, deterministic code or test fix suitable for the in-skill fixer. Examples: extract duplicated helper, add missing nil check, fix off-by-one, add missing test, remove dead code. Do not default to advisory when a concrete safe fix exists.",
118
- "gated_auto": "Concrete fix exists, but it changes behavior, permissions, contracts, or other sensitive areas that deserve explicit approval. Examples: add auth to unprotected endpoint, change API response shape.",
119
- "manual": "Actionable issue that requires design decisions or cross-cutting changes. Examples: redesign data model, add pagination strategy, choose between architectural approaches.",
120
- "advisory": "Informational or operational item that should be surfaced in the report only. Examples: design asymmetry the PR improves but does not fully resolve, residual risk notes, deployment considerations."
225
+ "parentFinding": {
226
+ "type": "object",
227
+ "required": [
228
+ "title",
229
+ "severity",
230
+ "file",
231
+ "line",
232
+ "why_it_matters",
233
+ "autofix_class",
234
+ "owner",
235
+ "requires_verification",
236
+ "confidence",
237
+ "evidence",
238
+ "disposition",
239
+ "pre_existing"
240
+ ],
241
+ "properties": {
242
+ "title": { "$ref": "#/definitions/findingProperties/properties/title" },
243
+ "severity": {
244
+ "$ref": "#/definitions/findingProperties/properties/severity"
245
+ },
246
+ "file": { "$ref": "#/definitions/findingProperties/properties/file" },
247
+ "line": { "$ref": "#/definitions/findingProperties/properties/line" },
248
+ "why_it_matters": {
249
+ "$ref": "#/definitions/findingProperties/properties/why_it_matters"
250
+ },
251
+ "autofix_class": {
252
+ "$ref": "#/definitions/findingProperties/properties/autofix_class"
253
+ },
254
+ "owner": { "$ref": "#/definitions/findingProperties/properties/owner" },
255
+ "requires_verification": {
256
+ "$ref": "#/definitions/findingProperties/properties/requires_verification"
257
+ },
258
+ "suggested_fix": {
259
+ "$ref": "#/definitions/findingProperties/properties/suggested_fix"
260
+ },
261
+ "confidence": {
262
+ "$ref": "#/definitions/findingProperties/properties/confidence"
263
+ },
264
+ "evidence": {
265
+ "$ref": "#/definitions/findingProperties/properties/evidence"
266
+ },
267
+ "disposition": {
268
+ "$ref": "#/definitions/findingProperties/properties/disposition"
269
+ },
270
+ "pre_existing": {
271
+ "$ref": "#/definitions/findingProperties/properties/pre_existing"
272
+ }
273
+ },
274
+ "additionalProperties": false
121
275
  },
122
- "owners": {
123
- "review-fixer": "The in-skill fixer can own this when policy allows.",
124
- "downstream-resolver": "Turn this into residual work for later resolution.",
125
- "human": "A person must make a judgment call before code changes should continue.",
126
- "release": "Operational or rollout follow-up; do not convert into code-fix work automatically."
276
+ "subAgentReturn": {
277
+ "type": "object",
278
+ "required": ["reviewer", "findings", "residual_risks", "testing_gaps"],
279
+ "properties": {
280
+ "reviewer": {
281
+ "$ref": "#/definitions/artifactProperties/properties/reviewer"
282
+ },
283
+ "findings": {
284
+ "allOf": [
285
+ { "$ref": "#/definitions/artifactProperties/properties/findings" },
286
+ {
287
+ "items": { "$ref": "#/definitions/subAgentFinding" }
288
+ }
289
+ ]
290
+ },
291
+ "residual_risks": {
292
+ "$ref": "#/definitions/artifactProperties/properties/residual_risks"
293
+ },
294
+ "testing_gaps": {
295
+ "$ref": "#/definitions/artifactProperties/properties/testing_gaps"
296
+ }
297
+ },
298
+ "additionalProperties": false
127
299
  },
128
- "return_tiers": {
129
- "description": "Finding fields are split into two tiers. The full schema (with all required fields) applies to the artifact file on disk. The compact return to the orchestrator omits detail-tier fields. Both are valid uses of this schema in different contexts.",
130
- "merge_tier": "Returned to orchestrator: title, severity, file, line, confidence, autofix_class, owner, requires_verification, pre_existing, suggested_fix (optional). Plus top-level reviewer, residual_risks, testing_gaps.",
131
- "detail_tier": "Required in artifact file, omitted from compact return: why_it_matters, evidence. The artifact file must pass full schema validation including all required fields. Headless output depends on why_it_matters and evidence being present in the artifact."
300
+ "parentRecord": {
301
+ "type": "object",
302
+ "required": [
303
+ "reviewer",
304
+ "harness",
305
+ "dispatch_outcome",
306
+ "findings",
307
+ "residual_risks",
308
+ "testing_gaps"
309
+ ],
310
+ "properties": {
311
+ "reviewer": {
312
+ "$ref": "#/definitions/artifactProperties/properties/reviewer"
313
+ },
314
+ "harness": {
315
+ "$ref": "#/definitions/artifactProperties/properties/harness"
316
+ },
317
+ "dispatch_outcome": {
318
+ "$ref": "#/definitions/artifactProperties/properties/dispatch_outcome"
319
+ },
320
+ "findings": {
321
+ "allOf": [
322
+ { "$ref": "#/definitions/artifactProperties/properties/findings" },
323
+ {
324
+ "items": { "$ref": "#/definitions/parentFinding" }
325
+ }
326
+ ]
327
+ },
328
+ "residual_risks": {
329
+ "$ref": "#/definitions/artifactProperties/properties/residual_risks"
330
+ },
331
+ "testing_gaps": {
332
+ "$ref": "#/definitions/artifactProperties/properties/testing_gaps"
333
+ }
334
+ },
335
+ "additionalProperties": false
132
336
  }
133
337
  }
134
338
  }
@@ -2,6 +2,14 @@
2
2
 
3
3
  13 reviewer personas organized into always-on, cross-cutting conditional, and stack-specific conditional layers, plus CE-specific agents. The orchestrator uses this catalog to select which reviewers to spawn for each review.
4
4
 
5
+ ## Shared persona pool
6
+
7
+ The `agents/review/` directory is a shared persona pool, not `ce:review`'s roster. Directory placement does not imply that a persona is selectable by `ce:review`. These shared personas are dispatched by other workflows and intentionally do not appear in this catalog's `ce:review` selection tables:
8
+
9
+ - `systematic:review:architecture-strategist` — dispatched by `deepen-plan` and `ce-plan`'s deepening workflow for architectural analysis.
10
+ - `systematic:review:pattern-recognition-specialist` — dispatched by `deepen-plan`, `ce-plan`'s deepening workflow, and `ce-compound` for consistency, duplication, and pattern analysis.
11
+ - `systematic:review:code-simplicity-reviewer` — dispatched by `ce-compound` for code-heavy issues.
12
+
5
13
  ## Always-on (4 personas + 2 CE agents)
6
14
 
7
15
  Spawned on every review regardless of diff content.
@@ -14,6 +14,7 @@ Use this **exact format** when presenting synthesized review findings. Findings
14
14
  **Mode:** autofix
15
15
 
16
16
  **Reviewers:** correctness, testing, maintainability, security, api-contract
17
+ - **Harness:** opencode
17
18
  - security -- new public endpoint accepts user-provided format parameter
18
19
  - api-contract -- new /api/orders/export route with response schema
19
20
 
@@ -124,7 +125,7 @@ This fails because: no pipe-delimited tables, no severity-grouped `###` headers,
124
125
  - **Pipe-delimited markdown tables** for findings -- never ASCII box-drawing characters or per-finding horizontal-rule separators between entries (the report-level `---` before the verdict is still required)
125
126
  - **Severity-grouped sections** -- `### P0 -- Critical`, `### P1 -- High`, `### P2 -- Moderate`, `### P3 -- Low`. Omit empty severity levels.
126
127
  - **Always include file:line location** for code review issues
127
- - **Reviewer column** shows which persona(s) flagged the issue. Multiple reviewers = cross-reviewer agreement.
128
+ - **Reviewer column** shows which persona(s) submitted the issue. Multiple reviewers indicate independent submissions, not merely agreement credit. The machine-readable synthesis artifact keeps `submitters` separate from `agreement_credit`; do not infer submission from an agreement boost or from the display column alone.
128
129
  - **Confidence column** shows the finding's confidence score
129
130
  - **Route column** shows the synthesized handling decision as ``<autofix_class> -> <owner>``.
130
131
  - **Header includes** scope, intent, and reviewer team with per-conditional justifications
@@ -136,7 +137,7 @@ This fails because: no pipe-delimited tables, no severity-grouped `###` headers,
136
137
  - **Learnings & Past Solutions section** -- results from learnings-researcher, with links to docs/solutions/ files
137
138
  - **Agent-Native Gaps section** -- results from agent-native-reviewer. Omit if no gaps found.
138
139
  - **Deployment Notes section** -- key checklist items from deployment-verification-agent. Omit if the agent did not run.
139
- - **Coverage section** -- suppressed count, residual risks, testing gaps, failed reviewers
140
+ - **Coverage section** -- suppressed count with original confidences, residual risks, testing gaps, failed reviewers, and disposition reconciliation
140
141
  - **Summary uses blockquotes** for verdict, reasoning, and fix order
141
142
  - **Horizontal rule** (`---`) separates findings from verdict
142
143
  - **`###` headers** for each section -- never plain text headers
@@ -148,8 +149,69 @@ In `mode:headless`, replace the interactive pipe-delimited table report with a s
148
149
  - **No pipe-delimited tables.** Findings use `[severity][autofix_class -> owner] File: <file:line> -- <title>` line format with indented Why/Evidence/Suggested fix lines.
149
150
  - **Findings grouped by autofix_class** (gated-auto, manual, advisory) instead of severity. Within each group, findings are sorted by severity.
150
151
  - **Verdict in header** (top of output) instead of bottom, so programmatic callers get it first.
151
- - **`Artifact:` line** in metadata header gives callers the path to the full run artifact.
152
+ - **`Artifact:` line** in metadata header gives callers the path to `review-summary.json`, the full run artifact with provenance, dispatch outcomes, and disposition reconciliation.
152
153
  - **`[needs-verification]` marker** on findings where `requires_verification: true`.
153
154
  - **Evidence lines** included per finding.
154
155
  - **"Filtered (not validated)" section** included when Stage 5b produced findings with `validated: false`. Uses `[severity][autofix_class -> owner] File: <file:line> -- <title>` format with an indented `Validator reason:` line. These findings are surfaced for human review, not removed.
155
156
  - **Completion signal:** "Review complete" as the final line.
157
+
158
+ ## Synthesis Artifact Contract
159
+
160
+ For interactive, autofix, and headless runs, the parent writes `.context/systematic/ce-review/<run-id>/review-summary.json` even when every selected persona returns `empty` and no finding survives. `mode:report-only` is the deliberate no-write exception.
161
+
162
+ The artifact must preserve the following distinctions:
163
+
164
+ ```json
165
+ {
166
+ "run_id": "<run-id>",
167
+ "mode": "<interactive | autofix | headless>",
168
+ "harness": "<opencode | pi | claude-code>",
169
+ "run_status": "<in_progress | completed | degraded | abnormal>",
170
+ "dispatches": [
171
+ {
172
+ "persona": "correctness",
173
+ "dispatch_outcome": "findings",
174
+ "input_finding_count": 2
175
+ },
176
+ {
177
+ "persona": "kieran-typescript",
178
+ "dispatch_outcome": "malformed",
179
+ "input_finding_count": 1,
180
+ "rejection_reason": "Rejected persona kieran-typescript return: field findings[0].evidence failed schema validation."
181
+ }
182
+ ],
183
+ "input_findings": [
184
+ {
185
+ "input_id": "correctness#1",
186
+ "reviewer": "correctness",
187
+ "confidence": 0.55,
188
+ "disposition": "suppressed",
189
+ "reason": "confidence 0.55 is below the 0.60 gate"
190
+ }
191
+ ],
192
+ "findings": [
193
+ {
194
+ "title": "<merged finding>",
195
+ "input_finding_ids": ["correctness#2", "testing#1"],
196
+ "provenance": {
197
+ "fingerprint": "<normalize(file) + line_bucket(line, +/-3) + normalize(title)>",
198
+ "submitters": ["correctness", "testing"],
199
+ "agreement_credit": []
200
+ }
201
+ }
202
+ ],
203
+ "disposition_counts": {
204
+ "surviving": 0,
205
+ "merged": 2,
206
+ "suppressed": 1,
207
+ "filtered": 0,
208
+ "rejected": 0
209
+ }
210
+ }
211
+ ```
212
+
213
+ - `dispatch_outcome` records what a persona returned: `findings`, `empty`, `malformed`, or `never_returned`. A rejection reason is preserved as the exact safe validation reason, naming persona and field without echoing the offending value.
214
+ - `disposition` records what happened to each input finding: `surviving`, `merged`, `suppressed`, `filtered`, or `rejected`. Every safely enumerable input has exactly one disposition and stated reason; the disposition counts must equal the input-finding count.
215
+ - `submitters` contains only personas with an input finding in the merged fingerprint group. `agreement_credit` contains only personas credited by the cross-reviewer agreement boost without an input finding in that group. A persona returning zero findings never appears in `submitters`.
216
+ - `filtered` findings remain available for human review with the validator's stated reason, but are not part of the surviving/actioned set. A suppressed finding retains its original confidence, including the P0 exception for confidence `0.50` or higher.
217
+ - The parent initializes the artifact as `in_progress` before dispatch. A completed run becomes `completed` or `degraded`; an interrupted or failed run is `abnormal` with its stated termination reason. An unfinished `in_progress` artifact is evidence of an abnormal run, not evidence of a clean run.
@@ -22,23 +22,11 @@ The supplied diff is the primary source of truth. Use the supplied paths and lin
22
22
  </bounded-investigation>
23
23
 
24
24
  <output-contract>
25
- You produce up to two outputs depending on whether a run ID was provided:
25
+ Return exactly one JSON payload to the parent. The payload contains the complete schema for every finding, including both the merge tier and the detail tier (`why_it_matters`, `evidence`, and `suggested_fix` when present).
26
26
 
27
- 1. **Artifact file (when run ID is present).** If a Run ID appears in <review-context> below, WRITE your full analysis (all schema fields, including why_it_matters, evidence, and suggested_fix) as JSON to:
28
- .context/systematic/ce-review/{run_id}/{reviewer_name}.json
29
- This is the ONE write operation you are permitted to make. Use the platform's file-write tool.
30
- If the write fails, continue -- the compact return still provides everything the merge needs.
31
- If no Run ID is provided (the field is empty or absent), skip this step entirely -- do not attempt any file write.
27
+ Do not write any file. Do not use a Run ID or an artifact path. Persistence is owned by the parent orchestrator: it validates this returned payload, adds parent-owned provenance, and writes only conforming data. This rule is the same in every supported harness.
32
28
 
33
- 2. **Compact return (always).** RETURN compact JSON to the parent with ONLY merge-tier fields per finding:
34
- title, severity, file, line, confidence, autofix_class, owner, requires_verification, pre_existing, suggested_fix.
35
- Do NOT include why_it_matters or evidence in the returned JSON.
36
- Include reviewer, residual_risks, and testing_gaps at the top level.
37
-
38
- The full file preserves detail for downstream consumers (headless output, debugging).
39
- The compact return keeps the orchestrator's context lean for merge and synthesis.
40
-
41
- The schema below describes the **full artifact file format** (all fields required). For the compact return, follow the field list above -- omit why_it_matters and evidence even though the schema marks them as required.
29
+ The schema below defines the payload's fields and bounds. Its transport is inline for this contract; any schema metadata describing a compact return or a separate detail artifact is superseded by this output contract.
42
30
 
43
31
  {schema}
44
32
 
@@ -62,9 +50,12 @@ False-positive categories to actively suppress:
62
50
 
63
51
  Rules:
64
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.
65
- - Every finding in the full artifact file MUST include at least one evidence item grounded in the actual code. The compact return omits evidence -- the evidence requirement applies to the disk artifact only.
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
+ - 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, while the parent-side validator in Unit 3 detects environment values because JSON Schema cannot infer where a string came from.
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` and `surviving`, `merged`, `suppressed`, `filtered`, `rejected`).
66
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.
67
- - You are operationally read-only. The one permitted exception is writing your full analysis to the `.context/` artifact path when a run ID is provided. You may also use non-mutating inspection commands, including read-oriented `git` / `gh` commands, to gather evidence. Do not edit project files, change branches, commit, push, create PRs, or otherwise mutate the checkout or repository state.
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.
68
59
  - Set `autofix_class` accurately -- not every finding is `advisory`. Use this decision guide:
69
60
  - `safe_auto`: The fix is local and deterministic — the fixer can apply it mechanically without design judgment. Examples: extracting a duplicated helper, adding a missing nil/null check, fixing an off-by-one, adding a missing test for an untested code path, removing dead code.
70
61
  - `gated_auto`: A concrete fix exists but it changes contracts, permissions, or crosses a module boundary in a way that deserves explicit approval. Examples: adding authentication to an unprotected endpoint, changing a public API response shape, switching from soft-delete to hard-delete.
@@ -83,7 +74,6 @@ Rules:
83
74
  </pr-context>
84
75
 
85
76
  <review-context>
86
- Run ID: {run_id}
87
77
  Reviewer name: {reviewer_name}
88
78
 
89
79
  Intent: {intent_summary}
@@ -106,5 +96,4 @@ Diff:
106
96
  | `{pr_metadata}` | Stage 1 output | PR title, body, and URL when reviewing a PR. Empty string when reviewing a branch or standalone checkout |
107
97
  | `{file_list}` | Stage 1 output | List of changed files from the scope step |
108
98
  | `{diff}` | Stage 1 output | The actual diff content to review |
109
- | `{run_id}` | Stage 4 output | Unique review run identifier for the artifact directory |
110
- | `{reviewer_name}` | Stage 3 output | Persona or agent name used as the artifact filename stem |
99
+ | `{reviewer_name}` | Stage 3 output | Persona name used in the returned `reviewer` field |