@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 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-return validator — packaged paths
58
+ ## Review synthesis pipeline validator — packaged paths
59
59
 
60
- The raw-return and aggregate validators ship as one self-contained Node bundle,
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`. Recorded execution evidence for
64
- this surface:
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 two subcommands and owns no validation logic itself.
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(["P0", "P1", "P2", "P3", "unknown"]);
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 = MAX_REVIEW_RETURN_BYTES + 1 - total;
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 > MAX_REVIEW_RETURN_BYTES)
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 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 a validated finding on the lost persona selection surface', 'satisfied risk coverage must cite an admitted ledger row owned by another persona'];
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<{