@rigour-labs/cli 2.11.0 ā 2.13.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/commands/studio.js +249 -229
- package/package.json +9 -3
- package/studio-dist/assets/index-CSj2lLc7.css +1 -0
- package/studio-dist/assets/index-CmJzYc99.js +259 -0
- package/studio-dist/index.html +17 -0
- package/src/cli.ts +0 -112
- package/src/commands/check.ts +0 -215
- package/src/commands/constants.ts +0 -209
- package/src/commands/explain.ts +0 -75
- package/src/commands/guide.ts +0 -21
- package/src/commands/index.ts +0 -105
- package/src/commands/init.ts +0 -413
- package/src/commands/run.ts +0 -135
- package/src/commands/setup.ts +0 -28
- package/src/commands/studio.ts +0 -273
- package/src/init-rules.test.ts +0 -59
- package/src/smoke.test.ts +0 -76
- package/src/templates/handshake.mdc +0 -36
- package/tsconfig.json +0 -10
- package/vitest.config.ts +0 -10
- package/vitest.setup.ts +0 -30
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>Rigour Studio | AI Governance</title>
|
|
8
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
9
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
10
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
|
11
|
+
<script type="module" crossorigin src="/assets/index-CmJzYc99.js"></script>
|
|
12
|
+
<link rel="stylesheet" crossorigin href="/assets/index-CSj2lLc7.css">
|
|
13
|
+
</head>
|
|
14
|
+
<body>
|
|
15
|
+
<div id="root"></div>
|
|
16
|
+
</body>
|
|
17
|
+
</html>
|
package/src/cli.ts
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { Command } from 'commander';
|
|
3
|
-
import { initCommand } from './commands/init.js';
|
|
4
|
-
import { checkCommand } from './commands/check.js';
|
|
5
|
-
import { explainCommand } from './commands/explain.js';
|
|
6
|
-
import { runLoop } from './commands/run.js';
|
|
7
|
-
import { guideCommand } from './commands/guide.js';
|
|
8
|
-
import { setupCommand } from './commands/setup.js';
|
|
9
|
-
import { indexCommand } from './commands/index.js';
|
|
10
|
-
import { studioCommand } from './commands/studio.js';
|
|
11
|
-
import chalk from 'chalk';
|
|
12
|
-
|
|
13
|
-
const program = new Command();
|
|
14
|
-
|
|
15
|
-
program.addCommand(indexCommand);
|
|
16
|
-
program.addCommand(studioCommand);
|
|
17
|
-
|
|
18
|
-
program
|
|
19
|
-
.name('rigour')
|
|
20
|
-
.description('š”ļø Rigour: The Quality Gate Loop for AI-Assisted Engineering')
|
|
21
|
-
.version('2.0.0')
|
|
22
|
-
.addHelpText('before', chalk.bold.cyan(`
|
|
23
|
-
____ _
|
|
24
|
-
/ __ \\(_)____ ___ __ __ _____
|
|
25
|
-
/ /_/ // // __ \`/ / / / / // ___/
|
|
26
|
-
/ _, _// // /_/ // /_/ / / // /
|
|
27
|
-
/_/ |_|/_/ \\__, / \\__,_/_/ /_/
|
|
28
|
-
/____/
|
|
29
|
-
`));
|
|
30
|
-
|
|
31
|
-
program
|
|
32
|
-
.command('init')
|
|
33
|
-
.description('Initialize Rigour in the current directory')
|
|
34
|
-
.option('-p, --preset <name>', 'Project preset (ui, api, infra, data)')
|
|
35
|
-
.option('--paradigm <name>', 'Coding paradigm (oop, functional, minimal)')
|
|
36
|
-
.option('--ide <name>', 'Target IDE (cursor, vscode, all). Auto-detects if not specified.')
|
|
37
|
-
.option('--dry-run', 'Show detected configuration without writing files')
|
|
38
|
-
.option('--explain', 'Show detection markers for roles and paradigms')
|
|
39
|
-
.addHelpText('after', `
|
|
40
|
-
Examples:
|
|
41
|
-
$ rigour init # Auto-discover role & paradigm
|
|
42
|
-
$ rigour init --preset api --explain # Force API role and show why
|
|
43
|
-
$ rigour init --ide vscode # Only create VS Code compatible files
|
|
44
|
-
$ rigour init --ide all # Create files for all IDEs
|
|
45
|
-
`)
|
|
46
|
-
.action(async (options: any) => {
|
|
47
|
-
await initCommand(process.cwd(), options);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
program
|
|
51
|
-
.command('check')
|
|
52
|
-
.description('Run quality gate checks')
|
|
53
|
-
.argument('[files...]', 'Specific files or directories to check')
|
|
54
|
-
.option('--ci', 'CI mode (minimal output, non-zero exit on fail)')
|
|
55
|
-
.option('--json', 'Output report in JSON format')
|
|
56
|
-
.option('-i, --interactive', 'Run in interactive mode with rich output')
|
|
57
|
-
.addHelpText('after', `
|
|
58
|
-
Examples:
|
|
59
|
-
$ rigour check # Run standard check
|
|
60
|
-
$ rigour check ./src # Check only the src directory
|
|
61
|
-
$ rigour check ./src/app.ts # Check only app.ts
|
|
62
|
-
$ rigour check --interactive # Run with rich, interactive output
|
|
63
|
-
$ rigour check --ci # Run in CI environment
|
|
64
|
-
`)
|
|
65
|
-
.action(async (files: string[], options: any) => {
|
|
66
|
-
await checkCommand(process.cwd(), files, options);
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
program
|
|
70
|
-
.command('explain')
|
|
71
|
-
.description('Explain the last quality gate report with actionable bullets')
|
|
72
|
-
.addHelpText('after', `
|
|
73
|
-
Examples:
|
|
74
|
-
$ rigour explain # Get a human-readable violation summary
|
|
75
|
-
`)
|
|
76
|
-
.action(async () => {
|
|
77
|
-
await explainCommand(process.cwd());
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
program
|
|
81
|
-
.command('run')
|
|
82
|
-
.description('Execute an agent command in a loop until quality gates pass')
|
|
83
|
-
.argument('[command...]', 'The agent command to run (e.g., cursor-agent ...)')
|
|
84
|
-
.option('-c, --max-cycles <number>', 'Maximum number of loop iterations', '3')
|
|
85
|
-
.option('--fail-fast', 'Abort loop immediately on first gate failure')
|
|
86
|
-
.addHelpText('after', `
|
|
87
|
-
Examples:
|
|
88
|
-
$ rigour run -- claude "fix issues" # Loop Claude until PASS
|
|
89
|
-
$ rigour run -c 5 -- cursor-agent # Run Cursor agent for up to 5 cycles
|
|
90
|
-
`)
|
|
91
|
-
.action(async (args: string[], options: any) => {
|
|
92
|
-
await runLoop(process.cwd(), args, {
|
|
93
|
-
iterations: parseInt(options.maxCycles),
|
|
94
|
-
failFast: !!options.failFast
|
|
95
|
-
});
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
program
|
|
99
|
-
.command('guide')
|
|
100
|
-
.description('Show the interactive engineering guide')
|
|
101
|
-
.action(async () => {
|
|
102
|
-
await guideCommand();
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
program
|
|
106
|
-
.command('setup')
|
|
107
|
-
.description('Show installation and global setup guidance')
|
|
108
|
-
.action(async () => {
|
|
109
|
-
await setupCommand();
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
program.parse();
|
package/src/commands/check.ts
DELETED
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
import fs from 'fs-extra';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import chalk from 'chalk';
|
|
4
|
-
import yaml from 'yaml';
|
|
5
|
-
import { GateRunner, ConfigSchema, Failure } from '@rigour-labs/core';
|
|
6
|
-
import inquirer from 'inquirer';
|
|
7
|
-
import { randomUUID } from 'crypto';
|
|
8
|
-
|
|
9
|
-
// Exit codes per spec
|
|
10
|
-
const EXIT_PASS = 0;
|
|
11
|
-
const EXIT_FAIL = 1;
|
|
12
|
-
const EXIT_CONFIG_ERROR = 2;
|
|
13
|
-
const EXIT_INTERNAL_ERROR = 3;
|
|
14
|
-
|
|
15
|
-
export interface CheckOptions {
|
|
16
|
-
ci?: boolean;
|
|
17
|
-
json?: boolean;
|
|
18
|
-
interactive?: boolean;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// Helper to log events for Rigour Studio
|
|
22
|
-
async function logStudioEvent(cwd: string, event: any) {
|
|
23
|
-
try {
|
|
24
|
-
const rigourDir = path.join(cwd, ".rigour");
|
|
25
|
-
await fs.ensureDir(rigourDir);
|
|
26
|
-
const eventsPath = path.join(rigourDir, "events.jsonl");
|
|
27
|
-
const logEntry = JSON.stringify({
|
|
28
|
-
id: randomUUID(),
|
|
29
|
-
timestamp: new Date().toISOString(),
|
|
30
|
-
...event
|
|
31
|
-
}) + "\n";
|
|
32
|
-
await fs.appendFile(eventsPath, logEntry);
|
|
33
|
-
} catch {
|
|
34
|
-
// Silent fail
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export async function checkCommand(cwd: string, files: string[] = [], options: CheckOptions = {}) {
|
|
39
|
-
const configPath = path.join(cwd, 'rigour.yml');
|
|
40
|
-
|
|
41
|
-
if (!(await fs.pathExists(configPath))) {
|
|
42
|
-
if (options.json) {
|
|
43
|
-
console.log(JSON.stringify({ error: 'CONFIG_ERROR', message: 'rigour.yml not found' }));
|
|
44
|
-
} else if (!options.ci) {
|
|
45
|
-
console.error(chalk.red('Error: rigour.yml not found. Run `rigour init` first.'));
|
|
46
|
-
}
|
|
47
|
-
process.exit(EXIT_CONFIG_ERROR);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
try {
|
|
51
|
-
const configContent = await fs.readFile(configPath, 'utf-8');
|
|
52
|
-
const rawConfig = yaml.parse(configContent);
|
|
53
|
-
const config = ConfigSchema.parse(rawConfig);
|
|
54
|
-
|
|
55
|
-
if (!options.ci && !options.json) {
|
|
56
|
-
console.log(chalk.blue('Running Rigour checks...\n'));
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const runner = new GateRunner(config);
|
|
60
|
-
|
|
61
|
-
const requestId = randomUUID();
|
|
62
|
-
await logStudioEvent(cwd, {
|
|
63
|
-
type: "tool_call",
|
|
64
|
-
requestId,
|
|
65
|
-
tool: "rigour_check",
|
|
66
|
-
arguments: { files }
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
const report = await runner.run(cwd, files.length > 0 ? files : undefined);
|
|
70
|
-
|
|
71
|
-
// Write machine report
|
|
72
|
-
const reportPath = path.join(cwd, config.output.report_path);
|
|
73
|
-
await fs.writeJson(reportPath, report, { spaces: 2 });
|
|
74
|
-
|
|
75
|
-
await logStudioEvent(cwd, {
|
|
76
|
-
type: "tool_response",
|
|
77
|
-
requestId,
|
|
78
|
-
tool: "rigour_check",
|
|
79
|
-
status: report.status === 'PASS' ? 'success' : 'error',
|
|
80
|
-
content: [{ type: "text", text: `Audit Result: ${report.status}` }],
|
|
81
|
-
_rigour_report: report
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
// Generate Fix Packet v2 on failure
|
|
85
|
-
if (report.status === 'FAIL') {
|
|
86
|
-
const { FixPacketService } = await import('@rigour-labs/core');
|
|
87
|
-
const fixPacketService = new FixPacketService();
|
|
88
|
-
const fixPacket = fixPacketService.generate(report, config);
|
|
89
|
-
const fixPacketPath = path.join(cwd, 'rigour-fix-packet.json');
|
|
90
|
-
await fs.writeJson(fixPacketPath, fixPacket, { spaces: 2 });
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// JSON output mode
|
|
94
|
-
if (options.json) {
|
|
95
|
-
console.log(JSON.stringify(report, null, 2));
|
|
96
|
-
process.exit(report.status === 'PASS' ? EXIT_PASS : EXIT_FAIL);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// CI mode: minimal output
|
|
100
|
-
if (options.ci) {
|
|
101
|
-
if (report.status === 'PASS') {
|
|
102
|
-
console.log('PASS');
|
|
103
|
-
} else {
|
|
104
|
-
console.log(`FAIL: ${report.failures.length} violation(s)`);
|
|
105
|
-
report.failures.forEach((f: Failure) => {
|
|
106
|
-
console.log(` - [${f.id}] ${f.title}`);
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
process.exit(report.status === 'PASS' ? EXIT_PASS : EXIT_FAIL);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
if (options.interactive && report.status === 'FAIL') {
|
|
113
|
-
await interactiveMode(report, config);
|
|
114
|
-
process.exit(EXIT_FAIL);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// Normal human-readable output
|
|
118
|
-
if (report.status === 'PASS') {
|
|
119
|
-
console.log(chalk.green.bold('ā PASS - All quality gates satisfied.'));
|
|
120
|
-
} else {
|
|
121
|
-
console.log(chalk.red.bold('ā FAIL - Quality gate violations found.\n'));
|
|
122
|
-
|
|
123
|
-
for (const failure of report.failures as Failure[]) {
|
|
124
|
-
console.log(chalk.red(`[${failure.id}] ${failure.title}`));
|
|
125
|
-
console.log(chalk.dim(` Details: ${failure.details}`));
|
|
126
|
-
if (failure.files && failure.files.length > 0) {
|
|
127
|
-
console.log(chalk.dim(' Files:'));
|
|
128
|
-
failure.files.forEach((f: string) => console.log(chalk.dim(` - ${f}`)));
|
|
129
|
-
}
|
|
130
|
-
if (failure.hint) {
|
|
131
|
-
console.log(chalk.cyan(` Hint: ${failure.hint}`));
|
|
132
|
-
}
|
|
133
|
-
console.log('');
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
console.log(chalk.yellow(`See ${config.output.report_path} for full details.`));
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
console.log(chalk.dim(`\nFinished in ${report.stats.duration_ms}ms`));
|
|
140
|
-
|
|
141
|
-
process.exit(report.status === 'PASS' ? EXIT_PASS : EXIT_FAIL);
|
|
142
|
-
|
|
143
|
-
} catch (error: any) {
|
|
144
|
-
if (error.name === 'ZodError') {
|
|
145
|
-
if (options.json) {
|
|
146
|
-
console.log(JSON.stringify({ error: 'CONFIG_ERROR', details: error.issues }));
|
|
147
|
-
} else {
|
|
148
|
-
console.error(chalk.red('\nInvalid rigour.yml configuration:'));
|
|
149
|
-
error.issues.forEach((issue: any) => {
|
|
150
|
-
console.error(chalk.red(` ⢠${issue.path.join('.')}: ${issue.message}`));
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
process.exit(EXIT_CONFIG_ERROR);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
if (options.json) {
|
|
157
|
-
console.log(JSON.stringify({ error: 'INTERNAL_ERROR', message: error.message }));
|
|
158
|
-
} else if (!options.ci) {
|
|
159
|
-
console.error(chalk.red(`Internal error: ${error.message}`));
|
|
160
|
-
}
|
|
161
|
-
process.exit(EXIT_INTERNAL_ERROR);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
async function interactiveMode(report: any, config: any) {
|
|
166
|
-
console.clear();
|
|
167
|
-
console.log(chalk.bold.blue('āā Rigour Interactive Review āā\n'));
|
|
168
|
-
console.log(chalk.yellow(`${report.failures.length} violations found.\n`));
|
|
169
|
-
|
|
170
|
-
const choices = report.failures.map((f: Failure, i: number) => ({
|
|
171
|
-
name: `[${f.id}] ${f.title}`,
|
|
172
|
-
value: i
|
|
173
|
-
}));
|
|
174
|
-
|
|
175
|
-
choices.push(new (inquirer as any).Separator());
|
|
176
|
-
choices.push({ name: 'Exit', value: -1 });
|
|
177
|
-
|
|
178
|
-
let exit = false;
|
|
179
|
-
while (!exit) {
|
|
180
|
-
const { index } = await inquirer.prompt([
|
|
181
|
-
{
|
|
182
|
-
type: 'list',
|
|
183
|
-
name: 'index',
|
|
184
|
-
message: 'Select a violation to view details:',
|
|
185
|
-
choices,
|
|
186
|
-
pageSize: 15
|
|
187
|
-
}
|
|
188
|
-
]);
|
|
189
|
-
|
|
190
|
-
if (index === -1) {
|
|
191
|
-
exit = true;
|
|
192
|
-
continue;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
const failure = report.failures[index];
|
|
196
|
-
console.clear();
|
|
197
|
-
console.log(chalk.bold.red(`\nViolation: ${failure.title}`));
|
|
198
|
-
console.log(chalk.dim(`ID: ${failure.id}`));
|
|
199
|
-
console.log(`\n${chalk.bold('Details:')}\n${failure.details}`);
|
|
200
|
-
|
|
201
|
-
if (failure.files && failure.files.length > 0) {
|
|
202
|
-
console.log(`\n${chalk.bold('Impacted Files:')}`);
|
|
203
|
-
failure.files.forEach((f: string) => console.log(chalk.dim(` - ${f}`)));
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
if (failure.hint) {
|
|
207
|
-
console.log(`\n${chalk.bold.cyan('Hint:')} ${failure.hint}`);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
console.log(chalk.dim('\n' + 'ā'.repeat(40)));
|
|
211
|
-
await inquirer.prompt([{ type: 'input', name: 'continue', message: 'Press Enter to return to list...' }]);
|
|
212
|
-
console.clear();
|
|
213
|
-
console.log(chalk.bold.blue('āā Rigour Interactive Review āā\n'));
|
|
214
|
-
}
|
|
215
|
-
}
|
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
export const CODE_QUALITY_RULES = `
|
|
2
|
-
# Code Quality Standards
|
|
3
|
-
|
|
4
|
-
## PRODUCTION-GRADE CODE ONLY
|
|
5
|
-
- No debug logging in production code
|
|
6
|
-
- No shortcuts or "temporary" fixes
|
|
7
|
-
- No over-engineering - simplest solution that works
|
|
8
|
-
- Follow existing code patterns and conventions
|
|
9
|
-
- Handle edge cases properly
|
|
10
|
-
- No TODO/FIXME comments in final code
|
|
11
|
-
|
|
12
|
-
## MODULAR CODE STRUCTURE
|
|
13
|
-
- Write SMALL, focused functions (< 50 lines ideally)
|
|
14
|
-
- One function = one job, clearly named
|
|
15
|
-
- New features go in SEPARATE FILES, not flooding existing ones
|
|
16
|
-
- Keep files under 500 lines - split if growing larger
|
|
17
|
-
- Extract reusable logic into utility modules
|
|
18
|
-
- Avoid "god files" that do everything
|
|
19
|
-
- When adding to existing code, check if a new module is more appropriate
|
|
20
|
-
|
|
21
|
-
## Technical Standards
|
|
22
|
-
|
|
23
|
-
### DRY Principle
|
|
24
|
-
- Extract repeated logic into utilities
|
|
25
|
-
- Single Responsibility: One function, one job
|
|
26
|
-
- Defensive coding: Validate inputs at boundaries
|
|
27
|
-
- Lazy initialization for external dependencies (secrets, connections)
|
|
28
|
-
- Graceful degradation over hard failures
|
|
29
|
-
|
|
30
|
-
### File Organization
|
|
31
|
-
\`\`\`
|
|
32
|
-
# Good: Separate concerns into focused files
|
|
33
|
-
governor/
|
|
34
|
-
main.py # Entry point only
|
|
35
|
-
drift_detector.py # Drift detection logic
|
|
36
|
-
lip_sync_analyzer.py # SyncNet integration
|
|
37
|
-
audio_analyzer.py # Audio analysis
|
|
38
|
-
|
|
39
|
-
# Bad: One massive file with everything
|
|
40
|
-
governor/
|
|
41
|
-
main.py (2000+ lines with all logic mixed)
|
|
42
|
-
\`\`\`
|
|
43
|
-
|
|
44
|
-
### API Design
|
|
45
|
-
- Consistent error responses
|
|
46
|
-
- Proper HTTP status codes
|
|
47
|
-
- Authentication at the edge
|
|
48
|
-
- Rate limiting on public endpoints
|
|
49
|
-
|
|
50
|
-
## PRODUCTION-READY SELF-REVIEW (THE GATEKEEPER)
|
|
51
|
-
|
|
52
|
-
Before asking for "approval," internally verify:
|
|
53
|
-
|
|
54
|
-
- **Zero-Dependency Check**: Does this fix rely on a local environment variable not yet in \`talentlyt-kv\`?
|
|
55
|
-
- **Side-Effect Audit**: Could this change trigger a 502 Bad Gateway at the \`/auth/callback\` or \`/api/agent\` endpoints?
|
|
56
|
-
- **Biometric Integrity**: If touching the \`Governor\`, have I verified that the \`similarity_score\` logic remains deterministic?
|
|
57
|
-
- **Cost Impact**: Does this change increase egress costs (e.g., unnecessary cross-region logging)?
|
|
58
|
-
- **Error Handling**: Does the UI have a graceful fallback if the backend service is slow?
|
|
59
|
-
`;
|
|
60
|
-
|
|
61
|
-
export const DEBUGGING_RULES = `
|
|
62
|
-
# Investigation & Debugging Protocol
|
|
63
|
-
|
|
64
|
-
## INVESTIGATION PROTOCOL
|
|
65
|
-
|
|
66
|
-
When debugging:
|
|
67
|
-
1. Check DEPLOYED environment (Azure, prod), not localhost unless explicitly asked
|
|
68
|
-
2. Trace the actual request flow end-to-end
|
|
69
|
-
3. Collect evidence at each step
|
|
70
|
-
4. Present findings before proposing fixes
|
|
71
|
-
|
|
72
|
-
## GAP ANALYSIS
|
|
73
|
-
|
|
74
|
-
When debugging or proposing changes:
|
|
75
|
-
|
|
76
|
-
1. **Trace the actual request flow** end-to-end:
|
|
77
|
-
- Client ā Cloudflare ā Vercel/Container App ā DB
|
|
78
|
-
|
|
79
|
-
2. **Identify Hidden Gaps** - Explicitly check if the change affects:
|
|
80
|
-
- **Cross-Region Handshakes**: Will this increase latency for users in Pakistan/India?
|
|
81
|
-
- **Forensic Continuity**: Does this change how Maya captures gaze or audio data?
|
|
82
|
-
- **Auth Persistence**: Will this interfere with WorkOS session tokens or M2M keys?
|
|
83
|
-
|
|
84
|
-
3. **Evidence-First**: Collect logs from \`talentlyt-dashboard\` before proposing a fix.
|
|
85
|
-
|
|
86
|
-
## Request Flow Tracing
|
|
87
|
-
|
|
88
|
-
\`\`\`
|
|
89
|
-
Client Browser
|
|
90
|
-
ā
|
|
91
|
-
Cloudflare (CDN/WAF)
|
|
92
|
-
ā
|
|
93
|
-
Azure Container Apps
|
|
94
|
-
āāā talentlyt-dashboard (Next.js)
|
|
95
|
-
āāā talentlyt-agent (Python/LiveKit)
|
|
96
|
-
ā
|
|
97
|
-
PostgreSQL Database
|
|
98
|
-
ā
|
|
99
|
-
Azure Blob Storage (recordings, evidence)
|
|
100
|
-
\`\`\`
|
|
101
|
-
|
|
102
|
-
## Evidence Collection
|
|
103
|
-
|
|
104
|
-
Before proposing any fix:
|
|
105
|
-
1. Get the actual error from logs (not assumed)
|
|
106
|
-
2. Identify the exact file and line number
|
|
107
|
-
3. Trace the data flow that led to the error
|
|
108
|
-
4. Verify the fix doesn't break other paths
|
|
109
|
-
`;
|
|
110
|
-
|
|
111
|
-
export const COLLABORATION_RULES = `
|
|
112
|
-
# Role & Collaboration
|
|
113
|
-
|
|
114
|
-
You are a Senior Staff Engineer working alongside a Principal Engineer (the user).
|
|
115
|
-
You do NOT work autonomously - you work collaboratively with approval at each step.
|
|
116
|
-
|
|
117
|
-
## 1. NO ASSUMPTIONS
|
|
118
|
-
- Never assume root cause without evidence from logs/code
|
|
119
|
-
- Never assume a fix works without verification
|
|
120
|
-
- Always trace the ACTUAL flow, not the expected flow
|
|
121
|
-
- When debugging, read the DEPLOYED code, not local code
|
|
122
|
-
|
|
123
|
-
## 2. APPROVAL REQUIRED
|
|
124
|
-
Before making ANY code change, you MUST:
|
|
125
|
-
1. Show the evidence (logs, code trace) proving the issue
|
|
126
|
-
2. Explain the root cause with proof
|
|
127
|
-
3. Propose the fix with rationale
|
|
128
|
-
4. Wait for explicit approval: "approved", "go ahead", "do it"
|
|
129
|
-
|
|
130
|
-
Exception: Only proceed without approval if user explicitly says "just do it" or "fix it"
|
|
131
|
-
|
|
132
|
-
## 3. NEVER LOSE TRACK
|
|
133
|
-
- Maintain TODO list for multi-step tasks
|
|
134
|
-
- Complete current task before starting new ones
|
|
135
|
-
- If interrupted, summarize current state before switching
|
|
136
|
-
- Reference previous findings, don't repeat investigations
|
|
137
|
-
|
|
138
|
-
## Communication
|
|
139
|
-
|
|
140
|
-
### When Reporting Issues
|
|
141
|
-
\`\`\`
|
|
142
|
-
**Evidence:** [actual log/error message]
|
|
143
|
-
**Location:** [file:line or endpoint]
|
|
144
|
-
**Root Cause:** [proven, not assumed]
|
|
145
|
-
**Privacy Impact:** [Does this affect biometric/PII data?]
|
|
146
|
-
**Fix:** [proposed solution]
|
|
147
|
-
\`\`\`
|
|
148
|
-
|
|
149
|
-
### When Asking for Approval
|
|
150
|
-
\`\`\`
|
|
151
|
-
I found: [evidence]
|
|
152
|
-
Root cause: [explanation]
|
|
153
|
-
Proposed fix: [code change summary]
|
|
154
|
-
|
|
155
|
-
Approve to proceed?
|
|
156
|
-
\`\`\`
|
|
157
|
-
|
|
158
|
-
### When Stuck
|
|
159
|
-
- Say "I need more information" not guess
|
|
160
|
-
- Ask specific questions
|
|
161
|
-
- Propose diagnostic steps
|
|
162
|
-
|
|
163
|
-
## ā ļø RIGOUR.YML IS SACRED
|
|
164
|
-
|
|
165
|
-
The \`rigour.yml\` file represents **team-agreed quality standards**. You are FORBIDDEN from:
|
|
166
|
-
|
|
167
|
-
1. ā Increasing thresholds to pass checks (e.g., raising \`complexity: 100\`)
|
|
168
|
-
2. ā Adding patterns to \`ignore:\` to skip problematic files
|
|
169
|
-
3. ā Removing items from \`required_files\`
|
|
170
|
-
4. ā Disabling gates to avoid failures
|
|
171
|
-
|
|
172
|
-
**Your job is to FIX THE CODE to meet the standards, NOT weaken the standards to pass the check.**
|
|
173
|
-
|
|
174
|
-
If thresholds genuinely need adjustment, escalate to the team lead with justification.
|
|
175
|
-
|
|
176
|
-
## Forbidden Actions
|
|
177
|
-
|
|
178
|
-
1. ā Making code changes without showing evidence first
|
|
179
|
-
2. ā Testing on localhost when asked to check production
|
|
180
|
-
3. ā Adding debug logs as a "fix"
|
|
181
|
-
4. ā Multiple deployment attempts hoping it works
|
|
182
|
-
5. ā Over-engineering simple solutions
|
|
183
|
-
6. ā Assuming secrets/env vars are available at init time
|
|
184
|
-
7. ā Ignoring user corrections
|
|
185
|
-
8. ā Losing context between messages
|
|
186
|
-
9. ā Modifying rigour.yml to pass quality checks
|
|
187
|
-
`;
|
|
188
|
-
|
|
189
|
-
export const AGNOSTIC_AI_INSTRUCTIONS = `
|
|
190
|
-
# š¤ CRITICAL INSTRUCTION FOR AI
|
|
191
|
-
|
|
192
|
-
When asked to implement a feature or fix an issue:
|
|
193
|
-
|
|
194
|
-
1. **FIRST**: Read ALL relevant rules files (e.g., \`.cursor/rules/*.mdc\`, \`.clinerules\`, \`docs/AGENT_INSTRUCTIONS.md\`).
|
|
195
|
-
2. **NEVER** claim "done" until you can demonstrate the feature WORKS or the fix is verified.
|
|
196
|
-
3. **ALWAYS** run \`npx @rigour-labs/cli check\` before claiming completion.
|
|
197
|
-
4. **CONNECTivity**:
|
|
198
|
-
- If you create backend code, you MUST wire it to the frontend.
|
|
199
|
-
- If you create a service, you MUST connect it to the UI.
|
|
200
|
-
|
|
201
|
-
## ā
VERIFICATION PROOF REQUIRED
|
|
202
|
-
|
|
203
|
-
Before saying "done", show ONE of:
|
|
204
|
-
- Screenshot/output proving it works.
|
|
205
|
-
- The exact commands the user can run to verify.
|
|
206
|
-
- The full flow from initiation (e.g., button click) to result.
|
|
207
|
-
|
|
208
|
-
"Code exists" ā "Feature works"
|
|
209
|
-
`;
|
package/src/commands/explain.ts
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import fs from 'fs-extra';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import chalk from 'chalk';
|
|
4
|
-
|
|
5
|
-
export async function explainCommand(cwd: string) {
|
|
6
|
-
const configPath = path.join(cwd, 'rigour.yml');
|
|
7
|
-
let reportPath = path.join(cwd, 'rigour-report.json');
|
|
8
|
-
|
|
9
|
-
// Try to read custom path from config
|
|
10
|
-
if (await fs.pathExists(configPath)) {
|
|
11
|
-
try {
|
|
12
|
-
const yaml = await import('yaml');
|
|
13
|
-
const configContent = await fs.readFile(configPath, 'utf-8');
|
|
14
|
-
const config = yaml.parse(configContent);
|
|
15
|
-
if (config?.output?.report_path) {
|
|
16
|
-
reportPath = path.join(cwd, config.output.report_path);
|
|
17
|
-
}
|
|
18
|
-
} catch (e) { }
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
if (!(await fs.pathExists(reportPath))) {
|
|
22
|
-
console.error(chalk.red(`Error: No report found at ${reportPath}`));
|
|
23
|
-
console.error(chalk.dim('Run `rigour check` first to generate a report.'));
|
|
24
|
-
process.exit(2);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
try {
|
|
28
|
-
const reportContent = await fs.readFile(reportPath, 'utf-8');
|
|
29
|
-
const report = JSON.parse(reportContent);
|
|
30
|
-
|
|
31
|
-
console.log(chalk.bold('\nš Rigour Report Explanation\n'));
|
|
32
|
-
console.log(chalk.bold('Status: ') + (report.status === 'PASS'
|
|
33
|
-
? chalk.green.bold('ā
PASS')
|
|
34
|
-
: chalk.red.bold('š FAIL')));
|
|
35
|
-
|
|
36
|
-
console.log(chalk.bold('\nGate Summary:'));
|
|
37
|
-
for (const [gate, status] of Object.entries(report.summary || {})) {
|
|
38
|
-
const icon = status === 'PASS' ? 'ā
' : status === 'FAIL' ? 'ā' : 'āļø';
|
|
39
|
-
console.log(` ${icon} ${gate}: ${status}`);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
if (report.failures && report.failures.length > 0) {
|
|
43
|
-
console.log(chalk.bold.red(`\nš§ ${report.failures.length} Violation(s) to Fix:\n`));
|
|
44
|
-
|
|
45
|
-
report.failures.forEach((failure: any, index: number) => {
|
|
46
|
-
console.log(chalk.white(`${index + 1}. `) + chalk.bold.yellow(`[${failure.id.toUpperCase()}]`) + chalk.white(` ${failure.title}`));
|
|
47
|
-
console.log(chalk.dim(` āā ${failure.details}`));
|
|
48
|
-
if (failure.files && failure.files.length > 0) {
|
|
49
|
-
console.log(chalk.cyan(` š Files: ${failure.files.join(', ')}`));
|
|
50
|
-
}
|
|
51
|
-
if (failure.hint) {
|
|
52
|
-
console.log(chalk.green(` š” Hint: ${failure.hint}`));
|
|
53
|
-
}
|
|
54
|
-
console.log('');
|
|
55
|
-
});
|
|
56
|
-
} else if (report.status === 'PASS') {
|
|
57
|
-
console.log(chalk.green('\n⨠All quality gates passed! No violations found.\n'));
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (report.status === 'FAIL') {
|
|
61
|
-
console.log(chalk.bold('\nš Next Steps:'));
|
|
62
|
-
console.log(chalk.dim(' 1. Refactor the code to address the violations above.'));
|
|
63
|
-
console.log(chalk.dim(' 2. Run `rigour check` again to verify your fixes.'));
|
|
64
|
-
console.log(chalk.dim(' 3. If using an agent, pass it the violations as constraints.\n'));
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (report.stats) {
|
|
68
|
-
console.log(chalk.dim(`Duration: ${report.stats.duration_ms}ms`));
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
} catch (error: any) {
|
|
72
|
-
console.error(chalk.red(`Error reading report: ${error.message}`));
|
|
73
|
-
process.exit(3);
|
|
74
|
-
}
|
|
75
|
-
}
|
package/src/commands/guide.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
|
-
|
|
3
|
-
export async function guideCommand() {
|
|
4
|
-
console.log(chalk.bold.cyan('\nš”ļø Rigour Labs | The Engineering Guide\n'));
|
|
5
|
-
|
|
6
|
-
console.log(chalk.bold('Getting Started:'));
|
|
7
|
-
console.log(chalk.dim(' 1. Run ') + chalk.cyan('rigour init') + chalk.dim(' to detect your project role and apply standards.'));
|
|
8
|
-
console.log(chalk.dim(' 2. Run ') + chalk.cyan('rigour check') + chalk.dim(' to see existing violations.'));
|
|
9
|
-
console.log(chalk.dim(' 3. Run ') + chalk.cyan('rigour run -- <your-agent-command>') + chalk.dim(' to automate the fix loop.\n'));
|
|
10
|
-
|
|
11
|
-
console.log(chalk.bold('Key Concepts:'));
|
|
12
|
-
console.log(chalk.yellow(' ⢠Fix Packet v2') + chalk.dim(': Structured diagnostics fed directly into AI agents.'));
|
|
13
|
-
console.log(chalk.yellow(' ⢠Safety Rails') + chalk.dim(': Prevents "explosive" refactoring (max files changed).'));
|
|
14
|
-
console.log(chalk.yellow(' ⢠Strategic Guardians') + chalk.dim(': Dependency and Architectural boundary enforcement.\n'));
|
|
15
|
-
|
|
16
|
-
console.log(chalk.bold('Workflow Integration:'));
|
|
17
|
-
console.log(chalk.green(' ⢠Cursor') + chalk.dim(': Add the MCP server or use the ') + chalk.cyan('.cursor/rules/rigour.mdc') + chalk.dim(' handshake.'));
|
|
18
|
-
console.log(chalk.green(' ⢠CI/CD') + chalk.dim(': Use ') + chalk.cyan('rigour check --ci') + chalk.dim(' to fail PRs that violate quality gates.\n'));
|
|
19
|
-
|
|
20
|
-
console.log(chalk.dim('For more detailed docs, visit: ') + chalk.underline('https://github.com/erashu212/rigour/docs\n'));
|
|
21
|
-
}
|