delimit-cli 4.5.1 → 4.5.3

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.
Files changed (55) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/README.md +15 -5
  3. package/bin/delimit-cli.js +109 -24
  4. package/gateway/ai/content_engine.py +3 -4
  5. package/gateway/ai/inbox_classifier.py +215 -0
  6. package/gateway/ai/integrations/opensage_wrapper.py +4 -1
  7. package/gateway/ai/ledger_manager.py +218 -38
  8. package/gateway/ai/license.py +26 -0
  9. package/gateway/ai/notify.py +68 -3
  10. package/gateway/ai/reddit_proxy.py +93 -15
  11. package/gateway/ai/reddit_scanner.py +36 -18
  12. package/gateway/ai/remote_resolve.py +422 -0
  13. package/gateway/ai/server.py +301 -117
  14. package/gateway/ai/social_capability/__init__.py +6 -0
  15. package/gateway/ai/social_capability/capability_validator.py +367 -0
  16. package/gateway/ai/social_capability/current_capabilities.yaml +95 -0
  17. package/gateway/ai/social_capability/fit_floor.py +360 -0
  18. package/gateway/ai/social_queue.py +307 -0
  19. package/gateway/ai/supabase_sync.py +14 -2
  20. package/gateway/ai/swarm.py +29 -11
  21. package/gateway/ai/tui.py +6 -2
  22. package/gateway/ai/vendor_news/__init__.py +14 -0
  23. package/gateway/ai/vendor_news/drafter.py +562 -0
  24. package/gateway/ai/vendor_news/sensor.py +509 -0
  25. package/gateway/ai/vendor_news/watchlist.yaml +71 -0
  26. package/gateway/ai/x_ranker.py +417 -0
  27. package/lib/attest-mcp.js +487 -0
  28. package/lib/attest-telemetry.js +48 -0
  29. package/lib/delimit-home.js +35 -0
  30. package/lib/delimit-template.js +14 -0
  31. package/package.json +25 -3
  32. package/scripts/postinstall.js +89 -40
  33. package/adapters/codex-security.js +0 -64
  34. package/adapters/codex-skill.js +0 -78
  35. package/gateway/ai/content_grounding/__init__.py +0 -98
  36. package/gateway/ai/content_grounding/build.py +0 -350
  37. package/gateway/ai/content_grounding/consume.py +0 -280
  38. package/gateway/ai/content_grounding/features.py +0 -218
  39. package/gateway/ai/content_grounding/fixtures/fail/01_missing_evidence.json +0 -9
  40. package/gateway/ai/content_grounding/fixtures/fail/02_unknown_evidence_prefix.json +0 -9
  41. package/gateway/ai/content_grounding/fixtures/fail/03_banned_comparative.json +0 -17
  42. package/gateway/ai/content_grounding/fixtures/fail/04_banned_adoption.json +0 -17
  43. package/gateway/ai/content_grounding/fixtures/fail/05_aggregate_no_numeric.json +0 -17
  44. package/gateway/ai/content_grounding/fixtures/fail/06_unversioned_inference_rule.json +0 -18
  45. package/gateway/ai/content_grounding/fixtures/pass/01_feature_shipped.json +0 -18
  46. package/gateway/ai/content_grounding/fixtures/pass/02_aggregate_claim.json +0 -23
  47. package/gateway/ai/content_grounding/fixtures/pass/03_attestation.json +0 -16
  48. package/gateway/ai/content_grounding/schemas/claim.schema.json +0 -40
  49. package/gateway/ai/content_grounding/schemas/event.schema.json +0 -23
  50. package/gateway/ai/content_grounding/schemas.py +0 -276
  51. package/gateway/ai/content_grounding/telemetry.py +0 -221
  52. package/gateway/ai/inbox_drafts/__init__.py +0 -61
  53. package/gateway/ai/inbox_drafts/registry.py +0 -412
  54. package/gateway/ai/inbox_drafts/schema.py +0 -374
  55. package/gateway/ai/inbox_executor.py +0 -565
@@ -1,47 +1,96 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
3
  * Postinstall — anonymous install ping + setup hint.
4
+ *
5
+ * v4.5.2 (LED-1188) install hardening:
6
+ * - Top-level try/catch ensures NO postinstall failure can ever block
7
+ * `npm install delimit-cli`. Per the customer-protection rule in
8
+ * /root/.claude/CLAUDE.md, npm publish is a production deploy and a
9
+ * postinstall crash on a Pro user's machine is a customer-facing
10
+ * incident regardless of root cause.
11
+ * - EROFS / EACCES / EPERM / ENOSPC / ENOENT on stdout writes soft-fail
12
+ * silently. (Some sandbox installers redirect stdout to a read-only
13
+ * pipe.)
14
+ * - Network telemetry stays best-effort; no crash if DNS / TLS / proxy
15
+ * misbehaves. DELIMIT_NO_TELEMETRY=1 honored as kill switch.
16
+ * - Idempotent — re-running install is a no-op, never corrupts state.
17
+ * This file does not write to ~/.delimit/; that's bin/delimit-setup.js.
18
+ *
4
19
  * No PII. Silent fail. Never blocks install.
