@oddessentials/odd-ai-reviewers 1.10.1 → 1.12.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/README.md +16 -9
- package/dist/agents/control_flow/types.d.ts +1 -1
- package/dist/agents/control_flow/types.js +1 -1
- package/dist/agents/index.d.ts +1 -0
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +2 -0
- package/dist/agents/index.js.map +1 -1
- package/dist/benchmark/adapter.d.ts.map +1 -1
- package/dist/benchmark/adapter.js +4 -2
- package/dist/benchmark/adapter.js.map +1 -1
- package/dist/cache/store.d.ts.map +1 -1
- package/dist/cache/store.js +26 -2
- package/dist/cache/store.js.map +1 -1
- package/dist/cli/commands/local-review.d.ts +13 -2
- package/dist/cli/commands/local-review.d.ts.map +1 -1
- package/dist/cli/commands/local-review.js +164 -33
- package/dist/cli/commands/local-review.js.map +1 -1
- package/dist/cli/execution-plan.d.ts +118 -0
- package/dist/cli/execution-plan.d.ts.map +1 -0
- package/dist/cli/execution-plan.js +260 -0
- package/dist/cli/execution-plan.js.map +1 -0
- package/dist/config/schemas.d.ts +103 -21
- package/dist/config/schemas.d.ts.map +1 -1
- package/dist/config/schemas.js +177 -10
- package/dist/config/schemas.js.map +1 -1
- package/dist/config.d.ts +8 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +15 -6
- package/dist/config.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +79 -8
- package/dist/main.js.map +1 -1
- package/dist/phases/execute.d.ts +3 -0
- package/dist/phases/execute.d.ts.map +1 -1
- package/dist/phases/execute.js +17 -5
- package/dist/phases/execute.js.map +1 -1
- package/dist/phases/index.d.ts +1 -1
- package/dist/phases/index.d.ts.map +1 -1
- package/dist/phases/index.js +1 -1
- package/dist/phases/index.js.map +1 -1
- package/dist/phases/report.d.ts +28 -4
- package/dist/phases/report.d.ts.map +1 -1
- package/dist/phases/report.js +86 -36
- package/dist/phases/report.js.map +1 -1
- package/dist/report/ado.d.ts +2 -1
- package/dist/report/ado.d.ts.map +1 -1
- package/dist/report/ado.js +9 -5
- package/dist/report/ado.js.map +1 -1
- package/dist/report/finding-validator.d.ts +1 -4
- package/dist/report/finding-validator.d.ts.map +1 -1
- package/dist/report/finding-validator.js +23 -54
- package/dist/report/finding-validator.js.map +1 -1
- package/dist/report/framework-pattern-filter.d.ts +1 -1
- package/dist/report/framework-pattern-filter.d.ts.map +1 -1
- package/dist/report/framework-pattern-filter.js +114 -99
- package/dist/report/framework-pattern-filter.js.map +1 -1
- package/dist/report/github.d.ts +2 -1
- package/dist/report/github.d.ts.map +1 -1
- package/dist/report/github.js +9 -5
- package/dist/report/github.js.map +1 -1
- package/dist/report/terminal.d.ts +42 -4
- package/dist/report/terminal.d.ts.map +1 -1
- package/dist/report/terminal.js +36 -8
- package/dist/report/terminal.js.map +1 -1
- package/dist/report/user-suppressions.d.ts +74 -0
- package/dist/report/user-suppressions.d.ts.map +1 -0
- package/dist/report/user-suppressions.js +264 -0
- package/dist/report/user-suppressions.js.map +1 -0
- package/dist/security-logger.d.ts +1 -1
- package/dist/security-logger.js +1 -1
- package/package.json +7 -6
- package/dist/__tests__/hermetic-setup.d.ts +0 -55
- package/dist/__tests__/hermetic-setup.d.ts.map +0 -1
- package/dist/__tests__/hermetic-setup.js +0 -62
- package/dist/__tests__/hermetic-setup.js.map +0 -1
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Execution Plan Module (FR-001 through FR-007)
|
|
3
|
+
*
|
|
4
|
+
* Produces a single, immutable ExecutionPlan object that is the sole source of truth
|
|
5
|
+
* for all downstream code paths (dry-run, cost-only, dependency check, execution).
|
|
6
|
+
*
|
|
7
|
+
* Pipeline: Parse -> Validate -> BuildExecutionPlan -> DependencyCheck -> Execute
|
|
8
|
+
*
|
|
9
|
+
* No downstream consumer may read raw CLI flags — they operate on the plan.
|
|
10
|
+
*/
|
|
11
|
+
import { AGENT_REGISTRY, getAgentById, getCompatibleAgents, } from '../config/schemas.js';
|
|
12
|
+
import { ConfigError, ConfigErrorCode } from '../types/errors.js';
|
|
13
|
+
import { assertNever } from '../types/assert-never.js';
|
|
14
|
+
/**
|
|
15
|
+
* The ONLY path to produce an exit code.
|
|
16
|
+
* No call site may hardcode an exit code number directly.
|
|
17
|
+
*/
|
|
18
|
+
export function exitCodeFromStatus(status) {
|
|
19
|
+
switch (status) {
|
|
20
|
+
case 'complete':
|
|
21
|
+
return 0;
|
|
22
|
+
case 'gating_failed':
|
|
23
|
+
return 1;
|
|
24
|
+
case 'config_error':
|
|
25
|
+
return 2;
|
|
26
|
+
case 'incomplete':
|
|
27
|
+
return 3;
|
|
28
|
+
default:
|
|
29
|
+
return assertNever(status);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
// =============================================================================
|
|
33
|
+
// Validation Helpers
|
|
34
|
+
// =============================================================================
|
|
35
|
+
/**
|
|
36
|
+
* Validate --pass flag against configured passes.
|
|
37
|
+
* Throws ConfigError if unknown.
|
|
38
|
+
*/
|
|
39
|
+
function validatePassFilter(passFilter, passes) {
|
|
40
|
+
const match = passes.find((p) => p.name === passFilter);
|
|
41
|
+
if (!match) {
|
|
42
|
+
const available = passes.map((p) => p.name).join(', ');
|
|
43
|
+
throw new ConfigError(`Unknown pass '${passFilter}'. Available: ${available}`, ConfigErrorCode.INVALID_VALUE, { field: 'pass', expected: available, actual: passFilter });
|
|
44
|
+
}
|
|
45
|
+
if (!match.enabled) {
|
|
46
|
+
throw new ConfigError(`Pass '${passFilter}' is disabled in configuration`, ConfigErrorCode.INVALID_VALUE, { field: 'pass', actual: passFilter });
|
|
47
|
+
}
|
|
48
|
+
return match;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Validate --agent flag against the agent registry.
|
|
52
|
+
* Throws ConfigError if unknown.
|
|
53
|
+
*/
|
|
54
|
+
function validateAgentFilter(agentFilter) {
|
|
55
|
+
const entry = getAgentById(agentFilter);
|
|
56
|
+
if (!entry) {
|
|
57
|
+
const validIds = AGENT_REGISTRY.map((a) => a.id).join(', ');
|
|
58
|
+
throw new ConfigError(`Unknown agent '${agentFilter}'. Valid: ${validIds}`, ConfigErrorCode.INVALID_VALUE, { field: 'agent', expected: validIds, actual: agentFilter });
|
|
59
|
+
}
|
|
60
|
+
return entry;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Validate pass composition at config time.
|
|
64
|
+
* Checks for unknown agents and duplicates within passes.
|
|
65
|
+
*/
|
|
66
|
+
function validatePassComposition(passes) {
|
|
67
|
+
for (const pass of passes) {
|
|
68
|
+
// Check for unknown agents
|
|
69
|
+
for (const agentId of pass.agents) {
|
|
70
|
+
if (!getAgentById(agentId)) {
|
|
71
|
+
const validIds = AGENT_REGISTRY.map((a) => a.id).join(', ');
|
|
72
|
+
throw new ConfigError(`Unknown agent '${agentId}' in pass '${pass.name}'. Valid: ${validIds}`, ConfigErrorCode.INVALID_VALUE, { field: `passes.${pass.name}.agents`, expected: validIds, actual: agentId });
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// Check for duplicates
|
|
76
|
+
const seen = new Set();
|
|
77
|
+
for (const agentId of pass.agents) {
|
|
78
|
+
if (seen.has(agentId)) {
|
|
79
|
+
throw new ConfigError(`Duplicate agent '${agentId}' in pass '${pass.name}'`, ConfigErrorCode.INVALID_VALUE, { field: `passes.${pass.name}.agents`, actual: agentId });
|
|
80
|
+
}
|
|
81
|
+
seen.add(agentId);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// =============================================================================
|
|
86
|
+
// Build Execution Plan
|
|
87
|
+
// =============================================================================
|
|
88
|
+
/**
|
|
89
|
+
* Build an immutable execution plan from config and CLI options.
|
|
90
|
+
*
|
|
91
|
+
* Enforces all invariants:
|
|
92
|
+
* - Pass/agent validation against registry
|
|
93
|
+
* - Provider compatibility filtering
|
|
94
|
+
* - Empty-pass rule (required+empty -> ConfigError; optional+empty -> skipped)
|
|
95
|
+
* - Combined --pass + --agent narrowing (FR-007)
|
|
96
|
+
*
|
|
97
|
+
* @throws ConfigError on validation failures (exit code 2)
|
|
98
|
+
*/
|
|
99
|
+
export function buildExecutionPlan(options) {
|
|
100
|
+
const { config, mode, passFilter, agentFilter, provider, model, configSource } = options;
|
|
101
|
+
// 1. Validate pass composition at config time
|
|
102
|
+
validatePassComposition(config.passes);
|
|
103
|
+
// 2. Start with enabled passes
|
|
104
|
+
let candidatePasses = config.passes.filter((p) => p.enabled);
|
|
105
|
+
// 3. Apply --pass filter
|
|
106
|
+
if (passFilter) {
|
|
107
|
+
const matchedPass = validatePassFilter(passFilter, config.passes);
|
|
108
|
+
candidatePasses = [matchedPass];
|
|
109
|
+
}
|
|
110
|
+
// 4. Validate --agent filter against registry
|
|
111
|
+
if (agentFilter) {
|
|
112
|
+
validateAgentFilter(agentFilter);
|
|
113
|
+
}
|
|
114
|
+
// 5. Get compatible agents for the provider
|
|
115
|
+
const compatibleAgents = getCompatibleAgents(provider);
|
|
116
|
+
const compatibleIds = new Set(compatibleAgents.map((a) => a.id));
|
|
117
|
+
const requestedAgentId = agentFilter;
|
|
118
|
+
// 6. Build planned passes with agent filtering
|
|
119
|
+
const plannedPasses = [];
|
|
120
|
+
const skippedPasses = [];
|
|
121
|
+
for (const pass of candidatePasses) {
|
|
122
|
+
// Filter agents by provider compatibility
|
|
123
|
+
let agents = pass.agents.filter((id) => compatibleIds.has(id));
|
|
124
|
+
// Log provider-incompatible agents as excluded (non-required passes only)
|
|
125
|
+
const excludedByProvider = pass.agents.filter((id) => !compatibleIds.has(id));
|
|
126
|
+
if (excludedByProvider.length > 0 && pass.required) {
|
|
127
|
+
// Required pass with incompatible agents -> config error
|
|
128
|
+
const incompatible = excludedByProvider.join(', ');
|
|
129
|
+
throw new ConfigError(`Required pass '${pass.name}' contains agents incompatible with provider '${provider}': ${incompatible}`, ConfigErrorCode.INVALID_VALUE, { field: `passes.${pass.name}.agents`, actual: incompatible });
|
|
130
|
+
}
|
|
131
|
+
// Apply --agent filter within pass
|
|
132
|
+
if (agentFilter) {
|
|
133
|
+
const passContainsRequestedAgent = pass.agents.includes(requestedAgentId);
|
|
134
|
+
if (passFilter &&
|
|
135
|
+
passContainsRequestedAgent &&
|
|
136
|
+
!compatibleIds.has(requestedAgentId)) {
|
|
137
|
+
throw new ConfigError(`Agent '${agentFilter}' in pass '${passFilter}' is incompatible with provider '${provider}'`, ConfigErrorCode.INVALID_VALUE, { field: 'agent', actual: agentFilter });
|
|
138
|
+
}
|
|
139
|
+
const hasAgent = agents.some((id) => id === agentFilter);
|
|
140
|
+
if (hasAgent) {
|
|
141
|
+
agents = agents.filter((id) => id === agentFilter);
|
|
142
|
+
}
|
|
143
|
+
else if (passFilter) {
|
|
144
|
+
// Combined: --pass + --agent, agent not in the selected pass
|
|
145
|
+
const otherPasses = config.passes
|
|
146
|
+
.filter((p) => p.enabled && p.agents.includes(agentFilter))
|
|
147
|
+
.map((p) => p.name);
|
|
148
|
+
const availableIn = otherPasses.length > 0 ? ` It is available in: ${otherPasses.join(', ')}` : '';
|
|
149
|
+
throw new ConfigError(`Agent '${agentFilter}' is not configured in pass '${passFilter}'.${availableIn}`, ConfigErrorCode.INVALID_VALUE, { field: 'agent', actual: agentFilter });
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
// Agent not in this pass, skip it (will be caught by check below if in no pass)
|
|
153
|
+
agents = [];
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
// Empty-pass rule
|
|
157
|
+
if (agents.length === 0) {
|
|
158
|
+
if (pass.required) {
|
|
159
|
+
throw new ConfigError(`Required pass '${pass.name}' has no runnable agents after filtering`, ConfigErrorCode.INVALID_VALUE, { field: `passes.${pass.name}` });
|
|
160
|
+
}
|
|
161
|
+
const reason = excludedByProvider.length > 0
|
|
162
|
+
? `Pass '${pass.name}' skipped: no agents compatible with provider '${provider}'`
|
|
163
|
+
: `Pass '${pass.name}' skipped: no matching agents after filtering`;
|
|
164
|
+
skippedPasses.push({ name: pass.name, reason });
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
plannedPasses.push({
|
|
168
|
+
name: pass.name,
|
|
169
|
+
agents: agents,
|
|
170
|
+
required: pass.required,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
// 7. If --agent was specified but found in no pass, error
|
|
174
|
+
if (agentFilter && !passFilter && plannedPasses.length === 0) {
|
|
175
|
+
// Check if the agent exists in any configured pass at all
|
|
176
|
+
const passesWithAgent = config.passes
|
|
177
|
+
.filter((p) => p.agents.includes(agentFilter))
|
|
178
|
+
.map((p) => p.name);
|
|
179
|
+
if (passesWithAgent.length === 0) {
|
|
180
|
+
throw new ConfigError(`Agent '${agentFilter}' not configured in any pass`, ConfigErrorCode.INVALID_VALUE, { field: 'agent', actual: agentFilter });
|
|
181
|
+
}
|
|
182
|
+
if (!compatibleIds.has(agentFilter)) {
|
|
183
|
+
throw new ConfigError(`Agent '${agentFilter}' is incompatible with provider '${provider}' and cannot run in configured passes: ${passesWithAgent.join(', ')}`, ConfigErrorCode.INVALID_VALUE, { field: 'agent', actual: agentFilter });
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
// 8. Assert structural invariant: no pass with empty agents
|
|
187
|
+
for (const pass of plannedPasses) {
|
|
188
|
+
if (pass.agents.length === 0) {
|
|
189
|
+
throw new Error(`Invariant violation: pass '${pass.name}' has empty agents list in execution plan`);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
// 9. Build limits snapshot
|
|
193
|
+
const limits = {
|
|
194
|
+
maxDiffLines: config.limits.max_diff_lines,
|
|
195
|
+
maxFiles: config.limits.max_files,
|
|
196
|
+
maxTokensPerPr: config.limits.max_tokens_per_pr,
|
|
197
|
+
maxUsdPerPr: config.limits.max_usd_per_pr,
|
|
198
|
+
};
|
|
199
|
+
// 10. Build gating snapshot
|
|
200
|
+
const gating = {
|
|
201
|
+
enabled: config.gating.enabled,
|
|
202
|
+
failOnSeverity: config.gating.fail_on_severity,
|
|
203
|
+
driftGate: config.gating.drift_gate,
|
|
204
|
+
};
|
|
205
|
+
const plan = {
|
|
206
|
+
mode,
|
|
207
|
+
passes: plannedPasses,
|
|
208
|
+
skippedPasses,
|
|
209
|
+
provider: provider ?? null,
|
|
210
|
+
model: model ?? null,
|
|
211
|
+
limits,
|
|
212
|
+
gating,
|
|
213
|
+
configSource,
|
|
214
|
+
schemaVersion: config.version,
|
|
215
|
+
};
|
|
216
|
+
return plan;
|
|
217
|
+
}
|
|
218
|
+
// =============================================================================
|
|
219
|
+
// Plan Serialization (Canonical, Redacted)
|
|
220
|
+
// =============================================================================
|
|
221
|
+
/**
|
|
222
|
+
* Safe-field allowlist for plan serialization.
|
|
223
|
+
* Only these fields appear in serialized output — everything else is excluded.
|
|
224
|
+
* Keys are emitted in alphabetical order at every level.
|
|
225
|
+
*/
|
|
226
|
+
export function serializeExecutionPlan(plan) {
|
|
227
|
+
const canonical = {
|
|
228
|
+
configSource: plan.configSource,
|
|
229
|
+
gating: {
|
|
230
|
+
driftGate: plan.gating.driftGate,
|
|
231
|
+
enabled: plan.gating.enabled,
|
|
232
|
+
failOnSeverity: plan.gating.failOnSeverity,
|
|
233
|
+
},
|
|
234
|
+
limits: {
|
|
235
|
+
maxDiffLines: plan.limits.maxDiffLines,
|
|
236
|
+
maxFiles: plan.limits.maxFiles,
|
|
237
|
+
maxTokensPerPr: plan.limits.maxTokensPerPr,
|
|
238
|
+
maxUsdPerPr: plan.limits.maxUsdPerPr,
|
|
239
|
+
},
|
|
240
|
+
mode: plan.mode,
|
|
241
|
+
model: plan.model,
|
|
242
|
+
passes: plan.passes.map((p) => ({
|
|
243
|
+
agents: [...p.agents].sort(),
|
|
244
|
+
name: p.name,
|
|
245
|
+
required: p.required,
|
|
246
|
+
})),
|
|
247
|
+
provider: plan.provider,
|
|
248
|
+
schemaVersion: plan.schemaVersion,
|
|
249
|
+
...(plan.skippedPasses.length > 0
|
|
250
|
+
? {
|
|
251
|
+
skippedPasses: plan.skippedPasses.map((s) => ({
|
|
252
|
+
name: s.name,
|
|
253
|
+
reason: s.reason,
|
|
254
|
+
})),
|
|
255
|
+
}
|
|
256
|
+
: {}),
|
|
257
|
+
};
|
|
258
|
+
return JSON.stringify(canonical, null, 2);
|
|
259
|
+
}
|
|
260
|
+
//# sourceMappingURL=execution-plan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execution-plan.js","sourceRoot":"","sources":["../../src/cli/execution-plan.ts"],"names":[],"mappings":"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"}
|
package/dist/config/schemas.d.ts
CHANGED
|
@@ -5,25 +5,41 @@
|
|
|
5
5
|
* Extracted from config.ts to improve modularity.
|
|
6
6
|
*/
|
|
7
7
|
import { z } from 'zod';
|
|
8
|
+
/**
|
|
9
|
+
* Metadata for a single agent in the canonical registry.
|
|
10
|
+
* Schema validation, CLI help, docs tables, and error messages all derive from this.
|
|
11
|
+
*/
|
|
12
|
+
export interface AgentRegistryEntry {
|
|
13
|
+
readonly id: string;
|
|
14
|
+
readonly name: string;
|
|
15
|
+
readonly description: string;
|
|
16
|
+
readonly requiresExternalTool: boolean;
|
|
17
|
+
readonly requiresApiKey: boolean;
|
|
18
|
+
readonly builtIn: boolean;
|
|
19
|
+
readonly compatibleProviders: readonly string[] | 'all';
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Canonical agent registry — the sole authority for agent identity.
|
|
23
|
+
* Adding a new agent without updating this registry is impossible because
|
|
24
|
+
* AgentSchema is derived from it.
|
|
25
|
+
*/
|
|
26
|
+
export declare const AGENT_REGISTRY: readonly AgentRegistryEntry[];
|
|
27
|
+
/**
|
|
28
|
+
* Look up an agent by ID from the registry.
|
|
29
|
+
*/
|
|
30
|
+
export declare function getAgentById(id: string): AgentRegistryEntry | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Get agents compatible with a given provider.
|
|
33
|
+
* Returns all agents if provider is null/undefined.
|
|
34
|
+
*/
|
|
35
|
+
export declare function getCompatibleAgents(provider: string | null | undefined): AgentRegistryEntry[];
|
|
8
36
|
export declare const AgentSchema: z.ZodEnum<{
|
|
9
|
-
|
|
10
|
-
semgrep: "semgrep";
|
|
11
|
-
reviewdog: "reviewdog";
|
|
12
|
-
opencode: "opencode";
|
|
13
|
-
pr_agent: "pr_agent";
|
|
14
|
-
local_llm: "local_llm";
|
|
15
|
-
ai_semantic_review: "ai_semantic_review";
|
|
37
|
+
[x: string]: string;
|
|
16
38
|
}>;
|
|
17
39
|
export declare const PassSchema: z.ZodObject<{
|
|
18
40
|
name: z.ZodString;
|
|
19
41
|
agents: z.ZodArray<z.ZodEnum<{
|
|
20
|
-
|
|
21
|
-
semgrep: "semgrep";
|
|
22
|
-
reviewdog: "reviewdog";
|
|
23
|
-
opencode: "opencode";
|
|
24
|
-
pr_agent: "pr_agent";
|
|
25
|
-
local_llm: "local_llm";
|
|
26
|
-
ai_semantic_review: "ai_semantic_review";
|
|
42
|
+
[x: string]: string;
|
|
27
43
|
}>>;
|
|
28
44
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
29
45
|
required: z.ZodDefault<z.ZodBoolean>;
|
|
@@ -120,6 +136,50 @@ export declare const ProviderSchema: z.ZodEnum<{
|
|
|
120
136
|
"azure-openai": "azure-openai";
|
|
121
137
|
ollama: "ollama";
|
|
122
138
|
}>;
|
|
139
|
+
export declare const SuppressionRuleSchema: z.ZodObject<{
|
|
140
|
+
rule: z.ZodOptional<z.ZodString>;
|
|
141
|
+
message: z.ZodOptional<z.ZodString>;
|
|
142
|
+
file: z.ZodOptional<z.ZodString>;
|
|
143
|
+
severity: z.ZodOptional<z.ZodEnum<{
|
|
144
|
+
error: "error";
|
|
145
|
+
warning: "warning";
|
|
146
|
+
info: "info";
|
|
147
|
+
}>>;
|
|
148
|
+
reason: z.ZodString;
|
|
149
|
+
breadth_override: z.ZodOptional<z.ZodBoolean>;
|
|
150
|
+
breadth_override_reason: z.ZodOptional<z.ZodString>;
|
|
151
|
+
approved_by: z.ZodOptional<z.ZodString>;
|
|
152
|
+
}, z.core.$strip>;
|
|
153
|
+
export declare const SuppressionsSchema: z.ZodObject<{
|
|
154
|
+
rules: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
155
|
+
rule: z.ZodOptional<z.ZodString>;
|
|
156
|
+
message: z.ZodOptional<z.ZodString>;
|
|
157
|
+
file: z.ZodOptional<z.ZodString>;
|
|
158
|
+
severity: z.ZodOptional<z.ZodEnum<{
|
|
159
|
+
error: "error";
|
|
160
|
+
warning: "warning";
|
|
161
|
+
info: "info";
|
|
162
|
+
}>>;
|
|
163
|
+
reason: z.ZodString;
|
|
164
|
+
breadth_override: z.ZodOptional<z.ZodBoolean>;
|
|
165
|
+
breadth_override_reason: z.ZodOptional<z.ZodString>;
|
|
166
|
+
approved_by: z.ZodOptional<z.ZodString>;
|
|
167
|
+
}, z.core.$strip>>>;
|
|
168
|
+
disable_matchers: z.ZodDefault<z.ZodArray<z.ZodEnum<{
|
|
169
|
+
"express-error-mw": "express-error-mw";
|
|
170
|
+
"ts-unused-prefix": "ts-unused-prefix";
|
|
171
|
+
"exhaustive-switch": "exhaustive-switch";
|
|
172
|
+
"react-query-dedup": "react-query-dedup";
|
|
173
|
+
"promise-allsettled-order": "promise-allsettled-order";
|
|
174
|
+
"safe-local-file-read": "safe-local-file-read";
|
|
175
|
+
"exhaustive-type-narrowed-switch": "exhaustive-type-narrowed-switch";
|
|
176
|
+
"error-object-xss": "error-object-xss";
|
|
177
|
+
"thin-wrapper-stdlib": "thin-wrapper-stdlib";
|
|
178
|
+
}>>>;
|
|
179
|
+
security_override_allowlist: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
180
|
+
}, z.core.$strip>;
|
|
181
|
+
export type SuppressionRule = z.infer<typeof SuppressionRuleSchema>;
|
|
182
|
+
export type Suppressions = z.infer<typeof SuppressionsSchema>;
|
|
123
183
|
export declare const ConfigSchema: z.ZodObject<{
|
|
124
184
|
version: z.ZodDefault<z.ZodNumber>;
|
|
125
185
|
trusted_only: z.ZodDefault<z.ZodBoolean>;
|
|
@@ -133,13 +193,7 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
133
193
|
passes: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
134
194
|
name: z.ZodString;
|
|
135
195
|
agents: z.ZodArray<z.ZodEnum<{
|
|
136
|
-
|
|
137
|
-
semgrep: "semgrep";
|
|
138
|
-
reviewdog: "reviewdog";
|
|
139
|
-
opencode: "opencode";
|
|
140
|
-
pr_agent: "pr_agent";
|
|
141
|
-
local_llm: "local_llm";
|
|
142
|
-
ai_semantic_review: "ai_semantic_review";
|
|
196
|
+
[x: string]: string;
|
|
143
197
|
}>>;
|
|
144
198
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
145
199
|
required: z.ZodDefault<z.ZodBoolean>;
|
|
@@ -272,6 +326,34 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
272
326
|
"azure-openai": "azure-openai";
|
|
273
327
|
ollama: "ollama";
|
|
274
328
|
}>>;
|
|
329
|
+
suppressions: z.ZodOptional<z.ZodObject<{
|
|
330
|
+
rules: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
331
|
+
rule: z.ZodOptional<z.ZodString>;
|
|
332
|
+
message: z.ZodOptional<z.ZodString>;
|
|
333
|
+
file: z.ZodOptional<z.ZodString>;
|
|
334
|
+
severity: z.ZodOptional<z.ZodEnum<{
|
|
335
|
+
error: "error";
|
|
336
|
+
warning: "warning";
|
|
337
|
+
info: "info";
|
|
338
|
+
}>>;
|
|
339
|
+
reason: z.ZodString;
|
|
340
|
+
breadth_override: z.ZodOptional<z.ZodBoolean>;
|
|
341
|
+
breadth_override_reason: z.ZodOptional<z.ZodString>;
|
|
342
|
+
approved_by: z.ZodOptional<z.ZodString>;
|
|
343
|
+
}, z.core.$strip>>>;
|
|
344
|
+
disable_matchers: z.ZodDefault<z.ZodArray<z.ZodEnum<{
|
|
345
|
+
"express-error-mw": "express-error-mw";
|
|
346
|
+
"ts-unused-prefix": "ts-unused-prefix";
|
|
347
|
+
"exhaustive-switch": "exhaustive-switch";
|
|
348
|
+
"react-query-dedup": "react-query-dedup";
|
|
349
|
+
"promise-allsettled-order": "promise-allsettled-order";
|
|
350
|
+
"safe-local-file-read": "safe-local-file-read";
|
|
351
|
+
"exhaustive-type-narrowed-switch": "exhaustive-type-narrowed-switch";
|
|
352
|
+
"error-object-xss": "error-object-xss";
|
|
353
|
+
"thin-wrapper-stdlib": "thin-wrapper-stdlib";
|
|
354
|
+
}>>>;
|
|
355
|
+
security_override_allowlist: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
356
|
+
}, z.core.$strip>>;
|
|
275
357
|
}, z.core.$strip>;
|
|
276
358
|
export type Config = z.infer<typeof ConfigSchema>;
|
|
277
359
|
export type Pass = z.infer<typeof PassSchema>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../src/config/schemas.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../src/config/schemas.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,oBAAoB,EAAE,OAAO,CAAC;IACvC,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,mBAAmB,EAAE,SAAS,MAAM,EAAE,GAAG,KAAK,CAAC;CACzD;AAED;;;;GAIG;AACH,eAAO,MAAM,cAAc,EAAE,SAAS,kBAAkB,EAgE9C,CAAC;AAKX;;GAEG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAEvE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,kBAAkB,EAAE,CAK7F;AAGD,eAAO,MAAM,WAAW;;EAAoB,CAAC;AAE7C,eAAO,MAAM,UAAU;;;;;;;iBAUrB,CAAC;AAEH,eAAO,MAAM,YAAY;;;;;;;iBAavB,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;;;;iBAMhC,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;iBAM7B,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;iBAG1B,CAAC;AAEH,eAAO,MAAM,YAAY;;;;;;;;iBAKvB,CAAC;AAEH,eAAO,MAAM,cAAc;;;;;;iBAGzB,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;iBAG5B,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,YAAY;;iBAGvB,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,cAAc;;;;;EAA4D,CAAC;AAmBxF,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;iBAuE/B,CAAC;AAEJ,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAU3B,CAAC;AAEL,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AACpE,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAgCvB,CAAC;AAGH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAClD,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAC9C,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAClD,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAClD,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC"}
|
package/dist/config/schemas.js
CHANGED
|
@@ -6,16 +6,95 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { z } from 'zod';
|
|
8
8
|
import { ControlFlowConfigSchema } from '../agents/control_flow/types.js';
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Canonical agent registry — the sole authority for agent identity.
|
|
11
|
+
* Adding a new agent without updating this registry is impossible because
|
|
12
|
+
* AgentSchema is derived from it.
|
|
13
|
+
*/
|
|
14
|
+
export const AGENT_REGISTRY = [
|
|
15
|
+
{
|
|
16
|
+
id: 'semgrep',
|
|
17
|
+
name: 'Semgrep',
|
|
18
|
+
description: 'Static analysis via Semgrep CLI',
|
|
19
|
+
requiresExternalTool: true,
|
|
20
|
+
requiresApiKey: false,
|
|
21
|
+
builtIn: false,
|
|
22
|
+
compatibleProviders: 'all',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
id: 'reviewdog',
|
|
26
|
+
name: 'Reviewdog',
|
|
27
|
+
description: 'Lint aggregation via Reviewdog CLI',
|
|
28
|
+
requiresExternalTool: true,
|
|
29
|
+
requiresApiKey: false,
|
|
30
|
+
builtIn: false,
|
|
31
|
+
compatibleProviders: 'all',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: 'opencode',
|
|
35
|
+
name: 'OpenCode',
|
|
36
|
+
description: 'AI code review via cloud LLM',
|
|
37
|
+
requiresExternalTool: false,
|
|
38
|
+
requiresApiKey: true,
|
|
39
|
+
builtIn: false,
|
|
40
|
+
compatibleProviders: ['anthropic', 'openai', 'azure-openai'],
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
id: 'pr_agent',
|
|
44
|
+
name: 'PR Agent',
|
|
45
|
+
description: 'AI pull request analysis via cloud LLM',
|
|
46
|
+
requiresExternalTool: false,
|
|
47
|
+
requiresApiKey: true,
|
|
48
|
+
builtIn: false,
|
|
49
|
+
compatibleProviders: ['anthropic', 'openai', 'azure-openai'],
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
id: 'local_llm',
|
|
53
|
+
name: 'Local LLM',
|
|
54
|
+
description: 'AI code review via local Ollama model',
|
|
55
|
+
requiresExternalTool: false,
|
|
56
|
+
requiresApiKey: false,
|
|
57
|
+
builtIn: false,
|
|
58
|
+
compatibleProviders: ['ollama'],
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
id: 'ai_semantic_review',
|
|
62
|
+
name: 'AI Semantic Review',
|
|
63
|
+
description: 'Semantic analysis via cloud LLM',
|
|
64
|
+
requiresExternalTool: false,
|
|
65
|
+
requiresApiKey: true,
|
|
66
|
+
builtIn: false,
|
|
67
|
+
compatibleProviders: ['anthropic', 'openai', 'azure-openai'],
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
id: 'control_flow',
|
|
71
|
+
name: 'Control Flow',
|
|
72
|
+
description: 'Built-in TypeScript control flow analysis',
|
|
73
|
+
requiresExternalTool: false,
|
|
74
|
+
requiresApiKey: false,
|
|
75
|
+
builtIn: true,
|
|
76
|
+
compatibleProviders: 'all',
|
|
77
|
+
},
|
|
78
|
+
];
|
|
79
|
+
/** All valid agent IDs, derived from the registry */
|
|
80
|
+
const AGENT_IDS = AGENT_REGISTRY.map((a) => a.id);
|
|
81
|
+
/**
|
|
82
|
+
* Look up an agent by ID from the registry.
|
|
83
|
+
*/
|
|
84
|
+
export function getAgentById(id) {
|
|
85
|
+
return AGENT_REGISTRY.find((a) => a.id === id);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Get agents compatible with a given provider.
|
|
89
|
+
* Returns all agents if provider is null/undefined.
|
|
90
|
+
*/
|
|
91
|
+
export function getCompatibleAgents(provider) {
|
|
92
|
+
if (!provider)
|
|
93
|
+
return [...AGENT_REGISTRY];
|
|
94
|
+
return AGENT_REGISTRY.filter((a) => a.compatibleProviders === 'all' || a.compatibleProviders.includes(provider));
|
|
95
|
+
}
|
|
96
|
+
// Schema definitions — AgentSchema derived from registry
|
|
97
|
+
export const AgentSchema = z.enum(AGENT_IDS);
|
|
19
98
|
export const PassSchema = z.object({
|
|
20
99
|
name: z.string(),
|
|
21
100
|
agents: z.array(AgentSchema),
|
|
@@ -87,6 +166,92 @@ export const ModelsSchema = z.object({
|
|
|
87
166
|
* Required when multiple provider keys are present with MODEL set.
|
|
88
167
|
*/
|
|
89
168
|
export const ProviderSchema = z.enum(['anthropic', 'openai', 'azure-openai', 'ollama']);
|
|
169
|
+
// =============================================================================
|
|
170
|
+
// Suppression Schema (FR-022)
|
|
171
|
+
// =============================================================================
|
|
172
|
+
/** Valid matcher IDs for disable_matchers */
|
|
173
|
+
const VALID_MATCHER_IDS = [
|
|
174
|
+
'express-error-mw',
|
|
175
|
+
'ts-unused-prefix',
|
|
176
|
+
'exhaustive-switch',
|
|
177
|
+
'react-query-dedup',
|
|
178
|
+
'promise-allsettled-order',
|
|
179
|
+
'safe-local-file-read',
|
|
180
|
+
'exhaustive-type-narrowed-switch',
|
|
181
|
+
'error-object-xss',
|
|
182
|
+
'thin-wrapper-stdlib',
|
|
183
|
+
];
|
|
184
|
+
export const SuppressionRuleSchema = z
|
|
185
|
+
.object({
|
|
186
|
+
/** Glob pattern against finding.ruleId */
|
|
187
|
+
rule: z.string().optional(),
|
|
188
|
+
/** Anchored regex pattern against finding.message */
|
|
189
|
+
message: z.string().optional(),
|
|
190
|
+
/** Glob pattern against finding.file */
|
|
191
|
+
file: z.string().optional(),
|
|
192
|
+
/** Exact match against finding.severity */
|
|
193
|
+
severity: z.enum(['error', 'warning', 'info']).optional(),
|
|
194
|
+
/** Mandatory audit reason */
|
|
195
|
+
reason: z.string().min(1),
|
|
196
|
+
/** Allow broad suppression (>20 matches in CI) */
|
|
197
|
+
breadth_override: z.boolean().optional(),
|
|
198
|
+
/** Justification for breadth override */
|
|
199
|
+
breadth_override_reason: z.string().optional(),
|
|
200
|
+
/** Person or team who approved the override */
|
|
201
|
+
approved_by: z.string().optional(),
|
|
202
|
+
})
|
|
203
|
+
.refine((rule) => rule.rule !== undefined || rule.message !== undefined || rule.file !== undefined, { message: 'Suppression rule must specify at least one of: rule, message, file' })
|
|
204
|
+
.refine((rule) => {
|
|
205
|
+
if (rule.message === undefined)
|
|
206
|
+
return true;
|
|
207
|
+
if (rule.message.length === 0)
|
|
208
|
+
return false;
|
|
209
|
+
// FR-022: Message patterns MUST be fully anchored (^ and $).
|
|
210
|
+
if (!(rule.message.startsWith('^') && rule.message.endsWith('$')))
|
|
211
|
+
return false;
|
|
212
|
+
// Reject blanket patterns that match everything (^.*$, ^.+$, ^.{0,}$)
|
|
213
|
+
const blanketPatterns = ['^.*$', '^.+$', '^.{0,}$'];
|
|
214
|
+
if (blanketPatterns.includes(rule.message))
|
|
215
|
+
return false;
|
|
216
|
+
return true;
|
|
217
|
+
}, {
|
|
218
|
+
message: "Message pattern must be fully anchored (^...$) and not a blanket match. Use '^specific pattern$' for exact match or '^.*specific.*$' for substring.",
|
|
219
|
+
})
|
|
220
|
+
.refine((rule) => {
|
|
221
|
+
if (rule.rule === undefined)
|
|
222
|
+
return true;
|
|
223
|
+
// Reject blanket rule globs that match all rule IDs
|
|
224
|
+
const blanketGlobs = ['*', '**', '**/*'];
|
|
225
|
+
return !blanketGlobs.includes(rule.rule);
|
|
226
|
+
}, { message: "Rule glob must be scoped (e.g., 'semantic/*'), not a blanket '*'." })
|
|
227
|
+
.refine((rule) => {
|
|
228
|
+
if (rule.file === undefined)
|
|
229
|
+
return true;
|
|
230
|
+
// Reject blanket file globs that match all files
|
|
231
|
+
const blanketGlobs = ['*', '**', '**/*', '**/**'];
|
|
232
|
+
return !blanketGlobs.includes(rule.file);
|
|
233
|
+
}, { message: "File glob must be scoped (e.g., 'tests/**'), not a blanket '**'." })
|
|
234
|
+
.refine((rule) => {
|
|
235
|
+
if (!rule.breadth_override)
|
|
236
|
+
return true;
|
|
237
|
+
return (rule.breadth_override_reason !== undefined &&
|
|
238
|
+
rule.breadth_override_reason.length > 0 &&
|
|
239
|
+
rule.approved_by !== undefined &&
|
|
240
|
+
rule.approved_by.length > 0);
|
|
241
|
+
}, {
|
|
242
|
+
message: 'breadth_override requires both breadth_override_reason and approved_by to be specified',
|
|
243
|
+
});
|
|
244
|
+
export const SuppressionsSchema = z
|
|
245
|
+
.object({
|
|
246
|
+
rules: z.array(SuppressionRuleSchema).default([]),
|
|
247
|
+
/** Matcher IDs to disable in the framework convention filter */
|
|
248
|
+
disable_matchers: z.array(z.enum(VALID_MATCHER_IDS)).default([]),
|
|
249
|
+
/** Rule reasons authorized to suppress error-severity findings with breadth override */
|
|
250
|
+
security_override_allowlist: z.array(z.string()).default([]),
|
|
251
|
+
})
|
|
252
|
+
.refine((s) => s.rules.length <= 50, {
|
|
253
|
+
message: 'Maximum 50 suppression rules allowed',
|
|
254
|
+
});
|
|
90
255
|
export const ConfigSchema = z.object({
|
|
91
256
|
version: z.number().default(1),
|
|
92
257
|
trusted_only: z.boolean().default(true),
|
|
@@ -117,5 +282,7 @@ export const ConfigSchema = z.object({
|
|
|
117
282
|
* REQUIRED when multiple provider keys are present AND MODEL is set (prevents ambiguity).
|
|
118
283
|
*/
|
|
119
284
|
provider: ProviderSchema.optional(),
|
|
285
|
+
/** User-configurable finding suppressions (FR-022) */
|
|
286
|
+
suppressions: SuppressionsSchema.optional(),
|
|
120
287
|
});
|
|
121
288
|
//# sourceMappingURL=schemas.js.map
|