@rigour-labs/cli 2.7.0 → 2.9.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.
@@ -1,3 +1,4 @@
1
1
  export declare const CODE_QUALITY_RULES = "\n# Code Quality Standards\n\n## PRODUCTION-GRADE CODE ONLY\n- No debug logging in production code\n- No shortcuts or \"temporary\" fixes\n- No over-engineering - simplest solution that works\n- Follow existing code patterns and conventions\n- Handle edge cases properly\n- No TODO/FIXME comments in final code\n\n## MODULAR CODE STRUCTURE\n- Write SMALL, focused functions (< 50 lines ideally)\n- One function = one job, clearly named\n- New features go in SEPARATE FILES, not flooding existing ones\n- Keep files under 500 lines - split if growing larger\n- Extract reusable logic into utility modules\n- Avoid \"god files\" that do everything\n- When adding to existing code, check if a new module is more appropriate\n\n## Technical Standards\n\n### DRY Principle\n- Extract repeated logic into utilities\n- Single Responsibility: One function, one job\n- Defensive coding: Validate inputs at boundaries\n- Lazy initialization for external dependencies (secrets, connections)\n- Graceful degradation over hard failures\n\n### File Organization\n```\n# Good: Separate concerns into focused files\ngovernor/\n main.py # Entry point only\n drift_detector.py # Drift detection logic\n lip_sync_analyzer.py # SyncNet integration\n audio_analyzer.py # Audio analysis\n\n# Bad: One massive file with everything\ngovernor/\n main.py (2000+ lines with all logic mixed)\n```\n\n### API Design\n- Consistent error responses\n- Proper HTTP status codes\n- Authentication at the edge\n- Rate limiting on public endpoints\n\n## PRODUCTION-READY SELF-REVIEW (THE GATEKEEPER)\n\nBefore asking for \"approval,\" internally verify:\n\n- **Zero-Dependency Check**: Does this fix rely on a local environment variable not yet in `talentlyt-kv`?\n- **Side-Effect Audit**: Could this change trigger a 502 Bad Gateway at the `/auth/callback` or `/api/agent` endpoints?\n- **Biometric Integrity**: If touching the `Governor`, have I verified that the `similarity_score` logic remains deterministic?\n- **Cost Impact**: Does this change increase egress costs (e.g., unnecessary cross-region logging)?\n- **Error Handling**: Does the UI have a graceful fallback if the backend service is slow?\n";
2
2
  export declare const DEBUGGING_RULES = "\n# Investigation & Debugging Protocol\n\n## INVESTIGATION PROTOCOL\n\nWhen debugging:\n1. Check DEPLOYED environment (Azure, prod), not localhost unless explicitly asked\n2. Trace the actual request flow end-to-end\n3. Collect evidence at each step\n4. Present findings before proposing fixes\n\n## GAP ANALYSIS\n\nWhen debugging or proposing changes:\n\n1. **Trace the actual request flow** end-to-end:\n - Client \u2192 Cloudflare \u2192 Vercel/Container App \u2192 DB\n\n2. **Identify Hidden Gaps** - Explicitly check if the change affects:\n - **Cross-Region Handshakes**: Will this increase latency for users in Pakistan/India?\n - **Forensic Continuity**: Does this change how Maya captures gaze or audio data?\n - **Auth Persistence**: Will this interfere with WorkOS session tokens or M2M keys?\n\n3. **Evidence-First**: Collect logs from `talentlyt-dashboard` before proposing a fix.\n\n## Request Flow Tracing\n\n```\nClient Browser\n \u2193\nCloudflare (CDN/WAF)\n \u2193\nAzure Container Apps\n \u251C\u2500\u2500 talentlyt-dashboard (Next.js)\n \u2514\u2500\u2500 talentlyt-agent (Python/LiveKit)\n \u2193\nPostgreSQL Database\n \u2193\nAzure Blob Storage (recordings, evidence)\n```\n\n## Evidence Collection\n\nBefore proposing any fix:\n1. Get the actual error from logs (not assumed)\n2. Identify the exact file and line number\n3. Trace the data flow that led to the error\n4. Verify the fix doesn't break other paths\n";
