@fro.bot/systematic 3.16.5 → 3.18.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.
- package/HARNESSES.md +26 -0
- package/dist/ce-review-validator.d.ts +23 -0
- package/dist/cli.d.ts +10 -0
- package/dist/cli.js +437 -29
- package/dist/{index-65g87tgr.js → index-y33enbkc.js} +5 -5
- package/dist/index.js +18 -13
- package/dist/lib/bundled-names.d.ts +1 -1
- package/dist/lib/config-schema.d.ts +426 -3
- package/dist/lib/review-artifact-schema.d.ts +171 -1
- package/dist/lib/review-return-validator.d.ts +59 -0
- package/dist/pi.js +7 -6
- package/dist/schemas/systematic-config.schema.json +1 -0
- package/package.json +6 -4
- package/skills/ce-review/SKILL.md +88 -38
- package/skills/ce-review/references/findings-schema.json +271 -192
- package/skills/ce-review/references/persona-catalog.md +39 -25
- package/skills/ce-review/references/review-output-template.md +3 -3
- package/skills/ce-review/references/review-summary-schema.json +7 -1
- package/skills/ce-review/references/subagent-template.md +8 -2
- package/skills/ce-review/references/synthesis-artifact-contract.md +102 -11
- package/skills/ce-review/scripts/ensure-ignore.mjs +599 -0
- package/skills/ce-review/scripts/validate-review.mjs +6922 -0
- package/skills/ce-review-cleanup/SKILL.md +69 -0
- package/skills/ce-review-cleanup/scripts/cleanup.mjs +1391 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Persona Catalog
|
|
2
2
|
|
|
3
|
-
13 reviewer personas organized into
|
|
3
|
+
13 reviewer personas organized into a three-persona core, cross-cutting conditional, and stack-specific conditional layers, plus CE-specific conditional agents. The orchestrator uses this catalog to select which reviewers to spawn for each review.
|
|
4
4
|
|
|
5
5
|
## Shared persona pool
|
|
6
6
|
|
|
@@ -10,38 +10,29 @@ The `agents/review/` directory is a shared persona pool, not `ce:review`'s roste
|
|
|
10
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
11
|
- `systematic:review:code-simplicity-reviewer` — dispatched by `ce-compound` for code-heavy issues.
|
|
12
12
|
|
|
13
|
-
## Always-on (
|
|
13
|
+
## Always-on (3 core personas)
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
**Persona agents (structured JSON output):**
|
|
15
|
+
Selected on every review regardless of diff content. These three are the only reviewers with no selection condition.
|
|
18
16
|
|
|
19
17
|
| Persona | Agent | Focus |
|
|
20
18
|
|---------|-------|-------|
|
|
21
19
|
| `correctness` | `systematic:review:correctness-reviewer` | Logic errors, edge cases, state bugs, error propagation, intent compliance |
|
|
22
20
|
| `testing` | `systematic:review:testing-reviewer` | Coverage gaps, weak assertions, brittle tests, missing edge case tests |
|
|
23
|
-
| `maintainability` | `systematic:review:maintainability-reviewer` | Coupling, complexity, naming, dead code, premature abstraction |
|
|
24
21
|
| `project-standards` | `systematic:review:project-standards-reviewer` | AGENTS.md compliance -- frontmatter, references, naming, cross-platform portability, tool selection |
|
|
25
22
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
| Agent | Focus |
|
|
29
|
-
|-------|-------|
|
|
30
|
-
| `systematic:review:agent-native-reviewer` | Verify new features are agent-accessible |
|
|
31
|
-
| `systematic:research:learnings-researcher` | Search docs/solutions/ for past issues related to this PR's modules and patterns |
|
|
32
|
-
|
|
33
|
-
## Conditional (8 personas)
|
|
23
|
+
## Conditional (9 personas)
|
|
34
24
|
|
|
35
|
-
Spawned when the orchestrator identifies relevant
|
|
25
|
+
Spawned only when the orchestrator identifies a relevant surface in the diff. The orchestrator reads the full diff and reasons about selection -- this is agent judgment, not keyword matching. Record `selection_reason` and a non-empty `selection_surface` for each selected conditional persona.
|
|
36
26
|
|
|
37
27
|
| Persona | Agent | Select when diff touches... |
|
|
38
28
|
|---------|-------|---------------------------|
|
|
29
|
+
| `maintainability` | `systematic:review:maintainability-reviewer` | Materially adds or reshapes abstractions, raises cross-module coupling, adds state/control-flow complexity, changes naming or ownership structure, removes dead code, or performs a broad refactor. Do not select it for a tiny prose or fixture correction with no structural decision and no user- or agent-facing or other specialist surface. |
|
|
39
30
|
| `security` | `systematic:review:security-reviewer` | Auth middleware, public endpoints, user input handling, permission checks, secrets management |
|
|
40
31
|
| `performance` | `systematic:review:performance-reviewer` | Database queries, ORM calls, loop-heavy data transforms, caching layers, async/concurrent code |
|
|
41
32
|
| `api-contract` | `systematic:review:api-contract-reviewer` | Route definitions, serializer/interface changes, event schemas, exported type signatures, API versioning |
|
|
42
33
|
| `data-migrations` | `systematic:review:data-migrations-reviewer` | Migration files, schema changes, backfill scripts, data transformations |
|
|
43
34
|
| `reliability` | `systematic:review:reliability-reviewer` | Error handling, retry logic, circuit breakers, timeouts, background jobs, async handlers, health checks |
|
|
44
|
-
| `adversarial` | `systematic:review:adversarial-reviewer` |
|
|
35
|
+
| `adversarial` | `systematic:review:adversarial-reviewer` | >=50 changed lines of executable production code, excluding tests, generated files, lockfiles, instruction/prose Markdown, JSON schemas, and config; OR regardless of file type for auth, payments, data mutations, external APIs, or another explicitly high-risk domain |
|
|
45
36
|
| `cli-readiness` | `systematic:review:cli-readiness-reviewer` | CLI command definitions, argument parsing, CLI framework usage, command handler implementations |
|
|
46
37
|
| `previous-comments` | `systematic:review:previous-comments-reviewer` | **PR-only.** Reviewing a PR that has existing review comments or review threads from prior review rounds. Skip entirely when no PR metadata was gathered in Stage 1. |
|
|
47
38
|
|
|
@@ -53,18 +44,41 @@ These reviewers keep their original opinionated lens. They are additive with the
|
|
|
53
44
|
|---------|-------|---------------------------|
|
|
54
45
|
| `kieran-typescript` | `systematic:review:kieran-typescript-reviewer` | TypeScript components, services, hooks, utilities, or shared types |
|
|
55
46
|
|
|
56
|
-
## CE Conditional Agents (
|
|
47
|
+
## CE Conditional Agents (3)
|
|
57
48
|
|
|
58
|
-
These CE-native agents provide specialized analysis beyond what the persona agents cover.
|
|
49
|
+
These CE-native agents provide specialized analysis beyond what the persona agents cover. Their output is unstructured and synthesized separately; they never receive a raw-return dispatch record. Announce and report their selection reason/surface in the team and Coverage instead.
|
|
59
50
|
|
|
60
|
-
| Agent |
|
|
61
|
-
|
|
62
|
-
| `systematic:review:
|
|
51
|
+
| Agent | Select when diff includes... |
|
|
52
|
+
|-------|------------------------------|
|
|
53
|
+
| `systematic:review:agent-native-reviewer` | A user- or agent-facing UI, CLI, tool, or workflow capability, or a changed access path where agent parity or discoverability is material. Do not select it for every review. |
|
|
54
|
+
| `systematic:research:learnings-researcher` | Bug, regression, or hardening work; a recurring failure class; a change to a documented solution or module; or a plan/PR that cites relevant prior art. Do not select it for every review. |
|
|
55
|
+
| `systematic:review:deployment-verification-agent` | Database migrations (`db/migrate/*.rb`, `db/schema.rb`) or data backfill scripts. |
|
|
63
56
|
|
|
64
57
|
## Selection rules
|
|
65
58
|
|
|
66
|
-
1. **Always
|
|
67
|
-
2. **For each cross-cutting conditional persona**,
|
|
59
|
+
1. **Always select exactly the three core personas:** `correctness`, `testing`, and `project-standards`. Nothing else is always-on.
|
|
60
|
+
2. **For each cross-cutting conditional persona**, read the diff and decide whether the persona's domain is relevant. This is a judgment call, not a keyword match. A tiny prose or fixture correction is core-only only when it has no structural decision and no user- or agent-facing behavior, access change, or other specialist surface; a structural refactor may add `maintainability`; an auth feature may add `security` and `reliability`.
|
|
68
61
|
3. **For each stack-specific conditional persona**, use file types and changed patterns as a starting point, then decide whether the diff actually introduces meaningful work for that reviewer. Do not spawn language-specific reviewers just because one config or generated file happens to match the extension.
|
|
69
|
-
4. **For CE conditional agents**,
|
|
70
|
-
5. **
|
|
62
|
+
4. **For CE conditional agents**, select `agent-native-reviewer` for agent-facing capability changes, `learnings-researcher` for bug/regression/hardening or recurring-defect work, and `deployment-verification-agent` for migrations or data backfills. Their output is unstructured; report their selection reason/surface in the team and Coverage rather than a dispatch record.
|
|
63
|
+
5. **Record selection metadata.** Every selected structured conditional persona records `selection_reason` and a non-empty `selection_surface`; core personas may omit both.
|
|
64
|
+
6. **Announce the team** before spawning with a one-line rationale and the triggering repository-relative paths/surfaces per selected conditional. Distinguish core reviewers, selected conditionals, an explicit "no conditional selected" case, and selected-but-failed/malformed/validation-unavailable reviewers. Never label an unselected reviewer as failed.
|
|
65
|
+
7. **Reviewer count is an outcome, not a target.** Never restore a fixed floor; a smaller selected set is not automatically better or worse than a larger one.
|
|
66
|
+
|
|
67
|
+
## Selection scenarios
|
|
68
|
+
|
|
69
|
+
| Scenario | Selected |
|
|
70
|
+
|----------|----------|
|
|
71
|
+
| Tiny prose or fixture correction with no structural decision and no user- or agent-facing or other specialist surface | `correctness`, `testing`, `project-standards` only; no runtime probe |
|
|
72
|
+
| Structural refactor adding or reshaping abstractions, coupling, state, or control flow | core plus `maintainability` |
|
|
73
|
+
| Agent-facing UI/CLI/tool/workflow capability or changed access path | core plus CE `agent-native-reviewer` |
|
|
74
|
+
| Bug, regression, or hardening work; recurring failure class; documented solution/module touched; plan/PR citing prior art | core plus CE `learnings-researcher` |
|
|
75
|
+
| Auth surface | core plus `security` |
|
|
76
|
+
| Migration or backfill | core plus `data-migrations` and CE `deployment-verification-agent` |
|
|
77
|
+
| Public API/route/serializer/type-signature change | core plus `api-contract` |
|
|
78
|
+
| Error handling, retries, timeouts, background jobs | core plus `reliability` |
|
|
79
|
+
| Query, loop, caching, or concurrency hot path | core plus `performance` |
|
|
80
|
+
| Renderer or asset-delivery change needing runtime evidence | a focused execution probe (independent of reviewer selection); a change that separately triggers a conditional still selects that reviewer |
|
|
81
|
+
|
|
82
|
+
## Execution probes (separate parent decision)
|
|
83
|
+
|
|
84
|
+
A focused execution probe is independent of reviewer selection. A pure renderer or asset-delivery change with no conditional surface may be core plus a probe, but a change that separately triggers `agent-native-reviewer`, `security`, or another conditional still selects those reviewers. An execution probe is not a reviewer and never substitutes for risk-critical reviewer coverage; selecting a probe never adds `maintainability` and never restores a reviewer floor. When selected, record the probe target and its permission boundary in Coverage.
|
|
@@ -134,10 +134,10 @@ This fails because: no pipe-delimited tables, no severity-grouped `###` headers,
|
|
|
134
134
|
- **Residual Actionable Work section** -- include only when unresolved actionable findings were handed off for later work
|
|
135
135
|
- **Pre-existing section** -- separate table, no confidence column (these are informational)
|
|
136
136
|
- **Filtered (not validated) section** -- findings where Stage 5b returned `validated: false`. Rendered as a pipe-delimited table with columns `#`, `File`, `Issue`, `Reviewer`, `Confidence`, `Validator reason`. These findings are surfaced for human review, not removed. Omit this section when Stage 5b produced no filtered findings.
|
|
137
|
-
- **Learnings & Past Solutions section** --
|
|
138
|
-
- **Agent-Native Gaps section** --
|
|
137
|
+
- **Learnings & Past Solutions section** -- render only when CE `learnings-researcher` was selected and returned relevant output; results with links to docs/solutions/ files. Omit otherwise.
|
|
138
|
+
- **Agent-Native Gaps section** -- render only when CE `agent-native-reviewer` was selected and returned relevant output. Omit otherwise.
|
|
139
139
|
- **Deployment Notes section** -- key checklist items from deployment-verification-agent. Omit if the agent did not run.
|
|
140
|
-
- **Coverage section** -- suppressed count with original confidences, residual risks, testing gaps, failed reviewers, disposition reconciliation, and risk-coverage entries with their citing input finding IDs and blocked-entry exit conditions
|
|
140
|
+
- **Coverage section** -- suppressed count with original confidences, residual risks, testing gaps, failed reviewers, disposition reconciliation, and risk-coverage entries with their citing input finding IDs and blocked-entry exit conditions. For raw returns, distinguish `findings`, `empty`, `malformed`, `never_returned`, `validation_unavailable` (the persisted raw dispatch outcome, distinct from the artifact-level `validation.status: "unavailable"`), and `environment-screen` rejection, and state what was admitted or withheld
|
|
141
141
|
- **Summary uses blockquotes** for verdict, reasoning, and fix order
|
|
142
142
|
- **Horizontal rule** (`---`) separates findings from verdict
|
|
143
143
|
- **`###` headers** for each section -- never plain text headers
|
|
@@ -57,7 +57,13 @@
|
|
|
57
57
|
},
|
|
58
58
|
"dispatch_outcome": {
|
|
59
59
|
"type": "string",
|
|
60
|
-
"enum": [
|
|
60
|
+
"enum": [
|
|
61
|
+
"findings",
|
|
62
|
+
"empty",
|
|
63
|
+
"malformed",
|
|
64
|
+
"never_returned",
|
|
65
|
+
"validation_unavailable"
|
|
66
|
+
]
|
|
61
67
|
},
|
|
62
68
|
"input_finding_count": {
|
|
63
69
|
"type": "integer",
|
|
@@ -24,7 +24,7 @@ The supplied diff is the primary source of truth. Use the supplied paths and lin
|
|
|
24
24
|
<output-contract>
|
|
25
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
|
-
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.
|
|
27
|
+
Do not write any file. Do not use a Run ID or an artifact path. Persistence is owned by the parent orchestrator: it structurally validates this returned payload with the packaged validator before it parses any field, adds parent-owned provenance, and writes only conforming data. Return exactly one JSON payload; never wrap it in prose, markdown, or a parent-owned annotation. This rule is the same in every supported harness.
|
|
28
28
|
|
|
29
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.
|
|
30
30
|
|
|
@@ -53,7 +53,7 @@ Rules:
|
|
|
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
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`).
|
|
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.
|
|
59
59
|
- Set `autofix_class` accurately -- not every finding is `advisory`. Use this decision guide:
|
|
@@ -78,6 +78,10 @@ Reviewer name: {reviewer_name}
|
|
|
78
78
|
|
|
79
79
|
Intent: {intent_summary}
|
|
80
80
|
|
|
81
|
+
Selection reason: {selection_reason}
|
|
82
|
+
|
|
83
|
+
Selection surface: {selection_surface}
|
|
84
|
+
|
|
81
85
|
Changed files: {file_list}
|
|
82
86
|
|
|
83
87
|
Diff:
|
|
@@ -97,3 +101,5 @@ Diff:
|
|
|
97
101
|
| `{file_list}` | Stage 1 output | List of changed files from the scope step |
|
|
98
102
|
| `{diff}` | Stage 1 output | The actual diff content to review |
|
|
99
103
|
| `{reviewer_name}` | Stage 3 output | Persona name used in the returned `reviewer` field |
|
|
104
|
+
| `{selection_reason}` | Stage 3 output | One-line reason this conditional persona was selected. Empty for core personas, which have no selection condition |
|
|
105
|
+
| `{selection_surface}` | Stage 3 output | Non-empty repository-relative paths/surfaces that triggered selection. Empty for core personas. These are bounded domain hints for the reviewer, not fields of the returned payload |
|
|
@@ -11,9 +11,18 @@ For interactive, autofix, and headless runs, the parent writes
|
|
|
11
11
|
`review-summary.json` even when every selected persona returns `empty` and no
|
|
12
12
|
finding survives. `mode:report-only` is the deliberate no-write exception.
|
|
13
13
|
|
|
14
|
+
Ignore preparation is a prerequisite check, not a run stage: when it blocks
|
|
15
|
+
(see `ce:review`'s Ignore preparation section), the run stops before any
|
|
16
|
+
run ID, directory, or dispatch exists. This is no artifact at all, not an
|
|
17
|
+
abnormal or partial one -- the parent never fabricates or claims a validated
|
|
18
|
+
run artifact for a run that never started.
|
|
19
|
+
|
|
14
20
|
The parent initializes the artifact as `in_progress` before dispatch, with all
|
|
15
21
|
selected personas initialized as `never_returned`, and updates each dispatch
|
|
16
|
-
entry as returns arrive. A
|
|
22
|
+
entry as returns arrive. A persona that returned but whose raw validator could
|
|
23
|
+
not run is updated from `never_returned` to `dispatch_outcome:
|
|
24
|
+
"validation_unavailable"`; it is never omitted and never left as
|
|
25
|
+
`never_returned`. A completed run becomes `completed` or `degraded`. An
|
|
17
26
|
interrupted or failed run becomes `abnormal` with its stated termination
|
|
18
27
|
reason. An unfinished `in_progress` artifact is evidence of an abnormal run,
|
|
19
28
|
not evidence of a clean run. Never infer a clean run from an absent artifact.
|
|
@@ -22,8 +31,8 @@ The artifact is parent-owned. Per-agent full-detail JSON files are written
|
|
|
22
31
|
only for findings admitted after the parent completes schema and
|
|
23
32
|
environment-value validation. A finding rejected by environment-value
|
|
24
33
|
detection is not persisted; other findings from the same return may proceed.
|
|
25
|
-
A payload rejected at top level, or a rejected
|
|
26
|
-
does not produce a per-agent file. If a later confidence or validation stage
|
|
34
|
+
A payload rejected at top level, or a rejected, never-returned, or
|
|
35
|
+
validation-unavailable persona, does not produce a per-agent file. If a later confidence or validation stage
|
|
27
36
|
changes an input disposition, the parent updates the record and synthesis
|
|
28
37
|
ledger before finalizing the artifact.
|
|
29
38
|
|
|
@@ -102,8 +111,9 @@ The artifact must preserve these distinctions:
|
|
|
102
111
|
```
|
|
103
112
|
|
|
104
113
|
- `dispatches` has an entry for every selected persona. `dispatch_outcome`
|
|
105
|
-
records what a persona returned: `findings`, `empty`, `malformed`,
|
|
106
|
-
`never_returned`. A rejection reason is the exact
|
|
114
|
+
records what a persona returned: `findings`, `empty`, `malformed`,
|
|
115
|
+
`never_returned`, or `validation_unavailable`. A rejection reason is the exact
|
|
116
|
+
safe validation reason,
|
|
107
117
|
naming persona and field without echoing the offending value. Dispatch
|
|
108
118
|
outcome is separate from finding disposition. Conditional selections record
|
|
109
119
|
their triggering changed-file paths in `selection_surface` and the announced
|
|
@@ -123,6 +133,13 @@ The artifact must preserve these distinctions:
|
|
|
123
133
|
never includes the offending value. Do not enumerate rejected findings or
|
|
124
134
|
assign them input IDs. A finding-level environment rejection uses the same
|
|
125
135
|
summary entry while admitted findings from that return continue normally.
|
|
136
|
+
New writers must emit a rejected-summary row only for `findings` or
|
|
137
|
+
`malformed`. The schema_version 1 validator deliberately continues to accept a
|
|
138
|
+
historical `empty` or `never_returned` rejected-summary row for backward
|
|
139
|
+
compatibility with existing artifacts, but that reader leniency is not
|
|
140
|
+
authoring permission to emit either. The validator rejects a rejected-summary
|
|
141
|
+
row for `validation_unavailable`, the additive outcome this contract
|
|
142
|
+
introduces, and writers must never emit it.
|
|
126
143
|
Disposition counts are weighted by `rejected_finding_count` for that summary
|
|
127
144
|
entry, so their sum equals the total number of findings observed, not the
|
|
128
145
|
number of ledger rows. A malformed JSON return with no safely enumerable
|
|
@@ -174,6 +191,71 @@ the review degrades while conforming returns continue through synthesis. Only
|
|
|
174
191
|
an orchestration or storage failure that prevents the parent from producing the
|
|
175
192
|
required run artifact is run-fatal.
|
|
176
193
|
|
|
194
|
+
## Raw-return admission and validation availability
|
|
195
|
+
|
|
196
|
+
Before a persona return is parsed into fields, screened for environment values,
|
|
197
|
+
assessed for evidence, synthesized, or persisted, the parent admits it with the
|
|
198
|
+
packaged structural validator:
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
# Resolve the validator relative to the skill's own directory.
|
|
202
|
+
SKILL_DIR="<skill directory stated when this skill loads>";
|
|
203
|
+
node "$SKILL_DIR/scripts/validate-review.mjs" return <<'REVIEW_RETURN_A1B2C3D4'
|
|
204
|
+
<the persona's returned JSON payload, copied verbatim>
|
|
205
|
+
REVIEW_RETURN_A1B2C3D4
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Before each invocation, choose a fresh delimiter for that exact raw payload from
|
|
209
|
+
a safe token alphabet (`A-Z`, `0-9`, `_`), verify the delimiter is absent as a
|
|
210
|
+
complete line in that exact payload, and never reuse a fixed delimiter. The
|
|
211
|
+
`REVIEW_RETURN_A1B2C3D4` token above is only an illustration. Open the heredoc
|
|
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.
|
|
216
|
+
|
|
217
|
+
The parent maps the result to `dispatch_outcome`, keeping lifecycle, structural
|
|
218
|
+
validity, environment screening, and evidence assessment separate:
|
|
219
|
+
|
|
220
|
+
- **exit 0** — structurally admitted. Parse the already structurally validated
|
|
221
|
+
JSON without logging the raw text, then run the existing environment-value
|
|
222
|
+
screen over that parsed object before persistence. Zero findings is `empty`;
|
|
223
|
+
one or more findings is `findings`. Admission is structural only: it never
|
|
224
|
+
asserts that a finding's claims or cited evidence are true.
|
|
225
|
+
- **exit 1** — `malformed`. Record bounded validator diagnostics only; do not
|
|
226
|
+
parse, screen, or persist payload fields or values.
|
|
227
|
+
- **exit 2**, a missing or unreadable helper, or a launch failure — validation
|
|
228
|
+
unavailable. Withhold the return and report the exact unavailability and what
|
|
229
|
+
was withheld. Update that selected persona's preinitialized dispatch entry
|
|
230
|
+
from `never_returned` to `dispatch_outcome: "validation_unavailable"` with
|
|
231
|
+
`input_finding_count: 0` and, optionally, a safe `rejection_reason` naming the
|
|
232
|
+
exit status, missing helper, or launch failure without payload values. Set
|
|
233
|
+
`run_status` to `degraded`. Never omit the dispatch entry, never leave it as
|
|
234
|
+
`never_returned`, never label it `malformed`, never admit the payload, and
|
|
235
|
+
never fabricate a rejected-summary ledger row. `never_returned` is a
|
|
236
|
+
task-lifecycle fact for a task that did not return. Validation unavailable is
|
|
237
|
+
not malformed and is not never_returned.
|
|
238
|
+
|
|
239
|
+
**Dispatch identity binding.** Structural admission does not prove who produced a
|
|
240
|
+
return. Immediately after `exit 0` and before the environment-value screen,
|
|
241
|
+
persistence, or synthesis, the parent parses the admitted return's `reviewer`
|
|
242
|
+
field and confirms it equals the dispatched persona. A return whose `reviewer`
|
|
243
|
+
does not match the dispatched persona is an identity mismatch: reject the whole
|
|
244
|
+
return as `dispatch_outcome: "malformed"`, record only a bounded rejection reason
|
|
245
|
+
naming the expected persona, set `run_status` to `degraded`, and do not admit,
|
|
246
|
+
screen, persist, or synthesize its payload.
|
|
247
|
+
|
|
248
|
+
`validation_unavailable` is an additive enum value: `schema_version` stays `1`,
|
|
249
|
+
existing v1 artifacts remain valid, and no new field or migration is introduced.
|
|
250
|
+
A run that contains `validation_unavailable` evidence records a zero
|
|
251
|
+
`input_finding_count`, no admitted input finding for that persona, and a
|
|
252
|
+
non-`completed` run status; unavailable evidence can never finalize as a clean,
|
|
253
|
+
completed run.
|
|
254
|
+
The word `unavailable` also names the artifact-level `validation.status` value;
|
|
255
|
+
that is a different object and phase, and these fields are never repurposed for
|
|
256
|
+
raw-dispatch availability. These admission states are surfaced in the report's
|
|
257
|
+
Coverage, which reports the exact unavailability and what was withheld.
|
|
258
|
+
|
|
177
259
|
## Environment-value validation
|
|
178
260
|
|
|
179
261
|
The parent recursively inspects every string leaf without logging the raw
|
|
@@ -211,10 +293,18 @@ validating it. This ordering makes the artifact validatable at all: without
|
|
|
211
293
|
a real validation result.
|
|
212
294
|
|
|
213
295
|
After writing `review-summary.json`, the parent resolves and runs a validator
|
|
214
|
-
in this order: the
|
|
215
|
-
|
|
216
|
-
command.
|
|
217
|
-
|
|
296
|
+
in this order: the skill-local helper first, then the bundled
|
|
297
|
+
`systematic-validate-review-artifact <path>` command, then the npm-installed
|
|
298
|
+
`systematic validate-review-artifact <path>` command. All can be present at
|
|
299
|
+
once. The skill-local helper ships beside the prose being executed, so it is
|
|
300
|
+
the one whose behavior matches the contract; the other two remain fallbacks.
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
# Resolve the validator relative to the skill's own directory.
|
|
304
|
+
SKILL_DIR="<skill directory stated when this skill loads>";
|
|
305
|
+
ARTIFACT_PATH="<review-summary.json path>";
|
|
306
|
+
node "$SKILL_DIR/scripts/validate-review.mjs" artifact "$ARTIFACT_PATH"
|
|
307
|
+
```
|
|
218
308
|
The parent runs the first command it resolves and reads its result; it does not
|
|
219
309
|
merely test whether a name is on `PATH`, because a version-manager shim can be
|
|
220
310
|
present there and fail on every invocation.
|
|
@@ -290,8 +380,9 @@ against at all.
|
|
|
290
380
|
The risk-critical surfaces are `security`, `data-migrations`, `api-contract`,
|
|
291
381
|
`reliability`, and `performance`. They are the conditional personas selected
|
|
292
382
|
specifically for the matching diff shape in Stage 3. If one of those selected
|
|
293
|
-
personas has `dispatch_outcome: "malformed"
|
|
294
|
-
`dispatch_outcome: "never_returned"`,
|
|
383
|
+
personas has `dispatch_outcome: "malformed"`,
|
|
384
|
+
`dispatch_outcome: "never_returned"`, or `dispatch_outcome:
|
|
385
|
+
"validation_unavailable"`, the review verdict must not be clean:
|
|
295
386
|
it is blocking unless another persona covered the lost surface with validated
|
|
296
387
|
evidence. For this rule, a validated finding from another persona covers a
|
|
297
388
|
lost risk-critical surface if and only if the finding's `file` appears in the
|