@fro.bot/systematic 3.12.4 → 3.13.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/dist/index.js CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  loadConfig,
16
16
  loadConfigWithSources,
17
17
  parseFrontmatter
18
- } from "./index-h26p98ny.js";
18
+ } from "./index-0stf3ag0.js";
19
19
 
20
20
  // src/index.ts
21
21
  import { createHash as createHash4 } from "crypto";
@@ -0,0 +1,239 @@
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'];
3
+ export declare const DispatchOutcomeSchema: z.ZodEnum<{
4
+ empty: "empty";
5
+ findings: "findings";
6
+ malformed: "malformed";
7
+ never_returned: "never_returned";
8
+ }>;
9
+ export declare const DispositionSchema: z.ZodEnum<{
10
+ filtered: "filtered";
11
+ merged: "merged";
12
+ rejected: "rejected";
13
+ suppressed: "suppressed";
14
+ surviving: "surviving";
15
+ }>;
16
+ export declare const HarnessSchema: z.ZodEnum<{
17
+ "claude-code": "claude-code";
18
+ opencode: "opencode";
19
+ pi: "pi";
20
+ }>;
21
+ export declare const RepoRelativePathSchema: z.ZodString;
22
+ export declare const InputFindingSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
23
+ record_type: z.ZodLiteral<"admitted">;
24
+ input_id: z.ZodString;
25
+ reviewer: z.ZodString;
26
+ confidence: z.ZodNumber;
27
+ disposition: z.ZodEnum<{
28
+ filtered: "filtered";
29
+ merged: "merged";
30
+ suppressed: "suppressed";
31
+ surviving: "surviving";
32
+ }>;
33
+ reason: z.ZodString;
34
+ }, z.core.$strict>, z.ZodObject<{
35
+ record_type: z.ZodLiteral<"rejected_summary">;
36
+ reviewer: z.ZodString;
37
+ dispatch_outcome: z.ZodEnum<{
38
+ empty: "empty";
39
+ findings: "findings";
40
+ malformed: "malformed";
41
+ never_returned: "never_returned";
42
+ }>;
43
+ rejected_finding_count: z.ZodNumber;
44
+ rejected_severities: z.ZodArray<z.ZodEnum<{
45
+ P0: "P0";
46
+ P1: "P1";
47
+ P2: "P2";
48
+ P3: "P3";
49
+ unknown: "unknown";
50
+ }>>;
51
+ disposition: z.ZodEnum<{
52
+ rejected: "rejected";
53
+ }>;
54
+ reason: z.ZodString;
55
+ }, z.core.$strict>], "record_type">;
56
+ declare const SynthesizedFindingFieldsSchema: z.ZodObject<{
57
+ title: z.ZodString;
58
+ severity: z.ZodEnum<{
59
+ P0: "P0";
60
+ P1: "P1";
61
+ P2: "P2";
62
+ P3: "P3";
63
+ }>;
64
+ file: z.ZodString;
65
+ line: z.ZodNumber;
66
+ why_it_matters: z.ZodString;
67
+ autofix_class: z.ZodEnum<{
68
+ advisory: "advisory";
69
+ gated_auto: "gated_auto";
70
+ manual: "manual";
71
+ safe_auto: "safe_auto";
72
+ }>;
73
+ owner: z.ZodEnum<{
74
+ "downstream-resolver": "downstream-resolver";
75
+ human: "human";
76
+ release: "release";
77
+ "review-fixer": "review-fixer";
78
+ }>;
79
+ requires_verification: z.ZodBoolean;
80
+ confidence: z.ZodNumber;
81
+ evidence: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
82
+ overflow: z.ZodLiteral<true>;
83
+ excerpt: z.ZodString;
84
+ }, z.core.$strict>]>>;
85
+ pre_existing: z.ZodBoolean;
86
+ suggested_fix: z.ZodOptional<z.ZodNullable<z.ZodString>>;
87
+ validated: z.ZodOptional<z.ZodBoolean>;
88
+ validation_reason: z.ZodOptional<z.ZodString>;
89
+ input_finding_ids: z.ZodArray<z.ZodString>;
90
+ provenance: z.ZodObject<{
91
+ fingerprint: z.ZodString;
92
+ submitters: z.ZodArray<z.ZodString>;
93
+ agreement_credit: z.ZodArray<z.ZodString>;
94
+ }, z.core.$strict>;
95
+ }, z.core.$strict>;
96
+ type SynthesizedFindingFields = z.infer<typeof SynthesizedFindingFieldsSchema>;
97
+ type SynthesizedFinding = Omit<SynthesizedFindingFields, 'validated' | 'validation_reason'> & ({
98
+ validated: false;
99
+ validation_reason: string;
100
+ } | {
101
+ validated?: true;
102
+ validation_reason?: string;
103
+ });
104
+ export declare const ReviewArtifactSchema: z.ZodObject<{
105
+ schema_version: z.ZodLiteral<1>;
106
+ run_id: z.ZodString;
107
+ mode: z.ZodEnum<{
108
+ autofix: "autofix";
109
+ headless: "headless";
110
+ interactive: "interactive";
111
+ }>;
112
+ harness: z.ZodEnum<{
113
+ "claude-code": "claude-code";
114
+ opencode: "opencode";
115
+ pi: "pi";
116
+ }>;
117
+ run_status: z.ZodEnum<{
118
+ abnormal: "abnormal";
119
+ completed: "completed";
120
+ degraded: "degraded";
121
+ in_progress: "in_progress";
122
+ }>;
123
+ verdict: z.ZodString;
124
+ dispatches: z.ZodArray<z.ZodObject<{
125
+ persona: z.ZodString;
126
+ dispatch_outcome: z.ZodEnum<{
127
+ empty: "empty";
128
+ findings: "findings";
129
+ malformed: "malformed";
130
+ never_returned: "never_returned";
131
+ }>;
132
+ input_finding_count: z.ZodNumber;
133
+ rejection_reason: z.ZodOptional<z.ZodString>;
134
+ }, z.core.$strict>>;
135
+ input_findings: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
136
+ record_type: z.ZodLiteral<"admitted">;
137
+ input_id: z.ZodString;
138
+ reviewer: z.ZodString;
139
+ confidence: z.ZodNumber;
140
+ disposition: z.ZodEnum<{
141
+ filtered: "filtered";
142
+ merged: "merged";
143
+ suppressed: "suppressed";
144
+ surviving: "surviving";
145
+ }>;
146
+ reason: z.ZodString;
147
+ }, z.core.$strict>, z.ZodObject<{
148
+ record_type: z.ZodLiteral<"rejected_summary">;
149
+ reviewer: z.ZodString;
150
+ dispatch_outcome: z.ZodEnum<{
151
+ empty: "empty";
152
+ findings: "findings";
153
+ malformed: "malformed";
154
+ never_returned: "never_returned";
155
+ }>;
156
+ rejected_finding_count: z.ZodNumber;
157
+ rejected_severities: z.ZodArray<z.ZodEnum<{
158
+ P0: "P0";
159
+ P1: "P1";
160
+ P2: "P2";
161
+ P3: "P3";
162
+ unknown: "unknown";
163
+ }>>;
164
+ disposition: z.ZodEnum<{
165
+ rejected: "rejected";
166
+ }>;
167
+ reason: z.ZodString;
168
+ }, z.core.$strict>], "record_type">>;
169
+ findings: z.ZodArray<z.ZodType<SynthesizedFinding, {
170
+ title: string;
171
+ severity: "P0" | "P1" | "P2" | "P3";
172
+ file: string;
173
+ line: number;
174
+ why_it_matters: string;
175
+ autofix_class: "advisory" | "gated_auto" | "manual" | "safe_auto";
176
+ owner: "downstream-resolver" | "human" | "release" | "review-fixer";
177
+ requires_verification: boolean;
178
+ confidence: number;
179
+ evidence: (string | {
180
+ overflow: true;
181
+ excerpt: string;
182
+ })[];
183
+ pre_existing: boolean;
184
+ suggested_fix?: string | null | undefined;
185
+ validated?: boolean | undefined;
186
+ validation_reason?: string | undefined;
187
+ input_finding_ids: string[];
188
+ provenance: {
189
+ fingerprint: string;
190
+ submitters: string[];
191
+ agreement_credit: string[];
192
+ };
193
+ }, z.core.$ZodTypeInternals<SynthesizedFinding, {
194
+ title: string;
195
+ severity: "P0" | "P1" | "P2" | "P3";
196
+ file: string;
197
+ line: number;
198
+ why_it_matters: string;
199
+ autofix_class: "advisory" | "gated_auto" | "manual" | "safe_auto";
200
+ owner: "downstream-resolver" | "human" | "release" | "review-fixer";
201
+ requires_verification: boolean;
202
+ confidence: number;
203
+ evidence: (string | {
204
+ overflow: true;
205
+ excerpt: string;
206
+ })[];
207
+ pre_existing: boolean;
208
+ suggested_fix?: string | null | undefined;
209
+ validated?: boolean | undefined;
210
+ validation_reason?: string | undefined;
211
+ input_finding_ids: string[];
212
+ provenance: {
213
+ fingerprint: string;
214
+ submitters: string[];
215
+ agreement_credit: string[];
216
+ };
217
+ }>>>;
218
+ disposition_counts: z.ZodObject<{
219
+ surviving: z.ZodNumber;
220
+ merged: z.ZodNumber;
221
+ suppressed: z.ZodNumber;
222
+ filtered: z.ZodNumber;
223
+ rejected: z.ZodNumber;
224
+ }, z.core.$strict>;
225
+ applied_fixes: z.ZodArray<z.ZodString>;
226
+ residual_actionable_work: z.ZodArray<z.ZodString>;
227
+ advisory_outputs: z.ZodArray<z.ZodString>;
228
+ coverage: z.ZodObject<{
229
+ reviewers: z.ZodOptional<z.ZodNumber>;
230
+ validators: z.ZodOptional<z.ZodNumber>;
231
+ residual_risks: z.ZodArray<z.ZodString>;
232
+ testing_gaps: z.ZodArray<z.ZodString>;
233
+ failed_reviewers: z.ZodArray<z.ZodString>;
234
+ validator_failures: z.ZodArray<z.ZodString>;
235
+ intent_uncertainty: z.ZodArray<z.ZodString>;
236
+ }, z.core.$strict>;
237
+ }, z.core.$strict>;
238
+ export type ReviewArtifact = z.infer<typeof ReviewArtifactSchema>;
239
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fro.bot/systematic",
3
- "version": "3.12.4",
3
+ "version": "3.13.1",
4
4
  "description": "Compound-engineering loops for OpenCode, Pi, and Claude Code",