3
3
  export declare const COLLABORATION_RULES = "\n# Role & Collaboration\n\nYou are a Senior Staff Engineer working alongside a Principal Engineer (the user). \nYou do NOT work autonomously - you work collaboratively with approval at each step.\n\n## 1. NO ASSUMPTIONS\n- Never assume root cause without evidence from logs/code\n- Never assume a fix works without verification\n- Always trace the ACTUAL flow, not the expected flow\n- When debugging, read the DEPLOYED code, not local code\n\n## 2. APPROVAL REQUIRED\nBefore making ANY code change, you MUST:\n1. Show the evidence (logs, code trace) proving the issue\n2. Explain the root cause with proof\n3. Propose the fix with rationale\n4. Wait for explicit approval: \"approved\", \"go ahead\", \"do it\"\n\nException: Only proceed without approval if user explicitly says \"just do it\" or \"fix it\"\n\n## 3. NEVER LOSE TRACK\n- Maintain TODO list for multi-step tasks\n- Complete current task before starting new ones\n- If interrupted, summarize current state before switching\n- Reference previous findings, don't repeat investigations\n\n## Communication\n\n### When Reporting Issues\n```\n**Evidence:** [actual log/error message]\n**Location:** [file:line or endpoint]\n**Root Cause:** [proven, not assumed]\n**Privacy Impact:** [Does this affect biometric/PII data?]\n**Fix:** [proposed solution]\n```\n\n### When Asking for Approval\n```\nI found: [evidence]\nRoot cause: [explanation]\nProposed fix: [code change summary]\n\nApprove to proceed?\n```\n\n### When Stuck\n- Say \"I need more information\" not guess\n- Ask specific questions\n- Propose diagnostic steps\n\n## \u26A0\uFE0F RIGOUR.YML IS SACRED\n\nThe `rigour.yml` file represents **team-agreed quality standards**. You are FORBIDDEN from:\n\n1. \u274C Increasing thresholds to pass checks (e.g., raising `complexity: 100`)\n2. \u274C Adding patterns to `ignore:` to skip problematic files\n3. \u274C Removing items from `required_files`\n4. \u274C Disabling gates to avoid failures\n\n**Your job is to FIX THE CODE to meet the standards, NOT weaken the standards to pass the check.**\n\nIf thresholds genuinely need adjustment, escalate to the team lead with justification.\n\n## Forbidden Actions\n\n1. \u274C Making code changes without showing evidence first\n2. \u274C Testing on localhost when asked to check production\n3. \u274C Adding debug logs as a \"fix\"\n4. \u274C Multiple deployment attempts hoping it works\n5. \u274C Over-engineering simple solutions\n6. \u274C Assuming secrets/env vars are available at init time\n7. \u274C Ignoring user corrections\n8. \u274C Losing context between messages\n9. \u274C Modifying rigour.yml to pass quality checks\n";
4
+ export declare const AGNOSTIC_AI_INSTRUCTIONS = "\n# \uD83E\uDD16 CRITICAL INSTRUCTION FOR AI\n\nWhen asked to implement a feature or fix an issue:\n\n1. **FIRST**: Read ALL relevant rules files (e.g., `.cursor/rules/*.mdc`, `.clinerules`, `docs/AGENT_INSTRUCTIONS.md`).\n2. **NEVER** claim \"done\" until you can demonstrate the feature WORKS or the fix is verified.\n3. **ALWAYS** run `npx @rigour-labs/cli check` before claiming completion.\n4. **CONNECTivity**: \n - If you create backend code, you MUST wire it to the frontend.\n - If you create a service, you MUST connect it to the UI.\n\n## \u2705 VERIFICATION PROOF REQUIRED\n\nBefore saying \"done\", show ONE of:\n- Screenshot/output proving it works.\n- The exact commands the user can run to verify.\n- The full flow from initiation (e.g., button click) to result.\n\n\"Code exists\" \u2260 \"Feature works\"\n";
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.COLLABORATION_RULES = exports.DEBUGGING_RULES = exports.CODE_QUALITY_RULES = void 0;
3
+ exports.AGNOSTIC_AI_INSTRUCTIONS = exports.COLLABORATION_RULES = exports.DEBUGGING_RULES = exports.CODE_QUALITY_RULES = void 0;
4
4
  exports.CODE_QUALITY_RULES = `
5
5
  # Code Quality Standards
6
6
 
@@ -186,3 +186,24 @@ If thresholds genuinely need adjustment, escalate to the team lead with justific
186
186
  8. ❌ Losing context between messages
187
187
  9. ❌ Modifying rigour.yml to pass quality checks
188
188
  `;
