@rigour-labs/cli 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Rigour Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const commander_1 = require("commander");
5
+ const init_js_1 = require("./commands/init.js");
6
+ const check_js_1 = require("./commands/check.js");
7
+ const run_js_1 = require("./commands/run.js");
8
+ const program = new commander_1.Command();
9
+ program
10
+ .name('rigour')
11
+ .description('A quality gate loop controller for AI-assisted coding')
12
+ .version('1.0.0');
13
+ program
14
+ .command('init')
15
+ .description('Initialize VibeGuard in the current directory')
16
+ .action(async () => {
17
+ await (0, init_js_1.initCommand)(process.cwd());
18
+ });
19
+ program
20
+ .command('check')
21
+ .description('Run quality gate checks')
22
+ .action(async () => {
23
+ await (0, check_js_1.checkCommand)(process.cwd());
24
+ });
25
+ program
26
+ .command('run')
27
+ .description('Execute an agent command in a loop until quality gates pass')
28
+ .argument('[command...]', 'The agent command to run (e.g., cursor-agent ...)')
29
+ .option('-i, --iterations <number>', 'Maximum number of loop iterations', '3')
30
+ .action(async (args, options) => {
31
+ await (0, run_js_1.runLoop)(process.cwd(), args, { iterations: parseInt(options.iterations) });
32
+ });
33
+ program.parse();
@@ -0,0 +1 @@
1
+ export declare function checkCommand(cwd: string): Promise<void>;
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.checkCommand = checkCommand;
7
+ const fs_extra_1 = __importDefault(require("fs-extra"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const chalk_1 = __importDefault(require("chalk"));
10
+ const yaml_1 = __importDefault(require("yaml"));
11
+ const core_1 = require("@rigour-labs/core");
12
+ async function checkCommand(cwd) {
13
+ const configPath = path_1.default.join(cwd, 'rigour.yml');
14
+ if (!(await fs_extra_1.default.pathExists(configPath))) {
15
+ console.error(chalk_1.default.red('Error: rigour.yml not found. Run `rigour init` first.'));
16
+ process.exit(1);
17
+ }
18
+ const configContent = await fs_extra_1.default.readFile(configPath, 'utf-8');
19
+ const rawConfig = yaml_1.default.parse(configContent);
20
+ const config = core_1.ConfigSchema.parse(rawConfig);
21
+ console.log(chalk_1.default.blue('Running Rigour checks...\n'));
22
+ const runner = new core_1.GateRunner(config);
23
+ const report = await runner.run(cwd);
24
+ // Write machine report
25
+ const reportPath = path_1.default.join(cwd, config.output.report_path);
26
+ await fs_extra_1.default.writeJson(reportPath, report, { spaces: 2 });
27
+ // Print human summary
28
+ if (report.status === 'PASS') {
29
+ console.log(chalk_1.default.green.bold('✔ PASS - All quality gates satisfied.'));
30
+ }
31
+ else {
32
+ console.log(chalk_1.default.red.bold('✘ FAIL - Quality gate violations found.\n'));
33
+ for (const failure of report.failures) {
34
+ console.log(chalk_1.default.red(`[${failure.id}] ${failure.title}`));
35
+ console.log(chalk_1.default.dim(` Details: ${failure.details}`));
36
+ if (failure.files && failure.files.length > 0) {
37
+ console.log(chalk_1.default.dim(' Files:'));
38
+ failure.files.forEach((f) => console.log(chalk_1.default.dim(` - ${f}`)));
39
+ }
40
+ if (failure.hint) {
41
+ console.log(chalk_1.default.cyan(` Hint: ${failure.hint}`));
42
+ }
43
+ console.log('');
44
+ }
45
+ console.log(chalk_1.default.yellow(`See ${config.output.report_path} for full details.`));
46
+ }
47
+ console.log(chalk_1.default.dim(`\nFinished in ${report.stats.duration_ms}ms`));
48
+ if (report.status !== 'PASS') {
49
+ process.exit(1);
50
+ }
51
+ }
@@ -0,0 +1 @@
1
+ export declare function initCommand(cwd: string): Promise<void>;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.initCommand = initCommand;
7
+ const fs_extra_1 = __importDefault(require("fs-extra"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const chalk_1 = __importDefault(require("chalk"));
10
+ const yaml_1 = __importDefault(require("yaml"));
11
+ const core_1 = require("@rigour-labs/core");
12
+ async function initCommand(cwd) {
13
+ const discovery = new core_1.DiscoveryService();
14
+ const recommendedConfig = await discovery.discover(cwd);
15
+ const configPath = path_1.default.join(cwd, 'rigour.yml');
16
+ if (await fs_extra_1.default.pathExists(configPath)) {
17
+ console.log(chalk_1.default.yellow('rigour.yml already exists. Skipping initialization.'));
18
+ return;
19
+ }
20
+ await fs_extra_1.default.writeFile(configPath, yaml_1.default.stringify(recommendedConfig));
21
+ console.log(chalk_1.default.green('✔ Created rigour.yml'));
22
+ // Create required directories and files
23
+ const requireddocs = recommendedConfig.gates.required_files || [];
24
+ for (const file of requireddocs) {
25
+ const filePath = path_1.default.join(cwd, file);
26
+ if (!(await fs_extra_1.default.pathExists(filePath))) {
27
+ await fs_extra_1.default.ensureFile(filePath);
28
+ console.log(chalk_1.default.dim(` - Created ${file}`));
29
+ }
30
+ }
31
+ // Agent Handshake (Cursor/AntiGravity)
32
+ const cursorRulesDir = path_1.default.join(cwd, '.cursor', 'rules');
33
+ await fs_extra_1.default.ensureDir(cursorRulesDir);
34
+ const rulePath = path_1.default.join(cursorRulesDir, 'rigour.mdc');
35
+ const ruleContent = `---
36
+ description: Enforcement of Rigour quality gates and best practices.
37
+ globs: **/*
38
+ ---
39
+
40
+ # Rigour Enforcement
41
+
42
+ You are operating under Rigour engineering discipline.
43
+
44
+ ## Core Rules
45
+ - **Never claim done** until you run \`rigour check\` and it returns PASS.
46
+ - If checks FAIL, fix **only** the listed failures. Do not add new features or refactor unrelated code.
47
+ - Maintain project memory in \`docs/SPEC.md\`, \`docs/ARCH.md\`, and \`docs/DECISIONS.md\`.
48
+ - Keep files modular. If a file exceeds 500 lines, you MUST break it into smaller components.
49
+ - No \`TODO\` or \`FIXME\` comments allowed in the final submission.
50
+
51
+ ## Workflow
52
+ 1. Write/Modify code.
53
+ 2. Run \`rigour check\`.
54
+ 3. If FAIL: Read \`rigour-report.json\` for exact failure points and fix them.
55
+ 4. If PASS: You may claim task completion.
56
+ `;
57
+ await fs_extra_1.default.writeFile(rulePath, ruleContent);
58
+ console.log(chalk_1.default.green('✔ Initialized Agent Handshake (.cursor/rules/rigour.mdc)'));
59
+ console.log(chalk_1.default.blue('\nRigour is ready. Run `rigour check` to verify your project.'));
60
+ }
@@ -0,0 +1,3 @@
1
+ export declare function runLoop(cwd: string, agentArgs: string[], options: {
2
+ iterations: number;
3
+ }): Promise<void>;
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.runLoop = runLoop;
7
+ const fs_extra_1 = __importDefault(require("fs-extra"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const chalk_1 = __importDefault(require("chalk"));
10
+ const yaml_1 = __importDefault(require("yaml"));
11
+ const execa_1 = require("execa");
12
+ const core_1 = require("@rigour-labs/core");
13
+ async function runLoop(cwd, agentArgs, options) {
14
+ const configPath = path_1.default.join(cwd, 'rigour.yml');
15
+ if (!(await fs_extra_1.default.pathExists(configPath))) {
16
+ console.error(chalk_1.default.red('Error: rigour.yml not found. Run `rigour init` first.'));
17
+ process.exit(1);
18
+ }
19
+ try {
20
+ const configContent = await fs_extra_1.default.readFile(configPath, 'utf-8');
21
+ const rawConfig = yaml_1.default.parse(configContent);
22
+ const config = core_1.ConfigSchema.parse(rawConfig);
23
+ const runner = new core_1.GateRunner(config);
24
+ let iteration = 0;
25
+ const maxIterations = options.iterations;
26
+ while (iteration < maxIterations) {
27
+ iteration++;
28
+ console.log(chalk_1.default.bold.blue(`\n══════════════════════════════════════════════════════════════════`));
29
+ console.log(chalk_1.default.bold.blue(` RIGOUR LOOP: Iteration ${iteration}/${maxIterations}`));
30
+ console.log(chalk_1.default.bold.blue(`══════════════════════════════════════════════════════════════════`));
31
+ // 1. Run the agent command
32
+ if (agentArgs.length > 0) {
33
+ console.log(chalk_1.default.cyan(`\n🚀 DEPLOYING AGENT:`));
34
+ console.log(chalk_1.default.dim(` Command: ${agentArgs.join(' ')}`));
35
+ try {
36
+ await (0, execa_1.execa)(agentArgs[0], agentArgs.slice(1), { shell: true, stdio: 'inherit', cwd });
37
+ }
38
+ catch (error) {
39
+ console.warn(chalk_1.default.yellow(`\n⚠️ Agent command finished with non-zero exit code. Rigour will now verify state...`));
40
+ }
41
+ }
42
+ // 2. Run Rigour Check
43
+ console.log(chalk_1.default.magenta('\n🔍 AUDITING QUALITY GATES...'));
44
+ const report = await runner.run(cwd);
45
+ if (report.status === 'PASS') {
46
+ console.log(chalk_1.default.green.bold('\n✨ PASS - All quality gates satisfied.'));
47
+ console.log(chalk_1.default.green(` Your solution meets the required Engineering Rigour criteria.\n`));
48
+ return;
49
+ }
50
+ // 3. Generate and print Fix Packet for next iteration
51
+ console.log(chalk_1.default.red.bold(`\n🛑 FAIL - Found ${report.failures.length} engineering violations.`));
52
+ const fixPacket = report.failures.map((f, i) => {
53
+ let msg = chalk_1.default.white(`${i + 1}. `) + chalk_1.default.bold.red(`[${f.id.toUpperCase()}] `) + chalk_1.default.white(f.title);
54
+ msg += `\n ├─ ` + chalk_1.default.dim(`Details: ${f.details}`);
55
+ if (f.hint)
56
+ msg += `\n └─ ` + chalk_1.default.yellow(`FIX: ${f.hint}`);
57
+ return msg;
58
+ }).join('\n\n');
59
+ console.log(chalk_1.default.bold.white('\n📋 ACTIONABLE FIX PACKET:'));
60
+ console.log(fixPacket);
61
+ console.log(chalk_1.default.dim('\nReturning control to agent for the next refinement cycle...'));
62
+ if (iteration === maxIterations) {
63
+ console.log(chalk_1.default.red.bold(`\n❌ CRITICAL: Reached maximum iterations (${maxIterations}).`));
64
+ console.log(chalk_1.default.red(` Quality gates remain unfulfilled. Refactor manually or check agent logs.`));
65
+ process.exit(1);
66
+ }
67
+ }
68
+ }
69
+ catch (error) {
70
+ console.error(chalk_1.default.red(`\n❌ FATAL ERROR: ${error.message}`));
71
+ if (error.issues) {
72
+ console.error(chalk_1.default.dim(JSON.stringify(error.issues, null, 2)));
73
+ }
74
+ process.exit(1);
75
+ }
76
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ (0, vitest_1.describe)('CLI Smoke Test', () => {
5
+ (0, vitest_1.it)('should pass', async () => {
6
+ (0, vitest_1.expect)(true).toBe(true);
7
+ });
8
+ });
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@rigour-labs/cli",
3
+ "version": "1.0.0",
4
+ "bin": {
5
+ "rigour": "dist/cli.js"
6
+ },
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/erashu212/rigour"
10
+ },
11
+ "publishConfig": {
12
+ "access": "public",
13
+ "provenance": true
14
+ },
15
+ "dependencies": {
16
+ "chalk": "^5.3.0",
17
+ "commander": "^12.0.0",
18
+ "cosmiconfig": "^9.0.0",
19
+ "execa": "^8.0.1",
20
+ "fs-extra": "^11.2.0",
21
+ "globby": "^14.0.1",
22
+ "yaml": "^2.8.2",
23
+ "@rigour-labs/core": "1.0.0"
24
+ },
25
+ "devDependencies": {
26
+ "@types/fs-extra": "^11.0.4",
27
+ "@types/node": "^25.0.3"
28
+ },
29
+ "scripts": {
30
+ "build": "tsc",
31
+ "test": "vitest run"
32
+ }
33
+ }
package/src/cli.ts ADDED
@@ -0,0 +1,37 @@
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 { runLoop } from './commands/run.js';
6
+
7
+ const program = new Command();
8
+
9
+ program
10
+ .name('rigour')
11
+ .description('A quality gate loop controller for AI-assisted coding')
12
+ .version('1.0.0');
13
+
14
+ program
15
+ .command('init')
16
+ .description('Initialize VibeGuard in the current directory')
17
+ .action(async () => {
18
+ await initCommand(process.cwd());
19
+ });
20
+
21
+ program
22
+ .command('check')
23
+ .description('Run quality gate checks')
24
+ .action(async () => {
25
+ await checkCommand(process.cwd());
26
+ });
27
+
28
+ program
29
+ .command('run')
30
+ .description('Execute an agent command in a loop until quality gates pass')
31
+ .argument('[command...]', 'The agent command to run (e.g., cursor-agent ...)')
32
+ .option('-i, --iterations <number>', 'Maximum number of loop iterations', '3')
33
+ .action(async (args, options) => {
34
+ await runLoop(process.cwd(), args, { iterations: parseInt(options.iterations) });
35
+ });
36
+
37
+ program.parse();
@@ -0,0 +1,55 @@
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
+
7
+ export async function checkCommand(cwd: string) {
8
+ const configPath = path.join(cwd, 'rigour.yml');
9
+
10
+ if (!(await fs.pathExists(configPath))) {
11
+ console.error(chalk.red('Error: rigour.yml not found. Run `rigour init` first.'));
12
+ process.exit(1);
13
+ }
14
+
15
+ const configContent = await fs.readFile(configPath, 'utf-8');
16
+ const rawConfig = yaml.parse(configContent);
17
+ const config = ConfigSchema.parse(rawConfig);
18
+
19
+ console.log(chalk.blue('Running Rigour checks...\n'));
20
+
21
+ const runner = new GateRunner(config);
22
+ const report = await runner.run(cwd);
23
+
24
+ // Write machine report
25
+ const reportPath = path.join(cwd, config.output.report_path);
26
+ await fs.writeJson(reportPath, report, { spaces: 2 });
27
+
28
+ // Print human summary
29
+ if (report.status === 'PASS') {
30
+ console.log(chalk.green.bold('✔ PASS - All quality gates satisfied.'));
31
+ } else {
32
+ console.log(chalk.red.bold('✘ FAIL - Quality gate violations found.\n'));
33
+
34
+ for (const failure of report.failures as Failure[]) {
35
+ console.log(chalk.red(`[${failure.id}] ${failure.title}`));
36
+ console.log(chalk.dim(` Details: ${failure.details}`));
37
+ if (failure.files && failure.files.length > 0) {
38
+ console.log(chalk.dim(' Files:'));
39
+ failure.files.forEach((f: string) => console.log(chalk.dim(` - ${f}`)));
40
+ }
41
+ if (failure.hint) {
42
+ console.log(chalk.cyan(` Hint: ${failure.hint}`));
43
+ }
44
+ console.log('');
45
+ }
46
+
47
+ console.log(chalk.yellow(`See ${config.output.report_path} for full details.`));
48
+ }
49
+
50
+ console.log(chalk.dim(`\nFinished in ${report.stats.duration_ms}ms`));
51
+
52
+ if (report.status !== 'PASS') {
53
+ process.exit(1);
54
+ }
55
+ }
@@ -0,0 +1,63 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ import chalk from 'chalk';
4
+ import yaml from 'yaml';
5
+ import { DiscoveryService } from '@rigour-labs/core';
6
+
7
+ export async function initCommand(cwd: string) {
8
+ const discovery = new DiscoveryService();
9
+ const recommendedConfig = await discovery.discover(cwd);
10
+
11
+ const configPath = path.join(cwd, 'rigour.yml');
12
+
13
+ if (await fs.pathExists(configPath)) {
14
+ console.log(chalk.yellow('rigour.yml already exists. Skipping initialization.'));
15
+ return;
16
+ }
17
+
18
+ await fs.writeFile(configPath, yaml.stringify(recommendedConfig));
19
+ console.log(chalk.green('✔ Created rigour.yml'));
20
+
21
+ // Create required directories and files
22
+ const requireddocs = recommendedConfig.gates.required_files || [];
23
+ for (const file of requireddocs) {
24
+ const filePath = path.join(cwd, file);
25
+ if (!(await fs.pathExists(filePath))) {
26
+ await fs.ensureFile(filePath);
27
+ console.log(chalk.dim(` - Created ${file}`));
28
+ }
29
+ }
30
+
31
+ // Agent Handshake (Cursor/AntiGravity)
32
+ const cursorRulesDir = path.join(cwd, '.cursor', 'rules');
33
+ await fs.ensureDir(cursorRulesDir);
34
+ const rulePath = path.join(cursorRulesDir, 'rigour.mdc');
35
+
36
+ const ruleContent = `---
37
+ description: Enforcement of Rigour quality gates and best practices.
38
+ globs: **/*
39
+ ---
40
+
41
+ # Rigour Enforcement
42
+
43
+ You are operating under Rigour engineering discipline.
44
+
45
+ ## Core Rules
46
+ - **Never claim done** until you run \`rigour check\` and it returns PASS.
47
+ - If checks FAIL, fix **only** the listed failures. Do not add new features or refactor unrelated code.
48
+ - Maintain project memory in \`docs/SPEC.md\`, \`docs/ARCH.md\`, and \`docs/DECISIONS.md\`.
49
+ - Keep files modular. If a file exceeds 500 lines, you MUST break it into smaller components.
50
+ - No \`TODO\` or \`FIXME\` comments allowed in the final submission.
51
+
52
+ ## Workflow
53
+ 1. Write/Modify code.
54
+ 2. Run \`rigour check\`.
55
+ 3. If FAIL: Read \`rigour-report.json\` for exact failure points and fix them.
56
+ 4. If PASS: You may claim task completion.
57
+ `;
58
+
59
+ await fs.writeFile(rulePath, ruleContent);
60
+ console.log(chalk.green('✔ Initialized Agent Handshake (.cursor/rules/rigour.mdc)'));
61
+
62
+ console.log(chalk.blue('\nRigour is ready. Run `rigour check` to verify your project.'));
63
+ }
@@ -0,0 +1,79 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ import chalk from 'chalk';
4
+ import yaml from 'yaml';
5
+ import { execa } from 'execa';
6
+ import { GateRunner, ConfigSchema } from '@rigour-labs/core';
7
+
8
+ export async function runLoop(cwd: string, agentArgs: string[], options: { iterations: number }) {
9
+ const configPath = path.join(cwd, 'rigour.yml');
10
+
11
+ if (!(await fs.pathExists(configPath))) {
12
+ console.error(chalk.red('Error: rigour.yml not found. Run `rigour init` first.'));
13
+ process.exit(1);
14
+ }
15
+
16
+ try {
17
+ const configContent = await fs.readFile(configPath, 'utf-8');
18
+ const rawConfig = yaml.parse(configContent);
19
+ const config = ConfigSchema.parse(rawConfig);
20
+ const runner = new GateRunner(config);
21
+
22
+ let iteration = 0;
23
+ const maxIterations = options.iterations;
24
+
25
+ while (iteration < maxIterations) {
26
+ iteration++;
27
+ console.log(chalk.bold.blue(`\n══════════════════════════════════════════════════════════════════`));
28
+ console.log(chalk.bold.blue(` RIGOUR LOOP: Iteration ${iteration}/${maxIterations}`));
29
+ console.log(chalk.bold.blue(`══════════════════════════════════════════════════════════════════`));
30
+
31
+ // 1. Run the agent command
32
+ if (agentArgs.length > 0) {
33
+ console.log(chalk.cyan(`\n🚀 DEPLOYING AGENT:`));
34
+ console.log(chalk.dim(` Command: ${agentArgs.join(' ')}`));
35
+ try {
36
+ await execa(agentArgs[0], agentArgs.slice(1), { shell: true, stdio: 'inherit', cwd });
37
+ } catch (error: any) {
38
+ console.warn(chalk.yellow(`\n⚠️ Agent command finished with non-zero exit code. Rigour will now verify state...`));
39
+ }
40
+ }
41
+
42
+ // 2. Run Rigour Check
43
+ console.log(chalk.magenta('\n🔍 AUDITING QUALITY GATES...'));
44
+ const report = await runner.run(cwd);
45
+
46
+ if (report.status === 'PASS') {
47
+ console.log(chalk.green.bold('\n✨ PASS - All quality gates satisfied.'));
48
+ console.log(chalk.green(` Your solution meets the required Engineering Rigour criteria.\n`));
49
+ return;
50
+ }
51
+
52
+ // 3. Generate and print Fix Packet for next iteration
53
+ console.log(chalk.red.bold(`\n🛑 FAIL - Found ${report.failures.length} engineering violations.`));
54
+
55
+ const fixPacket = report.failures.map((f, i) => {
56
+ let msg = chalk.white(`${i + 1}. `) + chalk.bold.red(`[${f.id.toUpperCase()}] `) + chalk.white(f.title);
57
+ msg += `\n ├─ ` + chalk.dim(`Details: ${f.details}`);
58
+ if (f.hint) msg += `\n └─ ` + chalk.yellow(`FIX: ${f.hint}`);
59
+ return msg;
60
+ }).join('\n\n');
61
+
62
+ console.log(chalk.bold.white('\n📋 ACTIONABLE FIX PACKET:'));
63
+ console.log(fixPacket);
64
+ console.log(chalk.dim('\nReturning control to agent for the next refinement cycle...'));
65
+
66
+ if (iteration === maxIterations) {
67
+ console.log(chalk.red.bold(`\n❌ CRITICAL: Reached maximum iterations (${maxIterations}).`));
68
+ console.log(chalk.red(` Quality gates remain unfulfilled. Refactor manually or check agent logs.`));
69
+ process.exit(1);
70
+ }
71
+ }
72
+ } catch (error: any) {
73
+ console.error(chalk.red(`\n❌ FATAL ERROR: ${error.message}`));
74
+ if (error.issues) {
75
+ console.error(chalk.dim(JSON.stringify(error.issues, null, 2)));
76
+ }
77
+ process.exit(1);
78
+ }
79
+ }
@@ -0,0 +1,7 @@
1
+ import { describe, it, expect } from 'vitest';
2
+
3
+ describe('CLI Smoke Test', () => {
4
+ it('should pass', async () => {
5
+ expect(true).toBe(true);
6
+ });
7
+ });
@@ -0,0 +1,39 @@
1
+ ---
2
+ description: Engineering Rigour Protocol - Enforces high software standards (SOLID, DRY, Patterns) via automated quality gates.
3
+ globs: **/*
4
+ ---
5
+
6
+ # 🛡️ Rigour: Engineering Excellence Protocol
7
+
8
+ You are an Elite Software Engineer. You do not just write code that "works"; you write code that is **modular, maintainable, and rigorously verified.**
9
+
10
+ ## 🚦 The Rigour Loop (Mandatory)
11
+ Before claiming "Done" for any task, you MUST follow this loop:
12
+
13
+ 1. **Check**: Run `rigour_check_status` (via MCP) or `rigour check` (via CLI).
14
+ 2. **Analyze**: If it fails, run `rigour_get_fix_packet` to understand the engineering violations.
15
+ 3. **Refactor**: Apply **SOLID** and **DRY** principles to resolve the violations.
16
+ 4. **Repeat**: Continue until `rigour_check_status` returns **PASS**.
17
+
18
+ ## 🧩 Engineering Standards
19
+ Your code will be judged against these gates:
20
+
21
+ ### 1. SOLID Principles
22
+ - **Single Responsibility**: Keep files small and focused.
23
+ - **Open/Closed**: Design for extension, not modification.
24
+ - **Interface Segregation**: Don't force dependencies on unused methods.
25
+
26
+ ### 2. DRY (Don't Repeat Yourself)
27
+ - Extract common logic into utilities or shared services.
28
+ - If Rigour detects duplication, you must refactor immediately.
29
+
30
+ ### 3. "Done is Done"
31
+ - No `TODO` or `FIXME` comments are allowed in the final state.
32
+ - Every placeholder is a failure of rigour.
33
+
34
+ ## 🛠️ Tools at your disposal
35
+ - `rigour_check_status`: Get the current PASS/FAIL state.
36
+ - `rigour_get_fix_packet`: Get actionable instructions for failures.
37
+ - `rigour run "<command>"`: Use this CLI command to run yourself in a loop until you pass (Experimental).
38
+
39
+ **Remember:** Rigour is not just a tool; it is your engineering conscience. Hold yourself to the highest standard.
package/tsconfig.json ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "dist",
5
+ "rootDir": "src"
6
+ },
7
+ "include": [
8
+ "src/**/*"
9
+ ]
10
+ }