@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.
- package/HARNESSES.md +1 -1
- package/agents/review/architecture-strategist.md +1 -1
- package/agents/review/code-simplicity-reviewer.md +1 -1
- package/agents/review/pattern-recognition-specialist.md +1 -1
- package/dist/index.js +119 -496
- package/dist/lib/agent-overlays.d.ts +0 -1
- package/dist/lib/config-handler.d.ts +0 -3
- package/package.json +1 -1
- package/skills/ce-review/SKILL.md +55 -42
- package/skills/ce-review/references/findings-schema.json +321 -117
- package/skills/ce-review/references/persona-catalog.md +8 -0
- package/skills/ce-review/references/review-output-template.md +65 -3
- package/skills/ce-review/references/subagent-template.md +9 -20
- package/dist/lib/model-availability.d.ts +0 -83
- package/dist/lib/source-model-defaults.d.ts +0 -117
|
@@ -41,4 +41,3 @@ export interface ResolvedAgentOverlaySet {
|
|
|
41
41
|
export declare function buildBundledAgentInventory(agentsDir: string, disabledAgents: string[]): BundledAgentInventory;
|
|
42
42
|
export declare function validateAgentOverlays({ inventory, overlays, nativeAgents, enabledSkills, }: ValidateAgentOverlaysOptions): ValidatedAgentOverlays;
|
|
43
43
|
export declare function resolveAgentOverlaySet(overlays: ValidatedAgentOverlays): ResolvedAgentOverlaySet;
|
|
44
|
-
export declare function assertSourceCategoryModelCoverage(categories: string[]): void;
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import type { Config } from '@opencode-ai/plugin';
|
|
2
|
-
import { type OpencodeClientLike } from './model-availability.js';
|
|
3
2
|
export interface ConfigHandlerDeps {
|
|
4
3
|
directory: string;
|
|
5
4
|
bundledSkillsDir: string;
|
|
6
5
|
bundledAgentsDir: string;
|
|
7
6
|
bundledCommandsDir: string;
|
|
8
|
-
/** OpenCode client for availability lookup. When omitted, availability falls back to empty set (last-resort resolution). */
|
|
9
|
-
client?: OpencodeClientLike;
|
|
10
7
|
/** Home directory for discovered-skill lookups. Defaults to `os.homedir()`; inject a temp dir in tests. */
|
|
11
8
|
homeDir?: string;
|
|
12
9
|
/** OpenCode global config directory override for discovered-skill lookups. Defaults to `<homeDir>/.config/opencode`. */
|
package/package.json
CHANGED
|
@@ -64,7 +64,7 @@ All tokens are optional. Each one present means one less thing to infer. When ab
|
|
|
64
64
|
- **Skip all user questions.** Never use the platform question tool (`question` in OpenCode, `request_user_input` in Codex, `ask_user` in Gemini; in Pi, use the blocking-question extension if available, otherwise present numbered options in chat and wait) or other interactive prompts. Infer intent conservatively if the diff metadata is thin.
|
|
65
65
|
- **Require a determinable diff scope.** If headless mode cannot determine a diff scope (no branch, PR, or `base:` ref determinable without user interaction), emit `Review failed (headless mode). Reason: no diff scope detected. Re-invoke with a branch name, PR number, or base:<ref>.` and stop without dispatching agents.
|
|
66
66
|
- **Apply only `safe_auto -> review-fixer` findings in a single pass.** No bounded re-review rounds. Leave `gated_auto`, `manual`, `human`, and `release` work unresolved and return them in the structured output.
|
|
67
|
-
- **Return all non-auto findings as structured text output.** Use the headless output envelope format (see Stage 6 below) preserving severity, autofix_class, owner, requires_verification, confidence, pre_existing, and suggested_fix per finding. Enrich with detail-tier fields (why_it_matters, evidence[]) from the
|
|
67
|
+
- **Return all non-auto findings as structured text output.** Use the headless output envelope format (see Stage 6 below) preserving severity, autofix_class, owner, requires_verification, confidence, pre_existing, and suggested_fix per finding. Enrich with detail-tier fields (why_it_matters, evidence[]) from the validated inline persona returns (see Detail enrichment in Stage 6).
|
|
68
68
|
- **Write a run artifact** under `.context/systematic/ce-review/<run-id>/` summarizing findings, applied fixes, and advisory outputs. Include the artifact path in the structured output.
|
|
69
69
|
- **Do not create todo files.** The caller receives structured findings and routes downstream work itself.
|
|
70
70
|
- **Do not switch the shared checkout.** If the caller passes an explicit PR or branch target, `mode:headless` must run in an isolated checkout/worktree or stop instead of running `gh pr checkout` / `git checkout`. When stopping, emit `Review failed (headless mode). Reason: cannot switch shared checkout. Re-invoke with base:<ref> to review the current checkout, or run from an isolated worktree.`
|
|
@@ -383,16 +383,18 @@ The orchestrator (this skill) stays on the default model because it handles inte
|
|
|
383
383
|
|
|
384
384
|
#### Run ID
|
|
385
385
|
|
|
386
|
-
Generate a unique run identifier before dispatching any agents. This ID scopes
|
|
386
|
+
Generate a unique run identifier before dispatching any agents. This ID scopes the parent-owned per-agent records and the post-review run artifact to the same directory.
|
|
387
387
|
|
|
388
388
|
```bash
|
|
389
389
|
RUN_ID=$(date +%Y%m%d-%H%M%S)-$(head -c4 /dev/urandom | od -An -tx1 | tr -d ' ')
|
|
390
390
|
mkdir -p ".context/systematic/ce-review/$RUN_ID"
|
|
391
391
|
```
|
|
392
392
|
|
|
393
|
-
|
|
393
|
+
Keep `{run_id}` in the parent orchestrator. Do not pass it, an artifact path, or any write instruction to persona sub-agents. The parent writes a per-agent record only after the returned payload passes validation.
|
|
394
394
|
|
|
395
|
-
|
|
395
|
+
Capture the actual invoking harness once in the parent (`opencode`, `pi`, or `claude-code`). Do not infer it from persona metadata or declared tools. Add this parent-owned value to each persisted record and to the synthesis artifact so R6 remains explicit. `mode:report-only` still records nothing because it has no run artifact.
|
|
396
|
+
|
|
397
|
+
**Report-only mode:** Skip run-id generation and directory creation. Agents return the same full JSON payload, with no file write, consistent with report-only's no-write contract.
|
|
396
398
|
|
|
397
399
|
#### Spawning
|
|
398
400
|
|
|
@@ -405,14 +407,14 @@ Spawn each selected persona reviewer as a parallel sub-agent using the subagent
|
|
|
405
407
|
3. The JSON output contract from the findings schema included below
|
|
406
408
|
4. PR metadata: title, body, and URL when reviewing a PR (empty string otherwise). Passed in a `<pr-context>` block so reviewers can verify code against stated intent
|
|
407
409
|
5. Review context: intent summary, file list, diff
|
|
408
|
-
6.
|
|
410
|
+
6. Reviewer name for the returned `reviewer` field
|
|
409
411
|
7. **For `project-standards` only:** the standards file path list from Stage 3b, wrapped in a `<standards-paths>` block appended to the review context
|
|
410
412
|
|
|
411
|
-
Persona sub-agents are **read-only** with respect to the project: they review and return structured JSON. They do not edit project files or propose refactors. The
|
|
413
|
+
Persona sub-agents are **read-only** with respect to the project: they review and return structured JSON. They do not edit project files, write artifacts, or propose refactors. The parent orchestrator owns all persistence.
|
|
412
414
|
|
|
413
415
|
Read-only here means **non-mutating**, not "no shell access." Reviewer sub-agents may use non-mutating inspection commands when needed to gather evidence or verify scope, including read-oriented `git` / `gh` usage such as `git diff`, `git show`, `git blame`, `git log`, and `gh pr view`. They must not edit project files, change branches, commit, push, create PRs, or otherwise mutate the checkout or repository state.
|
|
414
416
|
|
|
415
|
-
Each persona sub-agent
|
|
417
|
+
Each persona sub-agent returns one full JSON payload (all schema fields) to the parent:
|
|
416
418
|
|
|
417
419
|
```json
|
|
418
420
|
{
|
|
@@ -428,6 +430,10 @@ Each persona sub-agent writes full JSON (all schema fields) to `.context/systema
|
|
|
428
430
|
"owner": "downstream-resolver",
|
|
429
431
|
"requires_verification": true,
|
|
430
432
|
"pre_existing": false,
|
|
433
|
+
"why_it_matters": "An unowned lookup can expose another account's orders.",
|
|
434
|
+
"evidence": [
|
|
435
|
+
"orders_controller.rb:42 uses params[:id] without an ownership guard."
|
|
436
|
+
],
|
|
431
437
|
"suggested_fix": "Add current_user.owns?(account) guard before lookup"
|
|
432
438
|
}
|
|
433
439
|
],
|
|
@@ -436,7 +442,9 @@ Each persona sub-agent writes full JSON (all schema fields) to `.context/systema
|
|
|
436
442
|
}
|
|
437
443
|
```
|
|
438
444
|
|
|
439
|
-
|
|
445
|
+
`why_it_matters` and `evidence` are returned inline with the merge-tier fields. `suggested_fix` remains optional. The parent validates the complete payload before writing any per-agent record; a malformed or rejected return is never partially persisted.
|
|
446
|
+
|
|
447
|
+
Returning the detail tier inline increases parent context per persona. The previous compact/detail split kept synthesis context lean, so this is an intentional cost of deleting the sub-agent write path. Verify it against a real multi-persona run. If it materially degrades synthesis, use a second targeted request per persona and keep the write parent-side; never restore sub-agent disk access.
|
|
440
448
|
|
|
441
449
|
**CE always-on agents** (agent-native-reviewer, learnings-researcher) are dispatched as standard Agent calls in parallel with the persona agents. Give them the same review context bundle the personas receive: entry mode, any PR metadata gathered in Stage 1, intent summary, review base branch name when known, `BASE:` marker, file list, diff, and `UNTRACKED:` scope notes. Do not invoke them with a generic "review this" prompt. Their output is unstructured and synthesized separately in Stage 6.
|
|
442
450
|
|
|
@@ -444,22 +452,22 @@ Detail-tier fields (`why_it_matters`, `evidence`) are in the artifact file only.
|
|
|
444
452
|
|
|
445
453
|
### Stage 5: Merge findings
|
|
446
454
|
|
|
447
|
-
Convert multiple reviewer
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
- **
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
-
|
|
460
|
-
2. **Confidence gate.** Suppress findings below 0.60 confidence. Exception: P0 findings at 0.50+ confidence survive the gate -- critical-but-uncertain issues must not be silently dropped. Record the suppressed
|
|
461
|
-
3. **Deduplicate.** Compute fingerprint: `normalize(file) + line_bucket(line, +/-3) + normalize(title)`. When fingerprints match, merge: keep highest severity, keep highest confidence,
|
|
462
|
-
4. **Cross-reviewer agreement.** When 2+ independent reviewers flag the same issue (same fingerprint), boost the merged confidence by 0.10 (capped at 1.0). Cross-reviewer agreement is strong signal -- independent reviewers converging on the same issue is more reliable than any single reviewer's confidence.
|
|
455
|
+
Convert multiple reviewer JSON returns into one deduplicated, confidence-gated finding set. Each persona return already contains both tiers. The parent must retain the validated payload in memory for merge and synthesis, then persist only the same validated data.
|
|
456
|
+
|
|
457
|
+
Before applying the confidence gate, assign every finding in a valid return a stable parent-owned `input_id` of `<reviewer>#<1-based finding index>`. Keep an input ledger through every later stage. The ledger is the authoritative reconciliation record in the synthesis artifact; it is not part of the persona's returned payload. If a return is rejected but its parsed `findings` array can be safely enumerated, assign IDs and record every enumerated input as `rejected`. If the return is malformed JSON or has no safely enumerable findings, record no synthetic input findings; the persona-level dispatch record and its exact safe rejection reason still record the rejection.
|
|
458
|
+
|
|
459
|
+
1. **Validate before any write.** Treat every persona return as untrusted input. Parse the returned text as JSON without logging the raw text, then validate the complete parsed object against `references/findings-schema.json`, including `why_it_matters` and `evidence`.
|
|
460
|
+
- **Top-level required:** reviewer (string), findings (array), residual_risks (array), testing_gaps (array). Reject the entire persona return if any are missing or wrong type.
|
|
461
|
+
- **Per-finding required:** title, severity, file, line, why_it_matters, confidence, evidence, autofix_class, owner, requires_verification, pre_existing.
|
|
462
|
+
- **Schema constraints:** enforce every enum, type, confidence, line, path, evidence count, evidence length, and explicit overflow-marker bound from the schema. Empty evidence, absolute paths, and over-bound evidence are rejection cases, not truncation cases.
|
|
463
|
+
- **Environment-value detection:** JSON Schema cannot determine where a string came from, so recursively inspect every string leaf in the parsed payload before writing. Reject the payload when a string contains a shell/environment reference (`$NAME`, `${NAME}`, `process.env.NAME`, or `os.environ[...]`), an assignment using a known environment variable (`NAME=value`), or a current environment value as an exact or embedded match. Use a conservative match set of non-empty runtime environment values; never log the matched value. This detector is an additional parent-side check, not a schema claim.
|
|
464
|
+
- **Safe rejection message:** report only `Rejected persona <name> return: field <JSON path> failed <reason>.` Derive `<JSON path>` from the validator or recursive scan and use a fixed reason such as `schema validation`, `environment-value detection`, or `malformed JSON`; never include the offending value, raw return, or validator parameters.
|
|
465
|
+
- **No partial writes:** do not write a per-agent record or merge any finding until the entire persona payload passes schema and environment-value validation. A valid payload is then annotated by the parent with `harness` and `dispatch_outcome` and written by the parent only. Revalidate the enriched record before persistence.
|
|
466
|
+
- **Dispatch outcome:** a valid non-empty return is `findings`; a valid empty return is `empty`; invalid JSON or a rejected schema/environment payload is `malformed`; timeout or no return is `never_returned`. Keep these outcomes separate from finding `disposition`.
|
|
467
|
+
- **Rejection policy: degrade, do not fail the whole review.** Continue merging conforming returns, record the rejected persona's `dispatch_outcome` and safe rejection reason in the synthesis artifact, and give any rejected input the `rejected` disposition in the later reconciliation. If every persona fails or times out, use the existing degraded-review behavior. This preserves partial review coverage without ever persisting a non-conforming artifact; only an orchestration/storage failure that prevents the parent from producing its required run artifact is run-fatal.
|
|
468
|
+
2. **Confidence gate.** Suppress findings below 0.60 confidence. Exception: P0 findings at 0.50+ confidence survive the gate -- critical-but-uncertain issues must not be silently dropped. Record the suppressed finding's original confidence and an explicit reason in the input ledger. A retained P0 at 0.50+ is recorded as `surviving` unless it later participates in a deduplication merge. This matches the persona instructions and the schema's confidence thresholds.
|
|
469
|
+
3. **Deduplicate.** Compute fingerprint: `normalize(file) + line_bucket(line, +/-3) + normalize(title)`. When fingerprints match, merge: keep highest severity, keep highest confidence, preserve the exact fingerprint, and retain the input IDs that produced the merged entry. A singleton that passes the gate is `surviving`; each input in a multi-input merge is provisionally `merged`.
|
|
470
|
+
4. **Cross-reviewer agreement.** When 2+ independent reviewers flag the same issue (same fingerprint), boost the merged confidence by 0.10 (capped at 1.0). Cross-reviewer agreement is strong signal -- independent reviewers converging on the same issue is more reliable than any single reviewer's confidence. Preserve the distinction in the merged finding's artifact provenance: `submitters` contains only personas with an input finding in that fingerprint group; `agreement_credit` contains only personas credited by the agreement boost without an input finding in that group. A persona with zero findings never appears in `submitters`. Do not infer submission from the report's Reviewer column.
|
|
463
471
|
5. **Separate pre-existing.** Pull out findings with `pre_existing: true` into a separate list.
|
|
464
472
|
6. **Resolve disagreements.** When reviewers flag the same code region but disagree on severity, autofix_class, or owner, annotate the Reviewer column with the disagreement (e.g., "security (P0), correctness (P1) -- kept P0"). This transparency helps the user understand why a finding was routed the way it was.
|
|
465
473
|
7. **Normalize routing.** For each merged finding, set the final `autofix_class`, `owner`, and `requires_verification`. If reviewers disagree, keep the most conservative route. Synthesis may narrow a finding from `safe_auto` to `gated_auto` or `manual`, but must not widen it without new evidence.
|
|
@@ -470,10 +478,11 @@ Convert multiple reviewer compact JSON returns into one deduplicated, confidence
|
|
|
470
478
|
9. **Sort.** Order by severity (P0 first) -> confidence (descending) -> file path -> line number.
|
|
471
479
|
10. **Collect coverage data.** Union residual_risks and testing_gaps across reviewers.
|
|
472
480
|
11. **Preserve CE agent artifacts.** Keep the learnings, agent-native, schema-drift, and deployment-verification outputs alongside the merged finding set. Do not drop unstructured agent output just because it does not match the persona JSON schema.
|
|
481
|
+
12. **Keep the input ledger complete.** Every enumerated input finding has exactly one final disposition: `surviving`, `merged`, `suppressed`, `filtered`, or `rejected`, plus a reason. The ledger's disposition counts must sum to its input count. A rejected payload's reason is the exact safe rejection message produced by validation, not a bucket such as "invalid"; never include the offending value.
|
|
473
482
|
|
|
474
483
|
### Stage 5b: Validation pass
|
|
475
484
|
|
|
476
|
-
Run an independent validation pass over the merged finding set before synthesis. This pass annotates each gated finding `validated: true` or `validated: false` with a one-sentence reason.
|
|
485
|
+
Run an independent validation pass over the merged finding set before synthesis. This pass annotates each gated finding `validated: true` or `validated: false` with a one-sentence reason. A `validated: false` finding is dropped from the surviving/actioned set and receives disposition `filtered`, but is retained in the synthesis artifact and surfaced in the "Filtered (not validated)" group in Stage 6. It is not erased from the record.
|
|
477
486
|
|
|
478
487
|
**Gating band (default):** Validate only findings that are **P0 or P1 severity**, or that have `requires_verification: true`. Findings outside this band pass through to Stage 6 unvalidated and unfiltered — no validator is dispatched for them. This bounds cost: one validator subagent per gated finding.
|
|
479
488
|
|
|
@@ -482,9 +491,9 @@ Run an independent validation pass over the merged finding set before synthesis.
|
|
|
482
491
|
1. Identify all gated findings from the Stage 5 merged set.
|
|
483
492
|
2. For each gated finding, spawn one validator subagent in parallel using the validator template at `references/validator-template.md`. Pass the finding fields, the intent summary, the file list, and the full diff.
|
|
484
493
|
3. Collect `{validated, reason}` from each validator. Attach both fields to the finding.
|
|
485
|
-
4. **
|
|
486
|
-
5. Findings with `validated: true` flow through to Stage 6 unchanged — they appear in the normal severity tables.
|
|
487
|
-
6. Findings outside the gating band carry no `validated` annotation and appear in Stage 6 severity tables unchanged
|
|
494
|
+
4. **Reconcile filtered inputs.** A finding with `validated: false` moves to the "Filtered (not validated)" presentation group in Stage 6, and every input ID contributing to that merged finding is updated to disposition `filtered` with the validator's exact one-sentence reason. It is not `suppressed`, `rejected`, or silently excluded from the input ledger.
|
|
495
|
+
5. Findings with `validated: true` flow through to Stage 6 unchanged — they appear in the normal severity tables. Their input ledger dispositions remain `surviving` for singleton findings or `merged` for deduplicated groups.
|
|
496
|
+
6. Findings outside the gating band carry no `validated` annotation and appear in Stage 6 severity tables unchanged; their input ledger dispositions remain `surviving` or `merged`.
|
|
488
497
|
|
|
489
498
|
**Failure handling:** If a validator subagent fails or times out, treat the finding as `validated: true` (conservative fallback — keep it in the actioned set) and note the validator failure in the Coverage section.
|
|
490
499
|
|
|
@@ -494,7 +503,7 @@ Run an independent validation pass over the merged finding set before synthesis.
|
|
|
494
503
|
|
|
495
504
|
Assemble the final report using **pipe-delimited markdown tables for findings** from the review output template included below. The table format is mandatory for finding rows in interactive mode — do not render findings as freeform text blocks or horizontal-rule-separated prose. Other report sections (Applied Fixes, Learnings, Coverage, etc.) use bullet lists and the `---` separator before the verdict, as shown in the template.
|
|
496
505
|
|
|
497
|
-
1. **Header.** Scope, intent, mode, reviewer team with per-conditional justifications.
|
|
506
|
+
1. **Header.** Scope, intent, mode, harness, reviewer team with per-conditional justifications.
|
|
498
507
|
2. **Findings.** Rendered as pipe-delimited tables grouped by severity (`### P0 -- Critical`, `### P1 -- High`, `### P2 -- Moderate`, `### P3 -- Low`). Each finding row shows `#`, file, issue, reviewer(s), confidence, and synthesized route. Omit empty severity levels. Never render findings as freeform text blocks or numbered lists. Only findings with `validated: true` (or no `validated` annotation) appear in these tables.
|
|
499
508
|
3. **Requirements Completeness.** Include only when a plan was found in Stage 2b. For each requirement (R1, R2, etc.) and implementation unit in the plan, report whether corresponding work appears in the diff. Use a simple checklist: met / not addressed / partially addressed. Routing depends on `plan_source`:
|
|
500
509
|
- **`explicit`** (caller-provided or PR body): Flag unaddressed requirements as P1 findings with `autofix_class: manual`, `owner: downstream-resolver`. These enter the residual actionable queue and can become todos.
|
|
@@ -525,7 +534,7 @@ Scope: <scope-line>
|
|
|
525
534
|
Intent: <intent-summary>
|
|
526
535
|
Reviewers: <reviewer-list with conditional justifications>
|
|
527
536
|
Verdict: <Ready to merge | Ready with fixes | Not ready>
|
|
528
|
-
Artifact: .context/systematic/ce-review/<run-id>/
|
|
537
|
+
Artifact: .context/systematic/ce-review/<run-id>/review-summary.json
|
|
529
538
|
|
|
530
539
|
Applied N safe_auto fixes.
|
|
531
540
|
|
|
@@ -583,15 +592,15 @@ Coverage:
|
|
|
583
592
|
Review complete
|
|
584
593
|
```
|
|
585
594
|
|
|
586
|
-
**Detail enrichment (headless only):** The headless envelope includes `Why:`, `Evidence:`, and `Suggested fix:` lines. After merge (Stage 5),
|
|
587
|
-
- **Field tiers:** `Why:` and `Evidence:` are detail-tier
|
|
588
|
-
- **
|
|
589
|
-
- **Reviewer order:** Try contributing reviewers in the order they appear in the merged finding's reviewer list; use the first match.
|
|
590
|
-
- **No-match fallback:** If no
|
|
595
|
+
**Detail enrichment (headless only):** The headless envelope includes `Why:`, `Evidence:`, and `Suggested fix:` lines. After merge (Stage 5), use the validated full persona returns retained in parent memory for only the findings that survived dedup and confidence gating.
|
|
596
|
+
- **Field tiers:** `Why:` and `Evidence:` are detail-tier and are already present in the validated inline return. `Suggested fix:` is also available directly from that return and survives merge as optional fix context.
|
|
597
|
+
- **In-memory matching:** For each surviving finding, look up its detail-tier fields in the validated returns of the contributing reviewers. Match on `file + line_bucket(line, +/-3)` (the same tolerance used in Stage 5 dedup). When multiple entries fall within the line bucket, apply `normalize(title)` to the merged finding's title and each candidate entry's title as a tie-breaker.
|
|
598
|
+
- **Reviewer order:** Try contributing reviewers in the order they appear in the merged finding's reviewer list; use the first validated match.
|
|
599
|
+
- **No-match fallback:** If no validated in-memory return contains a match, omit the `Why:` and `Evidence:` lines for that finding and note the gap in Coverage. This should indicate a synthesis/matching gap, not a failed artifact-file write. Never re-read per-agent files to recover detail.
|
|
591
600
|
|
|
592
601
|
**Formatting rules:**
|
|
593
602
|
- The `[needs-verification]` marker appears only on findings where `requires_verification: true`.
|
|
594
|
-
- The `Artifact:` line gives callers the path to the
|
|
603
|
+
- The `Artifact:` line gives callers the path to the parent-written `review-summary.json` for machine-readable access to the complete findings schema, provenance, dispatch outcomes, and disposition ledger. The text envelope is the primary handoff; the artifact is for debugging and full-fidelity access.
|
|
595
604
|
- Findings with `owner: release` appear in the Advisory section (they are operational/rollout items, not code fixes).
|
|
596
605
|
- Findings with `pre_existing: true` appear in the Pre-existing section regardless of autofix_class.
|
|
597
606
|
- Findings with `validated: false` from Stage 5b appear in the "Filtered (not validated)" section. They are surfaced for human review — not removed. Include the validator reason on the indented `Validator reason:` line.
|
|
@@ -691,18 +700,22 @@ After presenting findings and verdict (Stage 6), route the next steps by mode. R
|
|
|
691
700
|
|
|
692
701
|
#### Step 4: Emit artifacts and downstream handoff
|
|
693
702
|
|
|
694
|
-
- In interactive, autofix, and headless modes, write
|
|
695
|
-
|
|
696
|
-
-
|
|
697
|
-
-
|
|
698
|
-
-
|
|
699
|
-
|
|
703
|
+
- In interactive, autofix, and headless modes, write **`review-summary.json` unconditionally** under `.context/systematic/ce-review/<run-id>/`, including when every persona returns `empty` and there are zero surviving findings. `mode:report-only` remains exempt: it skips run-id and directory creation and writes nothing.
|
|
704
|
+
- `review-summary.json` is the parent-owned synthesis artifact and must contain, at minimum:
|
|
705
|
+
- `run_id`, `mode`, `harness` (`opencode`, `pi`, or `claude-code`), and run lifecycle fields;
|
|
706
|
+
- a `dispatches` entry for every selected persona with `persona`, `dispatch_outcome` (`findings`, `empty`, `malformed`, or `never_returned`), the number of safely enumerated input findings, and the exact safe `rejection_reason` when applicable;
|
|
707
|
+
- an `input_findings` ledger with one entry per safely enumerated input, its `input_id`, reviewer, original confidence, final `disposition` (`surviving`, `merged`, `suppressed`, `filtered`, or `rejected`), and a stated reason. Its count must reconcile exactly with the sum of disposition counts. A malformed JSON return with no safely enumerable finding has zero ledger entries, not a fabricated finding;
|
|
708
|
+
- surviving synthesized findings and filtered findings, each retaining their original fields plus `input_finding_ids` and provenance. Every synthesized finding's provenance must include the exact dedup `fingerprint`, `submitters`, and `agreement_credit` arrays. `submitters` means independent input submissions; `agreement_credit` means agreement boost credit without a corresponding input submission;
|
|
709
|
+
- applied fixes, residual actionable work, advisory-only outputs, coverage data, and the harness value.
|
|
710
|
+
- During the pre-dispatch setup described in Stage 4, initialize the synthesis artifact with lifecycle state `in_progress` and all selected personas initialized as `never_returned`. Update each dispatch entry as returns arrive. Finalize it as `completed` or `degraded` after synthesis; if the parent catches an abort or storage/orchestration failure, finalize it as `abnormal` with the stated termination reason. If the process dies before finalization, the pre-written `in_progress` artifact is itself an explicit incomplete run and must be counted as abnormal rather than treated as a missing or clean run. Never infer a clean run from an absent artifact.
|
|
711
|
+
- Per-agent full-detail JSON files (`{reviewer_name}.json`) are written by the parent only after the persona return passes full-schema and environment-value validation. Rejected or never-returned personas do not produce a per-agent file; their dispatch outcome remains in the synthesis artifact. If a later confidence or validation stage changes an input disposition, update the parent-owned record and synthesis ledger before finalizing `review-summary.json`.
|
|
700
712
|
- Also write `metadata.json` alongside the findings so downstream skills can verify the artifact matches the current branch and HEAD. Minimum fields:
|
|
701
713
|
```json
|
|
702
714
|
{
|
|
703
715
|
"run_id": "<run-id>",
|
|
704
716
|
"branch": "<git branch --show-current at dispatch time>",
|
|
705
717
|
"head_sha": "<git rev-parse HEAD at dispatch time>",
|
|
718
|
+
"harness": "<opencode | pi | claude-code>",
|
|
706
719
|
"verdict": "<Ready to merge | Ready with fixes | Not ready>",
|
|
707
720
|
"completed_at": "<ISO 8601 UTC timestamp>"
|
|
708
721
|
}
|