delimit-cli 3.11.9 → 3.11.10

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.
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Delimit Security Skill for Codex CLI
4
+ *
5
+ * Validates that Codex-generated code doesn't introduce security anti-patterns.
6
+ * Runs as a security validation skill.
7
+ */
8
+
9
+ const fs = require('fs');
10
+ const path = require('path');
11
+
12
+ const SECURITY_PATTERNS = [
13
+ { pattern: /eval\s*\(/g, severity: 'high', message: 'eval() usage detected — potential code injection' },
14
+ { pattern: /exec\s*\(/g, severity: 'medium', message: 'exec() usage — verify input sanitization' },
15
+ { pattern: /shell\s*=\s*True/g, severity: 'high', message: 'subprocess with shell=True — command injection risk' },
16
+ { pattern: /dangerouslySetInnerHTML/g, severity: 'medium', message: 'dangerouslySetInnerHTML — XSS risk' },
17
+ { pattern: /password\s*=\s*["'][^"']+["']/gi, severity: 'high', message: 'Hardcoded password detected' },
18
+ { pattern: /api[_-]?key\s*=\s*["'][A-Za-z0-9]{10,}["']/gi, severity: 'high', message: 'Hardcoded API key detected' },
19
+ ];
20
+
21
+ function checkSecurity(context) {
22
+ const code = context.code || context.content || '';
23
+ if (!code) return { status: 'clean', findings: [] };
24
+
25
+ const findings = [];
26
+ for (const { pattern, severity, message } of SECURITY_PATTERNS) {
27
+ const matches = code.match(pattern);
28
+ if (matches) {
29
+ findings.push({ severity, message, count: matches.length });
30
+ }
31
+ }
32
+
33
+ // Audit
34
+ try {
35
+ const auditDir = path.join(process.env.HOME || '', '.delimit', 'audit');
36
+ fs.mkdirSync(auditDir, { recursive: true });
37
+ const record = {
38
+ timestamp: new Date().toISOString(),
39
+ source: 'codex-security',
40
+ findings_count: findings.length,
41
+ high_count: findings.filter(f => f.severity === 'high').length,
42
+ };
43
+ const auditFile = path.join(auditDir, `${new Date().toISOString().split('T')[0]}.jsonl`);
44
+ fs.appendFileSync(auditFile, JSON.stringify(record) + '\n');
45
+ } catch {}
46
+
47
+ const hasHigh = findings.some(f => f.severity === 'high');
48
+ return {
49
+ status: hasHigh ? 'flagged' : findings.length > 0 ? 'warnings' : 'clean',
50
+ findings,
51
+ };
52
+ }
53
+
54
+ const context = process.argv[2] ? JSON.parse(process.argv[2]) : {};
55
+ const result = checkSecurity(context);
56
+
57
+ if (result.status === 'flagged') {
58
+ for (const f of result.findings) {
59
+ console.error(`[Delimit Security] ${f.severity.toUpperCase()}: ${f.message}`);
60
+ }
61
+ process.exit(1);
62
+ }
63
+
64
+ process.exit(0);
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Delimit Governance Skill for Codex CLI
4
+ *
5
+ * Runs as a validation skill triggered on pre-code-generation and pre-suggestion.
6
+ * Checks governance state and policy compliance before Codex executes actions.
7
+ */
8
+
9
+ const fs = require('fs');
10
+ const path = require('path');
11
+
12
+ const DELIMIT_HOME = path.join(process.env.HOME || '', '.delimit');
13
+ const MODE_FILE = path.join(DELIMIT_HOME, 'enforcement_mode');
14
+
15
+ function getMode() {
16
+ try {
17
+ return fs.readFileSync(MODE_FILE, 'utf-8').trim();
18
+ } catch {
19
+ return 'guarded'; // Default
20
+ }
21
+ }
22
+
23
+ function checkGovernance(context) {
24
+ const mode = getMode();
25
+ const warnings = [];
26
+
27
+ // Check if governance is initialized
28
+ const policiesFile = path.join(process.cwd(), '.delimit', 'policies.yml');
29
+ if (!fs.existsSync(policiesFile)) {
30
+ warnings.push('No .delimit/policies.yml — run: delimit init');
31
+ }
32
+
33
+ // Check for sensitive file access
34
+ const sensitivePatterns = ['.env', 'credentials', '.ssh', 'secrets'];
35
+ const target = context.target || context.file || '';
36
+ for (const pattern of sensitivePatterns) {
37
+ if (target.includes(pattern)) {
38
+ if (mode === 'enforce') {
39
+ return { status: 'blocked', reason: `Access to sensitive path: ${target}` };
40
+ }
41
+ warnings.push(`Accessing sensitive path: ${target}`);
42
+ }
43
+ }
44
+
45
+ // Audit log
46
+ try {
47
+ const auditDir = path.join(DELIMIT_HOME, 'audit');
48
+ fs.mkdirSync(auditDir, { recursive: true });
49
+ const record = {
50
+ timestamp: new Date().toISOString(),
51
+ source: 'codex-skill',
52
+ mode,
53
+ context: typeof context === 'object' ? JSON.stringify(context).slice(0, 200) : String(context).slice(0, 200),
54
+ warnings,
55
+ };
56
+ const auditFile = path.join(auditDir, `${new Date().toISOString().split('T')[0]}.jsonl`);
57
+ fs.appendFileSync(auditFile, JSON.stringify(record) + '\n');
58
+ } catch {}
59
+
60
+ return { status: 'allowed', mode, warnings };
61
+ }
62
+
63
+ // Entry point — read context from stdin or args
64
+ const context = process.argv[2] ? JSON.parse(process.argv[2]) : {};
65
+ const result = checkGovernance(context);
66
+
67
+ if (result.status === 'blocked') {
68
+ console.error(`[Delimit] BLOCKED: ${result.reason}`);
69
+ process.exit(1);
70
+ }
71
+
72
+ if (result.warnings.length > 0) {
73
+ for (const w of result.warnings) {
74
+ console.error(`[Delimit] Warning: ${w}`);
75
+ }
76
+ }
77
+
78
+ process.exit(0);
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Delimit Governance Rules for Cursor
4
+ *
5
+ * Cursor doesn't have a hook system like Claude Code or Codex,
6
+ * so governance enforcement happens server-side via MCP tool calls.
7
+ * This adapter manages the .cursorrules and .cursor/rules/ files
8
+ * that guide Cursor's behavior.
9
+ */
10
+
11
+ const fs = require('fs');
12
+ const path = require('path');
13
+
14
+ const HOME = process.env.HOME || '';
15
+ const CURSOR_DIR = path.join(HOME, '.cursor');
16
+ const CURSOR_RULES_DIR = path.join(CURSOR_DIR, 'rules');
17
+ const CURSORRULES_FILE = path.join(HOME, '.cursorrules');
18
+
19
+ /**
20
+ * Install Delimit governance rules into Cursor.
21
+ * Creates both .cursorrules (legacy) and .cursor/rules/delimit.md (new).
22
+ */
23
+ function installRules(version) {
24
+ const rules = getDelimitRules(version);
25
+
26
+ // Install to .cursor/rules/delimit.md (new location, Cursor 0.45+)
27
+ if (fs.existsSync(CURSOR_DIR)) {
28
+ fs.mkdirSync(CURSOR_RULES_DIR, { recursive: true });
29
+ const rulesFile = path.join(CURSOR_RULES_DIR, 'delimit.md');
30
+ fs.writeFileSync(rulesFile, rules);
31
+ }
32
+
33
+ return { installed: true, paths: [CURSORRULES_FILE, path.join(CURSOR_RULES_DIR, 'delimit.md')] };
34
+ }
35
+
36
+ /**
37
+ * Remove Delimit rules from Cursor.
38
+ */
39
+ function uninstallRules() {
40
+ const removed = [];
41
+
42
+ // Remove from .cursor/rules/
43
+ const rulesFile = path.join(CURSOR_RULES_DIR, 'delimit.md');
44
+ if (fs.existsSync(rulesFile)) {
45
+ fs.unlinkSync(rulesFile);
46
+ removed.push(rulesFile);
47
+ }
48
+
49
+ return { removed };
50
+ }
51
+
52
+ function getDelimitRules(version) {
53
+ return `# Delimit Governance (v${version})
54
+
55
+ ## On every session start:
56
+ 1. Call \`delimit_ledger_context\` to check for open tasks
57
+ 2. Call \`delimit_gov_health\` to check governance status
58
+
59
+ ## After editing code:
60
+ - After editing UI/CSS: call \`delimit_design_validate_responsive\`
61
+ - After editing API specs: call \`delimit_lint\`
62
+ - After editing tests: call \`delimit_test_smoke\`
63
+
64
+ ## Before deploying:
65
+ 1. Call \`delimit_security_audit\`
66
+ 2. Call \`delimit_test_smoke\`
67
+ 3. Call \`delimit_deploy_plan\`
68
+
69
+ ## Before committing:
70
+ - Call \`delimit_repo_diagnose\` to check for common issues
71
+
72
+ ## Governance enforcement:
73
+ - All tool calls route through governance automatically (server-side)
74
+ - Critical actions are blocked until approved
75
+ - High-risk actions require approval in enforce mode
76
+ - Check mode: advisory (warn only), guarded (block critical), enforce (block critical + high-risk)
77
+
78
+ ## Links
79
+ - Docs: https://delimit.ai/docs
80
+ - GitHub: https://github.com/delimit-ai/delimit-mcp-server
81
+ `;
82
+ }
83
+
84
+ module.exports = { installRules, uninstallRules, getDelimitRules };
85
+
86
+ // CLI entry point
87
+ if (require.main === module) {
88
+ const action = process.argv[2] || 'install';
89
+ const version = process.argv[3] || '3.11.9';
90
+ if (action === 'install') {
91
+ const result = installRules(version);
92
+ console.log(`Installed Delimit rules to Cursor: ${result.paths.join(', ')}`);
93
+ } else if (action === 'uninstall') {
94
+ const result = uninstallRules();
95
+ console.log(`Removed: ${result.removed.join(', ') || 'nothing to remove'}`);
96
+ }
97
+ }
@@ -415,13 +415,23 @@ Run full governance compliance checks. Verify security, policy compliance, evide
415
415
  }
416
416
  }
417
417
 
418
- // Cursor rules
418
+ // Cursor rules (legacy .cursorrules + new .cursor/rules/ directory)
419
419
  const cursorRules = path.join(os.homedir(), '.cursorrules');
420
420
  if (fs.existsSync(path.join(os.homedir(), '.cursor'))) {
421
421
  const cursorResult = upsertDelimitSection(cursorRules);
422
422
  if (cursorResult.action !== 'unchanged') {
423
423
  log(` ${green('✓')} ${cursorResult.action === 'created' ? 'Created' : 'Updated'} ${cursorRules}`);
424
424
  }
425
+ // Also install to .cursor/rules/delimit.md (Cursor 0.45+)
426
+ try {
427
+ const cursorRulesDir = path.join(os.homedir(), '.cursor', 'rules');
428
+ fs.mkdirSync(cursorRulesDir, { recursive: true });
429
+ const cursorAdapter = require('../adapters/cursor-rules');
430
+ cursorAdapter.installRules(pkg.version);
431
+ log(` ${green('✓')} Installed governance rules to .cursor/rules/delimit.md`);
432
+ } catch (e) {
433
+ log(` ${dim(' Could not install .cursor/rules: ' + e.message)}`);
434
+ }
425
435
  }
426
436
 
427
437
  // Silent: auto-detect API keys and configure models.json (no output)
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "delimit-cli",
3
3
  "mcpName": "io.github.delimit-ai/delimit-mcp-server",
4
- "version": "3.11.9",
4
+ "version": "3.11.10",
5
5
  "description": "Unify Claude Code, Codex, Cursor, and Gemini CLI with persistent context, governance, and multi-model debate.",
6
6
  "main": "index.js",
7
7
  "files": [
8
8
  "bin/",
9
9
  "lib/",
10
+ "adapters/",
10
11
  "gateway/",
11
12
  "server.json",
12
13
  "README.md",