@fro.bot/systematic 3.18.3 → 3.18.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/HARNESSES.md +8 -4
- package/dist/ce-review-validator.d.ts +43 -2
- package/dist/cli.js +10 -16
- package/dist/lib/review-artifact-schema.d.ts +18 -1
- package/dist/lib/review-pipeline-contract.d.ts +1446 -0
- package/dist/lib/review-pipeline.d.ts +812 -0
- package/dist/lib/review-return-validator.d.ts +19 -0
- package/package.json +1 -1
- package/skills/ce-review/SKILL.md +54 -83
- package/skills/ce-review/references/pipeline-invocation.md +263 -0
- package/skills/ce-review/references/review-output-template.md +2 -1
- package/skills/ce-review/references/review-pipeline-schema.json +391 -0
- package/skills/ce-review/references/subagent-template.md +1 -1
- package/skills/ce-review/references/synthesis-artifact-contract.md +57 -68
- package/skills/ce-review/scripts/validate-review.mjs +3277 -58
package/HARNESSES.md
CHANGED
|
@@ -55,13 +55,17 @@ Behavioral enforcement rides a plugin output style (`force-for-plugin: true`), w
|
|
|
55
55
|
|
|
56
56
|
Honest capability boundary: output-style enforcement is real and applies automatically on install, but it operates at the system-prompt level — the same layer as any other instruction the model receives — so it is strong guidance, not a hard gate the model cannot violate. Coverage also differs by surface: plugin-bundled hooks fire app-wide, including in Cowork, while a project-local `.claude/settings.json` hook fires in the Code tab but not in Cowork — state or enforcement reaching Cowork sessions has to come through the plugin, not a project-local hook. Integration coverage lives in `tests/integration/claude-code.test.ts` [CC-10].
|
|
57
57
|
|
|
58
|
-
## Review
|
|
58
|
+
## Review synthesis pipeline validator — packaged paths
|
|
59
59
|
|
|
60
|
-
The raw-return and
|
|
60
|
+
The raw-return validator and the four-phase synthesis pipeline (`screen`, `prepare`, `merge`,
|
|
61
|
+
`finalize`) ship as one self-contained Node bundle,
|
|
61
62
|
`skills/ce-review/scripts/validate-review.mjs`, generated from
|
|
62
63
|
`src/ce-review-validator.ts` by `scripts/generate-ce-review-validator.ts` and
|
|
63
|
-
gated by `bun run ce-review-validator:drift`.
|
|
64
|
-
|
|
64
|
+
gated by `bun run ce-review-validator:drift`. The bundle dispatches six subcommands (`return`,
|
|
65
|
+
`artifact`, `screen`, `prepare`, `merge`, `finalize`) through one shared exit-code vocabulary (0
|
|
66
|
+
ok, 1 rejection/oversized/invalid UTF-8, 2 usage/TTY/read failure) and one exception boundary;
|
|
67
|
+
`merge` and `finalize` run through one shared strict-JSON stdin runner bounded by
|
|
68
|
+
`AGGREGATE_STDIN_BYTE_CAP`. Recorded execution evidence for this surface:
|
|
65
69
|
|
|
66
70
|
- **npm / OpenCode / Pi package layout** — real Node execution from an extracted
|
|
67
71
|
`npm pack --ignore-scripts` archive, resolving the script through its packaged
|
|
@@ -4,14 +4,55 @@ import { type ReadChunk } from './lib/review-return-validator.js';
|
|
|
4
4
|
* validator shim (`skills/ce-review/scripts/validate-review.mjs`).
|
|
5
5
|
*
|
|
6
6
|
* This is a thin packaging compatibility shim, not a public extension point:
|
|
7
|
-
* it dispatches exactly
|
|
7
|
+
* it dispatches exactly six subcommands and owns no validation logic
|
|
8
|
+
* beyond `screen`'s flag parsing and stdin plumbing.
|
|
8
9
|
* - `return` -> the bounded raw persona-return validator (stdin).
|
|
9
10
|
* - `artifact` -> the existing aggregate review-artifact validator.
|
|
11
|
+
* - `screen` -> executable reviewer-return admission (`screenReviewReturn`),
|
|
12
|
+
* reusing the same bounded stdin reader as `return`.
|
|
13
|
+
* - `prepare` -> executable candidate preparation (`prepareReviewCandidates`),
|
|
14
|
+
* reusing the same bounded stdin reader with the larger
|
|
15
|
+
* aggregate byte cap.
|
|
16
|
+
* - `merge` -> executable adjudication application
|
|
17
|
+
* (`applyReviewAdjudication`), reusing the same bounded
|
|
18
|
+
* stdin reader with the aggregate byte cap.
|
|
19
|
+
* - `finalize` -> executable finalize-envelope synthesis (`finalizeReview`),
|
|
20
|
+
* reusing the same bounded stdin reader with the aggregate
|
|
21
|
+
* byte cap.
|
|
10
22
|
*
|
|
11
23
|
* It exists because shipped skill layouts cannot all rely on the npm CLI or
|
|
12
24
|
* `dist/`; every harness invokes the committed bundle through `SKILL_DIR`.
|
|
13
25
|
*/
|
|
14
|
-
export declare const CE_REVIEW_VALIDATOR_USAGE = "Usage: node validate-review.mjs <return|artifact> [...]";
|
|
26
|
+
export declare const CE_REVIEW_VALIDATOR_USAGE = "Usage: node validate-review.mjs <return|artifact|screen|prepare|merge|finalize> [...]";
|
|
27
|
+
export declare const CE_REVIEW_SCREEN_USAGE = "Usage: node validate-review.mjs screen --reviewer <name> --harness <opencode|pi|claude-code>";
|
|
28
|
+
export declare const CE_REVIEW_SCREEN_STDIN_TTY_MESSAGE = "screen reads one raw reviewer return from stdin; interactive input is not supported";
|
|
29
|
+
export declare const CE_REVIEW_SCREEN_STDIN_READ_FAILED_MESSAGE = "screen could not read the reviewer return from stdin";
|
|
30
|
+
export declare const CE_REVIEW_SCREEN_STDIN_OVERSIZED_MESSAGE = "screen input exceeds the 1 MiB limit";
|
|
31
|
+
export declare const CE_REVIEW_SCREEN_STDIN_INVALID_UTF8_MESSAGE = "screen input is not valid UTF-8";
|
|
32
|
+
export declare const CE_REVIEW_SCREEN_STDIN_EMPTY_MESSAGE = "screen received empty stdin";
|
|
33
|
+
export declare const CE_REVIEW_SCREEN_REJECTED_MESSAGE = "screen rejected the reviewer return";
|
|
34
|
+
export declare const CE_REVIEW_SCREEN_INTERNAL_ERROR_MESSAGE = "ce-review-validator: internal error";
|
|
35
|
+
export declare const CE_REVIEW_PREPARE_USAGE = "Usage: node validate-review.mjs prepare";
|
|
36
|
+
export declare const CE_REVIEW_PREPARE_STDIN_TTY_MESSAGE = "prepare reads one aggregate JSON envelope from stdin; interactive input is not supported";
|
|
37
|
+
export declare const CE_REVIEW_PREPARE_STDIN_READ_FAILED_MESSAGE = "prepare could not read the aggregate envelope from stdin";
|
|
38
|
+
export declare const CE_REVIEW_PREPARE_STDIN_OVERSIZED_MESSAGE = "prepare input exceeds the aggregate byte cap";
|
|
39
|
+
export declare const CE_REVIEW_PREPARE_STDIN_INVALID_UTF8_MESSAGE = "prepare input is not valid UTF-8";
|
|
40
|
+
export declare const CE_REVIEW_PREPARE_STDIN_EMPTY_MESSAGE = "prepare received empty stdin";
|
|
41
|
+
export declare const CE_REVIEW_PREPARE_REJECTED_MESSAGE = "prepare rejected the aggregate envelope";
|
|
42
|
+
export declare const CE_REVIEW_MERGE_USAGE = "Usage: node validate-review.mjs merge";
|
|
43
|
+
export declare const CE_REVIEW_MERGE_STDIN_TTY_MESSAGE = "merge reads one aggregate JSON envelope from stdin; interactive input is not supported";
|
|
44
|
+
export declare const CE_REVIEW_MERGE_STDIN_READ_FAILED_MESSAGE = "merge could not read the aggregate envelope from stdin";
|
|
45
|
+
export declare const CE_REVIEW_MERGE_STDIN_OVERSIZED_MESSAGE = "merge input exceeds the aggregate byte cap";
|
|
46
|
+
export declare const CE_REVIEW_MERGE_STDIN_INVALID_UTF8_MESSAGE = "merge input is not valid UTF-8";
|
|
47
|
+
export declare const CE_REVIEW_MERGE_STDIN_EMPTY_MESSAGE = "merge received empty stdin";
|
|
48
|
+
export declare const CE_REVIEW_MERGE_REJECTED_MESSAGE = "merge rejected the aggregate envelope";
|
|
49
|
+
export declare const CE_REVIEW_FINALIZE_USAGE = "Usage: node validate-review.mjs finalize";
|
|
50
|
+
export declare const CE_REVIEW_FINALIZE_STDIN_TTY_MESSAGE = "finalize reads one aggregate JSON envelope from stdin; interactive input is not supported";
|
|
51
|
+
export declare const CE_REVIEW_FINALIZE_STDIN_READ_FAILED_MESSAGE = "finalize could not read the aggregate envelope from stdin";
|
|
52
|
+
export declare const CE_REVIEW_FINALIZE_STDIN_OVERSIZED_MESSAGE = "finalize input exceeds the aggregate byte cap";
|
|
53
|
+
export declare const CE_REVIEW_FINALIZE_STDIN_INVALID_UTF8_MESSAGE = "finalize input is not valid UTF-8";
|
|
54
|
+
export declare const CE_REVIEW_FINALIZE_STDIN_EMPTY_MESSAGE = "finalize received empty stdin";
|
|
55
|
+
export declare const CE_REVIEW_FINALIZE_REJECTED_MESSAGE = "finalize rejected the aggregate envelope";
|
|
15
56
|
export interface CeReviewValidatorOptions {
|
|
16
57
|
readonly argv: readonly string[];
|
|
17
58
|
readonly cwd?: string;
|
package/dist/cli.js
CHANGED
|
@@ -2204,7 +2204,6 @@ var REVIEW_ARTIFACT_CUSTOM_MESSAGES = [
|
|
|
2204
2204
|
"provenance.agreement_credit must not contain duplicate reviewers",
|
|
2205
2205
|
"provenance.agreement_credit must not overlap provenance.submitters",
|
|
2206
2206
|
"provenance.agreement_credit requires an eligible returned persona with admitted evidence",
|
|
2207
|
-
"satisfied risk coverage must cite a validated finding on the lost persona selection surface",
|
|
2208
2207
|
"satisfied risk coverage must cite an admitted ledger row owned by another persona"
|
|
2209
2208
|
];
|
|
2210
2209
|
var boundedText = (maxLength) => string().min(1).max(maxLength).regex(/\S/);
|
|
@@ -2243,7 +2242,13 @@ var RISK_CRITICAL_PERSONAS = [
|
|
|
2243
2242
|
];
|
|
2244
2243
|
var RiskCriticalPersonaSchema = _enum(RISK_CRITICAL_PERSONAS);
|
|
2245
2244
|
var FindingTitleSchema = boundedText(256);
|
|
2246
|
-
var SeveritySchema = _enum([
|
|
2245
|
+
var SeveritySchema = _enum([
|
|
2246
|
+
"P0",
|
|
2247
|
+
"P1",
|
|
2248
|
+
"P2",
|
|
2249
|
+
"P3",
|
|
2250
|
+
"unknown"
|
|
2251
|
+
]);
|
|
2247
2252
|
var FindingSeveritySchema = SeveritySchema.exclude(["unknown"]);
|
|
2248
2253
|
var AutofixClassSchema = _enum([
|
|
2249
2254
|
"safe_auto",
|
|
@@ -2592,17 +2597,6 @@ var ReviewArtifactSchema = object({
|
|
|
2592
2597
|
return;
|
|
2593
2598
|
}
|
|
2594
2599
|
if (owner === coverage.persona) {
|
|
2595
|
-
ctx.addIssue({
|
|
2596
|
-
code: "custom",
|
|
2597
|
-
path: ["risk_coverage", coverageIndex, "input_finding_id"],
|
|
2598
|
-
message: REVIEW_ARTIFACT_CUSTOM_MESSAGES[19]
|
|
2599
|
-
});
|
|
2600
|
-
return;
|
|
2601
|
-
}
|
|
2602
|
-
const lostDispatch = artifact.dispatches.find((dispatch) => dispatch.persona === coverage.persona);
|
|
2603
|
-
const surface = lostDispatch?.selection_surface ?? [];
|
|
2604
|
-
const covered = artifact.findings.some((finding) => finding.input_finding_ids.includes(citedId) && finding.validated !== false && surface.includes(finding.file));
|
|
2605
|
-
if (!covered) {
|
|
2606
2600
|
ctx.addIssue({
|
|
2607
2601
|
code: "custom",
|
|
2608
2602
|
path: ["risk_coverage", coverageIndex, "input_finding_id"],
|
|
@@ -2713,11 +2707,11 @@ function readChunkWithRetry(fd, buffer, toRead, readChunk) {
|
|
|
2713
2707
|
}
|
|
2714
2708
|
}
|
|
2715
2709
|
}
|
|
2716
|
-
function readBoundedStdin(fd, readChunk) {
|
|
2710
|
+
function readBoundedStdin(fd, readChunk, maxBytes = MAX_REVIEW_RETURN_BYTES) {
|
|
2717
2711
|
const chunks = [];
|
|
2718
2712
|
let total = 0;
|
|
2719
2713
|
while (true) {
|
|
2720
|
-
const remaining =
|
|
2714
|
+
const remaining = maxBytes + 1 - total;
|
|
2721
2715
|
if (remaining <= 0)
|
|
2722
2716
|
return { status: "oversized" };
|
|
2723
2717
|
const toRead = Math.min(READ_CHUNK_BYTES, remaining);
|
|
@@ -2729,7 +2723,7 @@ function readBoundedStdin(fd, readChunk) {
|
|
|
2729
2723
|
break;
|
|
2730
2724
|
total += read.bytesRead;
|
|
2731
2725
|
chunks.push(buffer.subarray(0, read.bytesRead));
|
|
2732
|
-
if (total >
|
|
2726
|
+
if (total > maxBytes)
|
|
2733
2727
|
return { status: "oversized" };
|
|
2734
2728
|
}
|
|
2735
2729
|
return { buffer: Buffer.concat(chunks, total), status: "ok" };
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
export declare const
|
|
2
|
+
export declare const MAX_INPUT_ID_LENGTH = 128;
|
|
3
|
+
export declare const MAX_REASON_LENGTH = 2048;
|
|
4
|
+
export declare const MAX_FINDINGS = 32;
|
|
5
|
+
export declare const MAX_PERSONAS = 64;
|
|
6
|
+
export declare const REVIEW_ARTIFACT_CUSTOM_MESSAGES: readonly ['severity count must match rejected finding count', 'filtered findings require a validation reason', 'risk-critical dispatches require a non-empty selection surface', 'satisfied risk coverage requires a citing input finding ID', 'unsatisfied risk coverage must not cite an input finding ID', 'passed validation must not include a reason; non-passed validation requires a reason', 'validation_unavailable dispatches must record zero input findings', 'a completed run must not contain validation_unavailable evidence', 'a validation_unavailable persona must not have an input finding', 'every synthesized input finding ID must resolve to an admitted ledger row', 'every provenance submitter must be represented by a cited admitted ledger row', 'satisfied risk coverage must cite an admitted ledger row', 'duplicate admitted input finding IDs are not allowed', 'every cited admitted reviewer must appear in provenance.submitters', 'provenance.submitters must not contain duplicate reviewers', 'provenance.agreement_credit must not contain duplicate reviewers', 'provenance.agreement_credit must not overlap provenance.submitters', 'provenance.agreement_credit requires an eligible returned persona with admitted evidence', 'satisfied risk coverage must cite an admitted ledger row owned by another persona'];
|
|
3
7
|
export declare const DispatchOutcomeSchema: z.ZodEnum<{
|
|
4
8
|
empty: "empty";
|
|
5
9
|
findings: "findings";
|
|
@@ -20,6 +24,14 @@ export declare const HarnessSchema: z.ZodEnum<{
|
|
|
20
24
|
pi: "pi";
|
|
21
25
|
}>;
|
|
22
26
|
export declare const RepoRelativePathSchema: z.ZodString;
|
|
27
|
+
export declare const RISK_CRITICAL_PERSONAS: readonly ['security', 'data-migrations', 'api-contract', 'reliability', 'performance'];
|
|
28
|
+
export declare const SeveritySchema: z.ZodEnum<{
|
|
29
|
+
P0: "P0";
|
|
30
|
+
P1: "P1";
|
|
31
|
+
P2: "P2";
|
|
32
|
+
P3: "P3";
|
|
33
|
+
unknown: "unknown";
|
|
34
|
+
}>;
|
|
23
35
|
export declare const InputFindingSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
24
36
|
record_type: z.ZodLiteral<"admitted">;
|
|
25
37
|
input_id: z.ZodString;
|
|
@@ -54,6 +66,11 @@ export declare const InputFindingSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
54
66
|
}>;
|
|
55
67
|
reason: z.ZodString;
|
|
56
68
|
}, z.core.$strict>], "record_type">;
|
|
69
|
+
export declare const ProvenanceSchema: z.ZodObject<{
|
|
70
|
+
fingerprint: z.ZodString;
|
|
71
|
+
submitters: z.ZodArray<z.ZodString>;
|
|
72
|
+
agreement_credit: z.ZodArray<z.ZodString>;
|
|
73
|
+
}, z.core.$strict>;
|
|
57
74
|
declare const SynthesizedFindingFieldsSchema: z.ZodObject<{
|
|
58
75
|
title: z.ZodString;
|
|
59
76
|
severity: z.ZodEnum<{
|