5
5
  "type": "module",
6
6
  "homepage": "https://fro.bot/systematic",
@@ -49,6 +49,8 @@
49
49
  "docs:generate": "bun docs/scripts/generate-stats.ts && bun docs/scripts/transform-content.ts && bun scripts/generate-config-schema.ts && bun docs/scripts/generate-config-reference.ts",
50
50
  "schema:generate": "bun scripts/generate-config-schema.ts",
51
51
  "schema:drift": "bun scripts/generate-config-schema.ts --check",
52
+ "review-schema:generate": "bun scripts/generate-review-artifact-schema.ts",
53
+ "review-schema:drift": "bun scripts/generate-review-artifact-schema.ts --check",
52
54
  "agent-browser:build": "bun scripts/generate-agent-browser-skill.ts",
53
55
  "agent-browser:drift": "bun scripts/generate-agent-browser-skill.ts --check",
54
56
  "registry:build": "bun scripts/build-registry.ts",
@@ -91,7 +93,7 @@
91
93
  }
92
94
  },
93
95
  "devDependencies": {
94
- "@biomejs/biome": "2.5.8",
96
+ "@biomejs/biome": "2.5.9",
95
97
  "@earendil-works/pi-coding-agent": "0.83.0",
96
98
  "@opencode-ai/plugin": "1.18.18",
97
99
  "@opencode-ai/sdk": "1.18.18",
@@ -100,15 +102,15 @@
100
102
  "@types/bun": "latest",
101
103
  "@types/js-yaml": "4.0.9",
102
104
  "@types/node": "26.2.0",
103
- "agent-browser": "0.33.1",
105
+ "agent-browser": "0.34.0",
104
106
  "ajv": "8.20.0",
105
107
  "ajv-formats": "3.0.1",
106
- "conventional-changelog-conventionalcommits": "10.3.0",
108
+ "conventional-changelog-conventionalcommits": "10.4.0",
107
109
  "markdownlint-cli": "0.49.1",
108
110
  "rimraf": "6.1.3",
109
111
  "semantic-release": "25.0.9",
110
112
  "semantic-release-export-data": "1.2.0",
111
- "typebox": "1.3.14",
113
+ "typebox": "1.3.16",
112
114
  "typescript": "7.0.2"
113
115
  },
