delimit-cli 4.5.0 → 4.5.2

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 (51) hide show
  1. package/CHANGELOG.md +108 -0
  2. package/README.md +2 -2
  3. package/adapters/cursor-rules.js +17 -4
  4. package/bin/delimit-cli.js +109 -24
  5. package/gateway/ai/content_engine.py +3 -4
  6. package/gateway/ai/inbox_classifier.py +215 -0
  7. package/gateway/ai/integrations/opensage_wrapper.py +4 -1
  8. package/gateway/ai/ledger_manager.py +218 -38
  9. package/gateway/ai/license.py +26 -0
  10. package/gateway/ai/notify.py +68 -3
  11. package/gateway/ai/reddit_proxy.py +93 -15
  12. package/gateway/ai/reddit_scanner.py +36 -18
  13. package/gateway/ai/server.py +128 -6
  14. package/gateway/ai/social_capability/__init__.py +6 -0
  15. package/gateway/ai/social_capability/capability_validator.py +273 -0
  16. package/gateway/ai/social_capability/current_capabilities.yaml +95 -0
  17. package/gateway/ai/social_queue.py +307 -0
  18. package/gateway/ai/supabase_sync.py +14 -2
  19. package/gateway/ai/swarm.py +29 -11
  20. package/gateway/ai/tui.py +6 -2
  21. package/gateway/ai/x_ranker.py +276 -0
  22. package/lib/attest-mcp.js +487 -0
  23. package/lib/attest-telemetry.js +48 -0
  24. package/lib/delimit-home.js +35 -0
  25. package/lib/delimit-template.js +14 -0
  26. package/lib/managed-section.js +92 -0
  27. package/lib/trust-page-engine.js +6 -2
  28. package/lib/wrap-engine.js +21 -4
  29. package/package.json +8 -2
  30. package/scripts/postinstall.js +89 -40
  31. package/gateway/ai/content_grounding/__init__.py +0 -98
  32. package/gateway/ai/content_grounding/build.py +0 -350
  33. package/gateway/ai/content_grounding/consume.py +0 -280
  34. package/gateway/ai/content_grounding/features.py +0 -218
  35. package/gateway/ai/content_grounding/fixtures/fail/01_missing_evidence.json +0 -9
  36. package/gateway/ai/content_grounding/fixtures/fail/02_unknown_evidence_prefix.json +0 -9
  37. package/gateway/ai/content_grounding/fixtures/fail/03_banned_comparative.json +0 -17
  38. package/gateway/ai/content_grounding/fixtures/fail/04_banned_adoption.json +0 -17
  39. package/gateway/ai/content_grounding/fixtures/fail/05_aggregate_no_numeric.json +0 -17
  40. package/gateway/ai/content_grounding/fixtures/fail/06_unversioned_inference_rule.json +0 -18
  41. package/gateway/ai/content_grounding/fixtures/pass/01_feature_shipped.json +0 -18
  42. package/gateway/ai/content_grounding/fixtures/pass/02_aggregate_claim.json +0 -23
  43. package/gateway/ai/content_grounding/fixtures/pass/03_attestation.json +0 -16
  44. package/gateway/ai/content_grounding/schemas/claim.schema.json +0 -40
  45. package/gateway/ai/content_grounding/schemas/event.schema.json +0 -23
  46. package/gateway/ai/content_grounding/schemas.py +0 -276
  47. package/gateway/ai/content_grounding/telemetry.py +0 -221
  48. package/gateway/ai/inbox_drafts/__init__.py +0 -61
  49. package/gateway/ai/inbox_drafts/registry.py +0 -412
  50. package/gateway/ai/inbox_drafts/schema.py +0 -374
  51. package/gateway/ai/inbox_executor.py +0 -565
