delimit-cli 4.5.13 → 4.6.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.
- package/CHANGELOG.md +45 -0
- package/README.md +9 -8
- package/bin/delimit-cli.js +162 -1
- package/bin/delimit-setup.js +46 -6
- package/gateway/ai/_compile_status.py +154 -0
- package/gateway/ai/agent_dispatch.py +36 -0
- package/gateway/ai/backends/tools_infra.py +150 -10
- package/gateway/ai/daemon.py +10 -0
- package/gateway/ai/daily_digest.py +1 -2
- package/gateway/ai/delimit_daemon.py +67 -0
- package/gateway/ai/dispatch_gate.py +399 -0
- package/gateway/ai/hot_reload.py +1 -2
- package/gateway/ai/led193_daemon/executor.py +9 -0
- package/gateway/ai/ledger_manager.py +9 -0
- package/gateway/ai/license_core.cpython-310-x86_64-linux-gnu.so +0 -0
- package/gateway/ai/notify.py +39 -0
- package/gateway/ai/outreach_substantive.py +676 -0
- package/gateway/ai/reaper.py +70 -0
- package/gateway/ai/reddit_scanner.py +10 -5
- package/gateway/ai/sensing/schema.py +1 -1
- package/gateway/ai/sensing/signal_store.py +0 -1
- package/gateway/ai/server.py +5171 -1462
- package/gateway/ai/social_capability/fit_floor.py +114 -12
- package/gateway/ai/tdqs_lint.py +611 -0
- package/gateway/ai/usage_allowlist.py +198 -0
- package/gateway/ai/workers/base.py +2 -2
- package/gateway/ai/workers/executor.py +32 -3
- package/gateway/ai/workers/outreach_drafter.py +0 -1
- package/gateway/ai/workers/pr_drafter.py +0 -1
- package/gateway/ai/x_ranker.py +12 -2
- package/gateway/core/json_schema_diff.py +25 -1
- package/lib/auth-signin.js +136 -0
- package/lib/auth-signout.js +169 -0
- package/lib/delimit-template.js +11 -0
- package/lib/migration-2092-banner.js +213 -0
- package/package.json +2 -2
- package/server.json +4 -4
package/lib/delimit-template.js
CHANGED
|
@@ -51,6 +51,17 @@ Non-trivial engineering work routes through in-session subagents, not in-thread
|
|
|
51
51
|
- **Session end or idle**: call \`delimit_soul_capture\` + \`delimit_session_handoff\`
|
|
52
52
|
- If returning user, summarize what's pending. If new project, call \`delimit_scan\`.
|
|
53
53
|
|
|
54
|
+
### Memory Rules
|
|
55
|
+
Delimit captures routine code changes from git automatically. You do NOT need to call \`memory_store\` for normal work.
|
|
56
|
+
|
|
57
|
+
Use \`delimit_memory_store\` when capturing:
|
|
58
|
+
- **Failed approaches** — "tried X, it didn't work because Y" (git only shows what survived, not dead ends)
|
|
59
|
+
- **Architecture decisions** — "chose PostgreSQL over Redis for sessions because Z"
|
|
60
|
+
- **Key context** — customer requirements, API constraints, deployment gotchas
|
|
61
|
+
- **Things that will confuse the next session** — non-obvious setups, workarounds, tech debt
|
|
62
|
+
|
|
63
|
+
Do NOT store: routine code changes, file lists, commit messages, status updates — these are in git.
|
|
64
|
+
|
|
54
65
|
### Code Development (debounced per edit batch)
|
|
55
66
|
- After editing UI/CSS: call \`delimit_design_validate_responsive\`
|
|
56
67
|
- After editing API specs: call \`delimit_lint\` + \`delimit_drift_check\`
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
// lib/migration-2092-banner.js
|
|
2
|
+
//
|
|
3
|
+
// LED-2095: one-time migration banner shown to existing Free-tier users
|
|
4
|
+
// who have BYOK deliberation configured. Surfaces the LED-2092 / LED-2093
|
|
5
|
+
// gateway behavior change: Free-tier BYOK deliberation is now operationally
|
|
6
|
+
// ephemeral (no persistent transcript, no signed attestation, no replay
|
|
7
|
+
// URL). Pro-tier behavior is unchanged.
|
|
8
|
+
//
|
|
9
|
+
// Trigger conditions (ALL must be true):
|
|
10
|
+
// 1. ~/.delimit/models.json exists with at least one BYOK entry
|
|
11
|
+
// (entry.enabled === true AND entry.api_key truthy)
|
|
12
|
+
// 2. User is on the Free tier (no Pro/Premium/Enterprise license active
|
|
13
|
+
// per the same check used by lib/wrap-engine.js)
|
|
14
|
+
// 3. The flag file ~/.delimit/migration_2092.shown does not exist yet
|
|
15
|
+
//
|
|
16
|
+
// On trigger: print the banner to stdout/stderr (caller's choice — we
|
|
17
|
+
// return the banner string and let the caller handle output) and write
|
|
18
|
+
// the flag file with `{ shown_at: ISO8601, version: <package version> }`
|
|
19
|
+
// so the banner never fires again on the same machine.
|
|
20
|
+
//
|
|
21
|
+
// Scope: trigger on the next deliberation-adjacent CLI call (deliberate,
|
|
22
|
+
// models). Do NOT trigger on every CLI call (would be noise). Do NOT
|
|
23
|
+
// trigger for Pro customers (no behavior change for them). Do NOT
|
|
24
|
+
// trigger for Free users without BYOK (they had no transcripts to lose).
|
|
25
|
+
|
|
26
|
+
const fs = require('fs');
|
|
27
|
+
const path = require('path');
|
|
28
|
+
const { delimitHome, homeSubpath } = require('./delimit-home');
|
|
29
|
+
|
|
30
|
+
const FLAG_FILE_BASENAME = 'migration_2092.shown';
|
|
31
|
+
const MODELS_CONFIG_BASENAME = 'models.json';
|
|
32
|
+
const LICENSE_FILE_BASENAME = 'license.json';
|
|
33
|
+
|
|
34
|
+
// Banner copy — locked. No em-dashes (per LED-2095 brief). No founder
|
|
35
|
+
// identity strings. Positive tone. The Pro upsell is a single line at
|
|
36
|
+
// the end with the pricing URL; do not expand without coordinated copy
|
|
37
|
+
// review.
|
|
38
|
+
const BANNER_BODY = [
|
|
39
|
+
'',
|
|
40
|
+
'Free deliberations now print to stdout only.',
|
|
41
|
+
'',
|
|
42
|
+
'Your existing transcripts under ~/.delimit/memory/deliberations/ are preserved.',
|
|
43
|
+
'New deliberations on Free tier are ephemeral by design.',
|
|
44
|
+
'',
|
|
45
|
+
'Pro turns every deliberation into a signed, replayable attestation',
|
|
46
|
+
'with 365-day retention: delimit.ai/pricing',
|
|
47
|
+
'',
|
|
48
|
+
].join('\n');
|
|
49
|
+
|
|
50
|
+
function flagFilePath() {
|
|
51
|
+
return homeSubpath(FLAG_FILE_BASENAME);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function modelsConfigPath() {
|
|
55
|
+
return homeSubpath(MODELS_CONFIG_BASENAME);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function licenseFilePath() {
|
|
59
|
+
return homeSubpath(LICENSE_FILE_BASENAME);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Detect whether the user has at least one BYOK model entry configured.
|
|
64
|
+
* Mirrors the truthiness rule used by bin/delimit-cli.js::getModelStatus:
|
|
65
|
+
* `entry.enabled === true AND entry.api_key truthy`.
|
|
66
|
+
*/
|
|
67
|
+
function hasByokConfigured() {
|
|
68
|
+
const p = modelsConfigPath();
|
|
69
|
+
if (!fs.existsSync(p)) return false;
|
|
70
|
+
let config;
|
|
71
|
+
try {
|
|
72
|
+
config = JSON.parse(fs.readFileSync(p, 'utf-8'));
|
|
73
|
+
} catch {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
if (!config || typeof config !== 'object' || Array.isArray(config)) {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
for (const entry of Object.values(config)) {
|
|
80
|
+
if (entry && typeof entry === 'object' && entry.enabled && entry.api_key) {
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Detect whether the user has an active Pro/Premium/Enterprise license.
|
|
89
|
+
* Mirrors the rule used by lib/wrap-engine.js::checkQuota — keep these in
|
|
90
|
+
* lockstep. A missing/malformed license.json means Free.
|
|
91
|
+
*/
|
|
92
|
+
function hasProLicense() {
|
|
93
|
+
const p = licenseFilePath();
|
|
94
|
+
if (!fs.existsSync(p)) return false;
|
|
95
|
+
try {
|
|
96
|
+
const lic = JSON.parse(fs.readFileSync(p, 'utf-8'));
|
|
97
|
+
if (lic && lic.valid && ['pro', 'premium', 'enterprise'].includes(lic.tier)) {
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
} catch {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Check whether the migration flag file has already been written. Once
|
|
108
|
+
* written, the banner is suppressed forever on this machine (the file is
|
|
109
|
+
* the source of truth — even a corrupt JSON body counts as "shown" so a
|
|
110
|
+
* partially-written flag does not re-trigger the banner).
|
|
111
|
+
*/
|
|
112
|
+
function hasShownBanner() {
|
|
113
|
+
return fs.existsSync(flagFilePath());
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Should the banner trigger right now? All three conditions must hold:
|
|
118
|
+
* BYOK configured, no Pro license, flag file absent.
|
|
119
|
+
*/
|
|
120
|
+
function shouldShowBanner() {
|
|
121
|
+
if (hasShownBanner()) return false;
|
|
122
|
+
if (hasProLicense()) return false;
|
|
123
|
+
if (!hasByokConfigured()) return false;
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Persist the flag file so the banner never fires again. Best-effort:
|
|
129
|
+
* directory is created at 0700 if missing, file is written at default
|
|
130
|
+
* mode (no secrets in this file — just a timestamp + version).
|
|
131
|
+
*
|
|
132
|
+
* @param {object} [args]
|
|
133
|
+
* @param {string} [args.now] ISO8601 override for tests
|
|
134
|
+
* @param {string} [args.version] CLI version string
|
|
135
|
+
*/
|
|
136
|
+
function writeShownFlag(args) {
|
|
137
|
+
const opts = args || {};
|
|
138
|
+
const home = delimitHome();
|
|
139
|
+
if (!fs.existsSync(home)) {
|
|
140
|
+
fs.mkdirSync(home, { recursive: true, mode: 0o700 });
|
|
141
|
+
}
|
|
142
|
+
const payload = {
|
|
143
|
+
shown_at: opts.now || new Date().toISOString(),
|
|
144
|
+
version: opts.version || resolveCliVersion(),
|
|
145
|
+
led: 'LED-2095',
|
|
146
|
+
};
|
|
147
|
+
const tmpPath = flagFilePath() + '.tmp';
|
|
148
|
+
fs.writeFileSync(tmpPath, JSON.stringify(payload, null, 2));
|
|
149
|
+
fs.renameSync(tmpPath, flagFilePath());
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function resolveCliVersion() {
|
|
153
|
+
try {
|
|
154
|
+
// package.json sits two levels up from lib/migration-2092-banner.js
|
|
155
|
+
const pkg = require(path.join(__dirname, '..', 'package.json'));
|
|
156
|
+
return pkg.version || 'unknown';
|
|
157
|
+
} catch {
|
|
158
|
+
return 'unknown';
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* The exact banner text shown to triggered users. Exposed so tests can
|
|
164
|
+
* snapshot it without re-running the trigger logic.
|
|
165
|
+
*/
|
|
166
|
+
function bannerText() {
|
|
167
|
+
return BANNER_BODY;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Composite entry point used by the CLI. If conditions are met, returns
|
|
172
|
+
* the banner string AND writes the flag file. If conditions are not met,
|
|
173
|
+
* returns "" and does not touch the filesystem.
|
|
174
|
+
*
|
|
175
|
+
* The CLI is responsible for printing the returned string. Returning the
|
|
176
|
+
* string (rather than printing here) keeps this module side-effect-light
|
|
177
|
+
* and lets tests assert on the output without capturing stdout.
|
|
178
|
+
*
|
|
179
|
+
* @param {object} [args]
|
|
180
|
+
* @param {string} [args.now] ISO8601 override for the flag-file
|
|
181
|
+
* timestamp (deterministic tests)
|
|
182
|
+
* @param {string} [args.version] Override the CLI version string
|
|
183
|
+
* @returns {{ shown: boolean, text: string }}
|
|
184
|
+
*/
|
|
185
|
+
function maybeShowMigrationBanner(args) {
|
|
186
|
+
if (!shouldShowBanner()) {
|
|
187
|
+
return { shown: false, text: '' };
|
|
188
|
+
}
|
|
189
|
+
try {
|
|
190
|
+
writeShownFlag(args);
|
|
191
|
+
} catch {
|
|
192
|
+
// If we cannot persist the flag, do NOT show the banner —
|
|
193
|
+
// showing it without persisting would re-fire on every call.
|
|
194
|
+
return { shown: false, text: '' };
|
|
195
|
+
}
|
|
196
|
+
return { shown: true, text: bannerText() };
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
module.exports = {
|
|
200
|
+
FLAG_FILE_BASENAME,
|
|
201
|
+
MODELS_CONFIG_BASENAME,
|
|
202
|
+
LICENSE_FILE_BASENAME,
|
|
203
|
+
flagFilePath,
|
|
204
|
+
modelsConfigPath,
|
|
205
|
+
licenseFilePath,
|
|
206
|
+
hasByokConfigured,
|
|
207
|
+
hasProLicense,
|
|
208
|
+
hasShownBanner,
|
|
209
|
+
shouldShowBanner,
|
|
210
|
+
writeShownFlag,
|
|
211
|
+
bannerText,
|
|
212
|
+
maybeShowMigrationBanner,
|
|
213
|
+
};
|
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": "4.
|
|
4
|
+
"version": "4.6.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": [
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"postinstall": "node scripts/postinstall.js",
|
|
57
57
|
"sync-gateway": "bash scripts/sync-gateway.sh",
|
|
58
58
|
"prepublishOnly": "bash scripts/publish-ci-guard.sh && npm run sync-gateway && bash scripts/build-license-core.sh && bash scripts/security-check.sh",
|
|
59
|
-
"test": "node --test tests/setup-onboarding.test.js tests/setup-matrix.test.js tests/setup-no-clobber.test.js tests/config-export-import.test.js tests/cross-model-hooks.test.js tests/golden-path.test.js tests/v420-features.test.js tests/v43-wrap-engine.test.js tests/v43-trust-page-engine.test.js tests/v43-ai-sbom-engine.test.js tests/attest-mcp.test.js tests/delimit-home.test.js tests/postinstall-hardening.test.js"
|
|
59
|
+
"test": "node --test tests/setup-onboarding.test.js tests/setup-matrix.test.js tests/setup-no-clobber.test.js tests/config-export-import.test.js tests/cross-model-hooks.test.js tests/golden-path.test.js tests/v420-features.test.js tests/v43-wrap-engine.test.js tests/v43-trust-page-engine.test.js tests/v43-ai-sbom-engine.test.js tests/attest-mcp.test.js tests/delimit-home.test.js tests/postinstall-hardening.test.js tests/auth-signin.test.js tests/auth-signout.test.js tests/migration-2092-banner.test.js"
|
|
60
60
|
},
|
|
61
61
|
"keywords": [
|
|
62
62
|
"openapi",
|
package/server.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
3
|
"name": "io.github.delimit-ai/delimit-mcp-server",
|
|
4
|
-
"title": "Delimit —
|
|
5
|
-
"description": "
|
|
4
|
+
"title": "Delimit — The merge gate for AI-written code",
|
|
5
|
+
"description": "The merge gate for AI-written code. Cross-vendor adjudication of every AI-assisted merge with a signed, replayable attestation. Persistent ledger and multi-model deliberation across Claude, Codex, Cursor, and Gemini CLI.",
|
|
6
6
|
"repository": {
|
|
7
7
|
"url": "https://github.com/delimit-ai/delimit-mcp-server",
|
|
8
8
|
"source": "github"
|
|
9
9
|
},
|
|
10
|
-
"version": "4.
|
|
10
|
+
"version": "4.5.13",
|
|
11
11
|
"websiteUrl": "https://delimit.ai",
|
|
12
12
|
"packages": [
|
|
13
13
|
{
|
|
14
14
|
"registryType": "npm",
|
|
15
15
|
"identifier": "delimit-cli",
|
|
16
|
-
"version": "4.
|
|
16
|
+
"version": "4.5.13",
|
|
17
17
|
"transport": {
|
|
18
18
|
"type": "stdio"
|
|
19
19
|
}
|