5
20
  */
6
21
 
7
- // Print setup hint with quick start
8
- const v = require('../package.json').version;
9
- console.log('');
10
- console.log(' \x1b[1m\x1b[35mDelimit\x1b[0m v' + v + ' installed');
11
- console.log('');
12
- console.log(' Quick start:');
13
- console.log(' \x1b[32mdelimit doctor\x1b[0m Check your setup, fix what\'s missing');
14
- console.log(' \x1b[32mdelimit simulate\x1b[0m Dry-run: see what governance would block');
15
- console.log(' \x1b[32mdelimit status\x1b[0m Visual dashboard of your governance posture');
16
- console.log(' \x1b[32mdelimit setup\x1b[0m Install MCP governance for AI assistants');
17
- console.log('');
18
- console.log(' Docs: \x1b[36mhttps://delimit.ai/docs\x1b[0m');
19
- console.log(' Star us: \x1b[36mhttps://github.com/delimit-ai/delimit-mcp-server\x1b[0m');
20
- console.log('');
22
+ (function postinstall() {
23
+ 'use strict';
21
24
 
22
- // Anonymous telemetry ping no PII, just "someone installed"
23
- try {
24
- const https = require('https');
25
- const data = JSON.stringify({
26
- event: 'install',
27
- version: require('../package.json').version,
28
- node: process.version,
29
- platform: process.platform,
30
- arch: process.arch,
31
- ts: new Date().toISOString()
32
- });
33
- const req = https.request({
34
- hostname: 'delimit.ai',
35
- path: '/api/telemetry',
36
- method: 'POST',
37
- headers: {
38
- 'Content-Type': 'application/json',
39
- 'Content-Length': Buffer.byteLength(data)
40
- },
41
- timeout: 3000
42
- });
43
- req.on('error', () => {}); // silent fail
44
- req.on('timeout', () => { req.destroy(); });
45
- req.write(data);
46
- req.end();
47
- } catch (e) { /* silent fail */ }
25
+ // --- 1. setup hint ------------------------------------------------------
26
+ // Wrapped in try/catch because console.log can throw on EPIPE / EBADF
27
+ // when the parent npm process closed stdout early.
28
+ let pkg;
29
+ try {
30
+ pkg = require('../package.json');
31
+ } catch (e) {
32
+ // package.json missing or unreadable — nothing to print, nothing
33
+ // to ping. This is a partial-install state; let the install
34
+ // complete so `delimit doctor` can diagnose later.
35
+ return;
36
+ }
37
+ const v = (pkg && pkg.version) || '?';
38
+
39
+ function safeLog(msg) {
40
+ try { process.stdout.write(msg + '\n'); }
41
+ catch (_) { /* EPIPE / EBADF / EROFS on stdout — give up silently */ }
42
+ }
43
+
44
+ try {
45
+ safeLog('');
46
+ safeLog(' \x1b[1m\x1b[35mDelimit\x1b[0m v' + v + ' installed');
47
+ safeLog('');
48
+ safeLog(' Quick start:');
49
+ safeLog(' \x1b[32mdelimit doctor\x1b[0m Check your setup, fix what\'s missing');
50
+ safeLog(' \x1b[32mdelimit simulate\x1b[0m Dry-run: see what governance would block');
51
+ safeLog(' \x1b[32mdelimit status\x1b[0m Visual dashboard of your governance posture');
52
+ safeLog(' \x1b[32mdelimit setup\x1b[0m Install MCP governance for AI assistants');
53
+ safeLog('');
54
+ safeLog(' Docs: \x1b[36mhttps://delimit.ai/docs\x1b[0m');
55
+ safeLog(' Star us: \x1b[36mhttps://github.com/delimit-ai/delimit-mcp-server\x1b[0m');
56
+ safeLog('');
57
+ } catch (_) { /* never block install on a print failure */ }
58
+
59
+ // --- 2. anonymous install telemetry ------------------------------------
60
+ // Honor opt-out and corporate proxy environments. The HTTPS request is
61
+ // silent-fail at every level (DNS / TCP / TLS / write / response).
62
+ const tele = (process.env.DELIMIT_NO_TELEMETRY || '').toLowerCase();
63
+ if (tele === '1' || tele === 'true' || tele === 'yes') return;
64
+
65
+ try {
66
+ const https = require('https');
67
+ const data = JSON.stringify({
68
+ event: 'install',
69
+ version: v,
70
+ node: process.version,
71
+ platform: process.platform,
72
+ arch: process.arch,
73
+ ts: new Date().toISOString()
74
+ });
75
+ const req = https.request({
76
+ hostname: 'delimit.ai',
77
+ path: '/api/telemetry',
78
+ method: 'POST',
79
+ headers: {
80
+ 'Content-Type': 'application/json',
81
+ 'Content-Length': Buffer.byteLength(data)
82
+ },
83
+ timeout: 3000
84
+ });
85
+ // Catch every error class: ENOTFOUND, ECONNREFUSED, ETIMEDOUT,
86
+ // CERT_HAS_EXPIRED, EPROTO, etc. None should ever propagate.
87
+ req.on('error', () => {});
88
+ req.on('timeout', () => { try { req.destroy(); } catch (_) {} });
89
+ req.write(data);
90
+ req.end();
91
+ } catch (_) { /* silent fail — never block install */ }
92
+ })();
93
+
94
+ // Outermost guard: even if the IIFE above throws synchronously somehow
95
+ // (require() race, V8 bug, etc), don't propagate a non-zero exit code.
96
+ process.on('uncaughtException', () => { /* swallow */ });
@@ -1,64 +0,0 @@
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' }, // nosec B-eval_usage: regex-pattern DEFINITION string for security scanner
14
- { pattern: /exec\s*\(/g, severity: 'medium', message: 'exec() usage — verify input sanitization' }, // nosec B-exec_usage: regex-pattern DEFINITION string for security scanner
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' }, // nosec B-dangerous_innerHTML: regex-pattern DEFINITION string
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);
@@ -1,78 +0,0 @@
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);
@@ -1,98 +0,0 @@
1
- """
2
- Delimit content grounding layer — LED-1084 Week 1.
3
-
4
- Purpose: normalize ledger entries, attestations, and git history into
5
- evidence-backed `GroundedEvent` records with typed atomic `Claim`s.
6
- Every downstream generator (blog, social drafter, storyline) consumes
7
- this layer and MUST NOT fabricate claims that aren't backed by an
8
- evidence_ref.
9
-
10
- Architectural amendments (per 2026-04-24 adversarial rebuttal,
11
- /home/delimit/delimit-private/strategy/CONTENT_GROUNDING_REBUTTAL_2026_04.md):
12
-
13
- A3. Week 1 is strictly NON-PUBLISHING. Publish endpoints are
14
- hard-disabled at the code level (see `_PUBLISH_DISABLED` below).
15
- A5. Claims are typed atomic objects with explicit evidence_refs,
16
- visibility, and optional versioned inference_rule.
17
- A6. Hard bans during Week 1/2: comparative, adoption, customer,
18
- aggregate, roadmap claims reject unless exact text whitelisted
19
- or (for aggregates) backed by structured numeric evidence.
20
- A9. Deterministic extraction gate: extract → classify → map to
21
- allowed claim IDs → reject on any unmatched/uncertain claim →
22
- persist audit record. All content passes through this gate.
23
- A10. One-strike kill semantics: any externally published ungrounded
24
- claim reverts ALL generators to manual-only mode.
25
-
26
- This module never generates public content. It only produces the
27
- grounded event + claim records that generators consume.
28
- """
29
- from .schemas import (
30
- ClaimType,
31
- Visibility,
32
- EventType,
33
- EvidenceRef,
34
- Claim,
35
- GroundedEvent,
36
- GroundingIndex,
37
- )
38
- from .build import (
39
- build_grounding_index,
40
- load_grounded_events,
41
- validate_claims,
42
- persist_grounding_index,
43
- )
44
- from .consume import (
45
- GroundingBundle,
46
- fetch_grounding_bundle,
47
- build_allowed_claim_set,
48
- load_feature_whitelist,
49
- unreleased_feature_detector,
50
- score_draft_grounding,
51
- )
52
- from .features import (
53
- build_feature_set,
54
- build_and_persist_features,
55
- extract_mcp_tools,
56
- extract_cli_commands,
57
- )
58
- from .telemetry import (
59
- summarize as summarize_gate_telemetry,
60
- recent_samples as recent_gate_samples,
61
- )
62
-
63
- __all__ = [
64
- # schemas
65
- "ClaimType",
66
- "Visibility",
67
- "EventType",
68
- "EvidenceRef",
69
- "Claim",
70
- "GroundedEvent",
71
- "GroundingIndex",
72
- # build
73
- "build_grounding_index",
74
- "load_grounded_events",
75
- "validate_claims",
76
- "persist_grounding_index",
77
- # consume (Week 2)
78
- "GroundingBundle",
79
- "fetch_grounding_bundle",
80
- "build_allowed_claim_set",
81
- "load_feature_whitelist",
82
- "unreleased_feature_detector",
83
- "score_draft_grounding",
84
- # features whitelist builder (Week 2)
85
- "build_feature_set",
86
- "build_and_persist_features",
87
- "extract_mcp_tools",
88
- "extract_cli_commands",
89
- # telemetry (Week 2 → Week 3 bridge)
90
- "summarize_gate_telemetry",
91
- "recent_gate_samples",
92
- ]
93
-
94
- # A3: publish paths are OFF. Any attempt to publish grounded content
95
- # externally during Week 1 raises. Flip to True only after Week 2
96
- # hardening (claim-type classifiers, implication detection) and explicit
97
- # founder approval.
98
- _PUBLISH_DISABLED = True