@@ -1,218 +0,0 @@
1
- """
2
- Feature whitelist builder for the content grounding layer (LED-1084 Week 2).
3
-
4
- Builds `~/.delimit/content/grounding/features.json` from two sources of truth:
5
- 1. MCP tool registry — every `@mcp.tool()` decorator in ai/server.py is
6
- a shipped capability the drafter may reference.
7
- 2. CLI subcommands — parsed from `delimit --help` output (bin/delimit-cli.js
8
- `program.command(...)` entries) when the CLI binary
9
- is on PATH. Best-effort; we fall back to just the
10
- MCP tool set if the CLI parse fails.
11
-
12
- The grounding gate in ai/content_grounding/consume.py calls
13
- `load_feature_whitelist()` which reads this file. An empty whitelist
14
- causes the gate to flag ANY feature-claim language, so populating this
15
- file is a direct prerequisite for meaningful gate scores.
16
-
17
- Running this builder is idempotent and safe — it overwrites `features.json`
18
- with the fresh set, keeps the schema stable, and records `built_at` +
19
- `source_counts` for audit.
20
-
21
- Usage:
22
- python -m ai.content_grounding.features build
23
- # or programmatically:
24
- from ai.content_grounding.features import build_and_persist_features
25
- build_and_persist_features()
26
- """
27
- from __future__ import annotations
28
-
29
- import json
30
- import logging
31
- import os
32
- import re
33
- import subprocess
34
- import sys
35
- from datetime import datetime, timezone
36
- from pathlib import Path
37
- from typing import Any, Dict, List, Optional, Set
38
-
39
- from .consume import FEATURES_FILE
40
-
41
- logger = logging.getLogger("delimit.ai.content_grounding.features")
42
-
43
- GATEWAY_ROOT = Path(os.environ.get("DELIMIT_GATEWAY_REPO", "/home/delimit/delimit-gateway"))
44
- NPM_BIN = Path(os.environ.get("DELIMIT_CLI_BIN", "/home/delimit/npm-delimit/bin/delimit-cli.js"))
45
-
46
-
47
- # ---------------------------------------------------------------------------
48
- # Source 1 — MCP tool registry (ai/server.py)
49
- # ---------------------------------------------------------------------------
50
-
51
- _MCP_TOOL_DEF_RE = re.compile(
52
- r"@mcp\.tool\(\)\s*\n\s*def\s+(delimit_[a-z0-9_]+)\s*\(",
53
- re.MULTILINE,
54
- )
55
-
56
-
57
- def extract_mcp_tools(server_py: Path) -> List[str]:
58
- """Extract every `delimit_<name>` tool registered in server.py.
59
-
60
- Returns sorted unique tool names. These are the shipped MCP tools the
61
- drafter is allowed to name. A draft that mentions `delimit_wrap` or
62
- `delimit_trust_page` passes the feature gate; one that mentions
63
- `delimit_coinbase_integration` fails.
64
- """
65
- if not server_py.is_file():
66
- logger.warning("MCP server source not found: %s", server_py)
67
- return []
68
- try:
69
- text = server_py.read_text(errors="replace")
70
- except Exception as e:
71
- logger.warning("could not read MCP server source: %s", e)
72
- return []
73
- tools = sorted(set(_MCP_TOOL_DEF_RE.findall(text)))
74
- return tools
75
-
76
-
77
- # ---------------------------------------------------------------------------
78
- # Source 2 — CLI subcommands (bin/delimit-cli.js)
79
- # ---------------------------------------------------------------------------
80
-
81
- # Commander.js patterns we grep for:
82
- # program.command("foo")
83
- # program.command('foo [bar]')
84
- # .command("foo <arg>")
85
- # Captures just the subcommand name (first token up to space).
86
- _CLI_COMMAND_RE = re.compile(
87
- r"""(?:^|\.)command\(\s*['"]([a-z][a-z0-9_-]*)""",
88
- re.MULTILINE | re.IGNORECASE,
89
- )
90
-
91
-
92
- def extract_cli_commands(cli_path: Path) -> List[str]:
93
- """Extract CLI subcommand names from bin/delimit-cli.js.
94
-
95
- Works statically (no subprocess), so it's safe on CI runners without
96
- node installed. Returns sorted unique command names.
97
- """
98
- if not cli_path.is_file():
99
- logger.warning("delimit CLI source not found: %s", cli_path)
100
- return []
101
- try:
102
- text = cli_path.read_text(errors="replace")
103
- except Exception as e:
104
- logger.warning("could not read CLI source: %s", e)
105
- return []
106
- commands = set()
107
- for m in _CLI_COMMAND_RE.finditer(text):
108
- name = m.group(1).strip().lower()
109
- # Filter out obvious false matches (method names that happen to start
110
- # with a word followed by '('). A real commander subcommand won't
111
- # contain certain tokens.
112
- if name in {"log", "error", "warn", "info", "on", "off", "then", "catch", "parse"}:
113
- continue
114
- commands.add(name)
115
- return sorted(commands)
116
-
117
-
118
- # ---------------------------------------------------------------------------
119
- # Build + persist
120
- # ---------------------------------------------------------------------------
121
-
122
- def build_feature_set(
123
- gateway_root: Optional[Path] = None,
124
- cli_path: Optional[Path] = None,
125
- ) -> Dict[str, Any]:
126
- """Aggregate features from both sources into a dict ready to persist.
127
-
128
- Shape:
129
- {
130
- "version": 1,
131
- "built_at": "2026-04-24T...",
132
- "features": ["delimit_lint", "delimit_wrap", "init", "scan", ...],
133
- "source_counts": {"mcp_tools": N, "cli_commands": M},
134
- "sources": {
135
- "mcp_tools": [...],
136
- "cli_commands": [...],
137
- }
138
- }
139
- """
140
- gw = gateway_root or GATEWAY_ROOT
141
- cp = cli_path or NPM_BIN
142
- mcp_tools = extract_mcp_tools(gw / "ai" / "server.py")
143
- cli_commands = extract_cli_commands(cp)
144
- features = sorted(set(mcp_tools) | set(cli_commands))
145
- return {
146
- "version": 1,
147
- "built_at": datetime.now(timezone.utc).isoformat(),
148
- "features": features,
149
- "source_counts": {
150
- "mcp_tools": len(mcp_tools),
151
- "cli_commands": len(cli_commands),
152
- "total_unique": len(features),
153
- },
154
- "sources": {
155
- "mcp_tools": mcp_tools,
156
- "cli_commands": cli_commands,
157
- },
158
- }
159
-
160
-
161
- def build_and_persist_features(
162
- out_path: Optional[Path] = None,
163
- gateway_root: Optional[Path] = None,
164
- cli_path: Optional[Path] = None,
165
- ) -> Path:
166
- """Build the feature set and write it to features.json.
167
-
168
- Returns the path written. Overwrites any previous file.
169
- """
170
- target = Path(out_path) if out_path else FEATURES_FILE
171
- target.parent.mkdir(parents=True, exist_ok=True)
172
- data = build_feature_set(gateway_root=gateway_root, cli_path=cli_path)
173
- target.write_text(json.dumps(data, indent=2))
174
- logger.info(
175
- "wrote features.json: %d mcp_tools + %d cli_commands → %d unique → %s",
176
- data["source_counts"]["mcp_tools"],
177
- data["source_counts"]["cli_commands"],
178
- data["source_counts"]["total_unique"],
179
- target,
180
- )
181
- return target
182
-
183
-
184
- # ---------------------------------------------------------------------------
185
- # CLI entry
186
- # ---------------------------------------------------------------------------
187
-
188
- def _main() -> int:
189
- if len(sys.argv) < 2 or sys.argv[1] not in ("build", "show"):
190
- print(
191
- "usage: python -m ai.content_grounding.features build | show\n"
192
- " build rebuild features.json from MCP + CLI sources\n"
193
- " show print current features.json stats",
194
- file=sys.stderr,
195
- )
196
- return 2
197
- if sys.argv[1] == "build":
198
- out = build_and_persist_features()
199
- data = json.loads(out.read_text())
200
- print(f"wrote {out}")
201
- print(f" mcp_tools: {data['source_counts']['mcp_tools']}")
202
- print(f" cli_commands: {data['source_counts']['cli_commands']}")
203
- print(f" total unique: {data['source_counts']['total_unique']}")
204
- return 0
205
- if sys.argv[1] == "show":
206
- if not FEATURES_FILE.exists():
207
- print(f"no features.json at {FEATURES_FILE}. run 'build' first.", file=sys.stderr)
208
- return 1
209
- data = json.loads(FEATURES_FILE.read_text())
210
- print(f"features.json built_at={data.get('built_at')}")
211
- print(f" total: {data['source_counts']['total_unique']}")
212
- print(f" sample: {data['features'][:8]} ...")
213
- return 0
214
- return 2
215
-
216
-
217
- if __name__ == "__main__":
218
- sys.exit(_main())
@@ -1,9 +0,0 @@
1
- {
2
- "event_id": "evt-ledger-LED-999",
3
- "type": "feature_shipped",
4
- "date": "2026-04-24T00:00:00Z",
5
- "venture": "delimit",
6
- "evidence_refs": [],
7
- "claims": [],
8
- "visibility": "internal"
9
- }
@@ -1,9 +0,0 @@
1
- {
2
- "event_id": "evt-ledger-LED-888",
3
- "type": "feature_shipped",
4
- "date": "2026-04-24T00:00:00Z",
5
- "venture": "delimit",
6
- "evidence_refs": ["jira:TICKET-123"],
7
- "claims": [],
8
- "visibility": "internal"
9
- }
@@ -1,17 +0,0 @@
1
- {
2
- "event_id": "evt-ledger-LED-777",
3
- "type": "feature_shipped",
4
- "date": "2026-04-24T00:00:00Z",
5
- "venture": "delimit",
6
- "evidence_refs": ["LED-777"],
7
- "claims": [
8
- {
9
- "claim_id": "CLM-LED-777-compare",
10
- "type": "comparative",
11
- "text": "Delimit is faster than openapi-diff in every benchmark.",
12
- "evidence_refs": ["LED-777"],
13
- "visibility": "public"
14
- }
15
- ],
16
- "visibility": "public"
17
- }
@@ -1,17 +0,0 @@
1
- {
2
- "event_id": "evt-ledger-LED-666",
3
- "type": "feature_shipped",
4
- "date": "2026-04-24T00:00:00Z",
5
- "venture": "delimit",
6
- "evidence_refs": ["LED-666"],
7
- "claims": [
8
- {
9
- "claim_id": "CLM-LED-666-adoption",
10
- "type": "adoption",
11
- "text": "Used in production by 12 open-source projects.",
12
- "evidence_refs": ["LED-666"],
13
- "visibility": "public"
14
- }
15
- ],
16
- "visibility": "public"
17
- }
@@ -1,17 +0,0 @@
1
- {
2
- "event_id": "evt-ledger-LED-555",
3
- "type": "release",
4
- "date": "2026-04-24T00:00:00Z",
5
- "venture": "delimit",
6
- "evidence_refs": ["LED-555"],
7
- "claims": [
8
- {
9
- "claim_id": "CLM-LED-555-tests",
10
- "type": "aggregate",
11
- "text": "Many tests pass.",
12
- "evidence_refs": ["LED-555"],
13
- "visibility": "public"
14
- }
15
- ],
16
- "visibility": "public"
17
- }
@@ -1,18 +0,0 @@
1
- {
2
- "event_id": "evt-ledger-LED-444",
3
- "type": "feature_shipped",
4
- "date": "2026-04-24T00:00:00Z",
5
- "venture": "delimit",
6
- "evidence_refs": ["LED-444"],
7
- "claims": [
8
- {
9
- "claim_id": "CLM-LED-444-inferred",
10
- "type": "feature",
11
- "text": "Delimit handles all the edge cases.",
12
- "evidence_refs": ["LED-444"],
13
- "visibility": "internal",
14
- "inference_rule": "generalization"
15
- }
16
- ],
17
- "visibility": "internal"
18
- }
@@ -1,18 +0,0 @@
1
- {
2
- "event_id": "evt-ledger-LED-1010",
3
- "type": "feature_shipped",
4
- "date": "2026-04-24T00:00:00Z",
5
- "venture": "delimit",
6
- "evidence_refs": ["LED-1010", "git:f6597185b72d"],
7
- "claims": [
8
- {
9
- "claim_id": "CLM-LED-1010-title",
10
- "type": "feature",
11
- "text": "Tailwind-aware extract_tokens emits framework default spacing, typography, and breakpoint scales.",
12
- "evidence_refs": ["LED-1010", "git:f6597185b72d"],
13
- "visibility": "public"
14
- }
15
- ],
16
- "visibility": "internal",
17
- "source": "ledger:feature"
18
- }
@@ -1,23 +0,0 @@
1
- {
2
- "event_id": "evt-ledger-LED-release-v4.3.4",
3
- "type": "release",
4
- "date": "2026-04-24T01:39:29Z",
5
- "venture": "delimit",
6
- "evidence_refs": ["LED-1079", "git:67578dc54e77"],
7
- "claims": [
8
- {
9
- "claim_id": "CLM-release-v4.3.4-test-count",
10
- "type": "aggregate",
11
- "text": "165 tests pass on delimit-cli v4.3.4.",
12
- "evidence_refs": ["git:67578dc54e77"],
13
- "visibility": "public",
14
- "numeric_evidence": {
15
- "value": 165,
16
- "unit": "tests",
17
- "commit_sha": "67578dc54e77b7dfbed0f6a9ce18baa4ae695c91"
18
- }
19
- }
20
- ],
21
- "visibility": "public",
22
- "source": "ledger:release"
23
- }
@@ -1,16 +0,0 @@
1
- {
2
- "event_id": "evt-att-att_a05050eb8e13277e",
3
- "type": "attestation",
4
- "date": "2026-04-23T23:52:51.823Z",
5
- "venture": "delimit",
6
- "evidence_refs": ["attest:att_a05050eb8e13277e", "git:ff0c729fda7b"],
7
- "claims": [],
8
- "visibility": "public",
9
- "source": "attestation",
10
- "raw": {
11
- "attestation_id": "att_a05050eb8e13277e",
12
- "kind": "merge_attestation",
13
- "wrapped_exit": 0,
14
- "signature_alg": "HMAC-SHA256"
15
- }
16
- }
@@ -1,40 +0,0 @@
1
- {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://delimit.ai/schemas/grounding/claim.schema.json",
4
- "title": "Claim",
5
- "type": "object",
6
- "required": ["claim_id", "type", "text", "evidence_refs", "visibility"],
7
- "additionalProperties": false,
8
- "properties": {
9
- "claim_id": { "type": "string", "pattern": "^CLM-.+" },
10
- "type": { "enum": ["feature", "capability", "incident", "comparative", "adoption", "customer", "aggregate", "roadmap", "process"] },
11
- "text": { "type": "string", "minLength": 1 },
12
- "evidence_refs": {
13
- "type": "array",
14
- "minItems": 1,
15
- "items": { "type": "string", "pattern": "^(LED-|sha256:|git:|attest:|url:).+" }
16
- },
17
- "visibility": { "enum": ["public", "internal", "private"] },
18
- "inference_rule": { "type": ["string", "null"] },
19
- "inference_rule_version": { "type": ["string", "null"] },
20
- "numeric_evidence": {
21
- "type": ["object", "null"],
22
- "properties": {
23
- "value": { "type": ["number", "string"] },
24
- "unit": { "type": ["string", "null"] },
25
- "commit_sha": { "type": "string" }
26
- },
27
- "required": ["value", "commit_sha"]
28
- }
29
- },
30
- "allOf": [
31
- {
32
- "if": { "properties": { "type": { "const": "aggregate" } } },
33
- "then": { "required": ["numeric_evidence"] }
34
- },
35
- {
36
- "if": { "required": ["inference_rule"], "properties": { "inference_rule": { "type": "string" } } },
37
- "then": { "required": ["inference_rule_version"] }
38
- }
39
- ]
40
- }
@@ -1,23 +0,0 @@
1
- {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://delimit.ai/schemas/grounding/event.schema.json",
4
- "title": "GroundedEvent",
5
- "type": "object",
6
- "required": ["event_id", "type", "date", "venture", "evidence_refs", "visibility"],
7
- "additionalProperties": false,
8
- "properties": {
9
- "event_id": { "type": "string", "pattern": "^evt-[a-z]+-.+" },
10
- "type": { "enum": ["feature_shipped", "release", "incident", "incident_resolved", "decision", "outreach_event", "attestation", "commit"] },
11
- "date": { "type": "string", "format": "date-time" },
12
- "venture": { "enum": ["delimit", "domainvested", "wirereport", "livetube"] },
13
- "evidence_refs": {
14
- "type": "array",
15
- "minItems": 1,
16
- "items": { "type": "string", "pattern": "^(LED-|sha256:|git:|attest:|url:).+" }
17
- },
18
- "claims": { "type": "array", "items": { "$ref": "claim.schema.json" } },
19
- "visibility": { "enum": ["public", "internal", "private"] },
20
- "source": { "type": ["string", "null"] },
21
- "raw": { "type": ["object", "null"] }
22
- }
23
- }