189
+ exports.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
+ `;
@@ -1,7 +1,7 @@
1
1
  export interface InitOptions {
2
2
  preset?: string;
3
3
  paradigm?: string;
4
- ide?: 'cursor' | 'vscode' | 'all';
4
+ ide?: 'cursor' | 'vscode' | 'cline' | 'claude' | 'gemini' | 'codex' | 'windsurf' | 'all';
5
5
  dryRun?: boolean;
6
6
  explain?: boolean;
7
7
  }
@@ -11,6 +11,26 @@ const yaml_1 = __importDefault(require("yaml"));
11
11
  const core_1 = require("@rigour-labs/core");
12
12
  const constants_js_1 = require("./constants.js");
13
13
  function detectIDE(cwd) {
14
+ // Check for Claude Code markers
15
+ if (fs_extra_1.default.existsSync(path_1.default.join(cwd, 'CLAUDE.md')) || fs_extra_1.default.existsSync(path_1.default.join(cwd, '.claude'))) {
16
+ return 'claude';
17
+ }
18
+ // Check for Gemini Code Assist markers
19
+ if (fs_extra_1.default.existsSync(path_1.default.join(cwd, '.gemini'))) {
20
+ return 'gemini';
21
+ }
22
+ // Check for Codex/Aider AGENTS.md (universal standard)
23
+ if (fs_extra_1.default.existsSync(path_1.default.join(cwd, 'AGENTS.md'))) {
24
+ return 'codex';
25
+ }
26
+ // Check for Windsurf markers
27
+ if (fs_extra_1.default.existsSync(path_1.default.join(cwd, '.windsurfrules')) || fs_extra_1.default.existsSync(path_1.default.join(cwd, '.windsurf'))) {
28
+ return 'windsurf';
29
+ }
30
+ // Check for Cline-specific markers
31
+ if (fs_extra_1.default.existsSync(path_1.default.join(cwd, '.clinerules'))) {
32
+ return 'cline';
33
+ }
14
34
  // Check for Cursor-specific markers
15
35
  if (fs_extra_1.default.existsSync(path_1.default.join(cwd, '.cursor'))) {
16
36
  return 'cursor';
@@ -19,15 +39,27 @@ function detectIDE(cwd) {
19
39
  if (fs_extra_1.default.existsSync(path_1.default.join(cwd, '.vscode'))) {
20
40
  return 'vscode';
21
41
  }
22
- // Check environment variables that IDEs set
42
+ // Check environment variables that IDEs/Agents set
23
43
  const termProgram = process.env.TERM_PROGRAM || '';
24
44
  const terminal = process.env.TERMINAL_EMULATOR || '';
45
+ const appName = process.env.APP_NAME || '';
25
46
  if (termProgram.toLowerCase().includes('cursor') || terminal.toLowerCase().includes('cursor')) {
26
47
  return 'cursor';
27
48
  }
49
+ if (termProgram.toLowerCase().includes('cline') || appName.toLowerCase().includes('cline')) {
50
+ return 'cline';
51
+ }
28
52
  if (termProgram.toLowerCase().includes('vscode') || process.env.VSCODE_INJECTION) {
29
53
  return 'vscode';
30
54
  }
55
+ // Check for Claude Code environment
56
+ if (process.env.CLAUDE_CODE || process.env.ANTHROPIC_API_KEY) {
57
+ return 'claude';
58
+ }
59
+ // Check for Gemini environment
60
+ if (process.env.GEMINI_API_KEY || process.env.GOOGLE_CLOUD_PROJECT) {
61
+ return 'gemini';
62
+ }
31
63
  return 'unknown';
32
64
  }
33
65
  async function initCommand(cwd, options = {}) {
@@ -136,6 +168,7 @@ npx @rigour-labs/cli check
136
168
  npx @rigour-labs/cli run -- <agent-command>
137
169
  \`\`\`
138
170
 
171
+ ${constants_js_1.AGNOSTIC_AI_INSTRUCTIONS}
139
172
  ${constants_js_1.CODE_QUALITY_RULES}
140
173
 
141
174
  ${constants_js_1.DEBUGGING_RULES}
@@ -168,10 +201,104 @@ ${ruleContent}`;
168
201
  console.log(chalk_1.default.green('✔ Initialized Cursor Handshake (.cursor/rules/rigour.mdc)'));
169
202
  }
170
203
  }
