delimit-cli 3.14.16 → 3.14.18
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/bin/delimit-cli.js +3 -0
- package/gateway/ai/agent_dispatch.py +458 -0
- package/gateway/ai/agent_policy.py +230 -0
- package/gateway/ai/drift_monitor.py +246 -0
- package/gateway/ai/server.py +791 -38
- package/lib/cross-model-hooks.js +104 -5
- package/package.json +1 -1
package/lib/cross-model-hooks.js
CHANGED
|
@@ -322,14 +322,14 @@ function installClaudeHooks(tool, hookConfig) {
|
|
|
322
322
|
if (!existingSecurity) {
|
|
323
323
|
config.hooks.PreToolUse.push({
|
|
324
324
|
matcher: 'Bash',
|
|
325
|
-
if: "command matches 'npm publish' or command matches 'npx deploy' or command matches 'deploy' or command matches 'release'",
|
|
325
|
+
if: "command matches 'npm publish' or command matches 'npx deploy' or command matches 'deploy' or command matches 'release' or command matches 'docker compose up' or command matches 'docker-compose up' or command matches 'docker build'",
|
|
326
326
|
hooks: [{
|
|
327
327
|
type: 'command',
|
|
328
|
-
command: `${npxCmd}
|
|
328
|
+
command: `${npxCmd} hook deploy-gate`,
|
|
329
329
|
timeout: 30,
|
|
330
330
|
}],
|
|
331
331
|
});
|
|
332
|
-
changes.push('PreToolUse:deploy-
|
|
332
|
+
changes.push('PreToolUse:deploy-gate');
|
|
333
333
|
}
|
|
334
334
|
}
|
|
335
335
|
}
|
|
@@ -696,14 +696,21 @@ async function hookSessionStart() {
|
|
|
696
696
|
lines.push('[Delimit] No policy file found -- run "delimit init" to set up governance');
|
|
697
697
|
}
|
|
698
698
|
|
|
699
|
-
//
|
|
699
|
+
// Auto-update check + install
|
|
700
700
|
try {
|
|
701
701
|
const pkgPath = path.join(__dirname, '..', 'package.json');
|
|
702
702
|
const currentVersion = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')).version;
|
|
703
703
|
const { execSync: execS } = require('child_process');
|
|
704
704
|
const latest = execS('npm view delimit-cli version 2>/dev/null', { encoding: 'utf-8', timeout: 5000 }).trim();
|
|
705
705
|
if (latest && latest !== currentVersion && latest > currentVersion) {
|
|
706
|
-
lines.push(`[Delimit]
|
|
706
|
+
lines.push(`[Delimit] Updating ${currentVersion} -> ${latest}...`);
|
|
707
|
+
try {
|
|
708
|
+
execS('npm install -g delimit-cli@latest 2>/dev/null', { timeout: 30000, stdio: 'pipe' });
|
|
709
|
+
execS('delimit-cli setup --yes 2>/dev/null', { timeout: 30000, stdio: 'pipe' });
|
|
710
|
+
lines.push(`[Delimit] Updated to ${latest}`);
|
|
711
|
+
} catch {
|
|
712
|
+
lines.push(`[Delimit] Auto-update failed. Run: npm install -g delimit-cli@latest`);
|
|
713
|
+
}
|
|
707
714
|
}
|
|
708
715
|
} catch { /* offline or timeout — skip silently */ }
|
|
709
716
|
|
|
@@ -937,6 +944,97 @@ async function hookPreCommit() {
|
|
|
937
944
|
|
|
938
945
|
// ---------------------------------------------------------------------------
|
|
939
946
|
// Exports
|
|
947
|
+
// ---------------------------------------------------------------------------
|
|
948
|
+
// Deploy gate hook — runs smoke test before any deploy (LED-024 feedback)
|
|
949
|
+
// ---------------------------------------------------------------------------
|
|
950
|
+
|
|
951
|
+
async function hookDeployGate() {
|
|
952
|
+
const lines = [];
|
|
953
|
+
lines.push('[Delimit] Deploy gate check');
|
|
954
|
+
lines.push('');
|
|
955
|
+
|
|
956
|
+
let blocked = false;
|
|
957
|
+
|
|
958
|
+
// 1. Check for common import/syntax errors
|
|
959
|
+
const cwd = process.cwd();
|
|
960
|
+
const hasDockerCompose = fs.existsSync(path.join(cwd, 'docker-compose.yml'))
|
|
961
|
+
|| fs.existsSync(path.join(cwd, 'docker-compose.yaml'))
|
|
962
|
+
|| fs.existsSync(path.join(cwd, 'compose.yml'));
|
|
963
|
+
|
|
964
|
+
// 2. Check for Python import errors if it's a Python project
|
|
965
|
+
const hasPython = fs.existsSync(path.join(cwd, 'requirements.txt'))
|
|
966
|
+
|| fs.existsSync(path.join(cwd, 'pyproject.toml'))
|
|
967
|
+
|| fs.existsSync(path.join(cwd, 'setup.py'));
|
|
968
|
+
|
|
969
|
+
if (hasPython) {
|
|
970
|
+
try {
|
|
971
|
+
// Find the main app module
|
|
972
|
+
const appDirs = ['app', 'src', 'api'];
|
|
973
|
+
for (const dir of appDirs) {
|
|
974
|
+
const initFile = path.join(cwd, dir, '__init__.py');
|
|
975
|
+
const mainFile = path.join(cwd, dir, 'main.py');
|
|
976
|
+
if (fs.existsSync(initFile) || fs.existsSync(mainFile)) {
|
|
977
|
+
try {
|
|
978
|
+
execSync(`python3 -c "import ${dir}" 2>&1`, {
|
|
979
|
+
encoding: 'utf-8',
|
|
980
|
+
timeout: 10000,
|
|
981
|
+
cwd,
|
|
982
|
+
});
|
|
983
|
+
lines.push(`[Delimit] ✓ ${dir}/ imports clean`);
|
|
984
|
+
} catch (e) {
|
|
985
|
+
lines.push(`[Delimit] ✗ ${dir}/ import error: ${e.stdout || e.stderr || e.message}`);
|
|
986
|
+
blocked = true;
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
} catch { /* ignore */ }
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
// 3. Check for Node.js syntax errors
|
|
994
|
+
const hasNode = fs.existsSync(path.join(cwd, 'package.json'));
|
|
995
|
+
if (hasNode) {
|
|
996
|
+
try {
|
|
997
|
+
execSync('node -e "require(\'./\')" 2>&1', {
|
|
998
|
+
encoding: 'utf-8',
|
|
999
|
+
timeout: 5000,
|
|
1000
|
+
cwd,
|
|
1001
|
+
});
|
|
1002
|
+
lines.push('[Delimit] ✓ Node.js entry point loads');
|
|
1003
|
+
} catch {
|
|
1004
|
+
// Not all projects have a main entry — skip silently
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
// 4. Check for uncommitted changes
|
|
1009
|
+
try {
|
|
1010
|
+
const status = execSync('git status --porcelain 2>/dev/null', {
|
|
1011
|
+
encoding: 'utf-8',
|
|
1012
|
+
timeout: 3000,
|
|
1013
|
+
cwd,
|
|
1014
|
+
}).trim();
|
|
1015
|
+
if (status) {
|
|
1016
|
+
const fileCount = status.split('\n').length;
|
|
1017
|
+
lines.push(`[Delimit] ⚠ ${fileCount} uncommitted file(s) — consider committing before deploy`);
|
|
1018
|
+
}
|
|
1019
|
+
} catch { /* not a git repo */ }
|
|
1020
|
+
|
|
1021
|
+
// 5. Result
|
|
1022
|
+
lines.push('');
|
|
1023
|
+
if (blocked) {
|
|
1024
|
+
lines.push('[Delimit] ✗ DEPLOY BLOCKED — fix import errors above');
|
|
1025
|
+
lines.push('[Delimit] Run: delimit_test_smoke for full diagnostics');
|
|
1026
|
+
} else {
|
|
1027
|
+
lines.push('[Delimit] ✓ Deploy gate passed');
|
|
1028
|
+
}
|
|
1029
|
+
lines.push('');
|
|
1030
|
+
|
|
1031
|
+
process.stdout.write(lines.join('\n') + '\n');
|
|
1032
|
+
|
|
1033
|
+
if (blocked) {
|
|
1034
|
+
process.exit(1);
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
|
|
940
1038
|
// ---------------------------------------------------------------------------
|
|
941
1039
|
|
|
942
1040
|
module.exports = {
|
|
@@ -954,6 +1052,7 @@ module.exports = {
|
|
|
954
1052
|
hookSessionStart,
|
|
955
1053
|
hookPreTool,
|
|
956
1054
|
hookPreCommit,
|
|
1055
|
+
hookDeployGate,
|
|
957
1056
|
countPendingStrategyItems,
|
|
958
1057
|
getTopStrategyItem,
|
|
959
1058
|
findClaudeHookGroup,
|
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.14.
|
|
4
|
+
"version": "3.14.18",
|
|
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": [
|