delimit-cli 4.6.0 → 4.6.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.
- package/CHANGELOG.md +71 -8
- package/bin/delimit-cli.js +59 -9
- package/bin/delimit-setup.js +7 -3
- package/gateway/ai/agent_dispatch.py +5 -0
- package/gateway/ai/backends/gateway_core.py +6 -0
- package/gateway/ai/backends/git_health.py +175 -0
- package/gateway/ai/backends/memory_bridge.py +210 -53
- package/gateway/ai/backends/tools_infra.py +93 -0
- package/gateway/ai/backends/tools_real.py +53 -7
- package/gateway/ai/cli_contract.py +185 -0
- package/gateway/ai/governance.py +181 -0
- package/gateway/ai/heartbeat.py +290 -0
- package/gateway/ai/ledger_manager.py +81 -4
- package/gateway/ai/ledger_proof.py +127 -0
- package/gateway/ai/license.py +132 -47
- package/gateway/ai/license_core.cpython-310-x86_64-linux-gnu.so +0 -0
- package/gateway/ai/license_core.pyi +1 -1
- package/gateway/ai/outreach_loop_daemon.py +349 -0
- package/gateway/ai/outreach_substantive.py +768 -7
- package/gateway/ai/pro_tools.yaml +167 -0
- package/gateway/ai/reddit_scanner.py +7 -1
- package/gateway/ai/server.py +295 -116
- package/gateway/ai/session_phoenix.py +121 -0
- package/gateway/ai/social_queue.py +166 -10
- package/gateway/ai/tenant_auth.py +329 -0
- package/gateway/ai/tenant_data.py +339 -0
- package/gateway/ai/tenant_paths.py +150 -0
- package/gateway/core/diff_engine_v2.py +517 -54
- package/gateway/core/semver_classifier.py +52 -6
- package/package.json +4 -1
- package/scripts/build-license-core.sh +0 -85
- package/scripts/security-check.sh +0 -66
- package/scripts/test-license-core-so.sh +0 -107
|
@@ -124,7 +124,16 @@ def _detect_venture(project_path: str = ".") -> Dict[str, str]:
|
|
|
124
124
|
|
|
125
125
|
|
|
126
126
|
def _register_venture(info: Dict[str, str]):
|
|
127
|
-
"""Silently register a venture in the global registry.
|
|
127
|
+
"""Silently register a venture in the global registry.
|
|
128
|
+
|
|
129
|
+
Phase C follow-up (2026-05-18): reject paths under /tmp/* or the
|
|
130
|
+
bare "/tmp" itself. Pytest tmp_path values leaked into the registry
|
|
131
|
+
as ventures (`tmp: /tmp`, `test_project: /tmp/pytest-of-root/...`),
|
|
132
|
+
causing every fresh tmp_path to match via path-prefix in
|
|
133
|
+
resolve_venture and breaking test_resolve_venture_unregistered_path.
|
|
134
|
+
The guard fails-silently — tests that pass tmp_path to functions
|
|
135
|
+
which auto-register simply don't pollute the registry going forward.
|
|
136
|
+
"""
|
|
128
137
|
GLOBAL_DIR.mkdir(parents=True, exist_ok=True)
|
|
129
138
|
ventures = {}
|
|
130
139
|
if VENTURES_FILE.exists():
|
|
@@ -134,9 +143,19 @@ def _register_venture(info: Dict[str, str]):
|
|
|
134
143
|
pass
|
|
135
144
|
|
|
136
145
|
name = info["name"]
|
|
146
|
+
path = info.get("path", "")
|
|
147
|
+
# Guard against the specific test-state pollution that broke
|
|
148
|
+
# test_resolve_venture_unregistered_path: a `tmp: /tmp` venture
|
|
149
|
+
# caught EVERY pytest tmp_path via path-prefix in resolve_venture.
|
|
150
|
+
# Reject bare "/tmp" only. Deeper /tmp/<X> paths are fine — they
|
|
151
|
+
# only path-prefix-match their own subtree, not every tmp_path,
|
|
152
|
+
# AND legitimate test fixtures (e.g. test_ledger_proof) register
|
|
153
|
+
# subpaths during a single test run and need that to work.
|
|
154
|
+
if path == "/tmp" or path.rstrip("/") == "/tmp":
|
|
155
|
+
return
|
|
137
156
|
if name not in ventures:
|
|
138
157
|
ventures[name] = {
|
|
139
|
-
"path":
|
|
158
|
+
"path": path,
|
|
140
159
|
"repo": info.get("repo", ""),
|
|
141
160
|
"type": info.get("type", ""),
|
|
142
161
|
"registered_at": time.strftime("%Y-%m-%dT%H:%M:%SZ"),
|
|
@@ -565,8 +584,18 @@ def update_item(
|
|
|
565
584
|
blocks: Optional[str] = None,
|
|
566
585
|
project_path: str = ".",
|
|
567
586
|
worked_by: str = "",
|
|
587
|
+
commit_sha: Optional[str] = None,
|
|
588
|
+
pr_url: Optional[str] = None,
|
|
568
589
|
) -> Dict[str, Any]:
|
|
569
|
-
"""Update an existing ledger item's fields.
|
|
590
|
+
"""Update an existing ledger item's fields.
|
|
591
|
+
|
|
592
|
+
LED-1408 Phase 1: when `status="done"` is requested, callers MAY provide
|
|
593
|
+
`commit_sha` and/or `pr_url` as proof that the work shipped to main.
|
|
594
|
+
The proof is recorded on the update event under `ship_proof` with a
|
|
595
|
+
`verified: bool` flag. Phase 1 does NOT enforce — items still
|
|
596
|
+
transition to `done` even without proof — but the flag lets future
|
|
597
|
+
audits and the Phase 2 reconciler find unverified-done items.
|
|
598
|
+
"""
|
|
570
599
|
_ensure(project_path)
|
|
571
600
|
ledger_dir = _project_ledger_dir(project_path)
|
|
572
601
|
|
|
@@ -633,6 +662,49 @@ def update_item(
|
|
|
633
662
|
update["blocked_by"] = blocked_by
|
|
634
663
|
if blocks:
|
|
635
664
|
update["blocks"] = blocks
|
|
665
|
+
|
|
666
|
+
# LED-1408 Phase 1: attach ship_proof block when status transitions to
|
|
667
|
+
# `done` or `shipped_pending`. Verified=True iff commit_sha or pr_url
|
|
668
|
+
# was supplied (directly or scraped from the note). Phase 2's
|
|
669
|
+
# reconciler will use this to distinguish "trustworthy done" from
|
|
670
|
+
# "marked done but never verified on main."
|
|
671
|
+
if status in ("done", "shipped_pending"):
|
|
672
|
+
try:
|
|
673
|
+
from ai.ledger_proof import build_ship_proof
|
|
674
|
+
update["ship_proof"] = build_ship_proof(
|
|
675
|
+
commit_sha=commit_sha,
|
|
676
|
+
pr_url=pr_url,
|
|
677
|
+
note=note,
|
|
678
|
+
)
|
|
679
|
+
# LED-1420 Phase 2 strict-mode flip: when DELIMIT_LEDGER_STRICT_DONE=1,
|
|
680
|
+
# an unverified `done` transition is downgraded to `shipped_pending`
|
|
681
|
+
# so the nightly reconciler (scripts/delimit_ledger_reconciler.py)
|
|
682
|
+
# can promote it to `done` once a commit-trailer match shows up on
|
|
683
|
+
# origin/main. Off by default so existing workflows keep closing
|
|
684
|
+
# items without hitting an unexpected gate; flip when the
|
|
685
|
+
# reconciler has been observed running for ~1 week without
|
|
686
|
+
# surprises.
|
|
687
|
+
strict = os.environ.get("DELIMIT_LEDGER_STRICT_DONE") == "1"
|
|
688
|
+
if (
|
|
689
|
+
strict
|
|
690
|
+
and status == "done"
|
|
691
|
+
and not update["ship_proof"].get("verified")
|
|
692
|
+
):
|
|
693
|
+
update["status"] = "shipped_pending"
|
|
694
|
+
existing_note = update.get("note") or ""
|
|
695
|
+
suffix = (
|
|
696
|
+
"[LED-1420 strict-mode: downgraded done → shipped_pending — "
|
|
697
|
+
"no commit_sha/pr_url proof; reconciler will upgrade to "
|
|
698
|
+
"done when it finds a Ledger-Item: " + item_id + " trailer "
|
|
699
|
+
"on origin/main]"
|
|
700
|
+
)
|
|
701
|
+
update["note"] = (existing_note + " " + suffix).strip() if existing_note else suffix
|
|
702
|
+
except Exception:
|
|
703
|
+
# Soft-fail: a ship_proof bug must not break ledger close.
|
|
704
|
+
# The unverified state will be re-detectable from the missing
|
|
705
|
+
# key on the next audit pass.
|
|
706
|
+
pass
|
|
707
|
+
|
|
636
708
|
_append(path, update)
|
|
637
709
|
|
|
638
710
|
# Sync to Supabase for dashboard visibility
|
|
@@ -1306,7 +1378,12 @@ def session_history(limit: int = 5) -> Dict[str, Any]:
|
|
|
1306
1378
|
# `archive` is a soft transition (status="archived", appended to JSONL); items
|
|
1307
1379
|
# stay in replay forever. NO hard delete. Per-item failures don't block others.
|
|
1308
1380
|
BULK_ACTIONS = ("archive", "set_status", "set_priority", "add_tag", "mark_done", "cancel")
|
|
1309
|
-
|
|
1381
|
+
# LED-1408: `shipped_pending` is the intermediate state between "committed" and
|
|
1382
|
+
# "verified on main." Items transition to shipped_pending when a worker reports
|
|
1383
|
+
# completion (commit exists somewhere) but the orchestrator hasn't yet verified
|
|
1384
|
+
# the commit is reachable from origin/main. The reconciler (Phase 2) promotes
|
|
1385
|
+
# shipped_pending → done once reachability is confirmed.
|
|
1386
|
+
_VALID_BULK_STATUSES = ("open", "in_progress", "blocked", "shipped_pending", "done", "cancelled", "archived", "completed")
|
|
1310
1387
|
_VALID_BULK_PRIORITIES = ("P0", "P1", "P2", "P3")
|
|
1311
1388
|
|
|
1312
1389
|
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"""Ledger ship-state proof helpers (LED-1408 Phase 1).
|
|
2
|
+
|
|
3
|
+
When a ledger item transitions to `done`, we want auditable evidence that the
|
|
4
|
+
fix actually shipped. Two forms of proof:
|
|
5
|
+
|
|
6
|
+
1. **Commit-trailer binding** — the merge commit carries a `Ledger-Item:
|
|
7
|
+
LED-NNNN` trailer. Lets a webhook or reconciler walk `git log
|
|
8
|
+
origin/main` and find every commit-to-ledger link without naming
|
|
9
|
+
conventions or fuzzy matching.
|
|
10
|
+
|
|
11
|
+
2. **PR-URL linkage** — `https://github.com/<org>/<repo>/pull/<N>` plus a
|
|
12
|
+
verified `merged_at` timestamp. Fallback for items closed without a
|
|
13
|
+
trailer.
|
|
14
|
+
|
|
15
|
+
Phase 1 (this module): parse + record. Items closed with proof get
|
|
16
|
+
`verified: true` on the event; items closed without proof get
|
|
17
|
+
`verified: false` so a future audit can find them.
|
|
18
|
+
|
|
19
|
+
Phase 2 (separate LED): the reconciler enforces stricter semantics —
|
|
20
|
+
items without proof default to `shipped_pending`, not `done`.
|
|
21
|
+
|
|
22
|
+
Memory anchor: feedback_agent_dashboard_done_means_committed_not_merged.md
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
import re
|
|
28
|
+
from typing import Dict, Optional
|
|
29
|
+
|
|
30
|
+
# Match `Ledger-Item: LED-1234` (case-insensitive, leading whitespace allowed).
|
|
31
|
+
# Pattern intentionally tolerant of trailing whitespace + multiple LED IDs:
|
|
32
|
+
# we extract the FIRST LED-N on the line.
|
|
33
|
+
_LEDGER_TRAILER_RE = re.compile(
|
|
34
|
+
r"(?im)^\s*Ledger-Item\s*:\s*(LED-\d+)",
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
# Match a GitHub PR URL: https://github.com/<owner>/<repo>/pull/<N>
|
|
38
|
+
_PR_URL_RE = re.compile(
|
|
39
|
+
r"https://github\.com/([\w.-]+)/([\w.-]+)/pull/(\d+)",
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def parse_ledger_trailer(commit_message: str) -> Optional[str]:
|
|
44
|
+
"""Extract the `Ledger-Item: LED-NNNN` trailer value from a commit message.
|
|
45
|
+
|
|
46
|
+
Returns the LED id (e.g. `LED-1408`) or None if no trailer is present.
|
|
47
|
+
The trailer must be on its own line; mentions inside prose (e.g.
|
|
48
|
+
`mentions LED-1408 in passing`) do NOT match.
|
|
49
|
+
"""
|
|
50
|
+
if not commit_message:
|
|
51
|
+
return None
|
|
52
|
+
match = _LEDGER_TRAILER_RE.search(commit_message)
|
|
53
|
+
if match:
|
|
54
|
+
return match.group(1)
|
|
55
|
+
return None
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def parse_pr_url(text: str) -> Optional[Dict[str, str]]:
|
|
59
|
+
"""Extract the first GitHub PR URL from any string.
|
|
60
|
+
|
|
61
|
+
Returns {owner, repo, number} or None.
|
|
62
|
+
"""
|
|
63
|
+
if not text:
|
|
64
|
+
return None
|
|
65
|
+
match = _PR_URL_RE.search(text)
|
|
66
|
+
if match:
|
|
67
|
+
return {
|
|
68
|
+
"owner": match.group(1),
|
|
69
|
+
"repo": match.group(2),
|
|
70
|
+
"number": match.group(3),
|
|
71
|
+
}
|
|
72
|
+
return None
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def build_ship_proof(
|
|
76
|
+
commit_sha: Optional[str] = None,
|
|
77
|
+
pr_url: Optional[str] = None,
|
|
78
|
+
note: Optional[str] = None,
|
|
79
|
+
) -> Dict[str, object]:
|
|
80
|
+
"""Build a ship-proof block to attach to a ledger `done` event.
|
|
81
|
+
|
|
82
|
+
Inputs may come from explicit MCP-tool args OR from inline mentions
|
|
83
|
+
in the note (the caller might paste a PR URL into the note field
|
|
84
|
+
without realizing it's also queryable).
|
|
85
|
+
|
|
86
|
+
Returns a dict with keys:
|
|
87
|
+
- verified: bool — True iff commit_sha OR pr_url was provided
|
|
88
|
+
- commit_sha: str or None
|
|
89
|
+
- pr_url: str or None
|
|
90
|
+
- pr_owner / pr_repo / pr_number: str or None (parsed from pr_url)
|
|
91
|
+
- ledger_trailer: str or None (parsed from note, if present)
|
|
92
|
+
|
|
93
|
+
The `verified` flag is the primary downstream signal. A future
|
|
94
|
+
reconciler will refuse to transition `done` without verified=True;
|
|
95
|
+
Phase 1 only records the flag without enforcing.
|
|
96
|
+
"""
|
|
97
|
+
proof: Dict[str, object] = {
|
|
98
|
+
"verified": bool(commit_sha or pr_url),
|
|
99
|
+
"commit_sha": commit_sha or None,
|
|
100
|
+
"pr_url": pr_url or None,
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if pr_url:
|
|
104
|
+
parsed = parse_pr_url(pr_url)
|
|
105
|
+
if parsed:
|
|
106
|
+
proof["pr_owner"] = parsed["owner"]
|
|
107
|
+
proof["pr_repo"] = parsed["repo"]
|
|
108
|
+
proof["pr_number"] = parsed["number"]
|
|
109
|
+
|
|
110
|
+
# If pr_url not explicitly passed but appears in the note, capture it
|
|
111
|
+
if not pr_url and note:
|
|
112
|
+
parsed = parse_pr_url(note)
|
|
113
|
+
if parsed:
|
|
114
|
+
proof["pr_url"] = f"https://github.com/{parsed['owner']}/{parsed['repo']}/pull/{parsed['number']}"
|
|
115
|
+
proof["pr_owner"] = parsed["owner"]
|
|
116
|
+
proof["pr_repo"] = parsed["repo"]
|
|
117
|
+
proof["pr_number"] = parsed["number"]
|
|
118
|
+
proof["verified"] = True
|
|
119
|
+
|
|
120
|
+
# Capture any Ledger-Item trailer from the note (rare but possible —
|
|
121
|
+
# a worker might paste the commit message into the close note).
|
|
122
|
+
if note:
|
|
123
|
+
trailer = parse_ledger_trailer(note)
|
|
124
|
+
if trailer:
|
|
125
|
+
proof["ledger_trailer"] = trailer
|
|
126
|
+
|
|
127
|
+
return proof
|
package/gateway/ai/license.py
CHANGED
|
@@ -20,12 +20,77 @@ try:
|
|
|
20
20
|
PRO_TOOLS as _CORE_PRO_TOOLS,
|
|
21
21
|
FREE_TRIAL_LIMITS,
|
|
22
22
|
)
|
|
23
|
-
# Extend compiled PRO_TOOLS with tools added after last binary build
|
|
23
|
+
# Extend compiled PRO_TOOLS with tools added after last binary build.
|
|
24
|
+
# LED-1260: keep this in lockstep with the fallback set below — any tool
|
|
25
|
+
# in the fallback PRO_TOOLS that's NOT in the compiled set must be added
|
|
26
|
+
# here, otherwise customers with the binary get those tools FREE while
|
|
27
|
+
# customers without the binary pay for them (regression-on-success).
|
|
28
|
+
# The runtime test in tests/test_license.py asserts both sets are
|
|
29
|
+
# equal. LED-1410 makes this stronger: the extension set below is
|
|
30
|
+
# CODEGEN from ai/pro_tools.yaml (same SSoT as the compiled
|
|
31
|
+
# set), so the two are equal by construction. The | union with
|
|
32
|
+
# _CORE_PRO_TOOLS is preserved so OLDER compiled .so files that
|
|
33
|
+
# were built before a YAML addition still pick up the new tool
|
|
34
|
+
# at runtime.
|
|
24
35
|
PRO_TOOLS = _CORE_PRO_TOOLS | frozenset({
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
36
|
+
# CODEGEN-START: EXTENSION_PRO_TOOLS
|
|
37
|
+
"delimit_agent_complete",
|
|
38
|
+
"delimit_agent_dispatch",
|
|
39
|
+
"delimit_agent_handoff",
|
|
40
|
+
"delimit_agent_status",
|
|
41
|
+
"delimit_cost_alert",
|
|
42
|
+
"delimit_cost_analyze",
|
|
43
|
+
"delimit_cost_optimize",
|
|
44
|
+
"delimit_deliberate",
|
|
45
|
+
"delimit_deploy_build",
|
|
46
|
+
"delimit_deploy_npm",
|
|
47
|
+
"delimit_deploy_plan",
|
|
48
|
+
"delimit_deploy_publish",
|
|
49
|
+
"delimit_deploy_rollback",
|
|
50
|
+
"delimit_deploy_site",
|
|
51
|
+
"delimit_deploy_status",
|
|
52
|
+
"delimit_deploy_verify",
|
|
53
|
+
"delimit_evidence_collect",
|
|
54
|
+
"delimit_evidence_verify",
|
|
55
|
+
"delimit_executor",
|
|
56
|
+
"delimit_gov_evaluate",
|
|
57
|
+
"delimit_gov_new_task",
|
|
58
|
+
"delimit_gov_policy",
|
|
59
|
+
"delimit_gov_run",
|
|
60
|
+
"delimit_gov_verify",
|
|
61
|
+
"delimit_loop_config",
|
|
62
|
+
"delimit_loop_status",
|
|
63
|
+
"delimit_memory_search",
|
|
64
|
+
"delimit_models",
|
|
65
|
+
"delimit_next_task",
|
|
66
|
+
"delimit_notify",
|
|
67
|
+
"delimit_obs_logs",
|
|
68
|
+
"delimit_obs_metrics",
|
|
69
|
+
"delimit_obs_status",
|
|
70
|
+
"delimit_os_gates",
|
|
71
|
+
"delimit_os_plan",
|
|
72
|
+
"delimit_os_status",
|
|
73
|
+
"delimit_release_plan",
|
|
74
|
+
"delimit_release_status",
|
|
75
|
+
"delimit_release_sync",
|
|
76
|
+
"delimit_repo_analyze",
|
|
77
|
+
"delimit_repo_config_audit",
|
|
78
|
+
"delimit_repo_config_validate",
|
|
79
|
+
"delimit_repo_diagnose",
|
|
80
|
+
"delimit_screen_record",
|
|
81
|
+
"delimit_screenshot",
|
|
82
|
+
"delimit_security_deliberate",
|
|
83
|
+
"delimit_security_ingest",
|
|
84
|
+
"delimit_social_approve",
|
|
85
|
+
"delimit_social_generate",
|
|
86
|
+
"delimit_social_history",
|
|
87
|
+
"delimit_social_post",
|
|
88
|
+
"delimit_task_complete",
|
|
89
|
+
"delimit_test_coverage",
|
|
90
|
+
"delimit_vault_health",
|
|
91
|
+
"delimit_vault_search",
|
|
92
|
+
"delimit_vault_snapshot",
|
|
93
|
+
# CODEGEN-END: EXTENSION_PRO_TOOLS
|
|
29
94
|
})
|
|
30
95
|
except ImportError:
|
|
31
96
|
# license_core not available — three known cases:
|
|
@@ -50,49 +115,69 @@ except ImportError:
|
|
|
50
115
|
|
|
51
116
|
LICENSE_FILE = Path.home() / ".delimit" / "license.json"
|
|
52
117
|
|
|
118
|
+
# LED-1410: CODEGEN from ai/pro_tools.yaml — same SSoT as the
|
|
119
|
+
# compiled set above. Memory note preserved here for source readers:
|
|
120
|
+
# delimit_memory_store + delimit_memory_recent are FREE (LED-193).
|
|
121
|
+
# Only delimit_memory_search is Pro.
|
|
53
122
|
PRO_TOOLS = frozenset({
|
|
54
|
-
#
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
123
|
+
# CODEGEN-START: FALLBACK_PRO_TOOLS
|
|
124
|
+
"delimit_agent_complete",
|
|
125
|
+
"delimit_agent_dispatch",
|
|
126
|
+
"delimit_agent_handoff",
|
|
127
|
+
"delimit_agent_status",
|
|
128
|
+
"delimit_cost_alert",
|
|
129
|
+
"delimit_cost_analyze",
|
|
130
|
+
"delimit_cost_optimize",
|
|
131
|
+
"delimit_deliberate",
|
|
132
|
+
"delimit_deploy_build",
|
|
133
|
+
"delimit_deploy_npm",
|
|
134
|
+
"delimit_deploy_plan",
|
|
135
|
+
"delimit_deploy_publish",
|
|
136
|
+
"delimit_deploy_rollback",
|
|
137
|
+
"delimit_deploy_site",
|
|
138
|
+
"delimit_deploy_status",
|
|
139
|
+
"delimit_deploy_verify",
|
|
140
|
+
"delimit_evidence_collect",
|
|
141
|
+
"delimit_evidence_verify",
|
|
142
|
+
"delimit_executor",
|
|
143
|
+
"delimit_gov_evaluate",
|
|
144
|
+
"delimit_gov_new_task",
|
|
145
|
+
"delimit_gov_policy",
|
|
146
|
+
"delimit_gov_run",
|
|
147
|
+
"delimit_gov_verify",
|
|
148
|
+
"delimit_loop_config",
|
|
149
|
+
"delimit_loop_status",
|
|
150
|
+
"delimit_memory_search",
|
|
151
|
+
"delimit_models",
|
|
152
|
+
"delimit_next_task",
|
|
153
|
+
"delimit_notify",
|
|
154
|
+
"delimit_obs_logs",
|
|
155
|
+
"delimit_obs_metrics",
|
|
156
|
+
"delimit_obs_status",
|
|
157
|
+
"delimit_os_gates",
|
|
158
|
+
"delimit_os_plan",
|
|
159
|
+
"delimit_os_status",
|
|
160
|
+
"delimit_release_plan",
|
|
161
|
+
"delimit_release_status",
|
|
162
|
+
"delimit_release_sync",
|
|
163
|
+
"delimit_repo_analyze",
|
|
164
|
+
"delimit_repo_config_audit",
|
|
165
|
+
"delimit_repo_config_validate",
|
|
166
|
+
"delimit_repo_diagnose",
|
|
167
|
+
"delimit_screen_record",
|
|
168
|
+
"delimit_screenshot",
|
|
169
|
+
"delimit_security_deliberate",
|
|
170
|
+
"delimit_security_ingest",
|
|
171
|
+
"delimit_social_approve",
|
|
172
|
+
"delimit_social_generate",
|
|
173
|
+
"delimit_social_history",
|
|
174
|
+
"delimit_social_post",
|
|
175
|
+
"delimit_task_complete",
|
|
176
|
+
"delimit_test_coverage",
|
|
177
|
+
"delimit_vault_health",
|
|
178
|
+
"delimit_vault_search",
|
|
179
|
+
"delimit_vault_snapshot",
|
|
180
|
+
# CODEGEN-END: FALLBACK_PRO_TOOLS
|
|
96
181
|
})
|
|
97
182
|
FREE_TRIAL_LIMITS = {"delimit_deliberate": 3}
|
|
98
183
|
|
|
Binary file
|
|
@@ -7,7 +7,7 @@ import os
|
|
|
7
7
|
from pathlib import Path
|
|
8
8
|
import hashlib
|
|
9
9
|
|
|
10
|
-
PRO_TOOLS = frozenset({'
|
|
10
|
+
PRO_TOOLS = frozenset({'delimit_agent_complete', 'delimit_agent_dispatch', 'delimit_agent_handoff', 'delimit_agent_status', 'delimit_cost_alert', 'delimit_cost_analyze', 'delimit_cost_optimize', 'delimit_deliberate', 'delimit_deploy_build', 'delimit_deploy_npm', 'delimit_deploy_plan', 'delimit_deploy_publish', 'delimit_deploy_rollback', 'delimit_deploy_site', 'delimit_deploy_status', 'delimit_deploy_verify', 'delimit_evidence_collect', 'delimit_evidence_verify', 'delimit_executor', 'delimit_gov_evaluate', 'delimit_gov_policy', 'delimit_gov_run', 'delimit_gov_verify', 'delimit_memory_search', 'delimit_models', 'delimit_notify', 'delimit_obs_logs', 'delimit_obs_metrics', 'delimit_obs_status', 'delimit_os_gates', 'delimit_os_plan', 'delimit_os_status', 'delimit_release_plan', 'delimit_release_status', 'delimit_release_sync', 'delimit_screen_record', 'delimit_screenshot', 'delimit_social_generate', 'delimit_social_history', 'delimit_social_post', 'delimit_vault_health', 'delimit_vault_search', 'delimit_vault_snapshot'})
|
|
11
11
|
def needs_revalidation(data: dict) -> bool:
|
|
12
12
|
...
|
|
13
13
|
def revalidate_license(data: dict) -> dict:
|