@rigour-labs/core 4.0.5 → 4.1.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/dist/gates/ast-handlers/typescript.js +39 -12
- package/dist/gates/ast-handlers/universal.js +9 -3
- package/dist/gates/ast.js +15 -1
- package/dist/gates/ast.test.d.ts +1 -0
- package/dist/gates/ast.test.js +112 -0
- package/dist/gates/content.d.ts +5 -0
- package/dist/gates/content.js +66 -7
- package/dist/gates/content.test.d.ts +1 -0
- package/dist/gates/content.test.js +73 -0
- package/dist/gates/context-window-artifacts.d.ts +1 -0
- package/dist/gates/context-window-artifacts.js +10 -3
- package/dist/gates/context.d.ts +1 -0
- package/dist/gates/context.js +29 -8
- package/dist/gates/deep-analysis.js +2 -2
- package/dist/gates/deprecated-apis.d.ts +1 -0
- package/dist/gates/deprecated-apis.js +15 -2
- package/dist/gates/hallucinated-imports.d.ts +14 -0
- package/dist/gates/hallucinated-imports.js +267 -60
- package/dist/gates/hallucinated-imports.test.js +164 -1
- package/dist/gates/inconsistent-error-handling.d.ts +1 -0
- package/dist/gates/inconsistent-error-handling.js +12 -1
- package/dist/gates/phantom-apis.d.ts +2 -0
- package/dist/gates/phantom-apis.js +28 -3
- package/dist/gates/phantom-apis.test.js +14 -0
- package/dist/gates/promise-safety.d.ts +2 -0
- package/dist/gates/promise-safety.js +31 -9
- package/dist/gates/runner.js +8 -2
- package/dist/gates/runner.test.d.ts +1 -0
- package/dist/gates/runner.test.js +65 -0
- package/dist/gates/security-patterns.d.ts +1 -0
- package/dist/gates/security-patterns.js +22 -6
- package/dist/gates/security-patterns.test.js +18 -0
- package/dist/hooks/templates.d.ts +1 -1
- package/dist/hooks/templates.js +12 -12
- package/dist/inference/executable.d.ts +6 -0
- package/dist/inference/executable.js +29 -0
- package/dist/inference/executable.test.d.ts +1 -0
- package/dist/inference/executable.test.js +41 -0
- package/dist/inference/model-manager.d.ts +3 -1
- package/dist/inference/model-manager.js +76 -8
- package/dist/inference/model-manager.test.d.ts +1 -0
- package/dist/inference/model-manager.test.js +24 -0
- package/dist/inference/sidecar-provider.d.ts +1 -0
- package/dist/inference/sidecar-provider.js +91 -15
- package/dist/services/context-engine.js +1 -1
- package/dist/templates/universal-config.js +3 -3
- package/dist/types/index.js +3 -3
- package/dist/utils/scanner.js +6 -0
- package/package.json +6 -6
|
@@ -4,21 +4,74 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import path from 'path';
|
|
6
6
|
import fs from 'fs-extra';
|
|
7
|
+
import { createHash } from 'crypto';
|
|
7
8
|
import { RIGOUR_DIR } from '../storage/db.js';
|
|
8
9
|
import { MODELS } from './types.js';
|
|
9
10
|
const MODELS_DIR = path.join(RIGOUR_DIR, 'models');
|
|
11
|
+
const SHA256_RE = /^[a-f0-9]{64}$/i;
|
|
12
|
+
function getModelMetadataPath(tier) {
|
|
13
|
+
return path.join(MODELS_DIR, MODELS[tier].filename + '.meta.json');
|
|
14
|
+
}
|
|
15
|
+
function isValidMetadata(raw) {
|
|
16
|
+
return !!raw &&
|
|
17
|
+
typeof raw.sha256 === 'string' &&
|
|
18
|
+
SHA256_RE.test(raw.sha256) &&
|
|
19
|
+
typeof raw.sizeBytes === 'number' &&
|
|
20
|
+
typeof raw.verifiedAt === 'string' &&
|
|
21
|
+
typeof raw.sourceUrl === 'string';
|
|
22
|
+
}
|
|
23
|
+
export function extractSha256FromEtag(etag) {
|
|
24
|
+
if (!etag)
|
|
25
|
+
return null;
|
|
26
|
+
const normalized = etag.replace(/^W\//i, '').replace(/^"+|"+$/g, '').trim();
|
|
27
|
+
return SHA256_RE.test(normalized) ? normalized.toLowerCase() : null;
|
|
28
|
+
}
|
|
29
|
+
export async function hashFileSha256(filePath) {
|
|
30
|
+
const hash = createHash('sha256');
|
|
31
|
+
const stream = fs.createReadStream(filePath);
|
|
32
|
+
for await (const chunk of stream) {
|
|
33
|
+
hash.update(chunk);
|
|
34
|
+
}
|
|
35
|
+
return hash.digest('hex');
|
|
36
|
+
}
|
|
37
|
+
async function writeModelMetadata(tier, metadata) {
|
|
38
|
+
const metadataPath = getModelMetadataPath(tier);
|
|
39
|
+
await fs.writeJson(metadataPath, metadata, { spaces: 2 });
|
|
40
|
+
}
|
|
41
|
+
async function readModelMetadata(tier) {
|
|
42
|
+
const metadataPath = getModelMetadataPath(tier);
|
|
43
|
+
if (!(await fs.pathExists(metadataPath))) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const raw = await fs.readJson(metadataPath);
|
|
48
|
+
return isValidMetadata(raw) ? raw : null;
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
10
54
|
/**
|
|
11
55
|
* Check if a model is already downloaded and valid.
|
|
12
56
|
*/
|
|
13
|
-
export function isModelCached(tier) {
|
|
57
|
+
export async function isModelCached(tier) {
|
|
14
58
|
const model = MODELS[tier];
|
|
15
59
|
const modelPath = path.join(MODELS_DIR, model.filename);
|
|
16
|
-
if (!fs.
|
|
60
|
+
if (!(await fs.pathExists(modelPath)))
|
|
17
61
|
return false;
|
|
18
|
-
|
|
19
|
-
|
|
62
|
+
const metadata = await readModelMetadata(tier);
|
|
63
|
+
if (!metadata)
|
|
64
|
+
return false;
|
|
65
|
+
// Size check + "changed since verification" check.
|
|
66
|
+
const stat = await fs.stat(modelPath);
|
|
20
67
|
const tolerance = model.sizeBytes * 0.1;
|
|
21
|
-
|
|
68
|
+
if (stat.size <= model.sizeBytes - tolerance)
|
|
69
|
+
return false;
|
|
70
|
+
if (metadata.sizeBytes !== stat.size)
|
|
71
|
+
return false;
|
|
72
|
+
if (new Date(metadata.verifiedAt).getTime() < stat.mtimeMs)
|
|
73
|
+
return false;
|
|
74
|
+
return true;
|
|
22
75
|
}
|
|
23
76
|
/**
|
|
24
77
|
* Get the path to a cached model.
|
|
@@ -42,7 +95,7 @@ export async function downloadModel(tier, onProgress) {
|
|
|
42
95
|
const tempPath = destPath + '.download';
|
|
43
96
|
fs.ensureDirSync(MODELS_DIR);
|
|
44
97
|
// Already cached
|
|
45
|
-
if (isModelCached(tier)) {
|
|
98
|
+
if (await isModelCached(tier)) {
|
|
46
99
|
onProgress?.(`Model ${model.name} already cached`, 100);
|
|
47
100
|
return destPath;
|
|
48
101
|
}
|
|
@@ -52,18 +105,22 @@ export async function downloadModel(tier, onProgress) {
|
|
|
52
105
|
if (!response.ok) {
|
|
53
106
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
54
107
|
}
|
|
108
|
+
const expectedSha256 = extractSha256FromEtag(response.headers.get('etag'));
|
|
55
109
|
const contentLength = parseInt(response.headers.get('content-length') || '0', 10);
|
|
56
110
|
const reader = response.body?.getReader();
|
|
57
111
|
if (!reader)
|
|
58
112
|
throw new Error('No response body');
|
|
59
113
|
const writeStream = fs.createWriteStream(tempPath);
|
|
114
|
+
const hash = createHash('sha256');
|
|
60
115
|
let downloaded = 0;
|
|
61
116
|
let lastProgressPercent = 0;
|
|
62
117
|
while (true) {
|
|
63
118
|
const { done, value } = await reader.read();
|
|
64
119
|
if (done)
|
|
65
120
|
break;
|
|
66
|
-
|
|
121
|
+
const chunk = Buffer.from(value);
|
|
122
|
+
writeStream.write(chunk);
|
|
123
|
+
hash.update(chunk);
|
|
67
124
|
downloaded += value.length;
|
|
68
125
|
if (contentLength > 0) {
|
|
69
126
|
const percent = Math.round((downloaded / contentLength) * 100);
|
|
@@ -78,8 +135,19 @@ export async function downloadModel(tier, onProgress) {
|
|
|
78
135
|
writeStream.on('finish', resolve);
|
|
79
136
|
writeStream.on('error', reject);
|
|
80
137
|
});
|
|
138
|
+
const actualSha256 = hash.digest('hex');
|
|
139
|
+
if (expectedSha256 && actualSha256 !== expectedSha256) {
|
|
140
|
+
throw new Error(`Model checksum mismatch for ${model.name}: expected ${expectedSha256}, got ${actualSha256}`);
|
|
141
|
+
}
|
|
81
142
|
// Atomic rename
|
|
82
143
|
fs.renameSync(tempPath, destPath);
|
|
144
|
+
await writeModelMetadata(tier, {
|
|
145
|
+
sha256: actualSha256,
|
|
146
|
+
sizeBytes: downloaded,
|
|
147
|
+
verifiedAt: new Date().toISOString(),
|
|
148
|
+
sourceUrl: model.url,
|
|
149
|
+
sourceEtag: response.headers.get('etag') || undefined,
|
|
150
|
+
});
|
|
83
151
|
onProgress?.(`Model ${model.name} ready`, 100);
|
|
84
152
|
return destPath;
|
|
85
153
|
}
|
|
@@ -93,7 +161,7 @@ export async function downloadModel(tier, onProgress) {
|
|
|
93
161
|
* Ensure a model is available, downloading if needed.
|
|
94
162
|
*/
|
|
95
163
|
export async function ensureModel(tier, onProgress) {
|
|
96
|
-
if (isModelCached(tier)) {
|
|
164
|
+
if (await isModelCached(tier)) {
|
|
97
165
|
return getModelPath(tier);
|
|
98
166
|
}
|
|
99
167
|
return downloadModel(tier, onProgress);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import os from 'os';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { extractSha256FromEtag, hashFileSha256 } from './model-manager.js';
|
|
6
|
+
describe('model manager integrity helpers', () => {
|
|
7
|
+
it('extracts sha256 digest from a strong ETag', () => {
|
|
8
|
+
const digest = 'a'.repeat(64);
|
|
9
|
+
expect(extractSha256FromEtag(`"${digest}"`)).toBe(digest);
|
|
10
|
+
expect(extractSha256FromEtag(`W/"${digest}"`)).toBe(digest);
|
|
11
|
+
});
|
|
12
|
+
it('returns null for non-sha ETags', () => {
|
|
13
|
+
expect(extractSha256FromEtag('"not-a-digest"')).toBeNull();
|
|
14
|
+
expect(extractSha256FromEtag(null)).toBeNull();
|
|
15
|
+
});
|
|
16
|
+
it('hashes file contents with sha256', async () => {
|
|
17
|
+
const dir = await fs.mkdtemp(path.join(os.tmpdir(), 'rigour-model-hash-'));
|
|
18
|
+
const filePath = path.join(dir, 'sample.gguf');
|
|
19
|
+
await fs.writeFile(filePath, 'rigour-model-check');
|
|
20
|
+
const digest = await hashFileSha256(filePath);
|
|
21
|
+
expect(digest).toBe('e123266ea4b37a81948a0a844dd58eddfc81737aa6fdf9dafc818fd23bae75f0');
|
|
22
|
+
await fs.remove(dir);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
@@ -11,6 +11,7 @@ export declare class SidecarProvider implements InferenceProvider {
|
|
|
11
11
|
analyze(prompt: string, options?: InferenceOptions): Promise<string>;
|
|
12
12
|
dispose(): void;
|
|
13
13
|
private getPlatformKey;
|
|
14
|
+
private getPlatformPackageName;
|
|
14
15
|
private resolveBinaryPath;
|
|
15
16
|
private installSidecarBinary;
|
|
16
17
|
}
|
|
@@ -10,7 +10,9 @@ import os from 'os';
|
|
|
10
10
|
import fs from 'fs-extra';
|
|
11
11
|
import { createRequire } from 'module';
|
|
12
12
|
import { ensureModel, isModelCached, getModelInfo } from './model-manager.js';
|
|
13
|
+
import { ensureExecutableBinary } from './executable.js';
|
|
13
14
|
const execFileAsync = promisify(execFile);
|
|
15
|
+
const SIDECAR_INSTALL_DIR = path.join(os.homedir(), '.rigour', 'sidecar');
|
|
14
16
|
/** Platform → npm package mapping */
|
|
15
17
|
const PLATFORM_PACKAGES = {
|
|
16
18
|
'darwin-arm64': '@rigour-labs/brain-darwin-arm64',
|
|
@@ -34,11 +36,10 @@ export class SidecarProvider {
|
|
|
34
36
|
return binary !== null;
|
|
35
37
|
}
|
|
36
38
|
async setup(onProgress) {
|
|
37
|
-
const
|
|
38
|
-
const packageName = PLATFORM_PACKAGES[platformKey];
|
|
39
|
+
const packageName = this.getPlatformPackageName();
|
|
39
40
|
// 1. Check/resolve binary
|
|
40
41
|
this.binaryPath = await this.resolveBinaryPath();
|
|
41
|
-
// Auto-bootstrap local sidecar
|
|
42
|
+
// Auto-bootstrap local sidecar when missing.
|
|
42
43
|
if (!this.binaryPath && packageName) {
|
|
43
44
|
const installed = await this.installSidecarBinary(packageName, onProgress);
|
|
44
45
|
if (installed) {
|
|
@@ -47,12 +48,31 @@ export class SidecarProvider {
|
|
|
47
48
|
}
|
|
48
49
|
if (!this.binaryPath) {
|
|
49
50
|
onProgress?.('⚠ Inference engine not found. Install @rigour-labs/brain-* or add llama-cli to PATH');
|
|
50
|
-
const installHint = packageName || `@rigour-labs/brain-${
|
|
51
|
+
const installHint = packageName || `@rigour-labs/brain-${this.getPlatformKey()}`;
|
|
51
52
|
throw new Error(`Sidecar binary not found. Run: npm install ${installHint}`);
|
|
52
53
|
}
|
|
54
|
+
let executableCheck = ensureExecutableBinary(this.binaryPath);
|
|
55
|
+
// If the discovered binary is not executable, try a managed reinstall once.
|
|
56
|
+
if (!executableCheck.ok && packageName) {
|
|
57
|
+
onProgress?.('⚠ Inference engine is present but not executable. Reinstalling managed sidecar...');
|
|
58
|
+
const installed = await this.installSidecarBinary(packageName, onProgress);
|
|
59
|
+
if (installed) {
|
|
60
|
+
const refreshedPath = await this.resolveBinaryPath();
|
|
61
|
+
if (refreshedPath) {
|
|
62
|
+
this.binaryPath = refreshedPath;
|
|
63
|
+
executableCheck = ensureExecutableBinary(this.binaryPath);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (!executableCheck.ok) {
|
|
68
|
+
throw new Error(`Sidecar binary is not executable: ${this.binaryPath}. Run: chmod +x "${this.binaryPath}"`);
|
|
69
|
+
}
|
|
70
|
+
if (executableCheck.fixed) {
|
|
71
|
+
onProgress?.('✓ Fixed execute permission for inference engine');
|
|
72
|
+
}
|
|
53
73
|
onProgress?.('✓ Inference engine ready');
|
|
54
74
|
// 2. Ensure model is downloaded
|
|
55
|
-
if (!isModelCached(this.tier)) {
|
|
75
|
+
if (!(await isModelCached(this.tier))) {
|
|
56
76
|
const modelInfo = getModelInfo(this.tier);
|
|
57
77
|
onProgress?.(`⬇ Downloading analysis model (${modelInfo.sizeHuman})...`);
|
|
58
78
|
}
|
|
@@ -86,9 +106,45 @@ export class SidecarProvider {
|
|
|
86
106
|
maxBuffer: 10 * 1024 * 1024, // 10MB
|
|
87
107
|
env: { ...process.env, LLAMA_LOG_DISABLE: '1' },
|
|
88
108
|
};
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
109
|
+
const runInference = async () => {
|
|
110
|
+
return process.platform === 'win32' && this.binaryPath.endsWith('.cmd')
|
|
111
|
+
? await execFileAsync('cmd.exe', ['/d', '/s', '/c', [this.binaryPath, ...args].map(quoteCmdArg).join(' ')], execOptions)
|
|
112
|
+
: await execFileAsync(this.binaryPath, args, execOptions);
|
|
113
|
+
};
|
|
114
|
+
let stdout;
|
|
115
|
+
try {
|
|
116
|
+
({ stdout } = await runInference());
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
// One retry path for stale/bad file mode in packaged installs.
|
|
120
|
+
if (error?.code === 'EACCES') {
|
|
121
|
+
const check = ensureExecutableBinary(this.binaryPath);
|
|
122
|
+
if (check.ok) {
|
|
123
|
+
({ stdout } = await runInference());
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
const packageName = this.getPlatformPackageName();
|
|
127
|
+
if (packageName) {
|
|
128
|
+
const installed = await this.installSidecarBinary(packageName);
|
|
129
|
+
if (installed) {
|
|
130
|
+
const refreshedPath = await this.resolveBinaryPath();
|
|
131
|
+
if (refreshedPath) {
|
|
132
|
+
this.binaryPath = refreshedPath;
|
|
133
|
+
const refreshedCheck = ensureExecutableBinary(this.binaryPath);
|
|
134
|
+
if (refreshedCheck.ok) {
|
|
135
|
+
({ stdout } = await runInference());
|
|
136
|
+
return stdout.trim();
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
throw error;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
throw error;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
92
148
|
// llama.cpp sometimes outputs to stderr for diagnostics — ignore
|
|
93
149
|
return stdout.trim();
|
|
94
150
|
}
|
|
@@ -96,6 +152,9 @@ export class SidecarProvider {
|
|
|
96
152
|
if (error.killed) {
|
|
97
153
|
throw new Error(`Inference timed out after ${(options?.timeout || 60000) / 1000}s`);
|
|
98
154
|
}
|
|
155
|
+
if (error?.code === 'EACCES') {
|
|
156
|
+
throw new Error(`Inference binary is not executable: ${this.binaryPath}. Run: chmod +x "${this.binaryPath}"`);
|
|
157
|
+
}
|
|
99
158
|
throw new Error(`Inference failed: ${error.message}`);
|
|
100
159
|
}
|
|
101
160
|
}
|
|
@@ -107,11 +166,25 @@ export class SidecarProvider {
|
|
|
107
166
|
getPlatformKey() {
|
|
108
167
|
return `${os.platform()}-${os.arch()}`;
|
|
109
168
|
}
|
|
169
|
+
getPlatformPackageName() {
|
|
170
|
+
const platformKey = this.getPlatformKey();
|
|
171
|
+
return PLATFORM_PACKAGES[platformKey];
|
|
172
|
+
}
|
|
110
173
|
async resolveBinaryPath() {
|
|
111
174
|
const platformKey = this.getPlatformKey();
|
|
112
175
|
// Strategy 1: Check @rigour-labs/brain-{platform} optional dependency
|
|
113
176
|
const packageName = PLATFORM_PACKAGES[platformKey];
|
|
114
177
|
if (packageName) {
|
|
178
|
+
// Prefer Rigour-managed sidecar install root first to avoid brittle global/homebrew layouts.
|
|
179
|
+
const managedPath = path.join(SIDECAR_INSTALL_DIR, 'node_modules', ...packageName.split('/'), 'bin', 'rigour-brain');
|
|
180
|
+
const managedCandidates = os.platform() === 'win32'
|
|
181
|
+
? [managedPath + '.exe', managedPath + '.cmd', managedPath]
|
|
182
|
+
: [managedPath];
|
|
183
|
+
for (const managedBinPath of managedCandidates) {
|
|
184
|
+
if (await fs.pathExists(managedBinPath)) {
|
|
185
|
+
return managedBinPath;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
115
188
|
try {
|
|
116
189
|
const require = createRequire(import.meta.url);
|
|
117
190
|
const pkgJsonPath = require.resolve(path.posix.join(packageName, 'package.json'));
|
|
@@ -165,9 +238,10 @@ export class SidecarProvider {
|
|
|
165
238
|
}
|
|
166
239
|
}
|
|
167
240
|
// Strategy 3: Check PATH for llama-cli (llama.cpp CLI)
|
|
241
|
+
const locator = os.platform() === 'win32' ? 'where' : 'which';
|
|
168
242
|
try {
|
|
169
|
-
const { stdout } = await execFileAsync(
|
|
170
|
-
const llamaPath = stdout.trim();
|
|
243
|
+
const { stdout } = await execFileAsync(locator, ['llama-cli']);
|
|
244
|
+
const llamaPath = stdout.split(/\r?\n/).map(s => s.trim()).find(Boolean) || '';
|
|
171
245
|
if (llamaPath && await fs.pathExists(llamaPath)) {
|
|
172
246
|
return llamaPath;
|
|
173
247
|
}
|
|
@@ -179,9 +253,10 @@ export class SidecarProvider {
|
|
|
179
253
|
const altNames = ['llama-cli', 'llama', 'main'];
|
|
180
254
|
for (const name of altNames) {
|
|
181
255
|
try {
|
|
182
|
-
const { stdout } = await execFileAsync(
|
|
183
|
-
|
|
184
|
-
|
|
256
|
+
const { stdout } = await execFileAsync(locator, [name]);
|
|
257
|
+
const resolved = stdout.split(/\r?\n/).map(s => s.trim()).find(Boolean);
|
|
258
|
+
if (resolved && await fs.pathExists(resolved))
|
|
259
|
+
return resolved;
|
|
185
260
|
}
|
|
186
261
|
catch {
|
|
187
262
|
// Continue
|
|
@@ -192,8 +267,9 @@ export class SidecarProvider {
|
|
|
192
267
|
async installSidecarBinary(packageName, onProgress) {
|
|
193
268
|
onProgress?.(`⬇ Inference engine missing. Attempting automatic install: ${packageName}`);
|
|
194
269
|
try {
|
|
195
|
-
await
|
|
196
|
-
|
|
270
|
+
await fs.ensureDir(SIDECAR_INSTALL_DIR);
|
|
271
|
+
await execFileAsync(os.platform() === 'win32' ? 'npm.cmd' : 'npm', ['install', '--no-save', '--no-package-lock', '--prefix', SIDECAR_INSTALL_DIR, packageName], {
|
|
272
|
+
cwd: SIDECAR_INSTALL_DIR,
|
|
197
273
|
timeout: 120000,
|
|
198
274
|
maxBuffer: 10 * 1024 * 1024,
|
|
199
275
|
});
|
|
@@ -113,9 +113,9 @@ export const UNIVERSAL_CONFIG = {
|
|
|
113
113
|
},
|
|
114
114
|
context_window_artifacts: {
|
|
115
115
|
enabled: true,
|
|
116
|
-
min_file_lines:
|
|
117
|
-
degradation_threshold: 0.
|
|
118
|
-
signals_required:
|
|
116
|
+
min_file_lines: 180,
|
|
117
|
+
degradation_threshold: 0.55,
|
|
118
|
+
signals_required: 4,
|
|
119
119
|
},
|
|
120
120
|
promise_safety: {
|
|
121
121
|
enabled: true,
|
package/dist/types/index.js
CHANGED
|
@@ -125,9 +125,9 @@ export const GatesSchema = z.object({
|
|
|
125
125
|
}).optional().default({}),
|
|
126
126
|
context_window_artifacts: z.object({
|
|
127
127
|
enabled: z.boolean().optional().default(true),
|
|
128
|
-
min_file_lines: z.number().optional().default(
|
|
129
|
-
degradation_threshold: z.number().min(0).max(1).optional().default(0.
|
|
130
|
-
signals_required: z.number().optional().default(
|
|
128
|
+
min_file_lines: z.number().optional().default(180),
|
|
129
|
+
degradation_threshold: z.number().min(0).max(1).optional().default(0.55),
|
|
130
|
+
signals_required: z.number().optional().default(4),
|
|
131
131
|
}).optional().default({}),
|
|
132
132
|
promise_safety: z.object({
|
|
133
133
|
enabled: z.boolean().optional().default(true),
|
package/dist/utils/scanner.js
CHANGED
|
@@ -6,6 +6,12 @@ export class FileScanner {
|
|
|
6
6
|
static DEFAULT_IGNORE = [
|
|
7
7
|
'**/node_modules/**',
|
|
8
8
|
'**/dist/**',
|
|
9
|
+
'**/studio-dist/**',
|
|
10
|
+
'**/.next/**',
|
|
11
|
+
'**/coverage/**',
|
|
12
|
+
'**/out/**',
|
|
13
|
+
'**/target/**',
|
|
14
|
+
'**/examples/**',
|
|
9
15
|
'**/package-lock.json',
|
|
10
16
|
'**/pnpm-lock.yaml',
|
|
11
17
|
'**/.git/**',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rigour-labs/core",
|
|
3
|
-
"version": "4.0
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"description": "Deterministic quality gate engine for AI-generated code. AST analysis, drift detection, and Fix Packet generation across TypeScript, JavaScript, Python, Go, Ruby, and C#.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://rigour.run",
|
|
@@ -59,11 +59,11 @@
|
|
|
59
59
|
"@xenova/transformers": "^2.17.2",
|
|
60
60
|
"better-sqlite3": "^11.0.0",
|
|
61
61
|
"openai": "^4.104.0",
|
|
62
|
-
"@rigour-labs/brain-darwin-arm64": "4.0
|
|
63
|
-
"@rigour-labs/brain-darwin-x64": "4.0
|
|
64
|
-
"@rigour-labs/brain-
|
|
65
|
-
"@rigour-labs/brain-linux-
|
|
66
|
-
"@rigour-labs/brain-
|
|
62
|
+
"@rigour-labs/brain-darwin-arm64": "4.1.0",
|
|
63
|
+
"@rigour-labs/brain-darwin-x64": "4.1.0",
|
|
64
|
+
"@rigour-labs/brain-win-x64": "4.1.0",
|
|
65
|
+
"@rigour-labs/brain-linux-x64": "4.1.0",
|
|
66
|
+
"@rigour-labs/brain-linux-arm64": "4.1.0"
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
69
|
"@types/better-sqlite3": "^7.6.12",
|