delimit-cli 3.15.13 → 4.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.
@@ -5,6 +5,7 @@ This module is distributed as a native binary (.so/.pyd), not readable Python.
5
5
  """
6
6
  import hashlib
7
7
  import json
8
+ import os
8
9
  import time
9
10
  from pathlib import Path
10
11
 
@@ -166,7 +167,7 @@ def activate(key: str) -> dict:
166
167
  def _revalidate(data: dict) -> dict:
167
168
  """Re-validate against Lemon Squeezy."""
168
169
  key = data.get("key", "")
169
- if not key or key.startswith("JAMSONS"):
170
+ if not key or key.startswith(os.environ.get("DELIMIT_INTERNAL_KEY_PREFIX", "")):
170
171
  return {"valid": True}
171
172
  try:
172
173
  import urllib.request
@@ -34,10 +34,10 @@ HISTORY_FILE = Path.home() / ".delimit" / "notifications.jsonl"
34
34
  INBOX_ROUTING_FILE = Path.home() / ".delimit" / "inbox_routing.jsonl"
35
35
 
36
36
  # ── Inbound email configuration ──────────────────────────────────────
37
- IMAP_HOST = "mail.spacemail.com"
38
- IMAP_PORT = 993
39
- IMAP_USER = "pro@delimit.ai"
40
- FORWARD_TO = "owner@example.com"
37
+ IMAP_HOST = os.environ.get("DELIMIT_IMAP_HOST", "")
38
+ IMAP_PORT = int(os.environ.get("DELIMIT_IMAP_PORT", "993"))
39
+ IMAP_USER = os.environ.get("DELIMIT_IMAP_USER", "")
40
+ FORWARD_TO = os.environ.get("DELIMIT_FORWARD_TO", "")
41
41
 
42
42
  # Domains/senders whose emails require owner action
43
43
  OWNER_ACTION_DOMAINS = {
@@ -60,9 +60,9 @@ OWNER_ACTION_DOMAINS = {
60
60
  "digitalocean.com",
61
61
  }
62
62
 
63
- OWNER_ACTION_SENDERS = {
64
- "owner@example.com",
65
- }
63
+ OWNER_ACTION_SENDERS = set(
64
+ filter(None, [os.environ.get("DELIMIT_OWNER_EMAIL", "")])
65
+ )
66
66
 
67
67
  # Subject patterns that indicate owner-action (compiled once)
68
68
  import re as _re
@@ -258,7 +258,7 @@ def send_email(
258
258
  smtp_pass = os.environ.get("DELIMIT_SMTP_PASS", "")
259
259
  smtp_from = os.environ.get("DELIMIT_SMTP_FROM", "")
260
260
 
261
- smtp_to = to or os.environ.get("DELIMIT_SMTP_TO", "owner@example.com")
261
+ smtp_to = to or os.environ.get("DELIMIT_SMTP_TO", "")
262
262
 
263
263
  if not all([smtp_host, smtp_from, smtp_to]):
264
264
  record = {
@@ -19,9 +19,8 @@ All tools follow the Adapter Boundary Contract v1.0:
19
19
  - Stateless between calls
20
20
  """
21
21
 
22
- # ── Founder Voice Doctrine ──────────────────────────────────────────────
22
+ # ── Output Quality Rules ──────────────────────────────────────────────
23
23
  # Applies to ALL outward-facing text generated by any tool in this server.
24
- # Full doctrine: /home/delimit/delimit-private/style/FOUNDER_VOICE_DOCTRINE.md
25
24
  #
26
25
  # Core: serious builder/operator, not a marketer. Credibility over persuasion.
27
26
  # Truth over excitement. Concrete mechanisms, not vague benefits.
