@integrity-labs/agt-cli 0.27.42 → 0.27.44

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/dist/bin/agt.js CHANGED
@@ -27,7 +27,7 @@ import {
27
27
  success,
28
28
  table,
29
29
  warn
30
- } from "../chunk-ZPBDGI7P.js";
30
+ } from "../chunk-BUJVZFTK.js";
31
31
  import {
32
32
  CHANNEL_REGISTRY,
33
33
  DEPLOYMENT_TEMPLATES,
@@ -56,8 +56,8 @@ import {
56
56
  } from "../chunk-GVM2KJOA.js";
57
57
 
58
58
  // src/bin/agt.ts
59
- import { join as join17 } from "path";
60
- import { homedir as homedir7 } from "os";
59
+ import { join as join18 } from "path";
60
+ import { homedir as homedir8 } from "os";
61
61
  import { Command } from "commander";
62
62
 
63
63
  // src/commands/whoami.ts
@@ -551,11 +551,11 @@ async function lintCommand(path) {
551
551
  process.exitCode = 1;
552
552
  return;
553
553
  }
554
- const { readdirSync: readdirSync4, statSync: statSync3 } = await import("fs");
555
- const entries = readdirSync4(augmentedDir);
554
+ const { readdirSync: readdirSync5, statSync: statSync4 } = await import("fs");
555
+ const entries = readdirSync5(augmentedDir);
556
556
  for (const entry of entries) {
557
557
  const entryPath = join2(augmentedDir, entry);
558
- if (statSync3(entryPath).isDirectory()) {
558
+ if (statSync4(entryPath).isDirectory()) {
559
559
  dirs.push({ name: entry, dir: entryPath });
560
560
  }
561
561
  }
@@ -4687,7 +4687,7 @@ import { execFileSync, execSync } from "child_process";
4687
4687
  import { existsSync as existsSync10, realpathSync as realpathSync2 } from "fs";
4688
4688
  import chalk18 from "chalk";
4689
4689
  import ora16 from "ora";
4690
- var cliVersion = true ? "0.27.42" : "dev";
4690
+ var cliVersion = true ? "0.27.44" : "dev";
4691
4691
  async function fetchLatestVersion() {
4692
4692
  const host2 = getHost();
4693
4693
  if (!host2) return null;
@@ -5059,6 +5059,111 @@ async function auditSubagentsCommand(options = {}) {
5059
5059
  }
5060
5060
  }
5061
5061
 
5062
+ // src/lib/mcp-render-allowlist-audit.ts
5063
+ import { readdirSync as readdirSync4, readFileSync as readFileSync10, statSync as statSync3 } from "fs";
5064
+ import { homedir as homedir7 } from "os";
5065
+ import { join as join17 } from "path";
5066
+ function expectedWildcard(serverKey) {
5067
+ return `mcp__${serverKey.replace(/-/g, "_")}__*`;
5068
+ }
5069
+ function parseMcpWildcardsFromToolsLine(content) {
5070
+ const toolsLine = content.split("\n").find((l) => l.startsWith("tools:"));
5071
+ if (!toolsLine) return null;
5072
+ const value = toolsLine.replace(/^tools:\s*/, "").trim();
5073
+ if (value.length === 0) return [];
5074
+ return value.split(/\s*,\s*/).map((t) => t.trim()).filter((t) => t.startsWith("mcp__"));
5075
+ }
5076
+ function readMcpServerKeys(mcpJsonPath) {
5077
+ try {
5078
+ const config = JSON.parse(readFileSync10(mcpJsonPath, "utf-8"));
5079
+ return Object.keys(config.mcpServers ?? {});
5080
+ } catch {
5081
+ return null;
5082
+ }
5083
+ }
5084
+ function auditMcpRenderAllowlist(rootDir = join17(homedir7(), ".augmented")) {
5085
+ const findings = [];
5086
+ let entries;
5087
+ try {
5088
+ entries = readdirSync4(rootDir);
5089
+ } catch {
5090
+ return findings;
5091
+ }
5092
+ for (const entry of entries) {
5093
+ const agentDir = join17(rootDir, entry);
5094
+ let s;
5095
+ try {
5096
+ s = statSync3(agentDir);
5097
+ } catch {
5098
+ continue;
5099
+ }
5100
+ if (!s.isDirectory() || entry.startsWith("_") || entry.startsWith(".")) continue;
5101
+ for (const scope of ["provision", "project"]) {
5102
+ const mcpJsonPath = scope === "provision" ? join17(agentDir, "provision", ".mcp.json") : join17(agentDir, "project", ".mcp.json");
5103
+ const keys = readMcpServerKeys(mcpJsonPath);
5104
+ if (keys === null || keys.length === 0) continue;
5105
+ const expected = new Set(keys.map(expectedWildcard));
5106
+ for (const subagent of ["channel-message-handler", "augmented-worker"]) {
5107
+ const mdPath = scope === "provision" ? join17(agentDir, ".claude", "agents", `${subagent}.md`) : join17(agentDir, "project", ".claude", "agents", `${subagent}.md`);
5108
+ let content;
5109
+ try {
5110
+ content = readFileSync10(mdPath, "utf-8");
5111
+ } catch {
5112
+ continue;
5113
+ }
5114
+ const declared = parseMcpWildcardsFromToolsLine(content);
5115
+ if (declared === null) continue;
5116
+ const declaredSet = new Set(declared);
5117
+ const missing = [...expected].filter((w) => !declaredSet.has(w));
5118
+ if (missing.length > 0) {
5119
+ findings.push({ agent: entry, subagent, scope, missing, file: mdPath });
5120
+ }
5121
+ }
5122
+ }
5123
+ }
5124
+ return findings;
5125
+ }
5126
+ function formatRenderDriftFinding(f) {
5127
+ return `[manager-worker] [mcp-render-drift] agent=${f.agent} subagent=${f.subagent} scope=${f.scope} missing=${JSON.stringify(f.missing)} file=${f.file}`;
5128
+ }
5129
+
5130
+ // src/commands/audit-mcp-render.ts
5131
+ async function auditMcpRenderCommand(options = {}) {
5132
+ const findings = auditMcpRenderAllowlist();
5133
+ if (options.json) {
5134
+ process.stdout.write(`${JSON.stringify({ findings }, null, 2)}
5135
+ `);
5136
+ } else if (findings.length === 0) {
5137
+ process.stdout.write(
5138
+ "No render drift found. Every managed agent's sub-agent .md `tools:` allowlist covers every server in its `.mcp.json`.\n"
5139
+ );
5140
+ } else {
5141
+ process.stdout.write(
5142
+ `Found ${findings.length} sub-agent .md file${findings.length === 1 ? "" : "s"} with a stale tools allowlist:
5143
+
5144
+ `
5145
+ );
5146
+ for (const f of findings) {
5147
+ process.stdout.write(` \u2022 ${f.agent}/${f.scope}/${f.subagent}.md
5148
+ `);
5149
+ process.stdout.write(` missing: ${f.missing.join(", ")}
5150
+ `);
5151
+ process.stdout.write(` file: ${f.file}
5152
+ `);
5153
+ }
5154
+ process.stdout.write(
5155
+ '\nA missing wildcard means the sub-agent will get "No such tool available." on any call to that MCP server. The fix is to force a re-render (e.g. by adding/removing any MCP server, which routes through syncMcpToProject), OR restart the manager so the next poll picks up the live `.mcp.json` state. The root-cause write path that bypassed the render chokepoint is tracked in ENG-5922.\n'
5156
+ );
5157
+ for (const f of findings) {
5158
+ process.stderr.write(`${formatRenderDriftFinding(f)}
5159
+ `);
5160
+ }
5161
+ }
5162
+ if (options.strict && findings.length > 0) {
5163
+ process.exit(2);
5164
+ }
5165
+ }
5166
+
5062
5167
  // src/commands/integration.ts
5063
5168
  import chalk19 from "chalk";
5064
5169
  import ora17 from "ora";
@@ -5360,7 +5465,7 @@ function handleError(err) {
5360
5465
  }
5361
5466
 
5362
5467
  // src/bin/agt.ts
5363
- var cliVersion2 = true ? "0.27.42" : "dev";
5468
+ var cliVersion2 = true ? "0.27.44" : "dev";
5364
5469
  var program = new Command();
5365
5470
  program.name("agt").description("Augmented CLI \u2014 agent provisioning and management").version(cliVersion2).option("--json", "Emit machine-readable JSON output (suppress spinners and colors)").option("--skip-update-check", "Skip the automatic update check on startup");
5366
5471
  program.hook("preAction", async (thisCommand, actionCommand) => {
@@ -5448,16 +5553,16 @@ host.command("pair <host-name>").description("Start an SSM port-forward + shell
5448
5553
  })
5449
5554
  );
5450
5555
  var manager = program.command("manager").description("Host config sync daemon \u2014 keeps local agent files in sync with API");
5451
- manager.command("start").description("Start the manager daemon (polls API for config changes and detects local drift)").option("--interval <seconds>", "Poll interval in seconds (min 5)", "10").option("--config-dir <dir>", "Config directory for agent files", join17(homedir7(), ".augmented")).option("--supervise", "Wrap the manager in a respawn-on-clean-exit loop so auto-upgrades can restart it transparently (ENG-4488)", false).action(managerStartCommand);
5452
- manager.command("stop").description("Stop the running manager daemon").option("--config-dir <dir>", "Config directory for agent files", join17(homedir7(), ".augmented")).action(managerStopCommand);
5453
- manager.command("status").description("Show the current manager daemon status and discovered agents").option("--config-dir <dir>", "Config directory for agent files", join17(homedir7(), ".augmented")).action(managerStatusCommand);
5454
- manager.command("watch").description("Live TUI dashboard \u2014 per-agent boxes, drill-in, log tail. Read-only (ENG-4555).").option("--config-dir <dir>", "Config directory for agent files", join17(homedir7(), ".augmented")).option("--no-tui", "Skip the TUI and stream the manager log to stdout instead (CI / scripts)").action(managerWatchCommand);
5455
- manager.command("install").description("Install OS-level supervisor (launchd LaunchAgent on macOS) so the manager auto-restarts after crash, reboot, or self-update (ENG-4593)").option("--interval <seconds>", "Poll interval in seconds (min 5)", "10").option("--config-dir <dir>", "Config directory for agent files", join17(homedir7(), ".augmented")).action(managerInstallCommand);
5556
+ manager.command("start").description("Start the manager daemon (polls API for config changes and detects local drift)").option("--interval <seconds>", "Poll interval in seconds (min 5)", "10").option("--config-dir <dir>", "Config directory for agent files", join18(homedir8(), ".augmented")).option("--supervise", "Wrap the manager in a respawn-on-clean-exit loop so auto-upgrades can restart it transparently (ENG-4488)", false).action(managerStartCommand);
5557
+ manager.command("stop").description("Stop the running manager daemon").option("--config-dir <dir>", "Config directory for agent files", join18(homedir8(), ".augmented")).action(managerStopCommand);
5558
+ manager.command("status").description("Show the current manager daemon status and discovered agents").option("--config-dir <dir>", "Config directory for agent files", join18(homedir8(), ".augmented")).action(managerStatusCommand);
5559
+ manager.command("watch").description("Live TUI dashboard \u2014 per-agent boxes, drill-in, log tail. Read-only (ENG-4555).").option("--config-dir <dir>", "Config directory for agent files", join18(homedir8(), ".augmented")).option("--no-tui", "Skip the TUI and stream the manager log to stdout instead (CI / scripts)").action(managerWatchCommand);
5560
+ manager.command("install").description("Install OS-level supervisor (launchd LaunchAgent on macOS) so the manager auto-restarts after crash, reboot, or self-update (ENG-4593)").option("--interval <seconds>", "Poll interval in seconds (min 5)", "10").option("--config-dir <dir>", "Config directory for agent files", join18(homedir8(), ".augmented")).action(managerInstallCommand);
5456
5561
  manager.command("uninstall").description("Remove the OS-level supervisor (launchctl unload + delete plist on macOS). Idempotent.").action(managerUninstallCommand);
5457
5562
  manager.command("install-system-unit").description("Install a system-level systemd unit (Linux, root) so the manager auto-starts on every boot. For headless EC2 hosts \u2014 survives reboot without `loginctl enable-linger`. (ENG-4706)").option("--interval <seconds>", "Poll interval in seconds (min 5)", "10").option("--config-dir <dir>", "Config directory for agent files (defaults to /root/.augmented or /home/<user>/.augmented)").option("--user <name>", "Unix user the manager runs as", "root").action(managerInstallSystemUnitCommand);
5458
5563
  manager.command("uninstall-system-unit").description("Remove the system-level systemd unit (Linux, root). Idempotent. (ENG-4706)").action(managerUninstallSystemUnitCommand);
5459
5564
  var agent = program.command("agent").description("Inspect and manage agents");
5460
- agent.command("show <code-name>").description("Display an agent's provisioned OpenClaw configuration").option("--config-dir <dir>", "Config directory", join17(homedir7(), ".augmented")).option("--all-channels", "Show all channels (including disabled)").action(agentShowCommand);
5565
+ agent.command("show <code-name>").description("Display an agent's provisioned OpenClaw configuration").option("--config-dir <dir>", "Config directory", join18(homedir8(), ".augmented")).option("--all-channels", "Show all channels (including disabled)").action(agentShowCommand);
5461
5566
  var kanban = program.command("kanban").description("Manage agent kanban boards");
5462
5567
  kanban.command("list").description("List kanban board items for an agent").requiredOption("--agent <code-name>", "Agent code name").action(kanbanListCommand);
5463
5568
  kanban.command("add <title>").description("Add a new item to an agent kanban board").requiredOption("--agent <code-name>", "Agent code name").option("--priority <1|2|3>", "Priority: 1=high, 2=medium, 3=low", "2").option("--status <status>", "Initial status: backlog | todo | in_progress", "todo").option("--description <text>", "Item description").option("--estimate <minutes>", "Estimated time in minutes").option("--deliverable <text>", "Expected output/deliverable").action(kanbanAddCommand);
@@ -5487,6 +5592,7 @@ integration.command("enrol").description("Enrol an integration with an API key o
5487
5592
  program.command("update").description("Check for and install CLI updates").option("--force", "Update even if manager or agent sessions are running").action(updateCommand);
5488
5593
  var audit = program.command("audit").description("Operator audits \u2014 sub-agent MCP bindings, etc.");
5489
5594
  audit.command("subagents").description("Find sub-agents whose tools allowlist would block mcp__* calls on dispatch (ENG-5897)").option("--strict", "Exit with code 2 if any findings (suitable for CI gating)").option("--json", "Emit findings as JSON to stdout").action(auditSubagentsCommand);
5595
+ audit.command("mcp-render").description("Find managed agents whose subagent .md tools allowlist is stale vs .mcp.json (ENG-5922)").option("--strict", "Exit with code 2 if any findings (suitable for CI gating)").option("--json", "Emit findings as JSON to stdout").action(auditMcpRenderCommand);
5490
5596
  var skipUpdateCheck = process.argv.includes("--skip-update-check") || process.argv.includes("--json") || process.argv[2] === "update";
5491
5597
  if (!skipUpdateCheck) {
5492
5598
  checkForUpdateOnStartup().catch(() => {