delimit-cli 3.1.1 → 3.2.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/bin/delimit-setup.js +39 -2
- package/gateway/ai/server.py +109 -0
- package/package.json +1 -1
package/bin/delimit-setup.js
CHANGED
|
@@ -262,8 +262,45 @@ Run full governance compliance checks. Verify security, policy compliance, evide
|
|
|
262
262
|
}
|
|
263
263
|
log(` ${green('✓')} ${installed} agents installed (${Object.keys(agents).length - installed} already existed)`);
|
|
264
264
|
|
|
265
|
-
// Step 5:
|
|
266
|
-
step(5, '
|
|
265
|
+
// Step 5: Create CLAUDE.md for first-run guidance
|
|
266
|
+
step(5, 'Setting up first-run guidance...');
|
|
267
|
+
|
|
268
|
+
const claudeMd = path.join(os.homedir(), 'CLAUDE.md');
|
|
269
|
+
if (!fs.existsSync(claudeMd)) {
|
|
270
|
+
fs.writeFileSync(claudeMd, `# Delimit AI Guardrails
|
|
271
|
+
|
|
272
|
+
Delimit governance tools are installed. On first use, try:
|
|
273
|
+
|
|
274
|
+
- "check governance health" — see the status of this project
|
|
275
|
+
- "initialize governance" — set up policies and ledger for this project
|
|
276
|
+
- "run test coverage" — measure test coverage
|
|
277
|
+
- "analyze this repo" — get a health report
|
|
278
|
+
|
|
279
|
+
## Quick Start
|
|
280
|
+
If this project hasn't been initialized for governance yet, say:
|
|
281
|
+
"initialize governance for this project"
|
|
282
|
+
|
|
283
|
+
This creates .delimit/policies.yml and a ledger directory.
|
|
284
|
+
|
|
285
|
+
## Available Agents
|
|
286
|
+
- /lint — check API specs for breaking changes
|
|
287
|
+
- /engineering — build, test, refactor with governance checks
|
|
288
|
+
- /governance — full compliance audit
|
|
289
|
+
|
|
290
|
+
## Key Tools
|
|
291
|
+
- delimit_init — bootstrap governance for a project
|
|
292
|
+
- delimit_lint — diff two OpenAPI specs
|
|
293
|
+
- delimit_test_coverage — measure test coverage
|
|
294
|
+
- delimit_gov_health — check governance status
|
|
295
|
+
- delimit_repo_analyze — full repo health report
|
|
296
|
+
`);
|
|
297
|
+
log(` ${green('✓')} Created ${claudeMd} with first-run guidance`);
|
|
298
|
+
} else {
|
|
299
|
+
log(` ${dim(' CLAUDE.md already exists — skipped')}`);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Step 6: Summary
|
|
303
|
+
step(6, 'Done!');
|
|
267
304
|
log('');
|
|
268
305
|
log(` ${green('Delimit is installed.')} Your AI agents are now monitored.`);
|
|
269
306
|
log('');
|
package/gateway/ai/server.py
CHANGED
|
@@ -1249,6 +1249,115 @@ def delimit_version() -> Dict[str, Any]:
|
|
|
1249
1249
|
}
|
|
1250
1250
|
|
|
1251
1251
|
|
|
1252
|
+
# ═══════════════════════════════════════════════════════════════════════
|
|
1253
|
+
# META TOOLS (help, diagnose)
|
|
1254
|
+
# ═══════════════════════════════════════════════════════════════════════
|
|
1255
|
+
|
|
1256
|
+
|
|
1257
|
+
TOOL_HELP = {
|
|
1258
|
+
"init": {"desc": "Initialize governance for a project", "example": "delimit_init(project_path='.', preset='default')", "params": "project_path (str), preset (strict|default|relaxed)"},
|
|
1259
|
+
"lint": {"desc": "Diff two OpenAPI specs and check policy violations", "example": "delimit_lint(old_spec='base.yaml', new_spec='new.yaml')", "params": "old_spec (path), new_spec (path), policy_file (optional path)"},
|
|
1260
|
+
"diff": {"desc": "Pure diff between two specs — no policy, just changes", "example": "delimit_diff(old_spec='base.yaml', new_spec='new.yaml')", "params": "old_spec (path), new_spec (path)"},
|
|
1261
|
+
"semver": {"desc": "Classify the semver bump for a spec change", "example": "delimit_semver(old_spec='base.yaml', new_spec='new.yaml', current_version='1.2.3')", "params": "old_spec, new_spec, current_version (optional)"},
|
|
1262
|
+
"explain": {"desc": "Human-readable explanation of API changes", "example": "delimit_explain(old_spec='base.yaml', new_spec='new.yaml', template='pr_comment')", "params": "old_spec, new_spec, template (developer|pr_comment|migration|changelog)"},
|
|
1263
|
+
"gov_health": {"desc": "Check governance status — is the project initialized?", "example": "delimit_gov_health(repo='.')", "params": "repo (path, default '.')"},
|
|
1264
|
+
"test_coverage": {"desc": "Measure test coverage for a project", "example": "delimit_test_coverage(project_path='.', threshold=80)", "params": "project_path, threshold (default 80)"},
|
|
1265
|
+
"repo_analyze": {"desc": "Full repo health report — code quality, security, dependencies", "example": "delimit_repo_analyze(target='.')", "params": "target (path)"},
|
|
1266
|
+
"zero_spec": {"desc": "Extract OpenAPI spec from source code (FastAPI, Express, NestJS)", "example": "delimit_zero_spec(project_dir='.')", "params": "project_dir (path)"},
|
|
1267
|
+
"sensor_github_issue": {"desc": "Monitor a GitHub issue for new comments", "example": "delimit_sensor_github_issue(repo='owner/repo', issue_number=123)", "params": "repo (owner/name), issue_number (int)"},
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
|
|
1271
|
+
@mcp.tool()
|
|
1272
|
+
def delimit_help(tool_name: str = "") -> Dict[str, Any]:
|
|
1273
|
+
"""Get help for a Delimit tool — what it does, parameters, and examples.
|
|
1274
|
+
|
|
1275
|
+
Args:
|
|
1276
|
+
tool_name: Tool name (e.g. 'lint', 'gov_health'). Leave empty for overview.
|
|
1277
|
+
"""
|
|
1278
|
+
if not tool_name:
|
|
1279
|
+
return {
|
|
1280
|
+
"message": "Delimit has 77 tools. Here are the most useful ones to start with:",
|
|
1281
|
+
"essential_tools": {k: v["desc"] for k, v in TOOL_HELP.items()},
|
|
1282
|
+
"tip": "Run delimit_help(tool_name='lint') for detailed help on a specific tool.",
|
|
1283
|
+
"all_tools": "Run delimit_version() for the complete list.",
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
# Normalize name
|
|
1287
|
+
clean = tool_name.replace("delimit_", "").replace("mcp__delimit__delimit_", "")
|
|
1288
|
+
info = TOOL_HELP.get(clean)
|
|
1289
|
+
if info:
|
|
1290
|
+
return {"tool": clean, **info}
|
|
1291
|
+
return {"error": f"No help for '{tool_name}'. Try: {', '.join(TOOL_HELP.keys())}"}
|
|
1292
|
+
|
|
1293
|
+
|
|
1294
|
+
@mcp.tool()
|
|
1295
|
+
def delimit_diagnose(project_path: str = ".") -> Dict[str, Any]:
|
|
1296
|
+
"""Diagnose your Delimit setup — check environment, config, and tool status.
|
|
1297
|
+
|
|
1298
|
+
Universal 'get me unstuck' command. Checks Python, MCP config, governance state,
|
|
1299
|
+
and reports any issues with suggested fixes.
|
|
1300
|
+
|
|
1301
|
+
Args:
|
|
1302
|
+
project_path: Project to diagnose.
|
|
1303
|
+
"""
|
|
1304
|
+
issues = []
|
|
1305
|
+
checks = {}
|
|
1306
|
+
|
|
1307
|
+
# Python version
|
|
1308
|
+
import sys
|
|
1309
|
+
checks["python"] = f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
|
|
1310
|
+
|
|
1311
|
+
# Check .delimit/ dir
|
|
1312
|
+
p = Path(project_path).resolve()
|
|
1313
|
+
delimit_dir = p / ".delimit"
|
|
1314
|
+
policies = delimit_dir / "policies.yml"
|
|
1315
|
+
ledger = delimit_dir / "ledger" / "events.jsonl"
|
|
1316
|
+
|
|
1317
|
+
checks["project_path"] = str(p)
|
|
1318
|
+
checks["delimit_initialized"] = delimit_dir.is_dir()
|
|
1319
|
+
checks["policies_file"] = policies.is_file()
|
|
1320
|
+
checks["ledger_file"] = ledger.is_file()
|
|
1321
|
+
|
|
1322
|
+
if not delimit_dir.is_dir():
|
|
1323
|
+
issues.append({
|
|
1324
|
+
"issue": "Project not initialized",
|
|
1325
|
+
"fix": "Run delimit_init(project_path='.') or say 'initialize governance for this project'",
|
|
1326
|
+
})
|
|
1327
|
+
elif not policies.is_file():
|
|
1328
|
+
issues.append({
|
|
1329
|
+
"issue": "Missing policies.yml",
|
|
1330
|
+
"fix": "Run delimit_init(project_path='.', preset='default')",
|
|
1331
|
+
})
|
|
1332
|
+
|
|
1333
|
+
# Check key dependencies
|
|
1334
|
+
for pkg in ["yaml", "pydantic", "packaging"]:
|
|
1335
|
+
try:
|
|
1336
|
+
__import__(pkg)
|
|
1337
|
+
checks[f"dep_{pkg}"] = True
|
|
1338
|
+
except ImportError:
|
|
1339
|
+
checks[f"dep_{pkg}"] = False
|
|
1340
|
+
issues.append({"issue": f"Missing Python package: {pkg}", "fix": f"pip install {pkg}"})
|
|
1341
|
+
|
|
1342
|
+
# Check fastmcp
|
|
1343
|
+
try:
|
|
1344
|
+
import fastmcp
|
|
1345
|
+
checks["fastmcp"] = True
|
|
1346
|
+
except ImportError:
|
|
1347
|
+
checks["fastmcp"] = False
|
|
1348
|
+
issues.append({"issue": "FastMCP not installed", "fix": "pip install fastmcp"})
|
|
1349
|
+
|
|
1350
|
+
# Summary
|
|
1351
|
+
status = "healthy" if not issues else "issues_found"
|
|
1352
|
+
return {
|
|
1353
|
+
"status": status,
|
|
1354
|
+
"checks": checks,
|
|
1355
|
+
"issues": issues,
|
|
1356
|
+
"issue_count": len(issues),
|
|
1357
|
+
"tip": "If everything looks good but tools aren't working, try restarting Claude Code.",
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
|
|
1252
1361
|
# ═══════════════════════════════════════════════════════════════════════
|
|
1253
1362
|
# ENTRY POINT
|
|
1254
1363
|
# ═══════════════════════════════════════════════════════════════════════
|