@@ -3438,7 +3437,7 @@ async def delimit_sensor_github_issue(
3438
3437
  with new comments, issue state, and severity classification.
3439
3438
 
3440
3439
  Args:
3441
- repo: GitHub repository in owner/repo format (e.g. "activepieces/activepieces").
3440
+ repo: GitHub repository in owner/repo format (e.g. "owner/repo").
3442
3441
  issue_number: The issue number to monitor.
3443
3442
  since_comment_id: Last seen comment ID. Pass 0 to get all comments.
3444
3443
  """
@@ -5700,14 +5699,7 @@ def delimit_social_post(text: str = "", category: str = "", platform: str = "twi
5700
5699
  Every post provides value — tips, insights, governance wisdom.
5701
5700
  Max 2 posts per day to stay authentic.
5702
5701
 
5703
- IMPORTANT — Platform tone rules (these are DIFFERENT per platform):
5704
- - Twitter: confident technical brand. Direct, professional, ALWAYS POSITIVE.
5705
- Celebrate wins and progress. Never complain or air gaps publicly.
5706
- No em dashes or en dashes. Include install commands when relevant.
5707
- - Reddit: proud builder posting as u/delimitdev. Casual, typed-on-phone energy.
5708
- ALWAYS POSITIVE. Mention Delimit ONLY when genuinely helpful.
5709
- NO bullet points/lists/bold/em dashes. 2-3 sentences max.
5710
- - LinkedIn: professional hook + insight + CTA
5702
+ Platform tone and posting guidelines are loaded from user config at runtime.
5711
5703
 
5712
5704
  Args:
5713
5705
  text: Tweet text. Leave empty to auto-generate.
@@ -5744,7 +5736,7 @@ def delimit_social_post(text: str = "", category: str = "", platform: str = "twi
5744
5736
  from ai.social import store_draft_message_id
5745
5737
 
5746
5738
  # Build contextual email body so the founder knows exactly what to do
5747
- _acct = account or ("delimitdev" if platform == "reddit" else "delimit_ai")
5739
+ _acct = account or os.environ.get("DELIMIT_SOCIAL_REDDIT_ACCOUNT", "delimit") if platform == "reddit" else account or os.environ.get("DELIMIT_SOCIAL_TWITTER_ACCOUNT", "delimit_ai")
5748
5740
  _lines = []
5749
5741
 
5750
5742
  if platform == "reddit":
@@ -6087,12 +6079,12 @@ def delimit_github_scan(
6087
6079
 
6088
6080
  Three cadences:
6089
6081
  pulse: Own repo health (stars, forks, issues, traffic). Fast, run often.
6090
- hunter: Competitor users, adoption leads, pain threads. Medium, run hourly.
6082
+ hunter: Repository signals, engagement threads. Medium, run hourly.
6091
6083
  deep: Full ecosystem intel. Slow, run daily.
6092
6084
 
6093
6085
  IMPORTANT -- TOOL CHAINING RULE:
6094
6086
  After scanning, the AI MUST process high-score findings:
6095
- 1. Auto-ledger items (score >= 75 competitor users) via delimit_ledger_add
6087
+ 1. Auto-ledger high-score findings via delimit_ledger_add
6096
6088
  2. Pain threads with existing_feature relevance via delimit_notify
6097
6089
  Never just return findings and stop. Always chain to the next action.
6098
6090
 
@@ -6521,7 +6513,7 @@ def delimit_notify(channel: str = "webhook", message: str = "",
6521
6513
  to: Recipient email address (email only). Overrides default DELIMIT_SMTP_TO.
6522
6514
  Send to any address — leave empty for default (owner@example.com).
6523
6515
  from_account: Sender account key from ~/.delimit/secrets/smtp-all.json
6524
- (e.g. 'pro@delimit.ai', 'admin@wire.report'). Email only.
6516
+ (e.g. 'notifications@example.com'). Email only.
6525
6517
  """
6526
6518
  from ai.notify import send_notification
6527
6519
  return _with_next_steps("notify", _safe_call(
@@ -39,7 +39,7 @@ DEFAULT_ROSTER = {
39
39
  "fallback_model": "codex-gpt-5.4",
40
40
  },
41
41
  "ops": {
42
- "role": "Strategy, Deliberation, Outreach, Competitive Intel",
42
+ "role": "Strategy, Deliberation, Community, Analysis",
43
43
  "default_model": "grok-4",
44
44
  "fallback_model": "gemini-3.1-pro-preview",
45
45
  },
@@ -274,7 +274,7 @@ APPROVAL_TIERS = {
274
274
  "deploy_staging": "auto_approved",
275
275
  "social_post": "founder_email",
276
276
  "social_low_risk": "auto_after_consensus",
277
- "outreach_issue": "founder_email",
277
+ "community_issue": "founder_email",
278
278
  "ledger_update": "auto_approved",
279
279
  "code_commit": "auto_approved",
280
280
  "security_audit": "auto_approved",
@@ -3,7 +3,7 @@ Delimit Contract Ledger
3
3
  Reads, validates, and queries the append-only JSONL event ledger.
4
4
  Optional SQLite index for fast lookups (never required for CI).
5
5
 
6
- Per Jamsons Doctrine:
6
+ Per Delimit Stability Contract:
7
7
  - Deterministic outputs
8
8
  - Append-only artifacts
9
9
  - SQLite index is optional, not required for CI
@@ -5,7 +5,7 @@ Constructs a deterministic service dependency graph from manifests.
5
5
  The graph maps each API/service to its downstream consumers,
6
6
  enabling impact analysis when an API contract changes.
7
7
 
8
- Per Jamsons Doctrine:
8
+ Per Delimit Stability Contract:
9
9
  - Deterministic outputs (sorted, reproducible)
10
10
  - No telemetry
11
11
  - Graceful degradation when manifests are missing
@@ -2,7 +2,7 @@
2
2
  Delimit Dependency Manifest
3
3
  Parses and validates .delimit/dependencies.yaml service dependency declarations.
4
4
 
5
- Per Jamsons Doctrine:
5
+ Per Delimit Stability Contract:
6
6
  - Deterministic outputs
7
7
  - No credential discovery
8
8
  - No telemetry
@@ -3,7 +3,7 @@ Delimit Event Backbone
3
3
  Constructs ledger events, generates SHA-256 hashes, links hash chains,
4
4
  and appends to the append-only JSONL ledger.
5
5
 
6
- Per Jamsons Doctrine:
6
+ Per Delimit Stability Contract:
7
7
  - Deterministic outputs
8
8
  - Append-only artifacts
9
9
  - Fail-closed CI behavior (ledger failures never affect CI)
@@ -199,7 +199,7 @@ class EventBackbone:
199
199
  This is the primary API for event generation. It is best-effort:
200
200
  if the ledger write fails, the event is still returned but not persisted.
201
201
 
202
- CRITICAL: This method NEVER raises exceptions. Per Jamsons Doctrine,
202
+ CRITICAL: This method NEVER raises exceptions. Per Delimit Stability Contract,
203
203
  ledger failures must not affect CI pass/fail outcome.
204
204
 
205
205
  Returns:
@@ -1,7 +1,7 @@
1
1
  """
2
2
  Delimit Event Schema
3
3
  Canonical event schema for API contract evolution tracking.
4
- Deterministic validation and serialization per Jamsons Doctrine.
4
+ Deterministic validation and serialization per Delimit Stability Contract.
5
5
  """
6
6
 
7
7
  import hashlib
@@ -3,7 +3,7 @@ Delimit Impact Analyzer
3
3
  Determines downstream consumers affected by an API change
4
4
  and produces informational impact summaries for CI output.
5
5
 
6
- Per Jamsons Doctrine:
6
+ Per Delimit Stability Contract:
7
7
  - Impact analysis is INFORMATIONAL ONLY
8
8
  - NEVER affects CI pass/fail outcome
9
9
  - Deterministic outputs
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "delimit-cli",
3
3
  "mcpName": "io.github.delimit-ai/delimit-mcp-server",
4
- "version": "3.15.13",
4
+ "version": "4.0.0",
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": [
@@ -14,6 +14,12 @@
14
14
  "!gateway/ai/founding_users.py",
15
15
  "!gateway/ai/inbox_daemon.py",
16
16
  "!gateway/ai/deliberation.py",
17
+ "!gateway/ai/reddit_scanner.py",
18
+ "!gateway/ai/github_scanner.py",
19
+ "!gateway/ai/cross_model_audit.py",
20
+ "!gateway/ai/session_phoenix.py",
21
+ "!gateway/ai/handoff_receipts.py",
22
+ "!gateway/ai/toolcard_cache.py",
17
23
  "scripts/",
18
24
  "server.json",
19
25
  "README.md",
@@ -25,7 +25,7 @@ fi
25
25
 
26
26
  # 2. Blocklist terms
27
27
  echo -n " Blocklist... "
28
- BLOCKLIST="jamsonsholdings|Bladabah|Domainvested26|Delimit26|home/jamsons|infracore|crypttrx|\.wr_env"
28
+ BLOCKLIST="jamsonsholdings|Bladabah|Domainvested26|Delimit26|home/jamsons|infracore|crypttrx|\.wr_env|delimitdev|typed-on-phone|em dash.*ai tell|PAIN_CATEGORIES|VENTURE_CONFIG|VENTURE_SUBREDDITS|karma_building"
29
29
  if grep -rEi "$BLOCKLIST" "$TMPDIR/package/" --include="*.py" --include="*.js" --include="*.json" 2>/dev/null; then
30
30
  echo "❌ BLOCKED TERMS FOUND"
31
31
  FAIL=1
@@ -42,9 +42,17 @@ else
42
42
  echo "✅ clean"
43
43
  fi
44
44
 
45
- # 4. Proprietary files that shouldn't ship
45
+ # 4. Internal ticket IDs
46
+ echo -n " Internal ticket IDs... "
47
+ if grep -rE "LED-[0-9]{3}|STR-[0-9]{3}" "$TMPDIR/package/" --include="*.py" --include="*.js" 2>/dev/null | grep -v "node_modules" | head -1; then
48
+ echo " WARNING: Internal ticket IDs found (cosmetic, not blocking)"
49
+ else
50
+ echo "clean"
51
+ fi
52
+
53
+ # 5. Proprietary files that shouldn't ship
46
54
  echo -n " Proprietary files... "
47
- PROPRIETARY="social_target\.py|social\.py|founding_users\.py|inbox_daemon\.py|deliberation\.py"
55
+ PROPRIETARY="social_target\.py|social\.py|founding_users\.py|inbox_daemon\.py|deliberation\.py|reddit_scanner\.py|github_scanner\.py|cross_model_audit\.py|session_phoenix\.py|handoff_receipts\.py|toolcard_cache\.py"
48
56
  if find "$TMPDIR/package/" -name "*.py" | grep -Ei "$PROPRIETARY" 2>/dev/null; then
49
57
  echo "❌ PROPRIETARY FILES IN PACKAGE"
50
58
  FAIL=1
@@ -52,15 +60,51 @@ else
52
60
  echo "✅ clean"
53
61
  fi
54
62
 
55
- # Cleanup
63
+ # Cleanup npm tarball
56
64
  rm -rf "$TMPDIR"
57
65
 
66
+ # ── PyPI dist scan (if dist/ exists) ─────────────────────────────────
67
+ PYPI_DIST="/home/delimit/delimit-gateway/dist"
68
+ if [ -d "$PYPI_DIST" ] && ls "$PYPI_DIST"/*.tar.gz 1>/dev/null 2>&1; then
69
+ echo ""
70
+ echo "PyPI dist scan..."
71
+ PYPI_TMPDIR=$(mktemp -d)
72
+ PYPI_TARBALL=$(ls -t "$PYPI_DIST"/*.tar.gz | head -1)
73
+ tar -xzf "$PYPI_TARBALL" -C "$PYPI_TMPDIR" 2>/dev/null
74
+
75
+ echo -n " Credentials... "
76
+ if grep -rEi '(password|passwd|secret|api_key|apikey)\s*[:=]\s*["\x27][^"\x27]{4,}' "$PYPI_TMPDIR/" --include="*.py" 2>/dev/null | grep -v 'environ\|getenv\|os\.environ\|<configured\|example\|placeholder\|REDACTED'; then
77
+ echo "FOUND CREDENTIALS IN PYPI DIST"
78
+ FAIL=1
79
+ else
80
+ echo "clean"
81
+ fi
82
+
83
+ echo -n " Blocklist... "
84
+ if grep -rEi "$BLOCKLIST" "$PYPI_TMPDIR/" --include="*.py" 2>/dev/null; then
85
+ echo "BLOCKED TERMS IN PYPI DIST"
86
+ FAIL=1
87
+ else
88
+ echo "clean"
89
+ fi
90
+
91
+ echo -n " PII... "
92
+ if grep -rEi '[a-z0-9._%+-]+@(gmail|yahoo|hotmail|outlook|proton|jamsons|wire\.report|domainvested)' "$PYPI_TMPDIR/" --include="*.py" 2>/dev/null | grep -v "example\|placeholder\|<configured\|noreply\|e\.g\.\|docstring"; then
93
+ echo "PII IN PYPI DIST"
94
+ FAIL=1
95
+ else
96
+ echo "clean"
97
+ fi
98
+
99
+ rm -rf "$PYPI_TMPDIR"
100
+ fi
101
+
58
102
  if [ $FAIL -ne 0 ]; then
59
103
  echo ""
60
- echo "SECURITY CHECK FAILED do not publish"
104
+ echo "SECURITY CHECK FAILED -- do not publish"
61
105
  exit 1
62
106
  fi
63
107
 
64
108
  echo ""
65
- echo "All security checks passed"
109
+ echo "All security checks passed"
66
110
  exit 0