@rigour-labs/core 6.6.6 → 6.7.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/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.test.js +2 -2
- 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 +1 -2
- package/dist/hooks/index.js +0 -1
- package/dist/hooks/types.d.ts +0 -14
- package/dist/hooks/types.js +1 -15
- package/dist/index.d.ts +6 -1
- package/dist/index.js +6 -1
- 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-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 +9 -4
- package/dist/review/backtest.js +19 -9
- package/dist/review/backtest.test.js +2 -2
- package/dist/review/baseline.js +2 -1
- package/dist/review/dead-code.test.js +7 -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.js +1 -1
- 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/review.js +2 -1
- package/dist/review/reviewer/adapters.d.ts +23 -7
- package/dist/review/reviewer/adapters.js +32 -7
- 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 +8 -1
- package/dist/review/reviewer/background.js +34 -9
- package/dist/review/reviewer/background.test.js +16 -2
- 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.js +6 -2
- 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 +2 -0
- package/dist/review/reviewer/inputs.js +5 -1
- 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 +11 -0
- package/dist/review/reviewer/prompt.js +26 -4
- 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 +25 -2
- package/dist/review/reviewer/store.js +43 -1
- 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 +15 -1
- package/dist/review/reviewer/verdict.js +17 -7
- package/dist/review/reviewer.d.ts +45 -2
- package/dist/review/reviewer.js +186 -25
- package/dist/review/reviewer.test.js +127 -12
- package/dist/review/test-files.d.ts +5 -1
- package/dist/review/test-files.js +6 -2
- package/dist/review/toolchain.js +10 -3
- package/dist/review/toolchain.test.js +6 -3
- package/dist/review/typed/program.d.ts +0 -1
- package/dist/review/typed/program.js +3 -3
- package/dist/review/typed/redundancy.js +43 -4
- package/dist/review/typed/redundancy.test.js +58 -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 +5 -6
- 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 +8 -45
- package/dist/types/index.d.ts +108 -566
- package/dist/types/index.js +41 -66
- 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).
|
|
@@ -295,10 +261,13 @@ export const GatesSchema = z.object({
|
|
|
295
261
|
* range on the same column, a nullable row type the query filters non-null, an optional member every host supplies, a
|
|
296
262
|
* property written and never read. Runs at push, in `rigour review` and in a backtest (the program takes seconds to build).
|
|
297
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.
|
|
298
266
|
*/
|
|
299
267
|
redundancy: z.object({
|
|
300
268
|
enabled: z.boolean().optional().default(true),
|
|
301
269
|
wire_contracts: z.array(z.string()).optional().default([]),
|
|
270
|
+
schema_migrations: z.array(z.string()).optional().default(['supabase/migrations']),
|
|
302
271
|
}).optional().default({}),
|
|
303
272
|
/** A parameter the change adds as optional that only tests omit (review/optional-params.ts). */
|
|
304
273
|
optional_params: z.object({ enabled: z.boolean().optional().default(true) }).optional().default({}),
|
|
@@ -344,20 +313,11 @@ export const GatesSchema = z.object({
|
|
|
344
313
|
track_branches: z.boolean().optional().default(false), // opt-in: counts change on purpose in most edits
|
|
345
314
|
track_returns: z.boolean().optional().default(false), // opt-in: same
|
|
346
315
|
}).optional().default({}),
|
|
347
|
-
//
|
|
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.
|
|
348
317
|
deep: z.object({
|
|
349
|
-
enabled: z.boolean().optional().default(false),
|
|
350
|
-
pro: z.boolean().optional().default(false),
|
|
351
|
-
max: z.boolean().optional().default(false), // local Qwen2.5-Coder-7B (4.7GB); needs ~8GB free memory
|
|
352
|
-
provider: z.string().optional().default('local'), // 'local' for sidecar, or any cloud: 'claude', 'openai', 'gemini', 'groq', 'mistral', 'together', etc.
|
|
353
|
-
api_key: z.string().optional(),
|
|
354
|
-
api_base_url: z.string().optional(), // custom API base URL (for self-hosted, proxies, any OpenAI-compatible endpoint)
|
|
355
|
-
model_name: z.string().optional(), // cloud model name override (e.g. 'gpt-4o', 'claude-sonnet-4-5-20250929', 'gemini-pro')
|
|
356
|
-
model_path: z.string().optional(), // custom local GGUF model path override
|
|
357
|
-
threads: z.number().optional().default(4),
|
|
358
318
|
max_tokens: z.number().optional(), // default per provider: local 1024, cloud 4096
|
|
359
319
|
temperature: z.number().optional().default(0.1),
|
|
360
|
-
timeout_ms: z.number().optional(), // per
|
|
320
|
+
timeout_ms: z.number().optional(), // per model call; default: cloud 120s, local 60s, local --max 240s
|
|
361
321
|
budget_ms: z.number().optional(), // whole deep run; files not started in time are reported as skipped
|
|
362
322
|
agentic: z.boolean().optional(), // cloud tier: the model may read the repository while it reviews (default true)
|
|
363
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)
|
|
@@ -389,26 +349,10 @@ export const CommandsSchema = z.object({
|
|
|
389
349
|
test: z.string().optional(),
|
|
390
350
|
});
|
|
391
351
|
export const HooksSchema = z.object({
|
|
392
|
-
enabled: z.boolean().optional().default(false),
|
|
393
|
-
tools: z.array(z.enum(['claude', 'cursor', 'cline', 'windsurf'])).optional().default([]),
|
|
394
|
-
fast_gates: z.array(z.string()).optional().default([
|
|
395
|
-
'hallucinated-imports',
|
|
396
|
-
'phantom-apis',
|
|
397
|
-
'deprecated-apis',
|
|
398
|
-
'promise-safety',
|
|
399
|
-
'security-patterns',
|
|
400
|
-
'side-effect-analysis',
|
|
401
|
-
'file-size',
|
|
402
|
-
]),
|
|
403
|
-
timeout_ms: z.number().optional().default(5000),
|
|
404
|
-
block_on_failure: z.boolean().optional().default(false),
|
|
405
352
|
/** Stop hook: hold "done" until the agent acknowledges each risky changed function (rigour_review_ack). */
|
|
406
353
|
require_review_ack: z.boolean().optional().default(false),
|
|
407
|
-
/** Enable DLP (Data Loss Prevention) pre-input hooks — default ON for security */
|
|
408
|
-
dlp: z.boolean().optional().default(true),
|
|
409
354
|
}).optional().default({});
|
|
410
355
|
export const ConfigSchema = z.object({
|
|
411
|
-
version: z.number().default(1),
|
|
412
356
|
preset: z.string().optional(),
|
|
413
357
|
paradigm: z.string().optional(),
|
|
414
358
|
commands: CommandsSchema.optional().default({}),
|
|
@@ -439,13 +383,44 @@ export const ConfigSchema = z.object({
|
|
|
439
383
|
/** single: the first installed reviewer. cross: prefer a vendor not on the commits' trailers. full: two vendors, verdicts merged. */
|
|
440
384
|
mode: z.enum(['single', 'cross', 'full']).optional().default('single'),
|
|
441
385
|
/** The model for the claude reviewer. */
|
|
442
|
-
model:
|
|
386
|
+
model: ModelName.optional(),
|
|
443
387
|
/** A model per reviewer name, e.g. { cursor: "auto" }. */
|
|
444
|
-
models: z.record(
|
|
388
|
+
models: z.record(ModelName).optional().default({}),
|
|
445
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({}),
|
|
446
422
|
}).optional().default({}),
|
|
447
423
|
}).optional().default({}),
|
|
448
|
-
planned: z.array(z.string()).optional().default([]),
|
|
449
424
|
ignore: z.array(z.string()).optional().default([]),
|
|
450
425
|
});
|
|
451
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.1",
|
|
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-darwin-
|
|
79
|
-
"@rigour-labs/brain-
|
|
80
|
-
"@rigour-labs/brain-linux-x64": "6.
|
|
81
|
-
"@rigour-labs/brain-
|
|
76
|
+
"@rigour-labs/brain-darwin-arm64": "6.7.1",
|
|
77
|
+
"@rigour-labs/brain-darwin-x64": "6.7.1",
|
|
78
|
+
"@rigour-labs/brain-linux-arm64": "6.7.1",
|
|
79
|
+
"@rigour-labs/brain-linux-x64": "6.7.1",
|
|
80
|
+
"@rigour-labs/brain-win-x64": "6.7.1"
|
|
82
81
|
},
|
|
83
82
|
"devDependencies": {
|
|
84
83
|
"@types/fs-extra": "^11.0.4",
|