@rigour-labs/core 4.3.3 → 4.3.5
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/inference/cloud-provider.js +6 -6
- package/dist/inference/model-manager.d.ts +9 -1
- package/dist/inference/model-manager.js +59 -2
- package/dist/inference/types.d.ts +17 -6
- package/dist/inference/types.js +42 -32
- package/dist/services/fix-packet-service.js +100 -3
- package/dist/types/fix-packet.d.ts +167 -5
- package/dist/types/fix-packet.js +43 -17
- package/package.json +6 -6
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
const DEFAULT_MODELS = {
|
|
3
3
|
claude: 'claude-opus-4-6',
|
|
4
4
|
anthropic: 'claude-sonnet-4-6',
|
|
5
|
-
openai: 'gpt-
|
|
6
|
-
gemini: 'gemini-
|
|
7
|
-
groq: 'llama-3.
|
|
5
|
+
openai: 'gpt-5-mini',
|
|
6
|
+
gemini: 'gemini-2.5-flash',
|
|
7
|
+
groq: 'llama-3.3-70b-versatile',
|
|
8
8
|
mistral: 'mistral-large-latest',
|
|
9
|
-
together: 'meta-llama/Llama-
|
|
10
|
-
fireworks: 'accounts/fireworks/models/llama-
|
|
11
|
-
deepseek: 'deepseek-
|
|
9
|
+
together: 'meta-llama/Llama-4-Maverick-17B-128E-Instruct-FP8',
|
|
10
|
+
fireworks: 'accounts/fireworks/models/llama-v3p3-70b-instruct',
|
|
11
|
+
deepseek: 'deepseek-v4',
|
|
12
12
|
perplexity: 'llama-3.1-sonar-large-128k-online',
|
|
13
13
|
ollama: 'qwen2.5-coder:7b',
|
|
14
14
|
lmstudio: 'qwen2.5-coder-7b-instruct',
|
|
@@ -13,9 +13,17 @@ export declare function getModelPath(tier: ModelTier): string;
|
|
|
13
13
|
* Get model info for a tier.
|
|
14
14
|
*/
|
|
15
15
|
export declare function getModelInfo(tier: ModelTier): ModelInfo;
|
|
16
|
+
/**
|
|
17
|
+
* Check HuggingFace for a newer model version (like antivirus signature updates).
|
|
18
|
+
* Reads latest_version.json from the RLAIF dataset repo. Non-blocking — if the
|
|
19
|
+
* check fails (offline, HF down), we silently use the cached/bundled version.
|
|
20
|
+
*
|
|
21
|
+
* Results are cached locally for 24 hours to avoid hammering HF on every run.
|
|
22
|
+
*/
|
|
23
|
+
export declare function checkForUpdates(onProgress?: (message: string, percent?: number) => void): Promise<string>;
|
|
16
24
|
/**
|
|
17
25
|
* Download a model from HuggingFace CDN.
|
|
18
|
-
*
|
|
26
|
+
* Checks for updates first, then tries fine-tuned model, falls back to stock Qwen.
|
|
19
27
|
*/
|
|
20
28
|
export declare function downloadModel(tier: ModelTier, onProgress?: (message: string, percent?: number) => void): Promise<string>;
|
|
21
29
|
/**
|
|
@@ -6,8 +6,11 @@ import path from 'path';
|
|
|
6
6
|
import fs from 'fs-extra';
|
|
7
7
|
import { createHash } from 'crypto';
|
|
8
8
|
import { RIGOUR_DIR } from '../storage/db.js';
|
|
9
|
-
import { MODELS, FALLBACK_MODELS } from './types.js';
|
|
9
|
+
import { MODELS, FALLBACK_MODELS, VERSION_CHECK_URL, BUNDLED_MODEL_VERSION, updateModelVersion } from './types.js';
|
|
10
10
|
const MODELS_DIR = path.join(RIGOUR_DIR, 'models');
|
|
11
|
+
const VERSION_CACHE_PATH = path.join(MODELS_DIR, '.latest_version.json');
|
|
12
|
+
const VERSION_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000; // Check once per day
|
|
13
|
+
const VERSION_CHECK_TIMEOUT_MS = 5000; // 5s timeout — don't block startup
|
|
11
14
|
const SHA256_RE = /^[a-f0-9]{64}$/i;
|
|
12
15
|
function getModelMetadataPath(filename) {
|
|
13
16
|
return path.join(MODELS_DIR, filename + '.meta.json');
|
|
@@ -173,12 +176,66 @@ async function downloadFromUrl(tier, model, onProgress) {
|
|
|
173
176
|
throw error;
|
|
174
177
|
}
|
|
175
178
|
}
|
|
179
|
+
/**
|
|
180
|
+
* Check HuggingFace for a newer model version (like antivirus signature updates).
|
|
181
|
+
* Reads latest_version.json from the RLAIF dataset repo. Non-blocking — if the
|
|
182
|
+
* check fails (offline, HF down), we silently use the cached/bundled version.
|
|
183
|
+
*
|
|
184
|
+
* Results are cached locally for 24 hours to avoid hammering HF on every run.
|
|
185
|
+
*/
|
|
186
|
+
export async function checkForUpdates(onProgress) {
|
|
187
|
+
fs.ensureDirSync(MODELS_DIR);
|
|
188
|
+
// Check local version cache first — avoid network on every run
|
|
189
|
+
try {
|
|
190
|
+
if (await fs.pathExists(VERSION_CACHE_PATH)) {
|
|
191
|
+
const cached = await fs.readJson(VERSION_CACHE_PATH);
|
|
192
|
+
const age = Date.now() - new Date(cached.checkedAt).getTime();
|
|
193
|
+
if (age < VERSION_CHECK_INTERVAL_MS && cached.version) {
|
|
194
|
+
const v = String(cached.version);
|
|
195
|
+
updateModelVersion(v);
|
|
196
|
+
return v;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
catch {
|
|
201
|
+
// Corrupted cache — proceed to network check
|
|
202
|
+
}
|
|
203
|
+
// Fetch latest version from HuggingFace (with timeout)
|
|
204
|
+
try {
|
|
205
|
+
const controller = new AbortController();
|
|
206
|
+
const timeout = setTimeout(() => controller.abort(), VERSION_CHECK_TIMEOUT_MS);
|
|
207
|
+
const response = await fetch(VERSION_CHECK_URL, { signal: controller.signal });
|
|
208
|
+
clearTimeout(timeout);
|
|
209
|
+
if (response.ok) {
|
|
210
|
+
const data = await response.json();
|
|
211
|
+
const latestVersion = String(data.version || BUNDLED_MODEL_VERSION);
|
|
212
|
+
// Cache the result locally
|
|
213
|
+
await fs.writeJson(VERSION_CACHE_PATH, {
|
|
214
|
+
version: latestVersion,
|
|
215
|
+
checkedAt: new Date().toISOString(),
|
|
216
|
+
source: 'huggingface',
|
|
217
|
+
}, { spaces: 2 }).catch(() => { });
|
|
218
|
+
// Update in-memory model definitions
|
|
219
|
+
updateModelVersion(latestVersion);
|
|
220
|
+
if (latestVersion !== BUNDLED_MODEL_VERSION) {
|
|
221
|
+
onProgress?.(`Model update available: v${latestVersion}`, 0);
|
|
222
|
+
}
|
|
223
|
+
return latestVersion;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
// Offline / HF down / timeout — use bundled version silently
|
|
228
|
+
}
|
|
229
|
+
return BUNDLED_MODEL_VERSION;
|
|
230
|
+
}
|
|
176
231
|
/**
|
|
177
232
|
* Download a model from HuggingFace CDN.
|
|
178
|
-
*
|
|
233
|
+
* Checks for updates first, then tries fine-tuned model, falls back to stock Qwen.
|
|
179
234
|
*/
|
|
180
235
|
export async function downloadModel(tier, onProgress) {
|
|
181
236
|
fs.ensureDirSync(MODELS_DIR);
|
|
237
|
+
// Check for newer model version (non-blocking, cached 24h)
|
|
238
|
+
await checkForUpdates(onProgress);
|
|
182
239
|
if (await isModelCached(tier)) {
|
|
183
240
|
onProgress?.(`Model ${MODELS[tier].name} already cached`, 100);
|
|
184
241
|
return getModelPath(tier);
|
|
@@ -62,7 +62,7 @@ export interface DeepAnalysisResult {
|
|
|
62
62
|
* Available model tiers.
|
|
63
63
|
*
|
|
64
64
|
* - deep: Qwen2.5-Coder-1.5B fine-tuned — full power, company-hosted
|
|
65
|
-
* - lite:
|
|
65
|
+
* - lite: Qwen2.5-Coder-0.5B fine-tuned — lightweight, ships as default CLI sidecar
|
|
66
66
|
* - legacy: Qwen2.5-Coder-0.5B fine-tuned — previous default, reproducibility
|
|
67
67
|
*/
|
|
68
68
|
export type ModelTier = 'deep' | 'lite' | 'legacy';
|
|
@@ -78,13 +78,24 @@ export interface ModelInfo {
|
|
|
78
78
|
sizeHuman: string;
|
|
79
79
|
}
|
|
80
80
|
/**
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
81
|
+
* Minimum bundled model version — used as fallback when the auto-update
|
|
82
|
+
* check fails (offline, HF down, first run). The RLAIF training pipeline
|
|
83
|
+
* publishes new versions to HuggingFace and updates latest_version.json.
|
|
84
|
+
* At startup, model-manager checks HF for the latest version and downloads
|
|
85
|
+
* it automatically (like antivirus signature updates).
|
|
84
86
|
*/
|
|
85
|
-
export declare const
|
|
86
|
-
/**
|
|
87
|
+
export declare const BUNDLED_MODEL_VERSION = "1";
|
|
88
|
+
/** HuggingFace dataset repo where latest_version.json lives */
|
|
89
|
+
export declare const VERSION_CHECK_URL = "https://huggingface.co/datasets/rigour-labs/rigour-rlaif-data/resolve/main/latest_version.json";
|
|
90
|
+
/** Build model info for a given tier and version */
|
|
91
|
+
export declare function buildModelInfo(tier: ModelTier, version: string): ModelInfo;
|
|
92
|
+
/** Current model definitions — initialized with bundled version, updated at runtime */
|
|
87
93
|
export declare const MODELS: Record<ModelTier, ModelInfo>;
|
|
94
|
+
/**
|
|
95
|
+
* Update MODELS in-place to point to a newer version.
|
|
96
|
+
* Called by model-manager after checking latest_version.json.
|
|
97
|
+
*/
|
|
98
|
+
export declare function updateModelVersion(version: string): void;
|
|
88
99
|
/**
|
|
89
100
|
* Fallback stock models — used when fine-tuned model is not yet
|
|
90
101
|
* available on HuggingFace (initial setup / first-time users).
|
package/dist/inference/types.js
CHANGED
|
@@ -1,36 +1,46 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Minimum bundled model version — used as fallback when the auto-update
|
|
3
|
+
* check fails (offline, HF down, first run). The RLAIF training pipeline
|
|
4
|
+
* publishes new versions to HuggingFace and updates latest_version.json.
|
|
5
|
+
* At startup, model-manager checks HF for the latest version and downloads
|
|
6
|
+
* it automatically (like antivirus signature updates).
|
|
5
7
|
*/
|
|
6
|
-
export const
|
|
7
|
-
/**
|
|
8
|
+
export const BUNDLED_MODEL_VERSION = '1';
|
|
9
|
+
/** HuggingFace dataset repo where latest_version.json lives */
|
|
10
|
+
export const VERSION_CHECK_URL = 'https://huggingface.co/datasets/rigour-labs/rigour-rlaif-data/resolve/main/latest_version.json';
|
|
11
|
+
/** Build model info for a given tier and version */
|
|
12
|
+
export function buildModelInfo(tier, version) {
|
|
13
|
+
const meta = {
|
|
14
|
+
deep: { base: 'Qwen2.5-Coder-1.5B', size: 900_000_000, sizeH: '900MB' },
|
|
15
|
+
lite: { base: 'Qwen2.5-Coder-0.5B', size: 500_000_000, sizeH: '500MB' },
|
|
16
|
+
legacy: { base: 'Qwen2.5-Coder-0.5B', size: 350_000_000, sizeH: '350MB' },
|
|
17
|
+
};
|
|
18
|
+
const m = meta[tier];
|
|
19
|
+
return {
|
|
20
|
+
tier,
|
|
21
|
+
name: `Rigour-${tier[0].toUpperCase() + tier.slice(1)}-v${version} (${m.base} fine-tuned)`,
|
|
22
|
+
filename: `rigour-${tier}-v${version}-q4_k_m.gguf`,
|
|
23
|
+
url: `https://huggingface.co/rigour-labs/rigour-${tier}-v${version}-gguf/resolve/main/rigour-${tier}-v${version}-q4_k_m.gguf`,
|
|
24
|
+
sizeBytes: m.size,
|
|
25
|
+
sizeHuman: m.sizeH,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/** Current model definitions — initialized with bundled version, updated at runtime */
|
|
8
29
|
export const MODELS = {
|
|
9
|
-
deep:
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
filename: `rigour-deep-v${MODEL_VERSION}-q4_k_m.gguf`,
|
|
13
|
-
url: `https://huggingface.co/rigour-labs/rigour-deep-v1-gguf/resolve/main/rigour-deep-v${MODEL_VERSION}-q4_k_m.gguf`,
|
|
14
|
-
sizeBytes: 900_000_000,
|
|
15
|
-
sizeHuman: '900MB',
|
|
16
|
-
},
|
|
17
|
-
lite: {
|
|
18
|
-
tier: 'lite',
|
|
19
|
-
name: 'Rigour-Lite-v1 (Qwen3.5-0.8B fine-tuned)',
|
|
20
|
-
filename: `rigour-lite-v${MODEL_VERSION}-q4_k_m.gguf`,
|
|
21
|
-
url: `https://huggingface.co/rigour-labs/rigour-lite-v1-gguf/resolve/main/rigour-lite-v${MODEL_VERSION}-q4_k_m.gguf`,
|
|
22
|
-
sizeBytes: 500_000_000,
|
|
23
|
-
sizeHuman: '500MB',
|
|
24
|
-
},
|
|
25
|
-
legacy: {
|
|
26
|
-
tier: 'legacy',
|
|
27
|
-
name: 'Rigour-Legacy-v1 (Qwen2.5-Coder-0.5B fine-tuned)',
|
|
28
|
-
filename: `rigour-legacy-v${MODEL_VERSION}-q4_k_m.gguf`,
|
|
29
|
-
url: `https://huggingface.co/rigour-labs/rigour-legacy-v1-gguf/resolve/main/rigour-legacy-v${MODEL_VERSION}-q4_k_m.gguf`,
|
|
30
|
-
sizeBytes: 350_000_000,
|
|
31
|
-
sizeHuman: '350MB',
|
|
32
|
-
},
|
|
30
|
+
deep: buildModelInfo('deep', BUNDLED_MODEL_VERSION),
|
|
31
|
+
lite: buildModelInfo('lite', BUNDLED_MODEL_VERSION),
|
|
32
|
+
legacy: buildModelInfo('legacy', BUNDLED_MODEL_VERSION),
|
|
33
33
|
};
|
|
34
|
+
/**
|
|
35
|
+
* Update MODELS in-place to point to a newer version.
|
|
36
|
+
* Called by model-manager after checking latest_version.json.
|
|
37
|
+
*/
|
|
38
|
+
export function updateModelVersion(version) {
|
|
39
|
+
for (const tier of ['deep', 'lite', 'legacy']) {
|
|
40
|
+
const updated = buildModelInfo(tier, version);
|
|
41
|
+
MODELS[tier] = updated;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
34
44
|
/**
|
|
35
45
|
* Fallback stock models — used when fine-tuned model is not yet
|
|
36
46
|
* available on HuggingFace (initial setup / first-time users).
|
|
@@ -46,9 +56,9 @@ export const FALLBACK_MODELS = {
|
|
|
46
56
|
},
|
|
47
57
|
lite: {
|
|
48
58
|
tier: 'lite',
|
|
49
|
-
name: '
|
|
50
|
-
filename: '
|
|
51
|
-
url: 'https://huggingface.co/Qwen/
|
|
59
|
+
name: 'Qwen2.5-Coder-0.5B-Instruct (stock)',
|
|
60
|
+
filename: 'qwen2.5-coder-0.5b-instruct-q4_k_m.gguf',
|
|
61
|
+
url: 'https://huggingface.co/Qwen/Qwen2.5-Coder-0.5B-Instruct-GGUF/resolve/main/qwen2.5-coder-0.5b-instruct-q4_k_m.gguf',
|
|
52
62
|
sizeBytes: 500_000_000,
|
|
53
63
|
sizeHuman: '500MB',
|
|
54
64
|
},
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { FixPacketV2Schema } from '../types/fix-packet.js';
|
|
2
2
|
export class FixPacketService {
|
|
3
3
|
generate(report, config) {
|
|
4
|
-
// Sort violations: critical first, then high, medium, low, info
|
|
5
4
|
const severityOrder = { critical: 0, high: 1, medium: 2, low: 3, info: 4 };
|
|
5
|
+
// Deduplicate failed gate IDs
|
|
6
|
+
const failedGates = [...new Set(report.failures.map(f => f.id))];
|
|
6
7
|
const violations = report.failures
|
|
7
8
|
.map(f => ({
|
|
8
9
|
id: f.id,
|
|
@@ -12,19 +13,32 @@ export class FixPacketService {
|
|
|
12
13
|
title: f.title,
|
|
13
14
|
details: f.details,
|
|
14
15
|
files: f.files,
|
|
16
|
+
locations: buildLocations(f),
|
|
15
17
|
hint: f.hint,
|
|
16
|
-
instructions: f
|
|
18
|
+
instructions: buildInstructions(f),
|
|
17
19
|
metrics: f.metrics,
|
|
18
20
|
}))
|
|
19
21
|
.sort((a, b) => (severityOrder[a.severity] ?? 2) - (severityOrder[b.severity] ?? 2));
|
|
22
|
+
// Build verification commands from config.commands
|
|
23
|
+
const verification = buildVerification(config);
|
|
24
|
+
// Build allowed scope from violation files (what the agent should touch)
|
|
25
|
+
const violationFiles = violations.flatMap(v => v.files || []);
|
|
26
|
+
const uniqueFiles = [...new Set(violationFiles.map(f => {
|
|
27
|
+
// Strip metadata like "(600 lines)" from file paths
|
|
28
|
+
const clean = f.replace(/\s*\(.*?\)\s*$/, '').trim();
|
|
29
|
+
return clean;
|
|
30
|
+
}))];
|
|
20
31
|
const packet = {
|
|
21
|
-
version:
|
|
32
|
+
version: 3,
|
|
22
33
|
goal: "Achieve PASS state by resolving all listed engineering violations.",
|
|
34
|
+
failed_gates: failedGates,
|
|
23
35
|
violations,
|
|
36
|
+
verification,
|
|
24
37
|
constraints: {
|
|
25
38
|
paradigm: config.paradigm,
|
|
26
39
|
protected_paths: config.gates.safety?.protected_paths,
|
|
27
40
|
do_not_touch: config.gates.safety?.protected_paths,
|
|
41
|
+
allowed_scope: uniqueFiles.length > 0 ? uniqueFiles : undefined,
|
|
28
42
|
max_files_changed: config.gates.safety?.max_files_changed_per_cycle,
|
|
29
43
|
no_new_deps: true,
|
|
30
44
|
},
|
|
@@ -32,3 +46,86 @@ export class FixPacketService {
|
|
|
32
46
|
return FixPacketV2Schema.parse(packet);
|
|
33
47
|
}
|
|
34
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* Build precise locations from failure's files + line numbers.
|
|
51
|
+
* If failure has both files[] and line/endLine, create a location per file.
|
|
52
|
+
* If only files[], locations are file-level (no line numbers).
|
|
53
|
+
*/
|
|
54
|
+
function buildLocations(f) {
|
|
55
|
+
if (!f.files || f.files.length === 0)
|
|
56
|
+
return undefined;
|
|
57
|
+
return f.files.map(file => {
|
|
58
|
+
const loc = {
|
|
59
|
+
file: file.replace(/\s*\(.*?\)\s*$/, '').trim(),
|
|
60
|
+
};
|
|
61
|
+
// If the failure has line numbers and there's only one file, attach them
|
|
62
|
+
if (f.files.length === 1) {
|
|
63
|
+
if (f.line)
|
|
64
|
+
loc.line = f.line;
|
|
65
|
+
if (f.endLine)
|
|
66
|
+
loc.endLine = f.endLine;
|
|
67
|
+
}
|
|
68
|
+
return loc;
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Build step-by-step instructions from the hint and failure context.
|
|
73
|
+
*/
|
|
74
|
+
function buildInstructions(f) {
|
|
75
|
+
const steps = [];
|
|
76
|
+
if (f.hint)
|
|
77
|
+
steps.push(f.hint);
|
|
78
|
+
// Add gate-specific guidance
|
|
79
|
+
switch (f.id) {
|
|
80
|
+
case 'file-size':
|
|
81
|
+
steps.push('Break the file into smaller modules following Single Responsibility Principle');
|
|
82
|
+
break;
|
|
83
|
+
case 'hallucinated-imports':
|
|
84
|
+
steps.push('Remove or replace the non-existent import with a real package');
|
|
85
|
+
break;
|
|
86
|
+
case 'phantom-apis':
|
|
87
|
+
steps.push('Check the actual API surface of the module and use a real method');
|
|
88
|
+
break;
|
|
89
|
+
case 'forbid-todos':
|
|
90
|
+
steps.push('Resolve the TODO/FIXME comment or remove it if no longer relevant');
|
|
91
|
+
break;
|
|
92
|
+
case 'security-patterns':
|
|
93
|
+
steps.push('Apply the security fix described above. Do NOT suppress the warning.');
|
|
94
|
+
break;
|
|
95
|
+
case 'promise-safety':
|
|
96
|
+
steps.push('Add proper error handling (try/catch or .catch()) to async operations');
|
|
97
|
+
break;
|
|
98
|
+
case 'deprecated-apis':
|
|
99
|
+
steps.push('Replace deprecated API usage with the recommended modern alternative');
|
|
100
|
+
break;
|
|
101
|
+
case 'duplication-drift':
|
|
102
|
+
steps.push('Extract the duplicated logic into a shared utility or module');
|
|
103
|
+
break;
|
|
104
|
+
case 'inconsistent-error-handling':
|
|
105
|
+
steps.push('Align error handling strategy across the module');
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
return steps.length > 0 ? steps : [];
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Build verification block from config.commands.
|
|
112
|
+
* These are the commands the agent MUST run after fixing to prove the fix works.
|
|
113
|
+
*/
|
|
114
|
+
function buildVerification(config) {
|
|
115
|
+
const commands = [];
|
|
116
|
+
if (config.commands?.typecheck) {
|
|
117
|
+
commands.push({ cmd: config.commands.typecheck, purpose: 'Ensure no type errors after changes' });
|
|
118
|
+
}
|
|
119
|
+
if (config.commands?.lint) {
|
|
120
|
+
commands.push({ cmd: config.commands.lint, purpose: 'Ensure no lint violations' });
|
|
121
|
+
}
|
|
122
|
+
if (config.commands?.test) {
|
|
123
|
+
commands.push({ cmd: config.commands.test, purpose: 'Ensure all tests pass' });
|
|
124
|
+
}
|
|
125
|
+
if (config.commands?.format) {
|
|
126
|
+
commands.push({ cmd: config.commands.format, purpose: 'Ensure code formatting is correct' });
|
|
127
|
+
}
|
|
128
|
+
// Always end with rigour check
|
|
129
|
+
commands.push({ cmd: 'rigour_check', purpose: 'Re-run all quality gates to confirm PASS' });
|
|
130
|
+
return { commands, gate_command: 'rigour_check' };
|
|
131
|
+
}
|
|
@@ -1,11 +1,91 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
/**
|
|
3
|
-
* Fix Packet
|
|
4
|
-
*
|
|
3
|
+
* Fix Packet v3 Schema
|
|
4
|
+
*
|
|
5
|
+
* Designed for high-fidelity, machine-readable communication with AI agents.
|
|
6
|
+
* Every violation tells the agent exactly: who failed, which files, what rule,
|
|
7
|
+
* where in the file, and what must pass to verify the fix.
|
|
8
|
+
*
|
|
9
|
+
* v3 changes from v2:
|
|
10
|
+
* - Violations now include `location` (file + line range) for precise targeting
|
|
11
|
+
* - Top-level `verification` block: commands the agent MUST run after fixing
|
|
12
|
+
* - `allowed_scope`: explicit list of file globs the agent IS allowed to edit
|
|
13
|
+
* - `failed_gates`: summary list of gate IDs that failed (quick machine check)
|
|
5
14
|
*/
|
|
15
|
+
declare const ViolationLocationSchema: z.ZodObject<{
|
|
16
|
+
file: z.ZodString;
|
|
17
|
+
line: z.ZodOptional<z.ZodNumber>;
|
|
18
|
+
endLine: z.ZodOptional<z.ZodNumber>;
|
|
19
|
+
}, "strip", z.ZodTypeAny, {
|
|
20
|
+
file: string;
|
|
21
|
+
line?: number | undefined;
|
|
22
|
+
endLine?: number | undefined;
|
|
23
|
+
}, {
|
|
24
|
+
file: string;
|
|
25
|
+
line?: number | undefined;
|
|
26
|
+
endLine?: number | undefined;
|
|
27
|
+
}>;
|
|
28
|
+
declare const ViolationSchema: z.ZodObject<{
|
|
29
|
+
id: z.ZodString;
|
|
30
|
+
gate: z.ZodString;
|
|
31
|
+
severity: z.ZodDefault<z.ZodEnum<["info", "low", "medium", "high", "critical"]>>;
|
|
32
|
+
category: z.ZodOptional<z.ZodString>;
|
|
33
|
+
title: z.ZodString;
|
|
34
|
+
details: z.ZodString;
|
|
35
|
+
files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
36
|
+
locations: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
37
|
+
file: z.ZodString;
|
|
38
|
+
line: z.ZodOptional<z.ZodNumber>;
|
|
39
|
+
endLine: z.ZodOptional<z.ZodNumber>;
|
|
40
|
+
}, "strip", z.ZodTypeAny, {
|
|
41
|
+
file: string;
|
|
42
|
+
line?: number | undefined;
|
|
43
|
+
endLine?: number | undefined;
|
|
44
|
+
}, {
|
|
45
|
+
file: string;
|
|
46
|
+
line?: number | undefined;
|
|
47
|
+
endLine?: number | undefined;
|
|
48
|
+
}>, "many">>;
|
|
49
|
+
hint: z.ZodOptional<z.ZodString>;
|
|
50
|
+
instructions: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
51
|
+
metrics: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
|
52
|
+
}, "strip", z.ZodTypeAny, {
|
|
53
|
+
id: string;
|
|
54
|
+
title: string;
|
|
55
|
+
details: string;
|
|
56
|
+
severity: "critical" | "high" | "medium" | "low" | "info";
|
|
57
|
+
gate: string;
|
|
58
|
+
files?: string[] | undefined;
|
|
59
|
+
hint?: string | undefined;
|
|
60
|
+
category?: string | undefined;
|
|
61
|
+
locations?: {
|
|
62
|
+
file: string;
|
|
63
|
+
line?: number | undefined;
|
|
64
|
+
endLine?: number | undefined;
|
|
65
|
+
}[] | undefined;
|
|
66
|
+
instructions?: string[] | undefined;
|
|
67
|
+
metrics?: Record<string, any> | undefined;
|
|
68
|
+
}, {
|
|
69
|
+
id: string;
|
|
70
|
+
title: string;
|
|
71
|
+
details: string;
|
|
72
|
+
gate: string;
|
|
73
|
+
severity?: "critical" | "high" | "medium" | "low" | "info" | undefined;
|
|
74
|
+
files?: string[] | undefined;
|
|
75
|
+
hint?: string | undefined;
|
|
76
|
+
category?: string | undefined;
|
|
77
|
+
locations?: {
|
|
78
|
+
file: string;
|
|
79
|
+
line?: number | undefined;
|
|
80
|
+
endLine?: number | undefined;
|
|
81
|
+
}[] | undefined;
|
|
82
|
+
instructions?: string[] | undefined;
|
|
83
|
+
metrics?: Record<string, any> | undefined;
|
|
84
|
+
}>;
|
|
6
85
|
export declare const FixPacketV2Schema: z.ZodObject<{
|
|
7
|
-
version: z.ZodLiteral<
|
|
86
|
+
version: z.ZodLiteral<3>;
|
|
8
87
|
goal: z.ZodDefault<z.ZodString>;
|
|
88
|
+
failed_gates: z.ZodArray<z.ZodString, "many">;
|
|
9
89
|
violations: z.ZodArray<z.ZodObject<{
|
|
10
90
|
id: z.ZodString;
|
|
11
91
|
gate: z.ZodString;
|
|
@@ -14,6 +94,19 @@ export declare const FixPacketV2Schema: z.ZodObject<{
|
|
|
14
94
|
title: z.ZodString;
|
|
15
95
|
details: z.ZodString;
|
|
16
96
|
files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
97
|
+
locations: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
98
|
+
file: z.ZodString;
|
|
99
|
+
line: z.ZodOptional<z.ZodNumber>;
|
|
100
|
+
endLine: z.ZodOptional<z.ZodNumber>;
|
|
101
|
+
}, "strip", z.ZodTypeAny, {
|
|
102
|
+
file: string;
|
|
103
|
+
line?: number | undefined;
|
|
104
|
+
endLine?: number | undefined;
|
|
105
|
+
}, {
|
|
106
|
+
file: string;
|
|
107
|
+
line?: number | undefined;
|
|
108
|
+
endLine?: number | undefined;
|
|
109
|
+
}>, "many">>;
|
|
17
110
|
hint: z.ZodOptional<z.ZodString>;
|
|
18
111
|
instructions: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
19
112
|
metrics: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
|
@@ -26,6 +119,11 @@ export declare const FixPacketV2Schema: z.ZodObject<{
|
|
|
26
119
|
files?: string[] | undefined;
|
|
27
120
|
hint?: string | undefined;
|
|
28
121
|
category?: string | undefined;
|
|
122
|
+
locations?: {
|
|
123
|
+
file: string;
|
|
124
|
+
line?: number | undefined;
|
|
125
|
+
endLine?: number | undefined;
|
|
126
|
+
}[] | undefined;
|
|
29
127
|
instructions?: string[] | undefined;
|
|
30
128
|
metrics?: Record<string, any> | undefined;
|
|
31
129
|
}, {
|
|
@@ -37,12 +135,43 @@ export declare const FixPacketV2Schema: z.ZodObject<{
|
|
|
37
135
|
files?: string[] | undefined;
|
|
38
136
|
hint?: string | undefined;
|
|
39
137
|
category?: string | undefined;
|
|
138
|
+
locations?: {
|
|
139
|
+
file: string;
|
|
140
|
+
line?: number | undefined;
|
|
141
|
+
endLine?: number | undefined;
|
|
142
|
+
}[] | undefined;
|
|
40
143
|
instructions?: string[] | undefined;
|
|
41
144
|
metrics?: Record<string, any> | undefined;
|
|
42
145
|
}>, "many">;
|
|
146
|
+
verification: z.ZodOptional<z.ZodObject<{
|
|
147
|
+
commands: z.ZodArray<z.ZodObject<{
|
|
148
|
+
cmd: z.ZodString;
|
|
149
|
+
purpose: z.ZodString;
|
|
150
|
+
}, "strip", z.ZodTypeAny, {
|
|
151
|
+
cmd: string;
|
|
152
|
+
purpose: string;
|
|
153
|
+
}, {
|
|
154
|
+
cmd: string;
|
|
155
|
+
purpose: string;
|
|
156
|
+
}>, "many">;
|
|
157
|
+
gate_command: z.ZodDefault<z.ZodString>;
|
|
158
|
+
}, "strip", z.ZodTypeAny, {
|
|
159
|
+
commands: {
|
|
160
|
+
cmd: string;
|
|
161
|
+
purpose: string;
|
|
162
|
+
}[];
|
|
163
|
+
gate_command: string;
|
|
164
|
+
}, {
|
|
165
|
+
commands: {
|
|
166
|
+
cmd: string;
|
|
167
|
+
purpose: string;
|
|
168
|
+
}[];
|
|
169
|
+
gate_command?: string | undefined;
|
|
170
|
+
}>>;
|
|
43
171
|
constraints: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
44
172
|
protected_paths: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
45
173
|
do_not_touch: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
174
|
+
allowed_scope: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
46
175
|
max_files_changed: z.ZodOptional<z.ZodNumber>;
|
|
47
176
|
no_new_deps: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
48
177
|
allowed_dependencies: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
@@ -52,19 +181,22 @@ export declare const FixPacketV2Schema: z.ZodObject<{
|
|
|
52
181
|
protected_paths?: string[] | undefined;
|
|
53
182
|
paradigm?: string | undefined;
|
|
54
183
|
do_not_touch?: string[] | undefined;
|
|
184
|
+
allowed_scope?: string[] | undefined;
|
|
55
185
|
max_files_changed?: number | undefined;
|
|
56
186
|
allowed_dependencies?: string[] | undefined;
|
|
57
187
|
}, {
|
|
58
188
|
protected_paths?: string[] | undefined;
|
|
59
189
|
paradigm?: string | undefined;
|
|
60
190
|
do_not_touch?: string[] | undefined;
|
|
191
|
+
allowed_scope?: string[] | undefined;
|
|
61
192
|
max_files_changed?: number | undefined;
|
|
62
193
|
no_new_deps?: boolean | undefined;
|
|
63
194
|
allowed_dependencies?: string[] | undefined;
|
|
64
195
|
}>>>;
|
|
65
196
|
}, "strip", z.ZodTypeAny, {
|
|
66
|
-
version:
|
|
197
|
+
version: 3;
|
|
67
198
|
goal: string;
|
|
199
|
+
failed_gates: string[];
|
|
68
200
|
violations: {
|
|
69
201
|
id: string;
|
|
70
202
|
title: string;
|
|
@@ -74,6 +206,11 @@ export declare const FixPacketV2Schema: z.ZodObject<{
|
|
|
74
206
|
files?: string[] | undefined;
|
|
75
207
|
hint?: string | undefined;
|
|
76
208
|
category?: string | undefined;
|
|
209
|
+
locations?: {
|
|
210
|
+
file: string;
|
|
211
|
+
line?: number | undefined;
|
|
212
|
+
endLine?: number | undefined;
|
|
213
|
+
}[] | undefined;
|
|
77
214
|
instructions?: string[] | undefined;
|
|
78
215
|
metrics?: Record<string, any> | undefined;
|
|
79
216
|
}[];
|
|
@@ -82,11 +219,20 @@ export declare const FixPacketV2Schema: z.ZodObject<{
|
|
|
82
219
|
protected_paths?: string[] | undefined;
|
|
83
220
|
paradigm?: string | undefined;
|
|
84
221
|
do_not_touch?: string[] | undefined;
|
|
222
|
+
allowed_scope?: string[] | undefined;
|
|
85
223
|
max_files_changed?: number | undefined;
|
|
86
224
|
allowed_dependencies?: string[] | undefined;
|
|
87
225
|
};
|
|
226
|
+
verification?: {
|
|
227
|
+
commands: {
|
|
228
|
+
cmd: string;
|
|
229
|
+
purpose: string;
|
|
230
|
+
}[];
|
|
231
|
+
gate_command: string;
|
|
232
|
+
} | undefined;
|
|
88
233
|
}, {
|
|
89
|
-
version:
|
|
234
|
+
version: 3;
|
|
235
|
+
failed_gates: string[];
|
|
90
236
|
violations: {
|
|
91
237
|
id: string;
|
|
92
238
|
title: string;
|
|
@@ -96,17 +242,33 @@ export declare const FixPacketV2Schema: z.ZodObject<{
|
|
|
96
242
|
files?: string[] | undefined;
|
|
97
243
|
hint?: string | undefined;
|
|
98
244
|
category?: string | undefined;
|
|
245
|
+
locations?: {
|
|
246
|
+
file: string;
|
|
247
|
+
line?: number | undefined;
|
|
248
|
+
endLine?: number | undefined;
|
|
249
|
+
}[] | undefined;
|
|
99
250
|
instructions?: string[] | undefined;
|
|
100
251
|
metrics?: Record<string, any> | undefined;
|
|
101
252
|
}[];
|
|
102
253
|
goal?: string | undefined;
|
|
254
|
+
verification?: {
|
|
255
|
+
commands: {
|
|
256
|
+
cmd: string;
|
|
257
|
+
purpose: string;
|
|
258
|
+
}[];
|
|
259
|
+
gate_command?: string | undefined;
|
|
260
|
+
} | undefined;
|
|
103
261
|
constraints?: {
|
|
104
262
|
protected_paths?: string[] | undefined;
|
|
105
263
|
paradigm?: string | undefined;
|
|
106
264
|
do_not_touch?: string[] | undefined;
|
|
265
|
+
allowed_scope?: string[] | undefined;
|
|
107
266
|
max_files_changed?: number | undefined;
|
|
108
267
|
no_new_deps?: boolean | undefined;
|
|
109
268
|
allowed_dependencies?: string[] | undefined;
|
|
110
269
|
} | undefined;
|
|
111
270
|
}>;
|
|
112
271
|
export type FixPacketV2 = z.infer<typeof FixPacketV2Schema>;
|
|
272
|
+
export type Violation = z.infer<typeof ViolationSchema>;
|
|
273
|
+
export type ViolationLocation = z.infer<typeof ViolationLocationSchema>;
|
|
274
|
+
export {};
|
package/dist/types/fix-packet.js
CHANGED
|
@@ -1,29 +1,55 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
/**
|
|
3
|
-
* Fix Packet
|
|
4
|
-
*
|
|
3
|
+
* Fix Packet v3 Schema
|
|
4
|
+
*
|
|
5
|
+
* Designed for high-fidelity, machine-readable communication with AI agents.
|
|
6
|
+
* Every violation tells the agent exactly: who failed, which files, what rule,
|
|
7
|
+
* where in the file, and what must pass to verify the fix.
|
|
8
|
+
*
|
|
9
|
+
* v3 changes from v2:
|
|
10
|
+
* - Violations now include `location` (file + line range) for precise targeting
|
|
11
|
+
* - Top-level `verification` block: commands the agent MUST run after fixing
|
|
12
|
+
* - `allowed_scope`: explicit list of file globs the agent IS allowed to edit
|
|
13
|
+
* - `failed_gates`: summary list of gate IDs that failed (quick machine check)
|
|
5
14
|
*/
|
|
15
|
+
const ViolationLocationSchema = z.object({
|
|
16
|
+
file: z.string(),
|
|
17
|
+
line: z.number().optional(),
|
|
18
|
+
endLine: z.number().optional(),
|
|
19
|
+
});
|
|
20
|
+
const ViolationSchema = z.object({
|
|
21
|
+
id: z.string(), // Gate ID, e.g. "file-size"
|
|
22
|
+
gate: z.string(), // Same as id (kept for backwards compat)
|
|
23
|
+
severity: z.enum(['info', 'low', 'medium', 'high', 'critical']).default('medium'),
|
|
24
|
+
category: z.string().optional(), // Provenance: "traditional", "ai-drift", "security", etc.
|
|
25
|
+
title: z.string(),
|
|
26
|
+
details: z.string(),
|
|
27
|
+
files: z.array(z.string()).optional(),
|
|
28
|
+
locations: z.array(ViolationLocationSchema).optional(), // Precise file + line targets
|
|
29
|
+
hint: z.string().optional(),
|
|
30
|
+
instructions: z.array(z.string()).optional(),
|
|
31
|
+
metrics: z.record(z.any()).optional(), // e.g. { complexity: 15, threshold: 10 }
|
|
32
|
+
});
|
|
33
|
+
const VerificationSchema = z.object({
|
|
34
|
+
commands: z.array(z.object({
|
|
35
|
+
cmd: z.string(), // e.g. "npm run typecheck"
|
|
36
|
+
purpose: z.string(), // e.g. "Ensure no TypeScript errors"
|
|
37
|
+
})),
|
|
38
|
+
gate_command: z.string().default('rigour_check'), // The rigour tool to re-run
|
|
39
|
+
});
|
|
6
40
|
export const FixPacketV2Schema = z.object({
|
|
7
|
-
version: z.literal(
|
|
41
|
+
version: z.literal(3),
|
|
8
42
|
goal: z.string().default('Achieve PASS state for all quality gates'),
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
severity: z.enum(['info', 'low', 'medium', 'high', 'critical']).default('medium'),
|
|
13
|
-
category: z.string().optional(),
|
|
14
|
-
title: z.string(),
|
|
15
|
-
details: z.string(),
|
|
16
|
-
files: z.array(z.string()).optional(),
|
|
17
|
-
hint: z.string().optional(),
|
|
18
|
-
instructions: z.array(z.string()).optional(), // Step-by-step fix instructions
|
|
19
|
-
metrics: z.record(z.any()).optional(), // e.g., { complexity: 15, max: 10 }
|
|
20
|
-
})),
|
|
43
|
+
failed_gates: z.array(z.string()), // Quick list: ["file-size", "hallucinated-imports"]
|
|
44
|
+
violations: z.array(ViolationSchema),
|
|
45
|
+
verification: VerificationSchema.optional(),
|
|
21
46
|
constraints: z.object({
|
|
22
47
|
protected_paths: z.array(z.string()).optional(),
|
|
23
|
-
do_not_touch: z.array(z.string()).optional(),
|
|
48
|
+
do_not_touch: z.array(z.string()).optional(),
|
|
49
|
+
allowed_scope: z.array(z.string()).optional(), // Globs the agent IS allowed to edit
|
|
24
50
|
max_files_changed: z.number().optional(),
|
|
25
51
|
no_new_deps: z.boolean().optional().default(true),
|
|
26
52
|
allowed_dependencies: z.array(z.string()).optional(),
|
|
27
|
-
paradigm: z.string().optional(),
|
|
53
|
+
paradigm: z.string().optional(),
|
|
28
54
|
}).optional().default({}),
|
|
29
55
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rigour-labs/core",
|
|
3
|
-
"version": "4.3.
|
|
3
|
+
"version": "4.3.5",
|
|
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.3.
|
|
63
|
-
"@rigour-labs/brain-
|
|
64
|
-
"@rigour-labs/brain-
|
|
65
|
-
"@rigour-labs/brain-
|
|
66
|
-
"@rigour-labs/brain-linux-
|
|
62
|
+
"@rigour-labs/brain-darwin-arm64": "4.3.5",
|
|
63
|
+
"@rigour-labs/brain-darwin-x64": "4.3.5",
|
|
64
|
+
"@rigour-labs/brain-win-x64": "4.3.5",
|
|
65
|
+
"@rigour-labs/brain-linux-x64": "4.3.5",
|
|
66
|
+
"@rigour-labs/brain-linux-arm64": "4.3.5"
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
69
|
"@types/better-sqlite3": "^7.6.12",
|