171
- if (targetIDE === 'vscode') {
204
+ if (targetIDE === 'vscode' || targetIDE === 'all') {
172
205
  // VS Code users use the universal AGENT_INSTRUCTIONS.md (already created above)
206
+ // We could also add .vscode/settings.json or snippets here if needed
173
207
  console.log(chalk_1.default.green('✔ VS Code mode - using Universal Handshake (docs/AGENT_INSTRUCTIONS.md)'));
174
208
  }
209
+ if (targetIDE === 'cline' || targetIDE === 'all') {
210
+ const clineRulesPath = path_1.default.join(cwd, '.clinerules');
211
+ if (!(await fs_extra_1.default.pathExists(clineRulesPath))) {
212
+ await fs_extra_1.default.writeFile(clineRulesPath, ruleContent);
213
+ console.log(chalk_1.default.green('✔ Initialized Cline Handshake (.clinerules)'));
214
+ }
215
+ }
216
+ // Claude Code (CLAUDE.md)
217
+ if (targetIDE === 'claude' || targetIDE === 'all') {
218
+ const claudePath = path_1.default.join(cwd, 'CLAUDE.md');
219
+ const claudeContent = `# CLAUDE.md - Project Instructions for Claude Code
220
+
221
+ This file provides Claude Code with context about this project.
222
+
223
+ ## Project Overview
224
+
225
+ This project uses Rigour for quality gates. Always run \`npx @rigour-labs/cli check\` before marking tasks complete.
226
+
227
+ ## Commands
228
+
229
+ \`\`\`bash
230
+ # Verify quality gates
231
+ npx @rigour-labs/cli check
232
+
233
+ # Get fix packet for failures
234
+ npx @rigour-labs/cli explain
235
+
236
+ # Self-healing agent loop
237
+ npx @rigour-labs/cli run -- claude "<task>"
238
+ \`\`\`
239
+
240
+ ${ruleContent}`;
241
+ if (!(await fs_extra_1.default.pathExists(claudePath))) {
242
+ await fs_extra_1.default.writeFile(claudePath, claudeContent);
243
+ console.log(chalk_1.default.green('✔ Initialized Claude Code Handshake (CLAUDE.md)'));
244
+ }
245
+ }
246
+ // Gemini Code Assist (.gemini/styleguide.md)
247
+ if (targetIDE === 'gemini' || targetIDE === 'all') {
248
+ const geminiDir = path_1.default.join(cwd, '.gemini');
249
+ await fs_extra_1.default.ensureDir(geminiDir);
250
+ const geminiStylePath = path_1.default.join(geminiDir, 'styleguide.md');
251
+ const geminiContent = `# Gemini Code Assist Style Guide
252
+
253
+ This project uses Rigour for quality gates.
254
+
255
+ ## Required Before Completion
256
+
257
+ Always run \`npx @rigour-labs/cli check\` before marking any task complete.
258
+
259
+ ${ruleContent}`;
260
+ if (!(await fs_extra_1.default.pathExists(geminiStylePath))) {
261
+ await fs_extra_1.default.writeFile(geminiStylePath, geminiContent);
262
+ console.log(chalk_1.default.green('✔ Initialized Gemini Handshake (.gemini/styleguide.md)'));
263
+ }
264
+ }
265
+ // OpenAI Codex / Aider (AGENTS.md - Universal Standard)
266
+ if (targetIDE === 'codex' || targetIDE === 'all') {
267
+ const agentsPath = path_1.default.join(cwd, 'AGENTS.md');
268
+ const agentsContent = `# AGENTS.md - Universal AI Agent Instructions
269
+
270
+ This file provides instructions for AI coding agents (Codex, Aider, and others).
271
+
272
+ ## Setup
273
+
274
+ \`\`\`bash
275
+ npm install
276
+ npm run dev
277
+ npm test
278
+ \`\`\`
279
+
280
+ ## Quality Gates
281
+
282
+ This project uses Rigour. Before completing any task:
283
+
284
+ \`\`\`bash
285
+ npx @rigour-labs/cli check
286
+ \`\`\`
287
+
288
+ ${ruleContent}`;
289
+ if (!(await fs_extra_1.default.pathExists(agentsPath))) {
290
+ await fs_extra_1.default.writeFile(agentsPath, agentsContent);
291
+ console.log(chalk_1.default.green('✔ Initialized Universal Agent Handshake (AGENTS.md)'));
292
+ }
293
+ }
294
+ // Windsurf (.windsurfrules)
295
+ if (targetIDE === 'windsurf' || targetIDE === 'all') {
296
+ const windsurfPath = path_1.default.join(cwd, '.windsurfrules');
297
+ if (!(await fs_extra_1.default.pathExists(windsurfPath))) {
298
+ await fs_extra_1.default.writeFile(windsurfPath, ruleContent);
299
+ console.log(chalk_1.default.green('✔ Initialized Windsurf Handshake (.windsurfrules)'));
300
+ }
301
+ }
175
302
  // 3. Update .gitignore
176
303
  const gitignorePath = path_1.default.join(cwd, '.gitignore');
177
304
  const ignorePatterns = ['rigour-report.json', 'rigour-fix-packet.json', '.rigour/'];
@@ -15,23 +15,29 @@ const path_1 = __importDefault(require("path"));
15
15
  (0, vitest_1.afterEach)(async () => {
16
16
  await fs_extra_1.default.remove(testDir);
17
17
  });
18
- (0, vitest_1.it)('should create universal instructions and cursor rules on init', async () => {
19
- // Run init in test directory
20
- await (0, init_js_1.initCommand)(testDir);
18
+ (0, vitest_1.it)('should create instructions with agnostic rules and cursor rules on init', async () => {
19
+ // Run init in test directory with all IDEs to verify rules in both locations
20
+ await (0, init_js_1.initCommand)(testDir, { ide: 'all' });
21
21
  const instructionsPath = path_1.default.join(testDir, 'docs', 'AGENT_INSTRUCTIONS.md');
22
22
  const mdcPath = path_1.default.join(testDir, '.cursor', 'rules', 'rigour.mdc');
23
23
  (0, vitest_1.expect)(await fs_extra_1.default.pathExists(instructionsPath)).toBe(true);
24
24
  (0, vitest_1.expect)(await fs_extra_1.default.pathExists(mdcPath)).toBe(true);
25
25
  const instructionsContent = await fs_extra_1.default.readFile(instructionsPath, 'utf-8');
26
26
  const mdcContent = await fs_extra_1.default.readFile(mdcPath, 'utf-8');
27
+ // Check for agnostic instructions
28
+ (0, vitest_1.expect)(instructionsContent).toContain('# 🤖 CRITICAL INSTRUCTION FOR AI');
29
+ (0, vitest_1.expect)(instructionsContent).toContain('VERIFICATION PROOF REQUIRED');
27
30
  // Check for key sections in universal instructions
28
31
  (0, vitest_1.expect)(instructionsContent).toContain('# 🛡️ Rigour: Engineering Excellence Protocol');
29
32
  (0, vitest_1.expect)(instructionsContent).toContain('# Code Quality Standards');
30
- (0, vitest_1.expect)(instructionsContent).toContain('# Investigation & Debugging Protocol');
31
- (0, vitest_1.expect)(instructionsContent).toContain('# Role & Collaboration');
32
- // Check that MDC includes frontmatter and same rules
33
- (0, vitest_1.expect)(mdcContent).toContain('---');
34
- (0, vitest_1.expect)(mdcContent).toContain('description: Enforcement of Rigour quality gates and best practices.');
35
- (0, vitest_1.expect)(mdcContent).toContain('# Code Quality Standards');
33
+ // Check that MDC includes agnostic rules
34
+ (0, vitest_1.expect)(mdcContent).toContain('# 🤖 CRITICAL INSTRUCTION FOR AI');
35
+ });
36
+ (0, vitest_1.it)('should create .clinerules when ide is cline or all', async () => {
37
+ await (0, init_js_1.initCommand)(testDir, { ide: 'cline' });
38
+ const clineRulesPath = path_1.default.join(testDir, '.clinerules');
39
+ (0, vitest_1.expect)(await fs_extra_1.default.pathExists(clineRulesPath)).toBe(true);
40
+ const content = await fs_extra_1.default.readFile(clineRulesPath, 'utf-8');
41
+ (0, vitest_1.expect)(content).toContain('# 🤖 CRITICAL INSTRUCTION FOR AI');
36
42
  });
37
43
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rigour-labs/cli",
3
- "version": "2.7.0",
3
+ "version": "2.9.0",
4
4
  "bin": {
5
5
  "rigour": "dist/cli.js"
6
6
  },
@@ -21,7 +21,7 @@
21
21
  "globby": "^14.0.1",
22
22
  "inquirer": "9.2.16",
23
23
  "yaml": "^2.8.2",
24
- "@rigour-labs/core": "2.7.0"
24
+ "@rigour-labs/core": "2.9.0"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@types/fs-extra": "^11.0.4",
@@ -185,3 +185,25 @@ If thresholds genuinely need adjustment, escalate to the team lead with justific
185
185
  8. ❌ Losing context between messages
186
186
  9. ❌ Modifying rigour.yml to pass quality checks
187
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
+ `;
@@ -3,44 +3,85 @@ import path from 'path';
3
3
  import chalk from 'chalk';
4
4
  import yaml from 'yaml';
5
5
  import { DiscoveryService } from '@rigour-labs/core';
6
- import { CODE_QUALITY_RULES, DEBUGGING_RULES, COLLABORATION_RULES } from './constants.js';
6
+ import { CODE_QUALITY_RULES, DEBUGGING_RULES, COLLABORATION_RULES, AGNOSTIC_AI_INSTRUCTIONS } from './constants.js';
7
7
 
8
8
  export interface InitOptions {
9
9
  preset?: string;
10
10
  paradigm?: string;
11
- ide?: 'cursor' | 'vscode' | 'all';
11
+ ide?: 'cursor' | 'vscode' | 'cline' | 'claude' | 'gemini' | 'codex' | 'windsurf' | 'all';
12
12
  dryRun?: boolean;
13
13
  explain?: boolean;
14
14
  }
15
15
 
16
- type DetectedIDE = 'cursor' | 'vscode' | 'unknown';
16
+ type DetectedIDE = 'cursor' | 'vscode' | 'cline' | 'claude' | 'gemini' | 'codex' | 'windsurf' | 'unknown';
17
17
 
18
18
  function detectIDE(cwd: string): DetectedIDE {
19
+ // Check for Claude Code markers
20
+ if (fs.existsSync(path.join(cwd, 'CLAUDE.md')) || fs.existsSync(path.join(cwd, '.claude'))) {
21
+ return 'claude';
22
+ }
23
+
24
+ // Check for Gemini Code Assist markers
25
+ if (fs.existsSync(path.join(cwd, '.gemini'))) {
26
+ return 'gemini';
27
+ }
28
+
29
+ // Check for Codex/Aider AGENTS.md (universal standard)
30
+ if (fs.existsSync(path.join(cwd, 'AGENTS.md'))) {
31
+ return 'codex';
32
+ }
33
+
34
+ // Check for Windsurf markers
35
+ if (fs.existsSync(path.join(cwd, '.windsurfrules')) || fs.existsSync(path.join(cwd, '.windsurf'))) {
36
+ return 'windsurf';
37
+ }
38
+
39
+ // Check for Cline-specific markers
40
+ if (fs.existsSync(path.join(cwd, '.clinerules'))) {
41
+ return 'cline';
42
+ }
43
+
19
44
  // Check for Cursor-specific markers
20
45
  if (fs.existsSync(path.join(cwd, '.cursor'))) {
21
46
  return 'cursor';
22
47
  }
23
-
48
+
24
49
  // Check for VS Code markers
25
50
  if (fs.existsSync(path.join(cwd, '.vscode'))) {
26
51
  return 'vscode';
27
52
  }
28
-
29
- // Check environment variables that IDEs set
53
+
54
+ // Check environment variables that IDEs/Agents set
30
55
  const termProgram = process.env.TERM_PROGRAM || '';
31
56
  const terminal = process.env.TERMINAL_EMULATOR || '';
32
-
57
+ const appName = process.env.APP_NAME || '';
58
+
33
59
  if (termProgram.toLowerCase().includes('cursor') || terminal.toLowerCase().includes('cursor')) {
34
60
  return 'cursor';
35
61
  }
36
-
62
+
63
+ if (termProgram.toLowerCase().includes('cline') || appName.toLowerCase().includes('cline')) {
64
+ return 'cline';
65
+ }
66
+
37
67
  if (termProgram.toLowerCase().includes('vscode') || process.env.VSCODE_INJECTION) {
38
68
  return 'vscode';
39
69
  }
40
-
70
+
71
+ // Check for Claude Code environment
72
+ if (process.env.CLAUDE_CODE || process.env.ANTHROPIC_API_KEY) {
73
+ return 'claude';
74
+ }
75
+
76
+ // Check for Gemini environment
77
+ if (process.env.GEMINI_API_KEY || process.env.GOOGLE_CLOUD_PROJECT) {
78
+ return 'gemini';
79
+ }
80
+
41
81
  return 'unknown';
42
82
  }
43
83
 
84
+
44
85
  export async function initCommand(cwd: string, options: InitOptions = {}) {
45
86
  const discovery = new DiscoveryService();
46
87
  const result = await discovery.discover(cwd);
@@ -152,6 +193,7 @@ npx @rigour-labs/cli check
152
193
  npx @rigour-labs/cli run -- <agent-command>
153
194
  \`\`\`
154
195
 
196
+ ${AGNOSTIC_AI_INSTRUCTIONS}
155
197
  ${CODE_QUALITY_RULES}
156
198
 
157
199
  ${DEBUGGING_RULES}
@@ -168,11 +210,11 @@ ${COLLABORATION_RULES}
168
210
  // 2. Create IDE-Specific Rules based on detection or user preference
169
211
  const detectedIDE = detectIDE(cwd);
170
212
  const targetIDE = options.ide || (detectedIDE !== 'unknown' ? detectedIDE : 'all');
171
-
213
+
172
214
  if (detectedIDE !== 'unknown' && !options.ide) {
173
215
  console.log(chalk.dim(` (Auto-detected IDE: ${detectedIDE})`));
174
216
  }
175
-
217
+
176
218
  if (targetIDE === 'cursor' || targetIDE === 'all') {
177
219
  const cursorRulesDir = path.join(cwd, '.cursor', 'rules');
178
220
  await fs.ensureDir(cursorRulesDir);
@@ -189,12 +231,114 @@ ${ruleContent}`;
189
231
  console.log(chalk.green('✔ Initialized Cursor Handshake (.cursor/rules/rigour.mdc)'));
190
232
  }
191
233
  }
192
-
193
- if (targetIDE === 'vscode') {
234
+
235
+ if (targetIDE === 'vscode' || targetIDE === 'all') {
194
236
  // VS Code users use the universal AGENT_INSTRUCTIONS.md (already created above)
237
+ // We could also add .vscode/settings.json or snippets here if needed
195
238
  console.log(chalk.green('✔ VS Code mode - using Universal Handshake (docs/AGENT_INSTRUCTIONS.md)'));
196
239
  }
197
240
 
241
+ if (targetIDE === 'cline' || targetIDE === 'all') {
242
+ const clineRulesPath = path.join(cwd, '.clinerules');
243
+ if (!(await fs.pathExists(clineRulesPath))) {
244
+ await fs.writeFile(clineRulesPath, ruleContent);
245
+ console.log(chalk.green('✔ Initialized Cline Handshake (.clinerules)'));
246
+ }
247
+ }
248
+
249
+ // Claude Code (CLAUDE.md)
250
+ if (targetIDE === 'claude' || targetIDE === 'all') {
251
+ const claudePath = path.join(cwd, 'CLAUDE.md');
252
+ const claudeContent = `# CLAUDE.md - Project Instructions for Claude Code
253
+
254
+ This file provides Claude Code with context about this project.
255
+
256
+ ## Project Overview
257
+
258
+ This project uses Rigour for quality gates. Always run \`npx @rigour-labs/cli check\` before marking tasks complete.
259
+
260
+ ## Commands
261
+
262
+ \`\`\`bash
263
+ # Verify quality gates
264
+ npx @rigour-labs/cli check
265
+
266
+ # Get fix packet for failures
267
+ npx @rigour-labs/cli explain
268
+
269
+ # Self-healing agent loop
270
+ npx @rigour-labs/cli run -- claude "<task>"
271
+ \`\`\`
272
+
273
+ ${ruleContent}`;
274
+
275
+ if (!(await fs.pathExists(claudePath))) {
276
+ await fs.writeFile(claudePath, claudeContent);
277
+ console.log(chalk.green('✔ Initialized Claude Code Handshake (CLAUDE.md)'));
278
+ }
279
+ }
280
+
281
+ // Gemini Code Assist (.gemini/styleguide.md)
282
+ if (targetIDE === 'gemini' || targetIDE === 'all') {
283
+ const geminiDir = path.join(cwd, '.gemini');
284
+ await fs.ensureDir(geminiDir);
285
+ const geminiStylePath = path.join(geminiDir, 'styleguide.md');
286
+ const geminiContent = `# Gemini Code Assist Style Guide
287
+
288
+ This project uses Rigour for quality gates.
289
+
290
+ ## Required Before Completion
291
+
292
+ Always run \`npx @rigour-labs/cli check\` before marking any task complete.
293
+
294
+ ${ruleContent}`;
295
+
296
+ if (!(await fs.pathExists(geminiStylePath))) {
297
+ await fs.writeFile(geminiStylePath, geminiContent);
298
+ console.log(chalk.green('✔ Initialized Gemini Handshake (.gemini/styleguide.md)'));
299
+ }
300
+ }
301
+
302
+ // OpenAI Codex / Aider (AGENTS.md - Universal Standard)
303
+ if (targetIDE === 'codex' || targetIDE === 'all') {
304
+ const agentsPath = path.join(cwd, 'AGENTS.md');
305
+ const agentsContent = `# AGENTS.md - Universal AI Agent Instructions
306
+
307
+ This file provides instructions for AI coding agents (Codex, Aider, and others).
308
+
309
+ ## Setup
310
+
311
+ \`\`\`bash
312
+ npm install
313
+ npm run dev
314
+ npm test
315
+ \`\`\`
316
+
317
+ ## Quality Gates
318
+
319
+ This project uses Rigour. Before completing any task:
320
+
321
+ \`\`\`bash
322
+ npx @rigour-labs/cli check
323
+ \`\`\`
324
+
325
+ ${ruleContent}`;
326
+
327
+ if (!(await fs.pathExists(agentsPath))) {
328
+ await fs.writeFile(agentsPath, agentsContent);
329
+ console.log(chalk.green('✔ Initialized Universal Agent Handshake (AGENTS.md)'));
330
+ }
331
+ }
332
+
333
+ // Windsurf (.windsurfrules)
334
+ if (targetIDE === 'windsurf' || targetIDE === 'all') {
335
+ const windsurfPath = path.join(cwd, '.windsurfrules');
336
+ if (!(await fs.pathExists(windsurfPath))) {
337
+ await fs.writeFile(windsurfPath, ruleContent);
338
+ console.log(chalk.green('✔ Initialized Windsurf Handshake (.windsurfrules)'));
339
+ }
340
+ }
341
+
198
342
  // 3. Update .gitignore
199
343
  const gitignorePath = path.join(cwd, '.gitignore');
200
344
  const ignorePatterns = ['rigour-report.json', 'rigour-fix-packet.json', '.rigour/'];
@@ -14,9 +14,9 @@ describe('Init Command Rules Verification', () => {
14
14
  await fs.remove(testDir);
15
15
  });
16
16
 
17
- it('should create universal instructions and cursor rules on init', async () => {
18
- // Run init in test directory
19
- await initCommand(testDir);
17
+ it('should create instructions with agnostic rules and cursor rules on init', async () => {
18
+ // Run init in test directory with all IDEs to verify rules in both locations
19
+ await initCommand(testDir, { ide: 'all' });
20
20
 
21
21
  const instructionsPath = path.join(testDir, 'docs', 'AGENT_INSTRUCTIONS.md');
22
22
  const mdcPath = path.join(testDir, '.cursor', 'rules', 'rigour.mdc');
@@ -27,15 +27,25 @@ describe('Init Command Rules Verification', () => {
27
27
  const instructionsContent = await fs.readFile(instructionsPath, 'utf-8');
28
28
  const mdcContent = await fs.readFile(mdcPath, 'utf-8');
29
29
 
30
+ // Check for agnostic instructions
31
+ expect(instructionsContent).toContain('# 🤖 CRITICAL INSTRUCTION FOR AI');
32
+ expect(instructionsContent).toContain('VERIFICATION PROOF REQUIRED');
33
+
30
34
  // Check for key sections in universal instructions
31
35
  expect(instructionsContent).toContain('# 🛡️ Rigour: Engineering Excellence Protocol');
32
36
  expect(instructionsContent).toContain('# Code Quality Standards');
33
- expect(instructionsContent).toContain('# Investigation & Debugging Protocol');
34
- expect(instructionsContent).toContain('# Role & Collaboration');
35
37
 
36
- // Check that MDC includes frontmatter and same rules
37
- expect(mdcContent).toContain('---');
38
- expect(mdcContent).toContain('description: Enforcement of Rigour quality gates and best practices.');
39
- expect(mdcContent).toContain('# Code Quality Standards');
38
+ // Check that MDC includes agnostic rules
39
+ expect(mdcContent).toContain('# 🤖 CRITICAL INSTRUCTION FOR AI');
40
40
  });
41
+
42
+ it('should create .clinerules when ide is cline or all', async () => {
43
+ await initCommand(testDir, { ide: 'cline' });
44
+ const clineRulesPath = path.join(testDir, '.clinerules');
45
+ expect(await fs.pathExists(clineRulesPath)).toBe(true);
46
+
47
+ const content = await fs.readFile(clineRulesPath, 'utf-8');
48
+ expect(content).toContain('# 🤖 CRITICAL INSTRUCTION FOR AI');
49
+ });
50
+
41
51
  });