114
116
  "dependencies": {
@@ -120,7 +122,8 @@
120
122
  },
121
123
  "overrides": {
122
124
  "@earendil-works/pi-ai": "0.83.0",
123
- "brace-expansion": "^5.0.8"
125
+ "brace-expansion": "^5.0.8",
126
+ "conventional-changelog-writer": ">=9"
124
127
  },
125
128
  "publishConfig": {
126
129
  "access": "public",
@@ -16,7 +16,14 @@ The `problem_type` determines which **track** applies. Each track has different
16
16
  | Track | problem_types | Description |
17
17
  |-------|--------------|-------------|
18
18
  | **Bug** | `build_error`, `test_failure`, `runtime_error`, `performance_issue`, `database_issue`, `security_issue`, `ui_bug`, `integration_issue`, `logic_error` | Defects and failures that were diagnosed and fixed |
19
- | **Knowledge** | `best_practice`, `documentation_gap`, `workflow_issue`, `developer_experience` | Practices, patterns, workflow improvements, and documentation |
19
+ | **Knowledge** | `best_practice`, `documentation_gap`, `workflow_issue`, `developer_experience`, `architecture_pattern`, `design_pattern`, `tooling_decision`, `convention` | Practices, patterns, workflow improvements, and documentation |
20
+
21
+ Prefer the narrowest applicable value. `best_practice` is the fallback when no narrower knowledge-track value fits.
22
+
23
+ - `architecture_pattern` — structural decisions about how components relate
24
+ - `design_pattern` — reusable solutions to recurring design problems
25
+ - `tooling_decision` — choices about tools, libraries, or build infrastructure
26
+ - `convention` — agreed-upon naming, formatting, or style rules
20
27
 
21
28
  ## Required Fields (both tracks)
22
29
 
@@ -35,6 +42,8 @@ Required:
35
42
 
36
43
  ## Knowledge Track Fields
37
44
 
45
+ Applies to every knowledge-track `problem_type` listed in the Tracks table above.
46
+
38
47
  No additional required fields beyond the shared ones. All fields below are optional:
39
48
 
40
49
  - **applies_when**: Conditions or situations where this guidance applies
@@ -73,6 +82,14 @@ Docs created before the track system may have `symptoms`/`root_cause`/`resolutio
73
82
  - `workflow_issue` -> `docs/solutions/workflow-issues/`
74
83
  - `best_practice` -> `docs/solutions/best-practices/`
75
84
  - `documentation_gap` -> `docs/solutions/documentation-gaps/`
85
+ - `architecture_pattern` -> `docs/solutions/best-practices/`
86
+ - `design_pattern` -> `docs/solutions/best-practices/`
87
+ - `tooling_decision` -> `docs/solutions/best-practices/`
88
+ - `convention` -> `docs/solutions/best-practices/`
89
+
90
+ The four narrower knowledge-track types share the `best-practices/` directory rather than each
91
+ getting their own. That matches where such docs are already filed, and avoids single-document
92
+ directories that fragment search.
76
93
 
77
94
  ## Validation Rules
78
95
 
@@ -704,6 +704,7 @@ After presenting findings and verdict (Stage 6), route the next steps by mode. R
704
704
 
705
705
  - In interactive, autofix, and headless modes, write **`review-summary.json` unconditionally** under `.context/systematic/ce-review/<run-id>`; `mode:report-only` remains the deliberate no-write exception.
706
706
  - `review-summary.json` is the parent-owned synthesis artifact. Its lifecycle, dispatch outcomes, complete input ledger, synthesized and filtered findings with provenance, disposition counts, and downstream work are defined in the [canonical synthesis artifact contract](./references/synthesis-artifact-contract.md), whose vocabulary and bounds are executable in [`findings-schema.json`](./references/findings-schema.json).
707
+ - Before finalizing, follow the [artifact validation and failure path](./references/synthesis-artifact-contract.md).
707
708
  - Initialize the artifact before dispatch and persist only validated parent-owned records. Finalize lifecycle and reconciliation after synthesis; preserve the existing degraded and abnormal-run behavior described in the canonical contract.
708
709
  - Also write `metadata.json` alongside the findings so downstream skills can verify the artifact matches the current branch and HEAD. Minimum fields:
709
710
  ```json