@rigour-labs/core 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 +21 -0
- package/dist/discovery.d.ts +5 -0
- package/dist/discovery.js +32 -0
- package/dist/gates/base.d.ts +11 -0
- package/dist/gates/base.js +21 -0
- package/dist/gates/content.d.ts +11 -0
- package/dist/gates/content.js +39 -0
- package/dist/gates/file.d.ts +10 -0
- package/dist/gates/file.js +30 -0
- package/dist/gates/runner.d.ts +13 -0
- package/dist/gates/runner.js +96 -0
- package/dist/gates/structure.d.ts +10 -0
- package/dist/gates/structure.js +32 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +21 -0
- package/dist/smoke.test.d.ts +1 -0
- package/dist/smoke.test.js +19 -0
- package/dist/templates/index.d.ts +8 -0
- package/dist/templates/index.js +70 -0
- package/dist/types/index.d.ts +199 -0
- package/dist/types/index.js +46 -0
- package/dist/utils/logger.d.ts +14 -0
- package/dist/utils/logger.js +44 -0
- package/dist/utils/scanner.d.ts +11 -0
- package/dist/utils/scanner.js +35 -0
- package/package.json +30 -0
- package/src/discovery.ts +30 -0
- package/src/gates/base.ts +21 -0
- package/src/gates/content.ts +47 -0
- package/src/gates/file.ts +38 -0
- package/src/gates/runner.ts +101 -0
- package/src/gates/structure.ts +36 -0
- package/src/index.ts +5 -0
- package/src/smoke.test.ts +18 -0
- package/src/templates/index.ts +76 -0
- package/src/types/index.ts +56 -0
- package/src/utils/logger.ts +43 -0
- package/src/utils/scanner.ts +37 -0
- package/tsconfig.json +10 -0
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.
|
|
@@ -0,0 +1,32 @@
|
|
|
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.DiscoveryService = void 0;
|
|
7
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const index_js_1 = require("./templates/index.js");
|
|
10
|
+
class DiscoveryService {
|
|
11
|
+
async discover(cwd) {
|
|
12
|
+
const config = { ...index_js_1.UNIVERSAL_CONFIG };
|
|
13
|
+
for (const template of index_js_1.TEMPLATES) {
|
|
14
|
+
const match = await this.hasAnyMarker(cwd, template.markers);
|
|
15
|
+
if (match) {
|
|
16
|
+
// Merge template config
|
|
17
|
+
config.commands = { ...config.commands, ...template.config.commands };
|
|
18
|
+
config.gates = { ...config.gates, ...template.config.gates };
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return config;
|
|
22
|
+
}
|
|
23
|
+
async hasAnyMarker(cwd, markers) {
|
|
24
|
+
for (const marker of markers) {
|
|
25
|
+
if (await fs_extra_1.default.pathExists(path_1.default.join(cwd, marker))) {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
exports.DiscoveryService = DiscoveryService;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Failure } from '../types/index.js';
|
|
2
|
+
export interface GateContext {
|
|
3
|
+
cwd: string;
|
|
4
|
+
}
|
|
5
|
+
export declare abstract class Gate {
|
|
6
|
+
readonly id: string;
|
|
7
|
+
readonly title: string;
|
|
8
|
+
constructor(id: string, title: string);
|
|
9
|
+
abstract run(context: GateContext): Promise<Failure[]>;
|
|
10
|
+
protected createFailure(details: string, files?: string[], hint?: string): Failure;
|
|
11
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Gate = void 0;
|
|
4
|
+
class Gate {
|
|
5
|
+
id;
|
|
6
|
+
title;
|
|
7
|
+
constructor(id, title) {
|
|
8
|
+
this.id = id;
|
|
9
|
+
this.title = title;
|
|
10
|
+
}
|
|
11
|
+
createFailure(details, files, hint) {
|
|
12
|
+
return {
|
|
13
|
+
id: this.id,
|
|
14
|
+
title: this.title,
|
|
15
|
+
details,
|
|
16
|
+
files,
|
|
17
|
+
hint,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
exports.Gate = Gate;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Gate, GateContext } from './base.js';
|
|
2
|
+
import { Failure } from '../types/index.js';
|
|
3
|
+
export interface ContentGateConfig {
|
|
4
|
+
forbidTodos: boolean;
|
|
5
|
+
forbidFixme: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare class ContentGate extends Gate {
|
|
8
|
+
private config;
|
|
9
|
+
constructor(config: ContentGateConfig);
|
|
10
|
+
run(context: GateContext): Promise<Failure[]>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ContentGate = void 0;
|
|
4
|
+
const base_js_1 = require("./base.js");
|
|
5
|
+
const scanner_js_1 = require("../utils/scanner.js");
|
|
6
|
+
class ContentGate extends base_js_1.Gate {
|
|
7
|
+
config;
|
|
8
|
+
constructor(config) {
|
|
9
|
+
super('content-check', 'Forbidden Content');
|
|
10
|
+
this.config = config;
|
|
11
|
+
}
|
|
12
|
+
async run(context) {
|
|
13
|
+
const patterns = [];
|
|
14
|
+
if (this.config.forbidTodos)
|
|
15
|
+
patterns.push(/TODO/i);
|
|
16
|
+
if (this.config.forbidFixme)
|
|
17
|
+
patterns.push(/FIXME/i);
|
|
18
|
+
if (patterns.length === 0)
|
|
19
|
+
return [];
|
|
20
|
+
const files = await scanner_js_1.FileScanner.findFiles({ cwd: context.cwd });
|
|
21
|
+
const contents = await scanner_js_1.FileScanner.readFiles(context.cwd, files);
|
|
22
|
+
const violations = [];
|
|
23
|
+
for (const [file, content] of contents) {
|
|
24
|
+
for (const pattern of patterns) {
|
|
25
|
+
if (pattern.test(content)) {
|
|
26
|
+
violations.push(file);
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (violations.length > 0) {
|
|
32
|
+
return [
|
|
33
|
+
this.createFailure('Forbidden placeholders found in the following files:', violations, 'Remove all TODO and FIXME comments. Use the "Done is Done" mentality—address the root cause or create a tracked issue.'),
|
|
34
|
+
];
|
|
35
|
+
}
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
exports.ContentGate = ContentGate;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Gate, GateContext } from './base.js';
|
|
2
|
+
import { Failure } from '../types/index.js';
|
|
3
|
+
export interface FileGateConfig {
|
|
4
|
+
maxLines: number;
|
|
5
|
+
}
|
|
6
|
+
export declare class FileGate extends Gate {
|
|
7
|
+
private config;
|
|
8
|
+
constructor(config: FileGateConfig);
|
|
9
|
+
run(context: GateContext): Promise<Failure[]>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FileGate = void 0;
|
|
4
|
+
const base_js_1 = require("./base.js");
|
|
5
|
+
const scanner_js_1 = require("../utils/scanner.js");
|
|
6
|
+
class FileGate extends base_js_1.Gate {
|
|
7
|
+
config;
|
|
8
|
+
constructor(config) {
|
|
9
|
+
super('file-size', 'File Size Limit');
|
|
10
|
+
this.config = config;
|
|
11
|
+
}
|
|
12
|
+
async run(context) {
|
|
13
|
+
const files = await scanner_js_1.FileScanner.findFiles({ cwd: context.cwd });
|
|
14
|
+
const contents = await scanner_js_1.FileScanner.readFiles(context.cwd, files);
|
|
15
|
+
const violations = [];
|
|
16
|
+
for (const [file, content] of contents) {
|
|
17
|
+
const lines = content.split('\n').length;
|
|
18
|
+
if (lines > this.config.maxLines) {
|
|
19
|
+
violations.push(`${file} (${lines} lines)`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
if (violations.length > 0) {
|
|
23
|
+
return [
|
|
24
|
+
this.createFailure(`The following files exceed the maximum limit of ${this.config.maxLines} lines:`, violations, 'Break these files into smaller, more modular components to improve maintainability (SOLID - Single Responsibility Principle).'),
|
|
25
|
+
];
|
|
26
|
+
}
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.FileGate = FileGate;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Gate } from './base.js';
|
|
2
|
+
import { Config, Report } from '../types/index.js';
|
|
3
|
+
export declare class GateRunner {
|
|
4
|
+
private config;
|
|
5
|
+
private gates;
|
|
6
|
+
constructor(config: Config);
|
|
7
|
+
private initializeGates;
|
|
8
|
+
/**
|
|
9
|
+
* Allows adding custom gates dynamically (SOLID - Open/Closed Principle)
|
|
10
|
+
*/
|
|
11
|
+
addGate(gate: Gate): void;
|
|
12
|
+
run(cwd: string): Promise<Report>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GateRunner = void 0;
|
|
4
|
+
const file_js_1 = require("./file.js");
|
|
5
|
+
const content_js_1 = require("./content.js");
|
|
6
|
+
const structure_js_1 = require("./structure.js");
|
|
7
|
+
const execa_1 = require("execa");
|
|
8
|
+
const logger_js_1 = require("../utils/logger.js");
|
|
9
|
+
class GateRunner {
|
|
10
|
+
config;
|
|
11
|
+
gates = [];
|
|
12
|
+
constructor(config) {
|
|
13
|
+
this.config = config;
|
|
14
|
+
this.initializeGates();
|
|
15
|
+
}
|
|
16
|
+
initializeGates() {
|
|
17
|
+
if (this.config.gates.max_file_lines) {
|
|
18
|
+
this.gates.push(new file_js_1.FileGate({ maxLines: this.config.gates.max_file_lines }));
|
|
19
|
+
}
|
|
20
|
+
this.gates.push(new content_js_1.ContentGate({
|
|
21
|
+
forbidTodos: !!this.config.gates.forbid_todos,
|
|
22
|
+
forbidFixme: !!this.config.gates.forbid_fixme,
|
|
23
|
+
}));
|
|
24
|
+
if (this.config.gates.required_files) {
|
|
25
|
+
this.gates.push(new structure_js_1.StructureGate({ requiredFiles: this.config.gates.required_files }));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Allows adding custom gates dynamically (SOLID - Open/Closed Principle)
|
|
30
|
+
*/
|
|
31
|
+
addGate(gate) {
|
|
32
|
+
this.gates.push(gate);
|
|
33
|
+
}
|
|
34
|
+
async run(cwd) {
|
|
35
|
+
const start = Date.now();
|
|
36
|
+
const failures = [];
|
|
37
|
+
const summary = {};
|
|
38
|
+
// 1. Run internal gates
|
|
39
|
+
for (const gate of this.gates) {
|
|
40
|
+
try {
|
|
41
|
+
const gateFailures = await gate.run({ cwd });
|
|
42
|
+
if (gateFailures.length > 0) {
|
|
43
|
+
failures.push(...gateFailures);
|
|
44
|
+
summary[gate.id] = 'FAIL';
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
summary[gate.id] = 'PASS';
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
logger_js_1.Logger.error(`Gate ${gate.id} failed with error: ${error.message}`);
|
|
52
|
+
summary[gate.id] = 'ERROR';
|
|
53
|
+
failures.push({
|
|
54
|
+
id: gate.id,
|
|
55
|
+
title: `Gate Error: ${gate.title}`,
|
|
56
|
+
details: error.message,
|
|
57
|
+
hint: 'There was an internal error running this gate. Check the logs.',
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// 2. Run command gates (lint, test, etc.)
|
|
62
|
+
const commands = this.config.commands;
|
|
63
|
+
if (commands) {
|
|
64
|
+
for (const [key, cmd] of Object.entries(commands)) {
|
|
65
|
+
if (!cmd) {
|
|
66
|
+
summary[key] = 'SKIP';
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
logger_js_1.Logger.info(`Running command gate: ${key} (${cmd})`);
|
|
71
|
+
await (0, execa_1.execa)(cmd, { shell: true, cwd });
|
|
72
|
+
summary[key] = 'PASS';
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
summary[key] = 'FAIL';
|
|
76
|
+
failures.push({
|
|
77
|
+
id: key,
|
|
78
|
+
title: `${key.toUpperCase()} Check Failed`,
|
|
79
|
+
details: error.stderr || error.stdout || error.message,
|
|
80
|
+
hint: `Fix the issues reported by \`${cmd}\`. Use rigorous standards (SOLID, DRY) in your resolution.`,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
const status = failures.length > 0 ? 'FAIL' : 'PASS';
|
|
86
|
+
return {
|
|
87
|
+
status,
|
|
88
|
+
summary,
|
|
89
|
+
failures,
|
|
90
|
+
stats: {
|
|
91
|
+
duration_ms: Date.now() - start,
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
exports.GateRunner = GateRunner;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Gate, GateContext } from './base.js';
|
|
2
|
+
import { Failure } from '../types/index.js';
|
|
3
|
+
export interface StructureGateConfig {
|
|
4
|
+
requiredFiles: string[];
|
|
5
|
+
}
|
|
6
|
+
export declare class StructureGate extends Gate {
|
|
7
|
+
private config;
|
|
8
|
+
constructor(config: StructureGateConfig);
|
|
9
|
+
run(context: GateContext): Promise<Failure[]>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
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.StructureGate = void 0;
|
|
7
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const base_js_1 = require("./base.js");
|
|
10
|
+
class StructureGate extends base_js_1.Gate {
|
|
11
|
+
config;
|
|
12
|
+
constructor(config) {
|
|
13
|
+
super('structure-check', 'Project Structure');
|
|
14
|
+
this.config = config;
|
|
15
|
+
}
|
|
16
|
+
async run(context) {
|
|
17
|
+
const missing = [];
|
|
18
|
+
for (const file of this.config.requiredFiles) {
|
|
19
|
+
const filePath = path_1.default.join(context.cwd, file);
|
|
20
|
+
if (!(await fs_extra_1.default.pathExists(filePath))) {
|
|
21
|
+
missing.push(file);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (missing.length > 0) {
|
|
25
|
+
return [
|
|
26
|
+
this.createFailure('The following required files are missing:', missing, 'Create these files to maintain project documentation and consistency.'),
|
|
27
|
+
];
|
|
28
|
+
}
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
exports.StructureGate = StructureGate;
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./types/index.js"), exports);
|
|
18
|
+
__exportStar(require("./gates/runner.js"), exports);
|
|
19
|
+
__exportStar(require("./discovery.js"), exports);
|
|
20
|
+
__exportStar(require("./templates/index.js"), exports);
|
|
21
|
+
__exportStar(require("./utils/logger.js"), exports);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const runner_js_1 = require("../src/gates/runner.js");
|
|
5
|
+
(0, vitest_1.describe)('GateRunner Smoke Test', () => {
|
|
6
|
+
(0, vitest_1.it)('should initialize with empty config', async () => {
|
|
7
|
+
const config = {
|
|
8
|
+
version: 1,
|
|
9
|
+
commands: {},
|
|
10
|
+
gates: {
|
|
11
|
+
max_file_lines: 500,
|
|
12
|
+
forbid_todos: true,
|
|
13
|
+
forbid_fixme: true,
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
const runner = new runner_js_1.GateRunner(config);
|
|
17
|
+
(0, vitest_1.expect)(runner).toBeDefined();
|
|
18
|
+
});
|
|
19
|
+
});
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UNIVERSAL_CONFIG = exports.TEMPLATES = void 0;
|
|
4
|
+
exports.TEMPLATES = [
|
|
5
|
+
{
|
|
6
|
+
name: 'Node.js',
|
|
7
|
+
markers: ['package.json'],
|
|
8
|
+
config: {
|
|
9
|
+
commands: {
|
|
10
|
+
lint: 'npm run lint',
|
|
11
|
+
test: 'npm test',
|
|
12
|
+
},
|
|
13
|
+
gates: {
|
|
14
|
+
max_file_lines: 500,
|
|
15
|
+
forbid_todos: true,
|
|
16
|
+
forbid_fixme: true,
|
|
17
|
+
forbid_paths: [],
|
|
18
|
+
required_files: ['docs/SPEC.md', 'docs/ARCH.md', 'README.md'],
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
name: 'Python',
|
|
24
|
+
markers: ['pyproject.toml', 'requirements.txt', 'setup.py'],
|
|
25
|
+
config: {
|
|
26
|
+
commands: {
|
|
27
|
+
lint: 'ruff check .',
|
|
28
|
+
test: 'pytest',
|
|
29
|
+
},
|
|
30
|
+
gates: {
|
|
31
|
+
max_file_lines: 500,
|
|
32
|
+
forbid_todos: true,
|
|
33
|
+
forbid_fixme: true,
|
|
34
|
+
forbid_paths: [],
|
|
35
|
+
required_files: ['docs/SPEC.md', 'docs/ARCH.md', 'README.md'],
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: 'Frontend (React/Vite/Next)',
|
|
41
|
+
markers: ['next.config.js', 'vite.config.ts', 'tailwind.config.js'],
|
|
42
|
+
config: {
|
|
43
|
+
commands: {
|
|
44
|
+
lint: 'npm run lint',
|
|
45
|
+
test: 'npm test',
|
|
46
|
+
},
|
|
47
|
+
gates: {
|
|
48
|
+
max_file_lines: 300, // Frontend files often should be smaller
|
|
49
|
+
forbid_todos: true,
|
|
50
|
+
forbid_fixme: true,
|
|
51
|
+
forbid_paths: [],
|
|
52
|
+
required_files: ['docs/SPEC.md', 'docs/ARCH.md', 'README.md'],
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
];
|
|
57
|
+
exports.UNIVERSAL_CONFIG = {
|
|
58
|
+
version: 1,
|
|
59
|
+
commands: {},
|
|
60
|
+
gates: {
|
|
61
|
+
max_file_lines: 500,
|
|
62
|
+
forbid_todos: true,
|
|
63
|
+
forbid_fixme: true,
|
|
64
|
+
forbid_paths: [],
|
|
65
|
+
required_files: ['docs/SPEC.md', 'docs/ARCH.md', 'docs/DECISIONS.md', 'docs/TASKS.md'],
|
|
66
|
+
},
|
|
67
|
+
output: {
|
|
68
|
+
report_path: 'rigour-report.json',
|
|
69
|
+
},
|
|
70
|
+
};
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const GatesSchema: z.ZodObject<{
|
|
3
|
+
max_file_lines: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
4
|
+
forbid_todos: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
5
|
+
forbid_fixme: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
6
|
+
forbid_paths: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
|
|
7
|
+
required_files: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
|
|
8
|
+
}, "strip", z.ZodTypeAny, {
|
|
9
|
+
max_file_lines: number;
|
|
10
|
+
forbid_todos: boolean;
|
|
11
|
+
forbid_fixme: boolean;
|
|
12
|
+
forbid_paths: string[];
|
|
13
|
+
required_files: string[];
|
|
14
|
+
}, {
|
|
15
|
+
max_file_lines?: number | undefined;
|
|
16
|
+
forbid_todos?: boolean | undefined;
|
|
17
|
+
forbid_fixme?: boolean | undefined;
|
|
18
|
+
forbid_paths?: string[] | undefined;
|
|
19
|
+
required_files?: string[] | undefined;
|
|
20
|
+
}>;
|
|
21
|
+
export declare const CommandsSchema: z.ZodObject<{
|
|
22
|
+
format: z.ZodOptional<z.ZodString>;
|
|
23
|
+
lint: z.ZodOptional<z.ZodString>;
|
|
24
|
+
typecheck: z.ZodOptional<z.ZodString>;
|
|
25
|
+
test: z.ZodOptional<z.ZodString>;
|
|
26
|
+
}, "strip", z.ZodTypeAny, {
|
|
27
|
+
format?: string | undefined;
|
|
28
|
+
lint?: string | undefined;
|
|
29
|
+
typecheck?: string | undefined;
|
|
30
|
+
test?: string | undefined;
|
|
31
|
+
}, {
|
|
32
|
+
format?: string | undefined;
|
|
33
|
+
lint?: string | undefined;
|
|
34
|
+
typecheck?: string | undefined;
|
|
35
|
+
test?: string | undefined;
|
|
36
|
+
}>;
|
|
37
|
+
export declare const ConfigSchema: z.ZodObject<{
|
|
38
|
+
version: z.ZodDefault<z.ZodNumber>;
|
|
39
|
+
commands: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
40
|
+
format: z.ZodOptional<z.ZodString>;
|
|
41
|
+
lint: z.ZodOptional<z.ZodString>;
|
|
42
|
+
typecheck: z.ZodOptional<z.ZodString>;
|
|
43
|
+
test: z.ZodOptional<z.ZodString>;
|
|
44
|
+
}, "strip", z.ZodTypeAny, {
|
|
45
|
+
format?: string | undefined;
|
|
46
|
+
lint?: string | undefined;
|
|
47
|
+
typecheck?: string | undefined;
|
|
48
|
+
test?: string | undefined;
|
|
49
|
+
}, {
|
|
50
|
+
format?: string | undefined;
|
|
51
|
+
lint?: string | undefined;
|
|
52
|
+
typecheck?: string | undefined;
|
|
53
|
+
test?: string | undefined;
|
|
54
|
+
}>>>;
|
|
55
|
+
gates: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
56
|
+
max_file_lines: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
57
|
+
forbid_todos: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
58
|
+
forbid_fixme: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
59
|
+
forbid_paths: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
|
|
60
|
+
required_files: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
|
|
61
|
+
}, "strip", z.ZodTypeAny, {
|
|
62
|
+
max_file_lines: number;
|
|
63
|
+
forbid_todos: boolean;
|
|
64
|
+
forbid_fixme: boolean;
|
|
65
|
+
forbid_paths: string[];
|
|
66
|
+
required_files: string[];
|
|
67
|
+
}, {
|
|
68
|
+
max_file_lines?: number | undefined;
|
|
69
|
+
forbid_todos?: boolean | undefined;
|
|
70
|
+
forbid_fixme?: boolean | undefined;
|
|
71
|
+
forbid_paths?: string[] | undefined;
|
|
72
|
+
required_files?: string[] | undefined;
|
|
73
|
+
}>>>;
|
|
74
|
+
output: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
75
|
+
report_path: z.ZodDefault<z.ZodString>;
|
|
76
|
+
}, "strip", z.ZodTypeAny, {
|
|
77
|
+
report_path: string;
|
|
78
|
+
}, {
|
|
79
|
+
report_path?: string | undefined;
|
|
80
|
+
}>>>;
|
|
81
|
+
}, "strip", z.ZodTypeAny, {
|
|
82
|
+
version: number;
|
|
83
|
+
commands: {
|
|
84
|
+
format?: string | undefined;
|
|
85
|
+
lint?: string | undefined;
|
|
86
|
+
typecheck?: string | undefined;
|
|
87
|
+
test?: string | undefined;
|
|
88
|
+
};
|
|
89
|
+
gates: {
|
|
90
|
+
max_file_lines: number;
|
|
91
|
+
forbid_todos: boolean;
|
|
92
|
+
forbid_fixme: boolean;
|
|
93
|
+
forbid_paths: string[];
|
|
94
|
+
required_files: string[];
|
|
95
|
+
};
|
|
96
|
+
output: {
|
|
97
|
+
report_path: string;
|
|
98
|
+
};
|
|
99
|
+
}, {
|
|
100
|
+
version?: number | undefined;
|
|
101
|
+
commands?: {
|
|
102
|
+
format?: string | undefined;
|
|
103
|
+
lint?: string | undefined;
|
|
104
|
+
typecheck?: string | undefined;
|
|
105
|
+
test?: string | undefined;
|
|
106
|
+
} | undefined;
|
|
107
|
+
gates?: {
|
|
108
|
+
max_file_lines?: number | undefined;
|
|
109
|
+
forbid_todos?: boolean | undefined;
|
|
110
|
+
forbid_fixme?: boolean | undefined;
|
|
111
|
+
forbid_paths?: string[] | undefined;
|
|
112
|
+
required_files?: string[] | undefined;
|
|
113
|
+
} | undefined;
|
|
114
|
+
output?: {
|
|
115
|
+
report_path?: string | undefined;
|
|
116
|
+
} | undefined;
|
|
117
|
+
}>;
|
|
118
|
+
export type Gates = z.infer<typeof GatesSchema>;
|
|
119
|
+
export type Commands = z.infer<typeof CommandsSchema>;
|
|
120
|
+
export type Config = z.infer<typeof ConfigSchema>;
|
|
121
|
+
export declare const StatusSchema: z.ZodEnum<["PASS", "FAIL", "SKIP", "ERROR"]>;
|
|
122
|
+
export type Status = z.infer<typeof StatusSchema>;
|
|
123
|
+
export declare const FailureSchema: z.ZodObject<{
|
|
124
|
+
id: z.ZodString;
|
|
125
|
+
title: z.ZodString;
|
|
126
|
+
details: z.ZodString;
|
|
127
|
+
files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
128
|
+
hint: z.ZodOptional<z.ZodString>;
|
|
129
|
+
}, "strip", z.ZodTypeAny, {
|
|
130
|
+
id: string;
|
|
131
|
+
title: string;
|
|
132
|
+
details: string;
|
|
133
|
+
files?: string[] | undefined;
|
|
134
|
+
hint?: string | undefined;
|
|
135
|
+
}, {
|
|
136
|
+
id: string;
|
|
137
|
+
title: string;
|
|
138
|
+
details: string;
|
|
139
|
+
files?: string[] | undefined;
|
|
140
|
+
hint?: string | undefined;
|
|
141
|
+
}>;
|
|
142
|
+
export type Failure = z.infer<typeof FailureSchema>;
|
|
143
|
+
export declare const ReportSchema: z.ZodObject<{
|
|
144
|
+
status: z.ZodEnum<["PASS", "FAIL", "SKIP", "ERROR"]>;
|
|
145
|
+
summary: z.ZodRecord<z.ZodString, z.ZodEnum<["PASS", "FAIL", "SKIP", "ERROR"]>>;
|
|
146
|
+
failures: z.ZodArray<z.ZodObject<{
|
|
147
|
+
id: z.ZodString;
|
|
148
|
+
title: z.ZodString;
|
|
149
|
+
details: z.ZodString;
|
|
150
|
+
files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
151
|
+
hint: z.ZodOptional<z.ZodString>;
|
|
152
|
+
}, "strip", z.ZodTypeAny, {
|
|
153
|
+
id: string;
|
|
154
|
+
title: string;
|
|
155
|
+
details: string;
|
|
156
|
+
files?: string[] | undefined;
|
|
157
|
+
hint?: string | undefined;
|
|
158
|
+
}, {
|
|
159
|
+
id: string;
|
|
160
|
+
title: string;
|
|
161
|
+
details: string;
|
|
162
|
+
files?: string[] | undefined;
|
|
163
|
+
hint?: string | undefined;
|
|
164
|
+
}>, "many">;
|
|
165
|
+
stats: z.ZodObject<{
|
|
166
|
+
duration_ms: z.ZodNumber;
|
|
167
|
+
}, "strip", z.ZodTypeAny, {
|
|
168
|
+
duration_ms: number;
|
|
169
|
+
}, {
|
|
170
|
+
duration_ms: number;
|
|
171
|
+
}>;
|
|
172
|
+
}, "strip", z.ZodTypeAny, {
|
|
173
|
+
status: "PASS" | "FAIL" | "SKIP" | "ERROR";
|
|
174
|
+
summary: Record<string, "PASS" | "FAIL" | "SKIP" | "ERROR">;
|
|
175
|
+
failures: {
|
|
176
|
+
id: string;
|
|
177
|
+
title: string;
|
|
178
|
+
details: string;
|
|
179
|
+
files?: string[] | undefined;
|
|
180
|
+
hint?: string | undefined;
|
|
181
|
+
}[];
|
|
182
|
+
stats: {
|
|
183
|
+
duration_ms: number;
|
|
184
|
+
};
|
|
185
|
+
}, {
|
|
186
|
+
status: "PASS" | "FAIL" | "SKIP" | "ERROR";
|
|
187
|
+
summary: Record<string, "PASS" | "FAIL" | "SKIP" | "ERROR">;
|
|
188
|
+
failures: {
|
|
189
|
+
id: string;
|
|
190
|
+
title: string;
|
|
191
|
+
details: string;
|
|
192
|
+
files?: string[] | undefined;
|
|
193
|
+
hint?: string | undefined;
|
|
194
|
+
}[];
|
|
195
|
+
stats: {
|
|
196
|
+
duration_ms: number;
|
|
197
|
+
};
|
|
198
|
+
}>;
|
|
199
|
+
export type Report = z.infer<typeof ReportSchema>;
|