@rigour-labs/core 6.6.5 → 6.7.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 -92
- package/dist/environment.test.js +0 -4
- package/dist/gates/agent-team.d.ts +0 -2
- package/dist/gates/agent-team.js +0 -8
- package/dist/gates/checkpoint.d.ts +0 -1
- package/dist/gates/checkpoint.js +0 -1
- package/dist/gates/context.d.ts +0 -4
- package/dist/gates/context.js +7 -17
- package/dist/gates/deep-analysis.d.ts +0 -1
- package/dist/gates/deep-runner.js +0 -1
- package/dist/gates/frontend-secret-exposure.d.ts +1 -1
- package/dist/gates/frontend-secret-exposure.js +9 -3
- package/dist/gates/frontend-secret-exposure.test.js +6 -3
- package/dist/gates/hallucinated-imports/index.d.ts +0 -2
- package/dist/gates/hallucinated-imports/index.js +2 -2
- package/dist/gates/hallucinated-imports/js-resolver.js +1 -0
- package/dist/gates/hallucinated-imports.test.js +10 -0
- package/dist/gates/runner.js +3 -4
- package/dist/gates/test-quality-matchers.d.ts +0 -4
- package/dist/gates/test-quality-matchers.js +0 -7
- package/dist/gates/test-quality.d.ts +0 -2
- package/dist/gates/test-quality.js +1 -10
- package/dist/hooks/checker.js +1 -1
- package/dist/hooks/index.d.ts +2 -3
- package/dist/hooks/index.js +1 -2
- package/dist/hooks/stop-review.d.ts +6 -9
- package/dist/hooks/stop-review.js +5 -10
- package/dist/hooks/types.d.ts +0 -14
- package/dist/hooks/types.js +1 -15
- package/dist/index.d.ts +11 -3
- package/dist/index.js +11 -3
- package/dist/inference/cloud-provider.d.ts +2 -0
- package/dist/inference/cloud-provider.js +16 -6
- package/dist/inference/cloud-provider.test.js +21 -0
- package/dist/pattern-index/embeddings.d.ts +0 -5
- package/dist/pattern-index/embeddings.js +11 -4
- package/dist/pattern-index/semantic-runtime.d.ts +10 -0
- package/dist/pattern-index/semantic-runtime.js +46 -0
- package/dist/pattern-index/semantic-runtime.test.d.ts +1 -0
- package/dist/pattern-index/semantic-runtime.test.js +31 -0
- package/dist/review/backtest-init.d.ts +8 -0
- package/dist/review/backtest-init.js +87 -0
- package/dist/review/backtest-init.test.d.ts +1 -0
- package/dist/review/backtest-init.test.js +74 -0
- package/dist/review/backtest-judges.d.ts +38 -0
- package/dist/review/backtest-judges.js +63 -0
- package/dist/review/backtest-judges.test.d.ts +1 -0
- package/dist/review/backtest-judges.test.js +32 -0
- package/dist/review/backtest.d.ts +320 -0
- package/dist/review/backtest.js +207 -0
- package/dist/review/backtest.test.d.ts +1 -0
- package/dist/review/backtest.test.js +129 -0
- package/dist/review/baseline.js +2 -1
- package/dist/review/dead-code.test.js +15 -0
- package/dist/review/fix-scope.d.ts +21 -0
- package/dist/review/fix-scope.js +94 -0
- package/dist/review/fix-scope.test.d.ts +1 -0
- package/dist/review/fix-scope.test.js +104 -0
- package/dist/review/lint-overlay.d.ts +21 -0
- package/dist/review/lint-overlay.js +89 -0
- package/dist/review/orphan-files.js +3 -2
- package/dist/review/partial-wiring.js +5 -3
- package/dist/review/query-patterns.js +3 -2
- package/dist/review/quiet.d.ts +6 -0
- package/dist/review/quiet.js +12 -2
- package/dist/review/quiet.test.js +11 -0
- package/dist/review/review.d.ts +6 -0
- package/dist/review/review.js +10 -2
- package/dist/review/reviewer/adapters.d.ts +51 -0
- package/dist/review/reviewer/adapters.js +181 -0
- package/dist/review/reviewer/adapters.test.d.ts +1 -0
- package/dist/review/reviewer/adapters.test.js +23 -0
- package/dist/review/reviewer/background.d.ts +41 -0
- package/dist/review/reviewer/background.js +153 -0
- package/dist/review/reviewer/background.test.d.ts +1 -0
- package/dist/review/reviewer/background.test.js +118 -0
- package/dist/review/reviewer/consensus.d.ts +36 -0
- package/dist/review/reviewer/consensus.js +144 -0
- package/dist/review/reviewer/context.d.ts +75 -0
- package/dist/review/reviewer/context.js +140 -0
- package/dist/review/reviewer/context.test.d.ts +1 -0
- package/dist/review/reviewer/context.test.js +18 -0
- package/dist/review/reviewer/exec.d.ts +17 -0
- package/dist/review/reviewer/exec.js +27 -0
- package/dist/review/reviewer/exec.test.d.ts +1 -0
- package/dist/review/reviewer/exec.test.js +23 -0
- package/dist/review/reviewer/inputs.d.ts +39 -0
- package/dist/review/reviewer/inputs.js +107 -0
- package/dist/review/reviewer/merge-impact.d.ts +2 -0
- package/dist/review/reviewer/merge-impact.js +64 -0
- package/dist/review/reviewer/panel.d.ts +67 -0
- package/dist/review/reviewer/panel.js +101 -0
- package/dist/review/reviewer/panel.test.d.ts +1 -0
- package/dist/review/reviewer/panel.test.js +110 -0
- package/dist/review/reviewer/prompt.d.ts +32 -0
- package/dist/review/reviewer/prompt.js +145 -0
- package/dist/review/reviewer/settings.d.ts +58 -0
- package/dist/review/reviewer/settings.js +152 -0
- package/dist/review/reviewer/settings.test.d.ts +1 -0
- package/dist/review/reviewer/settings.test.js +57 -0
- package/dist/review/reviewer/store.d.ts +49 -0
- package/dist/review/reviewer/store.js +99 -0
- package/dist/review/reviewer/usage.d.ts +2 -0
- package/dist/review/reviewer/usage.js +28 -0
- package/dist/review/reviewer/usage.test.d.ts +1 -0
- package/dist/review/reviewer/usage.test.js +14 -0
- package/dist/review/reviewer/verdict.d.ts +141 -0
- package/dist/review/reviewer/verdict.js +166 -0
- package/dist/review/reviewer.d.ts +84 -49
- package/dist/review/reviewer.js +364 -195
- package/dist/review/reviewer.test.js +316 -50
- package/dist/review/test-files.d.ts +5 -1
- package/dist/review/test-files.js +6 -2
- package/dist/review/toolchain.d.ts +5 -2
- package/dist/review/toolchain.js +89 -7
- package/dist/review/toolchain.test.js +45 -4
- package/dist/review/typed/program.d.ts +26 -0
- package/dist/review/typed/program.js +90 -0
- package/dist/review/typed/redundancy.d.ts +10 -0
- package/dist/review/typed/redundancy.js +378 -0
- package/dist/review/typed/redundancy.test.d.ts +1 -0
- package/dist/review/typed/redundancy.test.js +179 -0
- package/dist/review/typed/schema-nullability.d.ts +6 -0
- package/dist/review/typed/schema-nullability.js +218 -0
- package/dist/review/typed/schema-nullability.test.d.ts +1 -0
- package/dist/review/typed/schema-nullability.test.js +63 -0
- package/dist/review/unused-exports.js +10 -7
- package/dist/semantic/learn/types.d.ts +2 -2
- package/dist/services/adaptive-thresholds.d.ts +2 -52
- package/dist/services/adaptive-thresholds.js +2 -147
- package/dist/services/adaptive-thresholds.test.js +1 -81
- package/dist/settings.d.ts +14 -6
- package/dist/settings.js +0 -12
- package/dist/storage/team-diagnostics.js +1 -1
- package/dist/storage/team-schema.d.ts +1 -1
- package/dist/storage/team-schema.js +2 -0
- package/dist/storage/team-store.js +26 -3
- package/dist/storage/team-sync-scope.test.js +35 -2
- package/dist/telemetry/telemetry.d.ts +5 -0
- package/dist/telemetry/telemetry.js +11 -1
- package/dist/templates/paradigms.js +0 -8
- package/dist/templates/presets.d.ts +0 -1
- package/dist/templates/presets.js +0 -23
- package/dist/templates/universal-config.js +16 -46
- package/dist/types/index.d.ts +202 -574
- package/dist/types/index.js +64 -67
- package/dist/types/index.test.d.ts +1 -0
- package/dist/types/index.test.js +33 -0
- package/dist/utils/command-line.d.ts +8 -0
- package/dist/utils/command-line.js +8 -0
- package/dist/utils/command-line.test.d.ts +1 -0
- package/dist/utils/command-line.test.js +8 -0
- package/dist/utils/profile.js +1 -1
- package/package.json +6 -7
package/dist/types/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
/** A model name handed to an agent CLI as an argument: one that starts with "-" would be read as a flag. */
|
|
3
|
+
const ModelName = z.string().regex(/^[\w.:/@][\w.:/@-]*$/, 'a model name (letters, digits and . : / @ -), not starting with -');
|
|
2
4
|
export const GatesSchema = z.object({
|
|
3
5
|
max_file_lines: z.number().optional().default(500),
|
|
4
6
|
forbid_todos: z.boolean().optional().default(true),
|
|
5
7
|
forbid_fixme: z.boolean().optional().default(true),
|
|
6
|
-
forbid_paths: z.array(z.string()).optional().default([]),
|
|
7
8
|
required_files: z.array(z.string()).optional().default([
|
|
8
9
|
'docs/SPEC.md',
|
|
9
10
|
'docs/ARCH.md',
|
|
@@ -14,10 +15,6 @@ export const GatesSchema = z.object({
|
|
|
14
15
|
complexity: z.number().optional().default(10),
|
|
15
16
|
max_methods: z.number().optional().default(10),
|
|
16
17
|
max_params: z.number().optional().default(5),
|
|
17
|
-
max_nesting: z.number().optional().default(4),
|
|
18
|
-
max_inheritance_depth: z.number().optional().default(3),
|
|
19
|
-
max_class_dependencies: z.number().optional().default(5),
|
|
20
|
-
max_function_lines: z.number().optional().default(50),
|
|
21
18
|
}).optional().default({}),
|
|
22
19
|
staleness: z.object({
|
|
23
20
|
enabled: z.boolean().optional().default(false),
|
|
@@ -35,7 +32,6 @@ export const GatesSchema = z.object({
|
|
|
35
32
|
}).optional().default({}),
|
|
36
33
|
dependencies: z.object({
|
|
37
34
|
forbid: z.array(z.string()).optional().default([]),
|
|
38
|
-
trusted_registry: z.string().optional(),
|
|
39
35
|
detect_unused: z.boolean().optional().default(true),
|
|
40
36
|
detect_heavy_alternatives: z.boolean().optional().default(true),
|
|
41
37
|
detect_duplicate_purpose: z.boolean().optional().default(true),
|
|
@@ -56,12 +52,6 @@ export const GatesSchema = z.object({
|
|
|
56
52
|
enabled: z.boolean().optional().default(true),
|
|
57
53
|
sensitivity: z.number().min(0).max(1).optional().default(0.8), // 0.8 correlation threshold
|
|
58
54
|
mining_depth: z.number().optional().default(100), // Number of files to sample
|
|
59
|
-
ignored_patterns: z.array(z.string()).optional().default([]),
|
|
60
|
-
// v2.14+ Extended Context for frontier models
|
|
61
|
-
cross_file_patterns: z.boolean().optional().default(true),
|
|
62
|
-
naming_consistency: z.boolean().optional().default(true),
|
|
63
|
-
import_relationships: z.boolean().optional().default(true),
|
|
64
|
-
max_cross_file_depth: z.number().optional().default(50),
|
|
65
55
|
}).optional().default({}),
|
|
66
56
|
environment: z.object({
|
|
67
57
|
enabled: z.boolean().optional().default(true),
|
|
@@ -72,14 +62,11 @@ export const GatesSchema = z.object({
|
|
|
72
62
|
retry_loop_breaker: z.object({
|
|
73
63
|
enabled: z.boolean().optional().default(true),
|
|
74
64
|
max_retries: z.number().optional().default(3), // Fail after 3 consecutive failures in same category
|
|
75
|
-
auto_classify: z.boolean().optional().default(true), // Auto-detect failure category from error message
|
|
76
65
|
doc_sources: z.record(z.string()).optional().default({}), // Custom doc URLs per category
|
|
77
66
|
}).optional().default({}),
|
|
78
67
|
agent_team: z.object({
|
|
79
68
|
enabled: z.boolean().optional().default(false),
|
|
80
69
|
max_concurrent_agents: z.number().optional().default(3),
|
|
81
|
-
cross_agent_pattern_check: z.boolean().optional().default(true),
|
|
82
|
-
handoff_verification: z.boolean().optional().default(true),
|
|
83
70
|
task_ownership: z.enum(['strict', 'collaborative']).optional().default('strict'),
|
|
84
71
|
}).optional().default({}),
|
|
85
72
|
checkpoint: z.object({
|
|
@@ -87,7 +74,6 @@ export const GatesSchema = z.object({
|
|
|
87
74
|
interval_minutes: z.number().optional().default(15),
|
|
88
75
|
quality_threshold: z.number().optional().default(80),
|
|
89
76
|
drift_detection: z.boolean().optional().default(true),
|
|
90
|
-
auto_save_on_failure: z.boolean().optional().default(true),
|
|
91
77
|
}).optional().default({}),
|
|
92
78
|
security: z.object({
|
|
93
79
|
enabled: z.boolean().optional().default(true),
|
|
@@ -135,13 +121,6 @@ export const GatesSchema = z.object({
|
|
|
135
121
|
]),
|
|
136
122
|
allowlist_env_names: z.array(z.string()).optional().default([]),
|
|
137
123
|
}).optional().default({}),
|
|
138
|
-
adaptive: z.object({
|
|
139
|
-
enabled: z.boolean().optional().default(false),
|
|
140
|
-
base_coverage_threshold: z.number().optional().default(80),
|
|
141
|
-
base_quality_threshold: z.number().optional().default(80),
|
|
142
|
-
auto_detect_tier: z.boolean().optional().default(true),
|
|
143
|
-
forced_tier: z.enum(['hobby', 'startup', 'enterprise']).optional(),
|
|
144
|
-
}).optional().default({}),
|
|
145
124
|
// v2.16+ AI-Native Drift Detection Gates
|
|
146
125
|
duplication_drift: z.object({
|
|
147
126
|
enabled: z.boolean().optional().default(true),
|
|
@@ -150,8 +129,6 @@ export const GatesSchema = z.object({
|
|
|
150
129
|
}).optional().default({}),
|
|
151
130
|
hallucinated_imports: z.object({
|
|
152
131
|
enabled: z.boolean().optional().default(true),
|
|
153
|
-
check_relative: z.boolean().optional().default(true),
|
|
154
|
-
check_packages: z.boolean().optional().default(true),
|
|
155
132
|
ignore_patterns: z.array(z.string()).optional().default([
|
|
156
133
|
'\\.css$', '\\.scss$', '\\.less$', '\\.svg$', '\\.png$', '\\.jpg$',
|
|
157
134
|
'\\.json$', '\\.wasm$', '\\.graphql$', '\\.gql$',
|
|
@@ -203,10 +180,8 @@ export const GatesSchema = z.object({
|
|
|
203
180
|
check_empty_tests: z.boolean().optional().default(true),
|
|
204
181
|
check_tautological: z.boolean().optional().default(true),
|
|
205
182
|
check_mock_heavy: z.boolean().optional().default(true),
|
|
206
|
-
check_snapshot_abuse: z.boolean().optional().default(true),
|
|
207
183
|
check_assertion_free_async: z.boolean().optional().default(true),
|
|
208
184
|
max_mocks_per_test: z.number().optional().default(5),
|
|
209
|
-
ignore_patterns: z.array(z.string()).optional().default([]),
|
|
210
185
|
}).optional().default({}),
|
|
211
186
|
// v4.2+ Memory & Skills Governance
|
|
212
187
|
governance: z.object({
|
|
@@ -259,15 +234,6 @@ export const GatesSchema = z.object({
|
|
|
259
234
|
'.windsurf/hooks.json', // Rigour's own hook config
|
|
260
235
|
]),
|
|
261
236
|
}).optional().default({}),
|
|
262
|
-
// v4.2+ AI Agent DLP (Data Loss Prevention)
|
|
263
|
-
input_validation: z.object({
|
|
264
|
-
enabled: z.boolean().optional().default(true),
|
|
265
|
-
block_on_detection: z.boolean().optional().default(true),
|
|
266
|
-
min_secret_length: z.number().optional().default(8),
|
|
267
|
-
custom_patterns: z.array(z.string()).optional().default([]),
|
|
268
|
-
ignore_patterns: z.array(z.string()).optional().default([]),
|
|
269
|
-
audit_log: z.boolean().optional().default(true),
|
|
270
|
-
}).optional().default({}),
|
|
271
237
|
// v4.3+ Side-Effect Safety Analysis
|
|
272
238
|
// On by default: full scans of three real repositories reported no finding that was not a real defect.
|
|
273
239
|
// A supabase-js read no index can serve, proved from the repository's own migrations (advisory, off by default).
|
|
@@ -290,6 +256,19 @@ export const GatesSchema = z.object({
|
|
|
290
256
|
query_patterns: z.object({ enabled: z.boolean().optional().default(true) }).optional().default({}),
|
|
291
257
|
/** What a fix leaves half done: the narrower condition still used elsewhere, a prop wired into some sibling mounts only, an accumulator copied every step (review/partial-fixes.ts, partial-wiring.ts, loop-copies.ts). */
|
|
292
258
|
change_sweep: z.object({ enabled: z.boolean().optional().default(true) }).optional().default({}),
|
|
259
|
+
/**
|
|
260
|
+
* What a change made redundant, from the project's own TypeScript (review/typed/redundancy.ts): a null filter beside a
|
|
261
|
+
* range on the same column, a nullable row type the query filters non-null, an optional member every host supplies, a
|
|
262
|
+
* property written and never read. Runs at push, in `rigour review` and in a backtest (the program takes seconds to build).
|
|
263
|
+
* `wire_contracts`: files whose types another service reads, so their members are never write-only here.
|
|
264
|
+
* `schema_migrations`: folders of SQL migrations (relative, absolute, or `~/`; another repository's is fine, read only)
|
|
265
|
+
* replayed to learn which columns are NOT NULL, for the nullable-not-null-column note. Missing folders are skipped.
|
|
266
|
+
*/
|
|
267
|
+
redundancy: z.object({
|
|
268
|
+
enabled: z.boolean().optional().default(true),
|
|
269
|
+
wire_contracts: z.array(z.string()).optional().default([]),
|
|
270
|
+
schema_migrations: z.array(z.string()).optional().default(['supabase/migrations']),
|
|
271
|
+
}).optional().default({}),
|
|
293
272
|
/** A parameter the change adds as optional that only tests omit (review/optional-params.ts). */
|
|
294
273
|
optional_params: z.object({ enabled: z.boolean().optional().default(true) }).optional().default({}),
|
|
295
274
|
/** A changed function whose body duplicates another in the files the change touched (review/duplicate-functions.ts). */
|
|
@@ -334,20 +313,11 @@ export const GatesSchema = z.object({
|
|
|
334
313
|
track_branches: z.boolean().optional().default(false), // opt-in: counts change on purpose in most edits
|
|
335
314
|
track_returns: z.boolean().optional().default(false), // opt-in: same
|
|
336
315
|
}).optional().default({}),
|
|
337
|
-
//
|
|
316
|
+
// Model review. Whether it runs, the tier, the provider and its key come from flags and the person's settings, never from a committed file.
|
|
338
317
|
deep: z.object({
|
|
339
|
-
enabled: z.boolean().optional().default(false),
|
|
340
|
-
pro: z.boolean().optional().default(false),
|
|
341
|
-
max: z.boolean().optional().default(false), // local Qwen2.5-Coder-7B (4.7GB); needs ~8GB free memory
|
|
342
|
-
provider: z.string().optional().default('local'), // 'local' for sidecar, or any cloud: 'claude', 'openai', 'gemini', 'groq', 'mistral', 'together', etc.
|
|
343
|
-
api_key: z.string().optional(),
|
|
344
|
-
api_base_url: z.string().optional(), // custom API base URL (for self-hosted, proxies, any OpenAI-compatible endpoint)
|
|
345
|
-
model_name: z.string().optional(), // cloud model name override (e.g. 'gpt-4o', 'claude-sonnet-4-5-20250929', 'gemini-pro')
|
|
346
|
-
model_path: z.string().optional(), // custom local GGUF model path override
|
|
347
|
-
threads: z.number().optional().default(4),
|
|
348
318
|
max_tokens: z.number().optional(), // default per provider: local 1024, cloud 4096
|
|
349
319
|
temperature: z.number().optional().default(0.1),
|
|
350
|
-
timeout_ms: z.number().optional(), // per
|
|
320
|
+
timeout_ms: z.number().optional(), // per model call; default: cloud 120s, local 60s, local --max 240s
|
|
351
321
|
budget_ms: z.number().optional(), // whole deep run; files not started in time are reported as skipped
|
|
352
322
|
agentic: z.boolean().optional(), // cloud tier: the model may read the repository while it reviews (default true)
|
|
353
323
|
repo_rules: z.boolean().optional(), // show the reviewer the rules in AGENTS.md / CLAUDE.md / Cursor rules that name what the change touches (default false)
|
|
@@ -379,26 +349,10 @@ export const CommandsSchema = z.object({
|
|
|
379
349
|
test: z.string().optional(),
|
|
380
350
|
});
|
|
381
351
|
export const HooksSchema = z.object({
|
|
382
|
-
enabled: z.boolean().optional().default(false),
|
|
383
|
-
tools: z.array(z.enum(['claude', 'cursor', 'cline', 'windsurf'])).optional().default([]),
|
|
384
|
-
fast_gates: z.array(z.string()).optional().default([
|
|
385
|
-
'hallucinated-imports',
|
|
386
|
-
'phantom-apis',
|
|
387
|
-
'deprecated-apis',
|
|
388
|
-
'promise-safety',
|
|
389
|
-
'security-patterns',
|
|
390
|
-
'side-effect-analysis',
|
|
391
|
-
'file-size',
|
|
392
|
-
]),
|
|
393
|
-
timeout_ms: z.number().optional().default(5000),
|
|
394
|
-
block_on_failure: z.boolean().optional().default(false),
|
|
395
352
|
/** Stop hook: hold "done" until the agent acknowledges each risky changed function (rigour_review_ack). */
|
|
396
353
|
require_review_ack: z.boolean().optional().default(false),
|
|
397
|
-
/** Enable DLP (Data Loss Prevention) pre-input hooks — default ON for security */
|
|
398
|
-
dlp: z.boolean().optional().default(true),
|
|
399
354
|
}).optional().default({});
|
|
400
355
|
export const ConfigSchema = z.object({
|
|
401
|
-
version: z.number().default(1),
|
|
402
356
|
preset: z.string().optional(),
|
|
403
357
|
paradigm: z.string().optional(),
|
|
404
358
|
commands: CommandsSchema.optional().default({}),
|
|
@@ -415,15 +369,58 @@ export const ConfigSchema = z.object({
|
|
|
415
369
|
show_preexisting: z.boolean().optional().default(false),
|
|
416
370
|
/** The GitHub account whose token fetches the pull request's previous review (`gh auth token --user`). */
|
|
417
371
|
github_account: z.string().optional(),
|
|
418
|
-
/** The
|
|
372
|
+
/** The reviewer (review/reviewer.ts): the person's own coding-agent CLIs, headless and read-only. `enabled` runs it at push; `rigour review --reviewer` runs it on request. */
|
|
419
373
|
reviewer: z.object({
|
|
420
374
|
enabled: z.boolean().optional().default(false),
|
|
421
|
-
|
|
422
|
-
|
|
375
|
+
/**
|
|
376
|
+
* At push, once the deterministic gates pass: `background` (default) starts the model review of the pushed
|
|
377
|
+
* commit without holding the push; `wait` holds the push for it; `off` reviews only on request. Either way
|
|
378
|
+
* a model is asked only when the branch has an open, non-draft pull request (someone will read the push).
|
|
379
|
+
*/
|
|
380
|
+
on_push: z.enum(['background', 'wait', 'off']).optional().default('background'),
|
|
381
|
+
/** The adapters, in order: claude, cursor, codex. */
|
|
382
|
+
reviewers: z.array(z.string()).optional().default(['claude']),
|
|
383
|
+
/** single: the first installed reviewer. cross: prefer a vendor not on the commits' trailers. full: two vendors, verdicts merged. */
|
|
384
|
+
mode: z.enum(['single', 'cross', 'full']).optional().default('single'),
|
|
385
|
+
/** The model for the claude reviewer. */
|
|
386
|
+
model: ModelName.optional(),
|
|
387
|
+
/** A model per reviewer name, e.g. { cursor: "auto" }. */
|
|
388
|
+
models: z.record(ModelName).optional().default({}),
|
|
423
389
|
timeout_ms: z.number().optional().default(15 * 60_000),
|
|
390
|
+
/**
|
|
391
|
+
* With two vendors: match their findings, cross-examine only what one raised, and block only on what is
|
|
392
|
+
* confirmed (review/reviewer/panel.ts). `on` implies mode full. `required`: no user or run may turn it off,
|
|
393
|
+
* and a run without two vendors is unavailable instead of falling back to one.
|
|
394
|
+
*/
|
|
395
|
+
panel: z.enum(['off', 'on', 'required']).optional().default('off'),
|
|
396
|
+
/** No user or run may review with fewer than the team's mode (a protected branch, CI). */
|
|
397
|
+
mode_required: z.boolean().optional().default(false),
|
|
398
|
+
/**
|
|
399
|
+
* Whether people may dismiss a reviewer finding as not a bug (`rigour dismiss <id>`, Studio). Off by default:
|
|
400
|
+
* a wrong finding is fixed by improving the reviewer, a right one by fixing the code. A team decision only.
|
|
401
|
+
*/
|
|
402
|
+
dismissals: z.boolean().optional().default(false),
|
|
403
|
+
/** Findings cross-examined per review at most; the rest are shown as disputed. */
|
|
404
|
+
panel_max_items: z.number().int().positive().optional().default(20),
|
|
405
|
+
/**
|
|
406
|
+
* Spending caps per repository and local day, unset by default. Runs are checked before any judge starts
|
|
407
|
+
* (a cross-examination counts too); dollars are the ones the CLIs reported, so a cap stops new reviews once
|
|
408
|
+
* reached. Past a cap a review is skipped, or unavailable when the team requires the reviewer.
|
|
409
|
+
*/
|
|
410
|
+
max_runs_per_day: z.number().int().positive().optional(),
|
|
411
|
+
max_usd_per_day: z.number().positive().optional(),
|
|
412
|
+
/** Judges in a full or panel review, each from a different vendor; capped by the vendors installed. */
|
|
413
|
+
judges: z.union([z.literal(2), z.literal(3)]).optional().default(2),
|
|
414
|
+
/**
|
|
415
|
+
* When a full or panel review adds judges. `always`: every review. `risk`: only when the change has a
|
|
416
|
+
* risky function (the router's score), a human review exists, or the run is the --full hard stop; any
|
|
417
|
+
* other change gets one judge. Measured against `always` by the backtest before you rely on it.
|
|
418
|
+
*/
|
|
419
|
+
escalate: z.enum(['always', 'risk']).optional().default('always'),
|
|
420
|
+
/** A model per reviewer name for cross-examination (a narrow verification task), e.g. { claude: "haiku" }. */
|
|
421
|
+
cross_models: z.record(ModelName).optional().default({}),
|
|
424
422
|
}).optional().default({}),
|
|
425
423
|
}).optional().default({}),
|
|
426
|
-
planned: z.array(z.string()).optional().default([]),
|
|
427
424
|
ignore: z.array(z.string()).optional().default([]),
|
|
428
425
|
});
|
|
429
426
|
export const StatusSchema = z.enum(['PASS', 'FAIL', 'SKIP', 'ERROR']);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import yaml from 'yaml';
|
|
3
|
+
import { ConfigSchema } from './index.js';
|
|
4
|
+
describe('rigour.yml', () => {
|
|
5
|
+
it('still loads a file that sets the settings no check ever read, and keeps everything else', () => {
|
|
6
|
+
const old = yaml.parse(`
|
|
7
|
+
version: 1
|
|
8
|
+
planned: [Layer boundaries]
|
|
9
|
+
hooks: { enabled: true, tools: [claude], fast_gates: [file-size], timeout_ms: 5000, block_on_failure: true, dlp: false, require_review_ack: true }
|
|
10
|
+
gates:
|
|
11
|
+
max_file_lines: 300
|
|
12
|
+
forbid_paths: [secret/]
|
|
13
|
+
ast: { complexity: 7, max_nesting: 3, max_function_lines: 40 }
|
|
14
|
+
adaptive: { enabled: true, forced_tier: enterprise }
|
|
15
|
+
input_validation: { enabled: true, min_secret_length: 12 }
|
|
16
|
+
deep: { enabled: true, provider: claude, api_key: sk-test, model_name: x, threads: 8, temperature: 0.2 }
|
|
17
|
+
test_quality: { check_snapshot_abuse: false, ignore_patterns: [x], max_mocks_per_test: 3 }
|
|
18
|
+
`);
|
|
19
|
+
const config = ConfigSchema.parse(old);
|
|
20
|
+
expect(config.gates.max_file_lines).toBe(300);
|
|
21
|
+
expect(config.gates.ast.complexity).toBe(7);
|
|
22
|
+
expect(config.gates.deep.temperature).toBe(0.2);
|
|
23
|
+
expect(config.gates.test_quality.max_mocks_per_test).toBe(3);
|
|
24
|
+
expect(config.hooks.require_review_ack).toBe(true);
|
|
25
|
+
// What nothing read is dropped, so no code can start depending on it by accident.
|
|
26
|
+
expect(config).not.toHaveProperty('version');
|
|
27
|
+
expect(config).not.toHaveProperty('planned');
|
|
28
|
+
expect(config.gates).not.toHaveProperty('adaptive');
|
|
29
|
+
expect(config.gates).not.toHaveProperty('input_validation');
|
|
30
|
+
expect(config.gates.deep).not.toHaveProperty('api_key');
|
|
31
|
+
expect(config.hooks).not.toHaveProperty('block_on_failure');
|
|
32
|
+
});
|
|
33
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A `commands:` entry from rigour.yml as a program and its arguments. Run without a shell, so pipes,
|
|
3
|
+
* `&&` and variable assignments are not interpreted: a team that needs them points at a script.
|
|
4
|
+
*/
|
|
5
|
+
export declare function splitCommand(command: string): {
|
|
6
|
+
bin: string;
|
|
7
|
+
args: string[];
|
|
8
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A `commands:` entry from rigour.yml as a program and its arguments. Run without a shell, so pipes,
|
|
3
|
+
* `&&` and variable assignments are not interpreted: a team that needs them points at a script.
|
|
4
|
+
*/
|
|
5
|
+
export function splitCommand(command) {
|
|
6
|
+
const parts = command.match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g) ?? [command];
|
|
7
|
+
return { bin: parts[0], args: parts.slice(1).map(arg => arg.replace(/^["']|["']$/g, '')) };
|
|
8
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { splitCommand } from './command-line.js';
|
|
3
|
+
describe('splitCommand', () => {
|
|
4
|
+
it('splits on spaces and keeps a quoted argument whole, without its quotes', () => {
|
|
5
|
+
expect(splitCommand('npm run lint')).toEqual({ bin: 'npm', args: ['run', 'lint'] });
|
|
6
|
+
expect(splitCommand(`vitest run "src/a b.test.ts" --reporter 'dot'`)).toEqual({ bin: 'vitest', args: ['run', 'src/a b.test.ts', '--reporter', 'dot'] });
|
|
7
|
+
});
|
|
8
|
+
});
|
package/dist/utils/profile.js
CHANGED
|
@@ -16,7 +16,7 @@ import { spawnSync } from 'child_process';
|
|
|
16
16
|
import fs from 'fs';
|
|
17
17
|
import os from 'os';
|
|
18
18
|
import path from 'path';
|
|
19
|
-
const TEAM_ENV = ['RIGOUR_ORGANIZATION_ID', 'RIGOUR_TEAM_ID', 'RIGOUR_ACTOR_ID', 'RIGOUR_TEAM_REPOSITORIES', 'RIGOUR_TEAM_DATABASE_URL', 'RIGOUR_TEAM_DATABASE_URL_COMMAND', 'RIGOUR_TEAM_SEMANTIC'];
|
|
19
|
+
const TEAM_ENV = ['RIGOUR_ORGANIZATION_ID', 'RIGOUR_TEAM_ID', 'RIGOUR_ACTOR_ID', 'RIGOUR_TEAM_REPOSITORIES', 'RIGOUR_TEAM_DATABASE_URL', 'RIGOUR_TEAM_DATABASE_URL_COMMAND', 'RIGOUR_TEAM_SEMANTIC', 'RIGOUR_TEAM_SYNC_PERSONAL'];
|
|
20
20
|
/** Where profiles are listed: always the person's real home, never a profile's. */
|
|
21
21
|
export function profilesPath() {
|
|
22
22
|
return process.env.RIGOUR_PROFILES || path.join(os.homedir(), '.rigour', 'profiles.json');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rigour-labs/core",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.7.0",
|
|
4
4
|
"description": "Rigour's review engine: deterministic gates on changed lines, rules and lessons learned from your team's fixes, and per-check precision from what you fix versus dismiss, across TypeScript, JavaScript, Python, Go, Ruby and C#.",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=22"
|
|
@@ -70,15 +70,14 @@
|
|
|
70
70
|
},
|
|
71
71
|
"optionalDependencies": {
|
|
72
72
|
"@anthropic-ai/sdk": "^0.30.1",
|
|
73
|
-
"@xenova/transformers": "^2.17.2",
|
|
74
73
|
"pg": "^8.16.3",
|
|
75
74
|
"sqlite3": "^5.1.7",
|
|
76
75
|
"openai": "^4.104.0",
|
|
77
|
-
"@rigour-labs/brain-darwin-
|
|
78
|
-
"@rigour-labs/brain-
|
|
79
|
-
"@rigour-labs/brain-
|
|
80
|
-
"@rigour-labs/brain-
|
|
81
|
-
"@rigour-labs/brain-
|
|
76
|
+
"@rigour-labs/brain-darwin-x64": "6.7.0",
|
|
77
|
+
"@rigour-labs/brain-linux-arm64": "6.7.0",
|
|
78
|
+
"@rigour-labs/brain-darwin-arm64": "6.7.0",
|
|
79
|
+
"@rigour-labs/brain-win-x64": "6.7.0",
|
|
80
|
+
"@rigour-labs/brain-linux-x64": "6.7.0"
|
|
82
81
|
},
|
|
83
82
|
"devDependencies": {
|
|
84
83
|
"@types/fs-extra": "^11.0.4",
|