@rigour-labs/cli 4.0.5 → 4.1.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.
@@ -6,7 +6,7 @@ import { loadSettings, saveSettings, getSettingsPath, updateProviderKey, removeP
6
6
  * Like Claude Code's settings.json or Gemini CLI's config.
7
7
  * Stores API keys, default provider, multi-agent config, CLI preferences.
8
8
  */
9
- export async function settingsShowCommand() {
9
+ export function settingsShowCommand() {
10
10
  const settingsPath = getSettingsPath();
11
11
  const settings = loadSettings();
12
12
  console.log(chalk.bold.cyan('\n Rigour Settings'));
@@ -73,7 +73,7 @@ export async function settingsShowCommand() {
73
73
  console.log('');
74
74
  }
75
75
  }
76
- export async function settingsSetKeyCommand(provider, apiKey) {
76
+ export function settingsSetKeyCommand(provider, apiKey) {
77
77
  updateProviderKey(provider, apiKey);
78
78
  const masked = maskKey(apiKey);
79
79
  console.log(chalk.green(` ✓ ${provider} API key saved: ${masked}`));
@@ -82,11 +82,11 @@ export async function settingsSetKeyCommand(provider, apiKey) {
82
82
  console.log(chalk.dim(` Usage: rigour check --deep --provider ${provider}`));
83
83
  console.log(chalk.dim(` Or set as default: rigour settings set provider ${provider}`));
84
84
  }
85
- export async function settingsRemoveKeyCommand(provider) {
85
+ export function settingsRemoveKeyCommand(provider) {
86
86
  removeProviderKey(provider);
87
87
  console.log(chalk.green(` ✓ ${provider} API key removed`));
88
88
  }
89
- export async function settingsSetCommand(key, value) {
89
+ export function settingsSetCommand(key, value) {
90
90
  const settings = loadSettings();
91
91
  // Parse dot-notation keys: "deep.defaultProvider" -> settings.deep.defaultProvider
92
92
  const parts = key.split('.');
@@ -109,7 +109,7 @@ export async function settingsSetCommand(key, value) {
109
109
  saveSettings(settings);
110
110
  console.log(chalk.green(` ✓ ${key} = ${value}`));
111
111
  }
112
- export async function settingsGetCommand(key) {
112
+ export function settingsGetCommand(key) {
113
113
  const settings = loadSettings();
114
114
  const parts = key.split('.');
115
115
  let value = settings;
@@ -128,12 +128,12 @@ export async function settingsGetCommand(key) {
128
128
  console.log(` ${key} = ${value}`);
129
129
  }
130
130
  }
131
- export async function settingsResetCommand() {
131
+ export function settingsResetCommand() {
132
132
  saveSettings({});
133
133
  console.log(chalk.green(' ✓ Settings reset to defaults'));
134
134
  console.log(chalk.dim(` ${getSettingsPath()}`));
135
135
  }
136
- export async function settingsPathCommand() {
136
+ export function settingsPathCommand() {
137
137
  console.log(getSettingsPath());
138
138
  }
139
139
  function maskKey(key) {
@@ -43,8 +43,8 @@ export async function setupCommand() {
43
43
  // ── Section 3: Deep Analysis Readiness ──
44
44
  console.log(chalk.bold('\n Deep Analysis'));
45
45
  // Check local models
46
- const hasDeep = isModelCached('deep');
47
- const hasPro = isModelCached('pro');
46
+ const hasDeep = await isModelCached('deep');
47
+ const hasPro = await isModelCached('pro');
48
48
  if (hasDeep)
49
49
  console.log(chalk.green(' ✔ Local model: deep (Qwen2.5-Coder-0.5B, 350MB)'));
50
50
  if (hasPro)
@@ -57,7 +57,12 @@ export async function setupCommand() {
57
57
  let hasSidecar = false;
58
58
  try {
59
59
  const { execSync } = await import('child_process');
60
- execSync('which llama-cli 2>/dev/null || which rigour-brain 2>/dev/null', { encoding: 'utf-8', timeout: 3000 });
60
+ if (process.platform === 'win32') {
61
+ execSync('where llama-cli || where rigour-brain', { encoding: 'utf-8', timeout: 3000 });
62
+ }
63
+ else {
64
+ execSync('which llama-cli 2>/dev/null || which rigour-brain 2>/dev/null', { encoding: 'utf-8', timeout: 3000 });
65
+ }
61
66
  hasSidecar = true;
62
67
  console.log(chalk.green(' ✔ Inference binary found'));
63
68
  }
@@ -96,6 +101,7 @@ export async function setupCommand() {
96
101
  console.log(chalk.dim(' Global: ') + chalk.cyan('npm install -g @rigour-labs/cli'));
97
102
  console.log(chalk.dim(' Local: ') + chalk.cyan('npm install --save-dev @rigour-labs/cli'));
98
103
  console.log(chalk.dim(' No-install: ') + chalk.cyan('npx @rigour-labs/cli check'));
104
+ console.log(chalk.dim(' Diagnostics: ') + chalk.cyan('rigour doctor'));
99
105
  console.log(chalk.dim(' MCP: ') + chalk.cyan('packages/rigour-mcp/dist/index.js'));
100
106
  console.log('');
101
107
  }
@@ -84,9 +84,17 @@ export const studioCommand = new Command('studio')
84
84
  });
85
85
  });
86
86
  async function setupApiAndLaunch(apiPort, studioPort, eventsPath, cwd, studioProcess) {
87
+ const allowedOrigins = new Set([
88
+ `http://localhost:${studioPort}`,
89
+ `http://127.0.0.1:${studioPort}`,
90
+ ]);
87
91
  const apiServer = http.createServer(async (req, res) => {
88
92
  const url = new URL(req.url || '', `http://${req.headers.host || 'localhost'}`);
89
- res.setHeader('Access-Control-Allow-Origin', '*');
93
+ const requestOrigin = req.headers.origin;
94
+ if (typeof requestOrigin === 'string' && allowedOrigins.has(requestOrigin)) {
95
+ res.setHeader('Access-Control-Allow-Origin', requestOrigin);
96
+ res.setHeader('Vary', 'Origin');
97
+ }
90
98
  res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS, POST');
91
99
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
92
100
  if (req.method === 'OPTIONS') {
@@ -108,15 +116,19 @@ async function setupApiAndLaunch(apiPort, studioPort, eventsPath, cwd, studioPro
108
116
  }
109
117
  }
110
118
  await fs.ensureDir(path.dirname(eventsPath));
111
- const watcher = fs.watch(path.dirname(eventsPath), (eventType, filename) => {
119
+ const watcher = fs.watch(path.dirname(eventsPath), async (_eventType, filename) => {
112
120
  if (filename === 'events.jsonl') {
113
- fs.readFile(eventsPath, 'utf8').then(content => {
121
+ try {
122
+ const content = await fs.readFile(eventsPath, 'utf8');
114
123
  const lines = content.split('\n').filter(l => l.trim());
115
124
  const lastLine = lines[lines.length - 1];
116
125
  if (lastLine) {
117
126
  res.write(`data: ${lastLine}\n\n`);
118
127
  }
119
- }).catch(() => { });
128
+ }
129
+ catch {
130
+ // ignore transient file read failures during writes
131
+ }
120
132
  }
121
133
  });
122
134
  req.on('close', () => watcher.close());
@@ -61,7 +61,7 @@ gates:
61
61
  }
62
62
  }, 30_000);
63
63
  it('should check specific files when provided', async () => {
64
- await fs.writeFile(path.join(testDir, 'bad.js'), 'TODO: fixme');
64
+ await fs.writeFile(path.join(testDir, 'bad.js'), '// TODO: fixme');
65
65
  await fs.writeFile(path.join(testDir, 'good.js'), 'console.log("hello")');
66
66
  await fs.writeFile(path.join(testDir, 'rigour.yml'), `
67
67
  version: 1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rigour-labs/cli",
3
- "version": "4.0.5",
3
+ "version": "4.1.1",
4
4
  "description": "CLI quality gates for AI-generated code. Forces AI agents (Claude, Cursor, Copilot) to meet strict engineering standards with PASS/FAIL enforcement.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://rigour.run",
@@ -44,7 +44,7 @@
44
44
  "inquirer": "9.2.16",
45
45
  "ora": "^8.0.1",
46
46
  "yaml": "^2.8.2",
47
- "@rigour-labs/core": "4.0.5"
47
+ "@rigour-labs/core": "4.1.1"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@types/fs-extra": "^11.0.4",