@node9/proxy 1.21.0 → 1.21.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/dist/cli.js CHANGED
@@ -13728,10 +13728,10 @@ function readSessionUsage() {
13728
13728
  }
13729
13729
  }
13730
13730
  function formatContextStat(stat) {
13731
- const pctColor = stat.fillPct >= 80 ? import_chalk30.default.red : stat.fillPct >= 50 ? import_chalk30.default.yellow : import_chalk30.default.cyan;
13731
+ const pctColor = stat.fillPct >= 80 ? import_chalk29.default.red : stat.fillPct >= 50 ? import_chalk29.default.yellow : import_chalk29.default.cyan;
13732
13732
  const k = (n) => `${Math.round(n / 1e3)}k`;
13733
13733
  const modelShort = stat.model.replace(/@.*$/, "").replace(/-\d{8}$/, "").replace(/^claude-/, "");
13734
- return import_chalk30.default.dim("ctx: ") + pctColor(`${stat.fillPct}%`) + import_chalk30.default.dim(
13734
+ return import_chalk29.default.dim("ctx: ") + pctColor(`${stat.fillPct}%`) + import_chalk29.default.dim(
13735
13735
  ` (${k(stat.inputTokens)}/${k(getModelContextLimit(stat.model))} out ${k(stat.outputTokens)} \xB7 ${modelShort})`
13736
13736
  );
13737
13737
  }
@@ -13754,11 +13754,11 @@ function agentLabel(agent, mcpServer, sessionId) {
13754
13754
  const tag = sessionTag(sessionId);
13755
13755
  const tagSuffix = tag ? `\xB7${tag}` : "";
13756
13756
  if (!agent || agent === "Terminal") {
13757
- return mcpServer ? import_chalk30.default.dim(`[\u2192 ${mcpServer}] `) : "";
13757
+ return mcpServer ? import_chalk29.default.dim(`[\u2192 ${mcpServer}] `) : "";
13758
13758
  }
13759
13759
  const short = agent === "Claude Code" ? "Claude" : agent === "Gemini CLI" ? "Gemini" : agent === "Unknown Agent" ? "" : agent.split(" ")[0];
13760
- if (!short) return mcpServer ? import_chalk30.default.dim(`[\u2192 ${mcpServer}] `) : "";
13761
- return mcpServer ? import_chalk30.default.dim(`[${short}${tagSuffix} \u2192 ${mcpServer}] `) : import_chalk30.default.dim(`[${short}${tagSuffix}] `);
13760
+ if (!short) return mcpServer ? import_chalk29.default.dim(`[\u2192 ${mcpServer}] `) : "";
13761
+ return mcpServer ? import_chalk29.default.dim(`[${short}${tagSuffix} \u2192 ${mcpServer}] `) : import_chalk29.default.dim(`[${short}${tagSuffix}] `);
13762
13762
  }
13763
13763
  function formatBase(activity) {
13764
13764
  const time = new Date(activity.ts).toLocaleTimeString([], { hour12: false });
@@ -13766,20 +13766,20 @@ function formatBase(activity) {
13766
13766
  const toolName = activity.tool.slice(0, 16).padEnd(16);
13767
13767
  const argsStr = JSON.stringify(activity.args ?? {}).replace(/\s+/g, " ").replaceAll(import_os41.default.homedir(), "~");
13768
13768
  const argsPreview = argsStr.length > 70 ? argsStr.slice(0, 70) + "\u2026" : argsStr;
13769
- return `${import_chalk30.default.gray(time)} ${icon} ${agentLabel(activity.agent, activity.mcpServer, activity.sessionId)}${import_chalk30.default.white.bold(toolName)} ${import_chalk30.default.dim(argsPreview)}`;
13769
+ return `${import_chalk29.default.gray(time)} ${icon} ${agentLabel(activity.agent, activity.mcpServer, activity.sessionId)}${import_chalk29.default.white.bold(toolName)} ${import_chalk29.default.dim(argsPreview)}`;
13770
13770
  }
13771
13771
  function renderResult(activity, result) {
13772
13772
  const base = formatBase(activity);
13773
13773
  let status;
13774
13774
  if (result.status === "allow") {
13775
- status = import_chalk30.default.green("\u2713 ALLOW");
13775
+ status = import_chalk29.default.green("\u2713 ALLOW");
13776
13776
  } else if (result.status === "dlp") {
13777
- status = import_chalk30.default.bgRed.white.bold(" \u{1F6E1}\uFE0F DLP ");
13777
+ status = import_chalk29.default.bgRed.white.bold(" \u{1F6E1}\uFE0F DLP ");
13778
13778
  } else {
13779
- status = import_chalk30.default.red("\u2717 BLOCK");
13779
+ status = import_chalk29.default.red("\u2717 BLOCK");
13780
13780
  }
13781
13781
  const cost = result.costEstimate ?? activity.costEstimate;
13782
- const costSuffix = cost == null ? "" : import_chalk30.default.dim(` ~$${cost >= 1e-3 ? cost.toFixed(3) : "0.000"}`);
13782
+ const costSuffix = cost == null ? "" : import_chalk29.default.dim(` ~$${cost >= 1e-3 ? cost.toFixed(3) : "0.000"}`);
13783
13783
  if (process.stdout.isTTY) {
13784
13784
  if (pendingShownForId === activity.id && pendingWrappedLines > 1) {
13785
13785
  import_readline6.default.moveCursor(process.stdout, 0, -(pendingWrappedLines - 1));
@@ -13796,7 +13796,7 @@ function renderResult(activity, result) {
13796
13796
  }
13797
13797
  function renderPending(activity) {
13798
13798
  if (!process.stdout.isTTY) return;
13799
- const line = `${formatBase(activity)} ${import_chalk30.default.yellow("\u25CF \u2026")}`;
13799
+ const line = `${formatBase(activity)} ${import_chalk29.default.yellow("\u25CF \u2026")}`;
13800
13800
  pendingShownForId = activity.id;
13801
13801
  pendingWrappedLines = wrappedLineCount(line);
13802
13802
  process.stdout.write(`${line}\r`);
@@ -13808,7 +13808,7 @@ async function ensureDaemon() {
13808
13808
  const { port } = JSON.parse(import_fs45.default.readFileSync(PID_FILE, "utf-8"));
13809
13809
  pidPort = port;
13810
13810
  } catch {
13811
- console.error(import_chalk30.default.dim("\u26A0\uFE0F Could not read PID file; falling back to default port."));
13811
+ console.error(import_chalk29.default.dim("\u26A0\uFE0F Could not read PID file; falling back to default port."));
13812
13812
  }
13813
13813
  }
13814
13814
  const checkPort = pidPort ?? DAEMON_PORT;
@@ -13819,8 +13819,8 @@ async function ensureDaemon() {
13819
13819
  if (res.ok) return checkPort;
13820
13820
  } catch {
13821
13821
  }
13822
- console.log(import_chalk30.default.dim("\u{1F6E1}\uFE0F Starting Node9 daemon..."));
13823
- const child = (0, import_child_process13.spawn)(process.execPath, [process.argv[1], "daemon"], {
13822
+ console.log(import_chalk29.default.dim("\u{1F6E1}\uFE0F Starting Node9 daemon..."));
13823
+ const child = (0, import_child_process12.spawn)(process.execPath, [process.argv[1], "daemon"], {
13824
13824
  detached: true,
13825
13825
  stdio: "ignore",
13826
13826
  env: { ...process.env, NODE9_AUTO_STARTED: "1" }
@@ -13836,7 +13836,7 @@ async function ensureDaemon() {
13836
13836
  } catch {
13837
13837
  }
13838
13838
  }
13839
- console.error(import_chalk30.default.red("\u274C Daemon failed to start. Try: node9 daemon start"));
13839
+ console.error(import_chalk29.default.red("\u274C Daemon failed to start. Try: node9 daemon start"));
13840
13840
  process.exit(1);
13841
13841
  }
13842
13842
  function postDecisionHttp(id, decision, authToken, port, opts) {
@@ -13905,7 +13905,7 @@ function buildCardLines(req, localCount = 0) {
13905
13905
  const severityIcon = isBlock ? `${RED}\u{1F6D1}` : `${YELLOW}\u26A0 `;
13906
13906
  const rawDesc = req.riskMetadata?.ruleDescription ?? "";
13907
13907
  const description = rawDesc ? cleanReason(rawDesc) : "";
13908
- const agentSuffix = req.agent && req.agent !== "Terminal" ? ` ${RESET2}${import_chalk30.default.dim(`(${req.agent})`)}` : "";
13908
+ const agentSuffix = req.agent && req.agent !== "Terminal" ? ` ${RESET2}${import_chalk29.default.dim(`(${req.agent})`)}` : "";
13909
13909
  const lines = [
13910
13910
  ``,
13911
13911
  `${BOLD2}${CYAN}\u2554\u2550\u2550 Node9 Approval Required \u2550\u2550\u2557${RESET2}`,
@@ -13974,7 +13974,7 @@ function approverStatusLine() {
13974
13974
  const a = readApproversFromDisk();
13975
13975
  const fmt = (label, key) => {
13976
13976
  const on = a[key] !== false;
13977
- return `[${key[0]}]${label.slice(1)} ${on ? import_chalk30.default.green("\u2713") : import_chalk30.default.dim("\u2717")}`;
13977
+ return `[${key[0]}]${label.slice(1)} ${on ? import_chalk29.default.green("\u2713") : import_chalk29.default.dim("\u2717")}`;
13978
13978
  };
13979
13979
  return `${fmt("native", "native")} ${fmt("cloud", "cloud")} ${fmt("terminal", "terminal")}`;
13980
13980
  }
@@ -14019,7 +14019,7 @@ async function startTail(options = {}) {
14019
14019
  req2.end();
14020
14020
  });
14021
14021
  if (result.ok) {
14022
- console.log(import_chalk30.default.green("\u2713 Flight Recorder buffer cleared."));
14022
+ console.log(import_chalk29.default.green("\u2713 Flight Recorder buffer cleared."));
14023
14023
  } else if (result.code === "ECONNREFUSED") {
14024
14024
  throw new Error("Daemon is not running. Start it with: node9 daemon start");
14025
14025
  } else if (result.code === "ETIMEDOUT") {
@@ -14065,7 +14065,7 @@ async function startTail(options = {}) {
14065
14065
  const channel = name === "n" ? "native" : name === "c" ? "cloud" : name === "t" ? "terminal" : null;
14066
14066
  if (channel) {
14067
14067
  toggleApprover(channel);
14068
- console.log(import_chalk30.default.dim(` Approvers: ${approverStatusLine()}`));
14068
+ console.log(import_chalk29.default.dim(` Approvers: ${approverStatusLine()}`));
14069
14069
  }
14070
14070
  };
14071
14071
  process.stdin.on("keypress", idleKeypressHandler);
@@ -14131,7 +14131,7 @@ async function startTail(options = {}) {
14131
14131
  localAllowCounts.get(req2.toolName) ?? 0
14132
14132
  )
14133
14133
  );
14134
- const decisionStamp = action === "always-allow" ? import_chalk30.default.yellow("\u2605 ALWAYS ALLOW") : action === "trust" ? import_chalk30.default.cyan("\u23F1 TRUST 30m") : action === "allow" ? import_chalk30.default.green("\u2713 ALLOWED") : action === "redirect" ? import_chalk30.default.yellow("\u21A9 REDIRECT AI") : import_chalk30.default.red("\u2717 DENIED");
14134
+ const decisionStamp = action === "always-allow" ? import_chalk29.default.yellow("\u2605 ALWAYS ALLOW") : action === "trust" ? import_chalk29.default.cyan("\u23F1 TRUST 30m") : action === "allow" ? import_chalk29.default.green("\u2713 ALLOWED") : action === "redirect" ? import_chalk29.default.yellow("\u21A9 REDIRECT AI") : import_chalk29.default.red("\u2717 DENIED");
14135
14135
  stampedLines.push(` ${BOLD2}\u2192${RESET2} ${decisionStamp} ${GRAY}(terminal)${RESET2}`, ``);
14136
14136
  for (const line of stampedLines) process.stdout.write(line + "\n");
14137
14137
  process.stdout.write(SHOW_CURSOR);
@@ -14182,7 +14182,7 @@ async function startTail(options = {}) {
14182
14182
  );
14183
14183
  const stampedLines = buildCardLines(req2, priorCount);
14184
14184
  if (externalDecision) {
14185
- const source = externalDecision === "allow" ? import_chalk30.default.green("\u2713 ALLOWED") : import_chalk30.default.red("\u2717 DENIED");
14185
+ const source = externalDecision === "allow" ? import_chalk29.default.green("\u2713 ALLOWED") : import_chalk29.default.red("\u2717 DENIED");
14186
14186
  stampedLines.push(` ${BOLD2}\u2192${RESET2} ${source} ${GRAY}(external)${RESET2}`, ``);
14187
14187
  }
14188
14188
  for (const line of stampedLines) process.stdout.write(line + "\n");
@@ -14230,25 +14230,25 @@ async function startTail(options = {}) {
14230
14230
  if (unackedDlp > 0) {
14231
14231
  console.log("");
14232
14232
  console.log(
14233
- import_chalk30.default.bgRed.white.bold(
14233
+ import_chalk29.default.bgRed.white.bold(
14234
14234
  ` \u26A0\uFE0F DLP ALERT: ${unackedDlp} secret${unackedDlp !== 1 ? "s" : ""} found in Claude response text \u2014 run: node9 dlp `
14235
14235
  )
14236
14236
  );
14237
14237
  }
14238
14238
  } catch {
14239
14239
  }
14240
- console.log(import_chalk30.default.cyan.bold(`
14240
+ console.log(import_chalk29.default.cyan.bold(`
14241
14241
  \u{1F6F0}\uFE0F Node9 tail`));
14242
14242
  if (canApprove) {
14243
- console.log(import_chalk30.default.dim("Card: [\u21B5/y] Allow [n] Deny [a] Always [t] Trust 30m"));
14244
- console.log(import_chalk30.default.dim(`Approvers (toggle): ${approverStatusLine()} [q] quit`));
14243
+ console.log(import_chalk29.default.dim("Card: [\u21B5/y] Allow [n] Deny [a] Always [t] Trust 30m"));
14244
+ console.log(import_chalk29.default.dim(`Approvers (toggle): ${approverStatusLine()} [q] quit`));
14245
14245
  }
14246
14246
  const ctxStat = readSessionUsage();
14247
14247
  if (ctxStat) console.log(" " + formatContextStat(ctxStat));
14248
14248
  if (options.history) {
14249
- console.log(import_chalk30.default.dim("Showing history + live events.\n"));
14249
+ console.log(import_chalk29.default.dim("Showing history + live events.\n"));
14250
14250
  } else {
14251
- console.log(import_chalk30.default.dim("Showing live events only. Use --history to include past.\n"));
14251
+ console.log(import_chalk29.default.dim("Showing live events only. Use --history to include past.\n"));
14252
14252
  }
14253
14253
  process.on("SIGINT", () => {
14254
14254
  exitIdleMode();
@@ -14258,7 +14258,7 @@ async function startTail(options = {}) {
14258
14258
  import_readline6.default.clearLine(process.stdout, 0);
14259
14259
  import_readline6.default.cursorTo(process.stdout, 0);
14260
14260
  }
14261
- console.log(import_chalk30.default.dim("\n\u{1F6F0}\uFE0F Disconnected."));
14261
+ console.log(import_chalk29.default.dim("\n\u{1F6F0}\uFE0F Disconnected."));
14262
14262
  process.exit(0);
14263
14263
  });
14264
14264
  const STALL_THRESHOLD_MS = 6e4;
@@ -14270,7 +14270,7 @@ async function startTail(options = {}) {
14270
14270
  if (Date.now() - auditMtime >= STALL_THRESHOLD_MS) return;
14271
14271
  console.log("");
14272
14272
  console.log(
14273
- import_chalk30.default.yellow(
14273
+ import_chalk29.default.yellow(
14274
14274
  "\u26A0\uFE0F Tail appears stalled \u2014 hooks are firing but no events are arriving. Try: node9 daemon restart"
14275
14275
  )
14276
14276
  );
@@ -14287,7 +14287,7 @@ async function startTail(options = {}) {
14287
14287
  },
14288
14288
  (res) => {
14289
14289
  if (res.statusCode !== 200) {
14290
- console.error(import_chalk30.default.red(`Failed to connect: HTTP ${res.statusCode}`));
14290
+ console.error(import_chalk29.default.red(`Failed to connect: HTTP ${res.statusCode}`));
14291
14291
  process.exit(1);
14292
14292
  }
14293
14293
  if (canApprove) enterIdleMode();
@@ -14318,7 +14318,7 @@ async function startTail(options = {}) {
14318
14318
  import_readline6.default.clearLine(process.stdout, 0);
14319
14319
  import_readline6.default.cursorTo(process.stdout, 0);
14320
14320
  }
14321
- console.log(import_chalk30.default.red("\n\u274C Daemon disconnected."));
14321
+ console.log(import_chalk29.default.red("\n\u274C Daemon disconnected."));
14322
14322
  process.exit(1);
14323
14323
  });
14324
14324
  }
@@ -14331,7 +14331,7 @@ async function startTail(options = {}) {
14331
14331
  const parsed = JSON.parse(rawData);
14332
14332
  const msg = parsed.message ?? "Flight recorder is down \u2014 run: node9 daemon restart";
14333
14333
  console.log("");
14334
- console.log(import_chalk30.default.bgRed.white.bold(` \u26A0\uFE0F ${msg} `));
14334
+ console.log(import_chalk29.default.bgRed.white.bold(` \u26A0\uFE0F ${msg} `));
14335
14335
  } catch {
14336
14336
  }
14337
14337
  return;
@@ -14416,9 +14416,9 @@ async function startTail(options = {}) {
14416
14416
  const rawSummary = data.argsSummary ?? data.tool;
14417
14417
  const summary = shortenPathSummary(rawSummary);
14418
14418
  const fileCount = data.fileCount ?? 0;
14419
- const files = fileCount > 0 ? import_chalk30.default.dim(` \xB7 ${fileCount} file${fileCount === 1 ? "" : "s"}`) : "";
14419
+ const files = fileCount > 0 ? import_chalk29.default.dim(` \xB7 ${fileCount} file${fileCount === 1 ? "" : "s"}`) : "";
14420
14420
  process.stdout.write(
14421
- `${import_chalk30.default.dim(time)} ${import_chalk30.default.cyan("\u{1F4F8} snapshot")} ${import_chalk30.default.dim(hash)} ${summary}${files}
14421
+ `${import_chalk29.default.dim(time)} ${import_chalk29.default.cyan("\u{1F4F8} snapshot")} ${import_chalk29.default.dim(hash)} ${summary}${files}
14422
14422
  `
14423
14423
  );
14424
14424
  return;
@@ -14435,33 +14435,33 @@ async function startTail(options = {}) {
14435
14435
  if (event === "execution-result") {
14436
14436
  const exec = data;
14437
14437
  const time = new Date(Date.now()).toLocaleTimeString([], { hour12: false });
14438
- const arrow = exec.isError ? import_chalk30.default.red(" \u21B3 \u2717") : import_chalk30.default.green(" \u21B3 \u2713");
14438
+ const arrow = exec.isError ? import_chalk29.default.red(" \u21B3 \u2717") : import_chalk29.default.green(" \u21B3 \u2713");
14439
14439
  const label = agentLabel(exec.agent, exec.mcpServer);
14440
14440
  const tool = (exec.tool ?? "").slice(0, 16);
14441
- const duration = typeof exec.durationMs === "number" ? import_chalk30.default.dim(` (${exec.durationMs}ms)`) : "";
14441
+ const duration = typeof exec.durationMs === "number" ? import_chalk29.default.dim(` (${exec.durationMs}ms)`) : "";
14442
14442
  console.log(
14443
- `${import_chalk30.default.gray(time)} ${arrow} ${label}${import_chalk30.default.dim(tool)}${import_chalk30.default.dim(" completed")}${duration}`
14443
+ `${import_chalk29.default.gray(time)} ${arrow} ${label}${import_chalk29.default.dim(tool)}${import_chalk29.default.dim(" completed")}${duration}`
14444
14444
  );
14445
14445
  }
14446
14446
  }
14447
14447
  req.on("error", (err2) => {
14448
14448
  const msg = err2.code === "ECONNREFUSED" ? "Daemon is not running. Start it with: node9 daemon start" : err2.message;
14449
- console.error(import_chalk30.default.red(`
14449
+ console.error(import_chalk29.default.red(`
14450
14450
  \u274C ${msg}`));
14451
14451
  process.exit(1);
14452
14452
  });
14453
14453
  }
14454
- var import_http2, import_chalk30, import_fs45, import_os41, import_path47, import_readline6, import_child_process13, PID_FILE, ICONS, MODEL_CONTEXT_LIMITS, RESET2, BOLD2, RED, YELLOW, CYAN, GRAY, GREEN, HIDE_CURSOR, SHOW_CURSOR, ERASE_DOWN, pendingShownForId, pendingWrappedLines, DIVIDER;
14454
+ var import_http2, import_chalk29, import_fs45, import_os41, import_path47, import_readline6, import_child_process12, PID_FILE, ICONS, MODEL_CONTEXT_LIMITS, RESET2, BOLD2, RED, YELLOW, CYAN, GRAY, GREEN, HIDE_CURSOR, SHOW_CURSOR, ERASE_DOWN, pendingShownForId, pendingWrappedLines, DIVIDER;
14455
14455
  var init_tail = __esm({
14456
14456
  "src/tui/tail.ts"() {
14457
14457
  "use strict";
14458
14458
  import_http2 = __toESM(require("http"));
14459
- import_chalk30 = __toESM(require("chalk"));
14459
+ import_chalk29 = __toESM(require("chalk"));
14460
14460
  import_fs45 = __toESM(require("fs"));
14461
14461
  import_os41 = __toESM(require("os"));
14462
14462
  import_path47 = __toESM(require("path"));
14463
14463
  import_readline6 = __toESM(require("readline"));
14464
- import_child_process13 = require("child_process");
14464
+ import_child_process12 = require("child_process");
14465
14465
  init_daemon2();
14466
14466
  init_daemon();
14467
14467
  PID_FILE = import_path47.default.join(import_os41.default.homedir(), ".node9", "daemon.pid");
@@ -14889,7 +14889,7 @@ var import_commander = require("commander");
14889
14889
  init_core();
14890
14890
  init_setup();
14891
14891
  init_daemon2();
14892
- var import_chalk31 = __toESM(require("chalk"));
14892
+ var import_chalk30 = __toESM(require("chalk"));
14893
14893
  var import_fs47 = __toESM(require("fs"));
14894
14894
  var import_path49 = __toESM(require("path"));
14895
14895
  var import_os43 = __toESM(require("os"));
@@ -15683,7 +15683,7 @@ function detectAiAgent(payload) {
15683
15683
  return "Terminal";
15684
15684
  }
15685
15685
  function registerCheckCommand(program2) {
15686
- program2.command("check").description("Hook handler \u2014 evaluates a tool call before execution").argument("[data]", "JSON string of the tool call").action(async (data) => {
15686
+ program2.command("check", { hidden: true }).description("Hook handler \u2014 evaluates a tool call before execution").argument("[data]", "JSON string of the tool call").action(async (data) => {
15687
15687
  const processPayload = async (raw) => {
15688
15688
  try {
15689
15689
  if (!raw || raw.trim() === "") process.exit(0);
@@ -16081,7 +16081,7 @@ function sanitize3(value) {
16081
16081
  return value.replace(/[\x00-\x1F\x7F]/g, "");
16082
16082
  }
16083
16083
  function registerLogCommand(program2) {
16084
- program2.command("log").description("PostToolUse hook \u2014 records executed tool calls").argument("[data]", "JSON string of the tool call").action(async (data) => {
16084
+ program2.command("log", { hidden: true }).description("PostToolUse hook \u2014 records executed tool calls").argument("[data]", "JSON string of the tool call").action(async (data) => {
16085
16085
  const logPayload = async (raw) => {
16086
16086
  try {
16087
16087
  if (!raw || raw.trim() === "") process.exit(0);
@@ -16834,6 +16834,35 @@ function isTestEntry(entry, testTs) {
16834
16834
  }
16835
16835
  return false;
16836
16836
  }
16837
+ var SUPERSEDE_WINDOW_MS = 6e4;
16838
+ function buildSupersededSet(entries) {
16839
+ const superseded = /* @__PURE__ */ new Set();
16840
+ for (let i = 0; i < entries.length; i++) {
16841
+ const e = entries[i];
16842
+ if (e.decision !== "deny") continue;
16843
+ if (e.checkedBy !== "smart-rule-block-override") continue;
16844
+ if (!e.argsHash || !e.sessionId) continue;
16845
+ const eTs = Date.parse(e.ts);
16846
+ if (Number.isNaN(eTs)) continue;
16847
+ for (let j = i + 1; j < entries.length; j++) {
16848
+ const next = entries[j];
16849
+ const nextTs = Date.parse(next.ts);
16850
+ if (Number.isNaN(nextTs)) continue;
16851
+ if (nextTs - eTs > SUPERSEDE_WINDOW_MS) break;
16852
+ if (next.argsHash !== e.argsHash) continue;
16853
+ if (next.sessionId !== e.sessionId) continue;
16854
+ if (next.tool !== e.tool) continue;
16855
+ if (next.decision === "allow" && next.checkedBy === "daemon") {
16856
+ superseded.add(`${e.ts}|${e.argsHash}`);
16857
+ break;
16858
+ }
16859
+ }
16860
+ }
16861
+ return superseded;
16862
+ }
16863
+ function supersedeKey(e) {
16864
+ return `${e.ts}|${e.argsHash ?? ""}`;
16865
+ }
16837
16866
  function getDateRange(period, now) {
16838
16867
  const todayStart = new Date(now.getFullYear(), now.getMonth(), now.getDate());
16839
16868
  const end = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 23, 59, 59, 999);
@@ -17285,6 +17314,7 @@ function aggregateReportFromAudit(period, opts = {}) {
17285
17314
  }
17286
17315
  return true;
17287
17316
  });
17317
+ const superseded = buildSupersededSet(entries);
17288
17318
  let userApproved = 0;
17289
17319
  let userDenied = 0;
17290
17320
  let timedOut = 0;
@@ -17302,6 +17332,7 @@ function aggregateReportFromAudit(period, opts = {}) {
17302
17332
  const dailyMap = /* @__PURE__ */ new Map();
17303
17333
  const hourMap = /* @__PURE__ */ new Map();
17304
17334
  for (const e of entries) {
17335
+ if (superseded.has(supersedeKey(e))) continue;
17305
17336
  const allow = isAllow(e.decision);
17306
17337
  const dateKey = e.ts.slice(0, 10);
17307
17338
  const userInteracted = e.source === "daemon";
@@ -17312,6 +17343,7 @@ function aggregateReportFromAudit(period, opts = {}) {
17312
17343
  if (e.checkedBy === "timeout") timedOut++;
17313
17344
  else if (e.checkedBy === "observe-mode-dlp-would-block") observeDlp++;
17314
17345
  else if (isDlp(e.checkedBy)) dlpBlocked++;
17346
+ else if (e.checkedBy === "local-decision") userDenied++;
17315
17347
  else if (e.checkedBy !== "loop-detected") hardBlocked++;
17316
17348
  }
17317
17349
  if (e.checkedBy === "loop-detected") loopHits++;
@@ -17319,8 +17351,11 @@ function aggregateReportFromAudit(period, opts = {}) {
17319
17351
  t.calls++;
17320
17352
  if (!allow) t.blocked++;
17321
17353
  toolMap.set(e.tool, t);
17322
- if (!allow && e.checkedBy) {
17323
- blockMap.set(e.checkedBy, (blockMap.get(e.checkedBy) ?? 0) + 1);
17354
+ if (!allow) {
17355
+ const key = e.checkedBy ?? (e.source === "daemon" ? "local-decision" : null);
17356
+ if (key) {
17357
+ blockMap.set(key, (blockMap.get(key) ?? 0) + 1);
17358
+ }
17324
17359
  }
17325
17360
  if (!allow && e.ruleName) {
17326
17361
  ruleMap.set(e.ruleName, (ruleMap.get(e.ruleName) ?? 0) + 1);
@@ -17349,7 +17384,9 @@ function aggregateReportFromAudit(period, opts = {}) {
17349
17384
  start,
17350
17385
  end,
17351
17386
  excludedTests,
17352
- total: entries.length,
17387
+ // Subtract superseded rows so the headline event count agrees with
17388
+ // the bucket counters (which skip them in the loop above).
17389
+ total: entries.length - superseded.size,
17353
17390
  userApproved,
17354
17391
  userDenied,
17355
17392
  timedOut,
@@ -18247,7 +18284,7 @@ function registerInitCommand(program2) {
18247
18284
  const agentList = found.join(", ");
18248
18285
  console.log(import_chalk16.default.green.bold(`\u{1F6E1}\uFE0F Node9 is protecting ${agentList}!`));
18249
18286
  console.log("");
18250
- console.log(import_chalk16.default.white(" Watch live: ") + import_chalk16.default.cyan("node9 tail"));
18287
+ console.log(import_chalk16.default.white(" Watch live: ") + import_chalk16.default.cyan("node9 monitor"));
18251
18288
  console.log("");
18252
18289
  console.log(import_chalk16.default.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
18253
18290
  console.log(
@@ -18544,71 +18581,10 @@ function registerUndoCommand(program2) {
18544
18581
  });
18545
18582
  }
18546
18583
 
18547
- // src/cli/commands/watch.ts
18548
- var import_chalk19 = __toESM(require("chalk"));
18549
- var import_child_process10 = require("child_process");
18550
- init_daemon();
18551
- function registerWatchCommand(program2) {
18552
- program2.command("watch").description("Run a command under Node9 watch mode (daemon stays alive for the session)").argument("<command>", "Command to run").argument("[args...]", "Arguments for the command").action(async (cmd, args) => {
18553
- let port = DAEMON_PORT;
18554
- try {
18555
- const res = await fetch(`http://127.0.0.1:${DAEMON_PORT}/settings`, {
18556
- signal: AbortSignal.timeout(500)
18557
- });
18558
- if (res.ok) {
18559
- const data = await res.json();
18560
- if (typeof data.port === "number") port = data.port;
18561
- } else {
18562
- throw new Error("not running");
18563
- }
18564
- } catch {
18565
- console.error(import_chalk19.default.dim("\u{1F6E1}\uFE0F Starting Node9 daemon (watch mode)..."));
18566
- const child = (0, import_child_process10.spawn)(process.execPath, [process.argv[1], "daemon"], {
18567
- detached: true,
18568
- stdio: "ignore",
18569
- env: { ...process.env, NODE9_AUTO_STARTED: "1", NODE9_WATCH_MODE: "1" }
18570
- });
18571
- child.unref();
18572
- let ready = false;
18573
- for (let i = 0; i < 20; i++) {
18574
- await new Promise((r) => setTimeout(r, 250));
18575
- try {
18576
- const r = await fetch(`http://127.0.0.1:${DAEMON_PORT}/settings`, {
18577
- signal: AbortSignal.timeout(500)
18578
- });
18579
- if (r.ok) {
18580
- ready = true;
18581
- break;
18582
- }
18583
- } catch {
18584
- }
18585
- }
18586
- if (!ready) {
18587
- console.error(import_chalk19.default.red("\u274C Daemon failed to start. Try: node9 daemon start"));
18588
- process.exit(1);
18589
- }
18590
- }
18591
- console.error(
18592
- import_chalk19.default.cyan.bold("\u{1F6E1}\uFE0F Node9 watch") + import_chalk19.default.dim(` \u2192 localhost:${port}`) + import_chalk19.default.dim(
18593
- "\n Tip: run `node9 tail` in another terminal to review and approve AI actions.\n"
18594
- )
18595
- );
18596
- const result = (0, import_child_process10.spawnSync)(cmd, args, {
18597
- stdio: "inherit",
18598
- env: { ...process.env, NODE9_WATCH_MODE: "1" }
18599
- });
18600
- if (result.error) {
18601
- console.error(import_chalk19.default.red(`\u274C Failed to run command: ${result.error.message}`));
18602
- process.exit(1);
18603
- }
18604
- process.exit(result.status ?? 0);
18605
- });
18606
- }
18607
-
18608
18584
  // src/mcp-gateway/index.ts
18609
18585
  var import_readline4 = __toESM(require("readline"));
18610
- var import_chalk20 = __toESM(require("chalk"));
18611
- var import_child_process11 = require("child_process");
18586
+ var import_chalk19 = __toESM(require("chalk"));
18587
+ var import_child_process10 = require("child_process");
18612
18588
  var import_execa3 = require("execa");
18613
18589
  init_orchestrator();
18614
18590
  init_provenance();
@@ -18769,13 +18745,13 @@ async function runMcpGateway(upstreamCommand) {
18769
18745
  const prov = checkProvenance(executable);
18770
18746
  if (prov.trustLevel === "suspect") {
18771
18747
  console.error(
18772
- import_chalk20.default.red(
18748
+ import_chalk19.default.red(
18773
18749
  `\u26A0\uFE0F Node9: Upstream MCP server binary is suspect \u2014 ${prov.reason} (${prov.resolvedPath})`
18774
18750
  )
18775
18751
  );
18776
- console.error(import_chalk20.default.red(" Verify this binary is trusted before proceeding."));
18752
+ console.error(import_chalk19.default.red(" Verify this binary is trusted before proceeding."));
18777
18753
  }
18778
- console.error(import_chalk20.default.green(`\u{1F680} Node9 MCP Gateway: Monitoring [${upstreamCommand}]`));
18754
+ console.error(import_chalk19.default.green(`\u{1F680} Node9 MCP Gateway: Monitoring [${upstreamCommand}]`));
18779
18755
  const UPSTREAM_INJECTOR_VARS = /* @__PURE__ */ new Set([
18780
18756
  "NODE_OPTIONS",
18781
18757
  "NODE_PATH",
@@ -18794,7 +18770,7 @@ async function runMcpGateway(upstreamCommand) {
18794
18770
  const safeEnv = Object.fromEntries(
18795
18771
  Object.entries(process.env).filter(([k]) => !UPSTREAM_INJECTOR_VARS.has(k))
18796
18772
  );
18797
- const child = (0, import_child_process11.spawn)(executable, cmdArgs, {
18773
+ const child = (0, import_child_process10.spawn)(executable, cmdArgs, {
18798
18774
  stdio: ["pipe", "pipe", "inherit"],
18799
18775
  // control stdin/stdout; inherit stderr
18800
18776
  shell: false,
@@ -18888,10 +18864,10 @@ async function runMcpGateway(upstreamCommand) {
18888
18864
  mcpServer
18889
18865
  });
18890
18866
  if (!result.approved) {
18891
- console.error(import_chalk20.default.red(`
18867
+ console.error(import_chalk19.default.red(`
18892
18868
  \u{1F6D1} Node9 MCP Gateway: Action Blocked`));
18893
- console.error(import_chalk20.default.gray(` Tool: ${toolName}`));
18894
- console.error(import_chalk20.default.gray(` Reason: ${result.reason ?? "Security Policy"}
18869
+ console.error(import_chalk19.default.gray(` Tool: ${toolName}`));
18870
+ console.error(import_chalk19.default.gray(` Reason: ${result.reason ?? "Security Policy"}
18895
18871
  `));
18896
18872
  const blockedByLabel = result.blockedByLabel ?? result.reason ?? "Security Policy";
18897
18873
  const isHumanDecision = blockedByLabel.toLowerCase().includes("user") || blockedByLabel.toLowerCase().includes("daemon") || blockedByLabel.toLowerCase().includes("decision");
@@ -19003,7 +18979,7 @@ async function runMcpGateway(upstreamCommand) {
19003
18979
  updatePin(serverKey, upstreamCommand, currentHash, toolNames);
19004
18980
  pinState = "validated";
19005
18981
  console.error(
19006
- import_chalk20.default.green(
18982
+ import_chalk19.default.green(
19007
18983
  `\u{1F512} Node9: Pinned ${toolNames.length} tool definition(s) for this MCP server`
19008
18984
  )
19009
18985
  );
@@ -19016,11 +18992,11 @@ async function runMcpGateway(upstreamCommand) {
19016
18992
  } else if (pinStatus === "corrupt") {
19017
18993
  pinState = "quarantined";
19018
18994
  console.error(
19019
- import_chalk20.default.red("\n\u{1F6A8} Node9: MCP pin file is corrupt or unreadable \u2014 session quarantined!")
18995
+ import_chalk19.default.red("\n\u{1F6A8} Node9: MCP pin file is corrupt or unreadable \u2014 session quarantined!")
19020
18996
  );
19021
- console.error(import_chalk20.default.red(" Tool calls are blocked until the pin file is repaired."));
18997
+ console.error(import_chalk19.default.red(" Tool calls are blocked until the pin file is repaired."));
19022
18998
  console.error(
19023
- import_chalk20.default.yellow(` Run: node9 mcp pin reset (to clear and re-pin on next connect)
18999
+ import_chalk19.default.yellow(` Run: node9 mcp pin reset (to clear and re-pin on next connect)
19024
19000
  `)
19025
19001
  );
19026
19002
  const errorResponse = {
@@ -19037,13 +19013,13 @@ async function runMcpGateway(upstreamCommand) {
19037
19013
  } else {
19038
19014
  pinState = "quarantined";
19039
19015
  console.error(
19040
- import_chalk20.default.red("\n\u{1F6A8} Node9: MCP tool definitions have changed since last verified!")
19016
+ import_chalk19.default.red("\n\u{1F6A8} Node9: MCP tool definitions have changed since last verified!")
19041
19017
  );
19042
19018
  console.error(
19043
- import_chalk20.default.red(" This could indicate a supply chain attack (tool poisoning / rug pull).")
19019
+ import_chalk19.default.red(" This could indicate a supply chain attack (tool poisoning / rug pull).")
19044
19020
  );
19045
- console.error(import_chalk20.default.red(" Session quarantined \u2014 all tool calls blocked."));
19046
- console.error(import_chalk20.default.yellow(` Run: node9 mcp pin update ${serverKey}
19021
+ console.error(import_chalk19.default.red(" Session quarantined \u2014 all tool calls blocked."));
19022
+ console.error(import_chalk19.default.yellow(` Run: node9 mcp pin update ${serverKey}
19047
19023
  `));
19048
19024
  const errorResponse = {
19049
19025
  jsonrpc: "2.0",
@@ -19086,7 +19062,7 @@ async function runMcpGateway(upstreamCommand) {
19086
19062
  const toolName = callId !== void 0 ? pendingCallNames.get(callId) ?? "unknown" : "unknown";
19087
19063
  if (callId !== void 0) pendingCallNames.delete(callId);
19088
19064
  console.error(
19089
- import_chalk20.default.yellow(
19065
+ import_chalk19.default.yellow(
19090
19066
  `\u26A1 Node9: Large MCP response from '${toolName}' (${(line.length / 1024).toFixed(0)}KB) \u2014 context window enlarged`
19091
19067
  )
19092
19068
  );
@@ -19140,7 +19116,7 @@ var import_readline5 = __toESM(require("readline"));
19140
19116
  var import_fs39 = __toESM(require("fs"));
19141
19117
  var import_os35 = __toESM(require("os"));
19142
19118
  var import_path41 = __toESM(require("path"));
19143
- var import_child_process12 = require("child_process");
19119
+ var import_child_process11 = require("child_process");
19144
19120
  init_core();
19145
19121
  init_daemon();
19146
19122
  init_shields();
@@ -19614,7 +19590,7 @@ function handleRuleAdd(args) {
19614
19590
  return `Rule "${name}" added to ~/.node9/config.json \u2014 verdict: ${verdict} when ${field} matches "${pattern}"`;
19615
19591
  }
19616
19592
  function runCliCommand(subArgs) {
19617
- const result = (0, import_child_process12.spawnSync)(process.execPath, [process.argv[1], ...subArgs], {
19593
+ const result = (0, import_child_process11.spawnSync)(process.execPath, [process.argv[1], ...subArgs], {
19618
19594
  encoding: "utf-8",
19619
19595
  timeout: 6e4,
19620
19596
  // Disable colors — stdout is piped (not a TTY), chalk auto-detects, but be explicit
@@ -19808,7 +19784,7 @@ function registerMcpServerCommand(program2) {
19808
19784
  }
19809
19785
 
19810
19786
  // src/cli/commands/trust.ts
19811
- var import_chalk21 = __toESM(require("chalk"));
19787
+ var import_chalk20 = __toESM(require("chalk"));
19812
19788
  init_trusted_hosts();
19813
19789
  function isValidHost(host) {
19814
19790
  return /^(\*\.)?[a-z0-9][a-z0-9.-]*\.[a-z]{2,}$/.test(host);
@@ -19819,51 +19795,51 @@ function registerTrustCommand(program2) {
19819
19795
  const normalized = normalizeHost(host.trim());
19820
19796
  if (!isValidHost(normalized)) {
19821
19797
  console.error(
19822
- import_chalk21.default.red(`
19798
+ import_chalk20.default.red(`
19823
19799
  \u274C Invalid host: "${host}"
19824
- `) + import_chalk21.default.gray(" Use an FQDN like api.mycompany.com or *.mycompany.com\n")
19800
+ `) + import_chalk20.default.gray(" Use an FQDN like api.mycompany.com or *.mycompany.com\n")
19825
19801
  );
19826
19802
  process.exit(1);
19827
19803
  }
19828
19804
  addTrustedHost(normalized);
19829
- console.log(import_chalk21.default.green(`
19805
+ console.log(import_chalk20.default.green(`
19830
19806
  \u2705 ${normalized} added to trusted hosts.`));
19831
19807
  console.log(
19832
- import_chalk21.default.gray(" Pipe-chain blocks to this host: critical \u2192 review, high \u2192 allow\n")
19808
+ import_chalk20.default.gray(" Pipe-chain blocks to this host: critical \u2192 review, high \u2192 allow\n")
19833
19809
  );
19834
19810
  });
19835
19811
  trustCmd.command("remove <host>").description("Remove a trusted host").action((host) => {
19836
19812
  const normalized = normalizeHost(host.trim());
19837
19813
  const removed = removeTrustedHost(normalized);
19838
19814
  if (!removed) {
19839
- console.error(import_chalk21.default.yellow(`
19815
+ console.error(import_chalk20.default.yellow(`
19840
19816
  \u26A0\uFE0F "${normalized}" is not in the trusted hosts list.
19841
19817
  `));
19842
19818
  process.exit(1);
19843
19819
  }
19844
- console.log(import_chalk21.default.green(`
19820
+ console.log(import_chalk20.default.green(`
19845
19821
  \u2705 ${normalized} removed from trusted hosts.
19846
19822
  `));
19847
19823
  });
19848
19824
  trustCmd.command("list").description("Show all trusted hosts").action(() => {
19849
19825
  const hosts = readTrustedHosts();
19850
19826
  if (hosts.length === 0) {
19851
- console.log(import_chalk21.default.gray("\n No trusted hosts configured.\n"));
19852
- console.log(` Add one: ${import_chalk21.default.cyan("node9 trust add api.mycompany.com")}
19827
+ console.log(import_chalk20.default.gray("\n No trusted hosts configured.\n"));
19828
+ console.log(` Add one: ${import_chalk20.default.cyan("node9 trust add api.mycompany.com")}
19853
19829
  `);
19854
19830
  return;
19855
19831
  }
19856
- console.log(import_chalk21.default.bold("\n\u{1F513} Trusted Hosts\n"));
19832
+ console.log(import_chalk20.default.bold("\n\u{1F513} Trusted Hosts\n"));
19857
19833
  for (const entry of hosts) {
19858
19834
  const date = new Date(entry.addedAt).toLocaleDateString();
19859
- console.log(` ${import_chalk21.default.cyan(entry.host.padEnd(40))} ${import_chalk21.default.gray(`added ${date}`)}`);
19835
+ console.log(` ${import_chalk20.default.cyan(entry.host.padEnd(40))} ${import_chalk20.default.gray(`added ${date}`)}`);
19860
19836
  }
19861
19837
  console.log("");
19862
19838
  });
19863
19839
  }
19864
19840
 
19865
19841
  // src/cli/commands/mcp-pin.ts
19866
- var import_chalk22 = __toESM(require("chalk"));
19842
+ var import_chalk21 = __toESM(require("chalk"));
19867
19843
  function registerMcpPinCommand(program2) {
19868
19844
  const pinCmd = program2.command("mcp").description("Manage MCP server tool definition pinning (rug pull defense)");
19869
19845
  const pinSubCmd = pinCmd.command("pin").description("Manage pinned MCP server tool definitions");
@@ -19871,31 +19847,31 @@ function registerMcpPinCommand(program2) {
19871
19847
  const result = readMcpPinsSafe();
19872
19848
  if (!result.ok) {
19873
19849
  if (result.reason === "missing") {
19874
- console.log(import_chalk22.default.gray("\nNo MCP servers are pinned yet."));
19850
+ console.log(import_chalk21.default.gray("\nNo MCP servers are pinned yet."));
19875
19851
  console.log(
19876
- import_chalk22.default.gray("Pins are created automatically when the MCP gateway first connects.\n")
19852
+ import_chalk21.default.gray("Pins are created automatically when the MCP gateway first connects.\n")
19877
19853
  );
19878
19854
  return;
19879
19855
  }
19880
- console.error(import_chalk22.default.red(`
19856
+ console.error(import_chalk21.default.red(`
19881
19857
  \u274C Pin file is corrupt: ${result.detail}`));
19882
- console.error(import_chalk22.default.yellow(" Run: node9 mcp pin reset\n"));
19858
+ console.error(import_chalk21.default.yellow(" Run: node9 mcp pin reset\n"));
19883
19859
  process.exit(1);
19884
19860
  }
19885
19861
  const entries = Object.entries(result.pins.servers);
19886
19862
  if (entries.length === 0) {
19887
- console.log(import_chalk22.default.gray("\nNo MCP servers are pinned yet."));
19863
+ console.log(import_chalk21.default.gray("\nNo MCP servers are pinned yet."));
19888
19864
  console.log(
19889
- import_chalk22.default.gray("Pins are created automatically when the MCP gateway first connects.\n")
19865
+ import_chalk21.default.gray("Pins are created automatically when the MCP gateway first connects.\n")
19890
19866
  );
19891
19867
  return;
19892
19868
  }
19893
- console.log(import_chalk22.default.bold("\n\u{1F512} Pinned MCP Servers\n"));
19869
+ console.log(import_chalk21.default.bold("\n\u{1F512} Pinned MCP Servers\n"));
19894
19870
  for (const [key, entry] of entries) {
19895
- console.log(` ${import_chalk22.default.cyan(key)} ${import_chalk22.default.gray(entry.label)}`);
19896
- console.log(` Tools (${entry.toolCount}): ${import_chalk22.default.white(entry.toolNames.join(", "))}`);
19897
- console.log(` Hash: ${import_chalk22.default.gray(entry.toolsHash.slice(0, 16))}...`);
19898
- console.log(` Pinned: ${import_chalk22.default.gray(entry.pinnedAt)}`);
19871
+ console.log(` ${import_chalk21.default.cyan(key)} ${import_chalk21.default.gray(entry.label)}`);
19872
+ console.log(` Tools (${entry.toolCount}): ${import_chalk21.default.white(entry.toolNames.join(", "))}`);
19873
+ console.log(` Hash: ${import_chalk21.default.gray(entry.toolsHash.slice(0, 16))}...`);
19874
+ console.log(` Pinned: ${import_chalk21.default.gray(entry.pinnedAt)}`);
19899
19875
  console.log("");
19900
19876
  }
19901
19877
  });
@@ -19906,127 +19882,127 @@ function registerMcpPinCommand(program2) {
19906
19882
  try {
19907
19883
  pins = readMcpPins();
19908
19884
  } catch {
19909
- console.error(import_chalk22.default.red("\n\u274C Pin file is corrupt."));
19910
- console.error(import_chalk22.default.yellow(" Run: node9 mcp pin reset\n"));
19885
+ console.error(import_chalk21.default.red("\n\u274C Pin file is corrupt."));
19886
+ console.error(import_chalk21.default.yellow(" Run: node9 mcp pin reset\n"));
19911
19887
  process.exit(1);
19912
19888
  }
19913
19889
  if (!pins.servers[serverKey]) {
19914
- console.error(import_chalk22.default.red(`
19890
+ console.error(import_chalk21.default.red(`
19915
19891
  \u274C No pin found for server key "${serverKey}"
19916
19892
  `));
19917
- console.error(`Run ${import_chalk22.default.cyan("node9 mcp pin list")} to see pinned servers.
19893
+ console.error(`Run ${import_chalk21.default.cyan("node9 mcp pin list")} to see pinned servers.
19918
19894
  `);
19919
19895
  process.exit(1);
19920
19896
  }
19921
19897
  const label = pins.servers[serverKey].label;
19922
19898
  removePin2(serverKey);
19923
- console.log(import_chalk22.default.green(`
19924
- \u{1F513} Pin removed for ${import_chalk22.default.cyan(serverKey)}`));
19925
- console.log(import_chalk22.default.gray(` Server: ${label}`));
19926
- console.log(import_chalk22.default.gray(" Next connection will re-pin with current tool definitions.\n"));
19899
+ console.log(import_chalk21.default.green(`
19900
+ \u{1F513} Pin removed for ${import_chalk21.default.cyan(serverKey)}`));
19901
+ console.log(import_chalk21.default.gray(` Server: ${label}`));
19902
+ console.log(import_chalk21.default.gray(" Next connection will re-pin with current tool definitions.\n"));
19927
19903
  });
19928
19904
  pinSubCmd.command("reset").description("Clear all MCP pins (next connection to each server will re-pin)").action(() => {
19929
19905
  const result = readMcpPinsSafe();
19930
19906
  if (!result.ok && result.reason === "missing") {
19931
- console.log(import_chalk22.default.gray("\nNo pins to clear.\n"));
19907
+ console.log(import_chalk21.default.gray("\nNo pins to clear.\n"));
19932
19908
  return;
19933
19909
  }
19934
19910
  const count = result.ok ? Object.keys(result.pins.servers).length : "?";
19935
19911
  clearAllPins2();
19936
- console.log(import_chalk22.default.green(`
19912
+ console.log(import_chalk21.default.green(`
19937
19913
  \u{1F513} Cleared ${count} MCP pin(s).`));
19938
- console.log(import_chalk22.default.gray(" Next connection to each server will re-pin.\n"));
19914
+ console.log(import_chalk21.default.gray(" Next connection to each server will re-pin.\n"));
19939
19915
  });
19940
19916
  }
19941
19917
 
19942
19918
  // src/cli/commands/sync.ts
19943
- var import_chalk23 = __toESM(require("chalk"));
19919
+ var import_chalk22 = __toESM(require("chalk"));
19944
19920
  init_sync();
19945
19921
  function registerSyncCommand(program2) {
19946
19922
  const policy = program2.command("policy").description("Manage cloud policy rules");
19947
19923
  policy.command("sync").description("Sync cloud policy rules to local cache (~/.node9/rules-cache.json)").action(async () => {
19948
- process.stdout.write(import_chalk23.default.cyan("Syncing cloud policy rules\u2026"));
19924
+ process.stdout.write(import_chalk22.default.cyan("Syncing cloud policy rules\u2026"));
19949
19925
  const result = await runCloudSync();
19950
19926
  process.stdout.write("\n");
19951
19927
  if (!result.ok) {
19952
- console.error(import_chalk23.default.red(`\u2717 ${result.reason}`));
19928
+ console.error(import_chalk22.default.red(`\u2717 ${result.reason}`));
19953
19929
  process.exit(1);
19954
19930
  }
19955
19931
  if (result.unchanged) {
19956
19932
  console.log(
19957
- import_chalk23.default.green(
19933
+ import_chalk22.default.green(
19958
19934
  `\u2713 Already up to date \u2014 ${result.rules} rule${result.rules === 1 ? "" : "s"} cached`
19959
19935
  )
19960
19936
  );
19961
- console.log(import_chalk23.default.gray(` Cached at: ${result.fetchedAt}`));
19962
- console.log(import_chalk23.default.gray(` Server returned 304 (no changes since last sync)`));
19937
+ console.log(import_chalk22.default.gray(` Cached at: ${result.fetchedAt}`));
19938
+ console.log(import_chalk22.default.gray(` Server returned 304 (no changes since last sync)`));
19963
19939
  } else {
19964
19940
  console.log(
19965
- import_chalk23.default.green(`\u2713 Synced ${result.rules} rule${result.rules === 1 ? "" : "s"} from cloud`)
19941
+ import_chalk22.default.green(`\u2713 Synced ${result.rules} rule${result.rules === 1 ? "" : "s"} from cloud`)
19966
19942
  );
19967
- console.log(import_chalk23.default.gray(` Cached at: ${result.fetchedAt}`));
19968
- console.log(import_chalk23.default.gray(` File: ~/.node9/rules-cache.json`));
19943
+ console.log(import_chalk22.default.gray(` Cached at: ${result.fetchedAt}`));
19944
+ console.log(import_chalk22.default.gray(` File: ~/.node9/rules-cache.json`));
19969
19945
  }
19970
19946
  });
19971
19947
  policy.command("show").description("List all cloud policy rules in the local cache").action(() => {
19972
19948
  const status = getCloudSyncStatus();
19973
19949
  if (!status.cached) {
19974
- console.log(import_chalk23.default.yellow("\n No cloud rules cached \u2014 run: node9 policy sync\n"));
19950
+ console.log(import_chalk22.default.yellow("\n No cloud rules cached \u2014 run: node9 policy sync\n"));
19975
19951
  return;
19976
19952
  }
19977
19953
  const rules = getCloudRules() ?? [];
19978
19954
  const age = Math.round((Date.now() - new Date(status.fetchedAt).getTime()) / 6e4);
19979
19955
  console.log(
19980
- import_chalk23.default.bold(`
19981
- Cloud policy rules`) + import_chalk23.default.gray(
19956
+ import_chalk22.default.bold(`
19957
+ Cloud policy rules`) + import_chalk22.default.gray(
19982
19958
  ` (${rules.length} rule${rules.length === 1 ? "" : "s"}, synced ${age}m ago)
19983
19959
  `
19984
19960
  )
19985
19961
  );
19986
19962
  if (rules.length === 0) {
19987
- console.log(import_chalk23.default.gray(" No rules defined in cloud policy.\n"));
19963
+ console.log(import_chalk22.default.gray(" No rules defined in cloud policy.\n"));
19988
19964
  return;
19989
19965
  }
19990
19966
  for (const rule of rules) {
19991
19967
  const r = rule;
19992
- const verdictColor = r.verdict === "block" ? import_chalk23.default.red : r.verdict === "allow" ? import_chalk23.default.green : import_chalk23.default.yellow;
19968
+ const verdictColor = r.verdict === "block" ? import_chalk22.default.red : r.verdict === "allow" ? import_chalk22.default.green : import_chalk22.default.yellow;
19993
19969
  console.log(
19994
19970
  ` ${verdictColor(
19995
19971
  String(r.verdict ?? "unknown").toUpperCase().padEnd(6)
19996
- )} ${import_chalk23.default.white(String(r.name ?? "(unnamed)"))}`
19972
+ )} ${import_chalk22.default.white(String(r.name ?? "(unnamed)"))}`
19997
19973
  );
19998
- if (r.reason) console.log(import_chalk23.default.gray(` ${String(r.reason)}`));
19974
+ if (r.reason) console.log(import_chalk22.default.gray(` ${String(r.reason)}`));
19999
19975
  }
20000
19976
  console.log("");
20001
19977
  });
20002
19978
  policy.command("status").description("Show current cloud policy cache status").action(() => {
20003
19979
  const s = getCloudSyncStatus();
20004
19980
  if (!s.cached) {
20005
- console.log(import_chalk23.default.yellow("\n No cache yet \u2014 run: node9 policy sync\n"));
19981
+ console.log(import_chalk22.default.yellow("\n No cache yet \u2014 run: node9 policy sync\n"));
20006
19982
  return;
20007
19983
  }
20008
19984
  const age = Math.round((Date.now() - new Date(s.fetchedAt).getTime()) / 6e4);
20009
19985
  console.log(`
20010
- Rules : ${import_chalk23.default.green(String(s.rules))} cloud rules loaded`);
19986
+ Rules : ${import_chalk22.default.green(String(s.rules))} cloud rules loaded`);
20011
19987
  console.log(
20012
- ` Synced : ${import_chalk23.default.gray(`${age} minute${age === 1 ? "" : "s"} ago`)} (${s.fetchedAt})`
19988
+ ` Synced : ${import_chalk22.default.gray(`${age} minute${age === 1 ? "" : "s"} ago`)} (${s.fetchedAt})`
20013
19989
  );
20014
19990
  if (s.workspaceId) {
20015
- console.log(` Workspace: ${import_chalk23.default.gray(s.workspaceId)}`);
19991
+ console.log(` Workspace: ${import_chalk22.default.gray(s.workspaceId)}`);
20016
19992
  }
20017
19993
  if (s.panicMode) {
20018
19994
  console.log(
20019
- ` ${import_chalk23.default.red.bold("\u{1F6A8} Panic mode : ON")} ` + import_chalk23.default.dim("(every review-verdict becomes block)")
19995
+ ` ${import_chalk22.default.red.bold("\u{1F6A8} Panic mode : ON")} ` + import_chalk22.default.dim("(every review-verdict becomes block)")
20020
19996
  );
20021
19997
  }
20022
19998
  if (s.shadowMode) {
20023
19999
  console.log(
20024
- ` ${import_chalk23.default.yellow.bold("\u{1F441} Shadow mode : ON")} ` + import_chalk23.default.dim("(blocks become would-block log entries)")
20000
+ ` ${import_chalk22.default.yellow.bold("\u{1F441} Shadow mode : ON")} ` + import_chalk22.default.dim("(blocks become would-block log entries)")
20025
20001
  );
20026
20002
  }
20027
20003
  if (s.syncIntervalHours) {
20028
20004
  console.log(
20029
- import_chalk23.default.gray(
20005
+ import_chalk22.default.gray(
20030
20006
  ` Polling : every ${s.syncIntervalHours} hour${s.syncIntervalHours === 1 ? "" : "s"}`
20031
20007
  )
20032
20008
  );
@@ -20036,7 +20012,7 @@ function registerSyncCommand(program2) {
20036
20012
  }
20037
20013
 
20038
20014
  // src/cli/commands/agents.ts
20039
- var import_chalk24 = __toESM(require("chalk"));
20015
+ var import_chalk23 = __toESM(require("chalk"));
20040
20016
  init_setup();
20041
20017
  var SETUP_FN = {
20042
20018
  claude: setupClaude,
@@ -20066,23 +20042,23 @@ function registerAgentsCommand(program2) {
20066
20042
  console.log(` ${"Agent".padEnd(14)}${"Installed".padEnd(11)}${"Wired".padEnd(8)}Mode`);
20067
20043
  console.log(" " + "\u2500".repeat(44));
20068
20044
  for (const s of statuses) {
20069
- const installed = s.installed ? import_chalk24.default.green("\u2713") : import_chalk24.default.gray("\u2717");
20070
- const wired = !s.installed ? import_chalk24.default.gray("\u2014") : s.wired ? import_chalk24.default.green("\u2713") : import_chalk24.default.yellow("\u2717");
20071
- const mode = s.mode ? import_chalk24.default.gray(s.mode) : import_chalk24.default.gray("\u2014");
20072
- const hint = s.installed && !s.wired ? import_chalk24.default.gray(` \u2190 node9 agents add ${s.name}`) : "";
20045
+ const installed = s.installed ? import_chalk23.default.green("\u2713") : import_chalk23.default.gray("\u2717");
20046
+ const wired = !s.installed ? import_chalk23.default.gray("\u2014") : s.wired ? import_chalk23.default.green("\u2713") : import_chalk23.default.yellow("\u2717");
20047
+ const mode = s.mode ? import_chalk23.default.gray(s.mode) : import_chalk23.default.gray("\u2014");
20048
+ const hint = s.installed && !s.wired ? import_chalk23.default.gray(` \u2190 node9 agents add ${s.name}`) : "";
20073
20049
  console.log(` ${s.label.padEnd(14)}${installed} ${wired} ${mode}${hint}`);
20074
20050
  }
20075
20051
  console.log("");
20076
20052
  if (!anyInstalled) {
20077
20053
  console.log(
20078
- import_chalk24.default.gray(" No AI agents detected. Install Claude Code, Gemini CLI, Cursor,\n") + import_chalk24.default.gray(" Windsurf, VSCode, or Codex then run: node9 agents list\n")
20054
+ import_chalk23.default.gray(" No AI agents detected. Install Claude Code, Gemini CLI, Cursor,\n") + import_chalk23.default.gray(" Windsurf, VSCode, or Codex then run: node9 agents list\n")
20079
20055
  );
20080
20056
  return;
20081
20057
  }
20082
20058
  const unwired = statuses.filter((s) => s.installed && !s.wired);
20083
20059
  if (unwired.length > 0) {
20084
20060
  console.log(
20085
- import_chalk24.default.yellow(` ${unwired.length} agent(s) not yet wired. Run: `) + import_chalk24.default.white(`node9 agents add ${unwired[0].name}`) + "\n"
20061
+ import_chalk23.default.yellow(` ${unwired.length} agent(s) not yet wired. Run: `) + import_chalk23.default.white(`node9 agents add ${unwired[0].name}`) + "\n"
20086
20062
  );
20087
20063
  }
20088
20064
  });
@@ -20090,7 +20066,7 @@ function registerAgentsCommand(program2) {
20090
20066
  const name = agent.toLowerCase();
20091
20067
  const fn = SETUP_FN[name];
20092
20068
  if (!fn) {
20093
- console.error(import_chalk24.default.red(`Unknown agent: "${agent}". Supported: ${AGENT_NAMES.join(", ")}`));
20069
+ console.error(import_chalk23.default.red(`Unknown agent: "${agent}". Supported: ${AGENT_NAMES.join(", ")}`));
20094
20070
  process.exit(1);
20095
20071
  }
20096
20072
  await fn();
@@ -20099,14 +20075,14 @@ function registerAgentsCommand(program2) {
20099
20075
  const name = agent.toLowerCase();
20100
20076
  const fn = TEARDOWN_FN[name];
20101
20077
  if (!fn) {
20102
- console.error(import_chalk24.default.red(`Unknown agent: "${agent}". Supported: ${AGENT_NAMES.join(", ")}`));
20078
+ console.error(import_chalk23.default.red(`Unknown agent: "${agent}". Supported: ${AGENT_NAMES.join(", ")}`));
20103
20079
  process.exit(1);
20104
20080
  }
20105
- console.log(import_chalk24.default.cyan(`
20081
+ console.log(import_chalk23.default.cyan(`
20106
20082
  \u{1F6E1}\uFE0F Node9: removing from ${name}...
20107
20083
  `));
20108
20084
  fn();
20109
- console.log(import_chalk24.default.gray("\n Restart the agent for changes to take effect."));
20085
+ console.log(import_chalk23.default.gray("\n Restart the agent for changes to take effect."));
20110
20086
  });
20111
20087
  }
20112
20088
 
@@ -20114,7 +20090,7 @@ function registerAgentsCommand(program2) {
20114
20090
  init_scan();
20115
20091
 
20116
20092
  // src/cli/commands/sessions.ts
20117
- var import_chalk25 = __toESM(require("chalk"));
20093
+ var import_chalk24 = __toESM(require("chalk"));
20118
20094
  var import_fs40 = __toESM(require("fs"));
20119
20095
  var import_path42 = __toESM(require("path"));
20120
20096
  var import_os36 = __toESM(require("os"));
@@ -20623,11 +20599,11 @@ function toolInputSummary(tool, input) {
20623
20599
  }
20624
20600
  function toolColor(tool) {
20625
20601
  const t = tool.toLowerCase();
20626
- if (t === "bash" || t === "execute_bash") return import_chalk25.default.red;
20627
- if (t === "write") return import_chalk25.default.green;
20628
- if (t === "edit" || t === "notebookedit") return import_chalk25.default.yellow;
20629
- if (t === "read") return import_chalk25.default.cyan;
20630
- return import_chalk25.default.gray;
20602
+ if (t === "bash" || t === "execute_bash") return import_chalk24.default.red;
20603
+ if (t === "write") return import_chalk24.default.green;
20604
+ if (t === "edit" || t === "notebookedit") return import_chalk24.default.yellow;
20605
+ if (t === "read") return import_chalk24.default.cyan;
20606
+ return import_chalk24.default.gray;
20631
20607
  }
20632
20608
  function barStr2(value, max, width) {
20633
20609
  if (max === 0 || width <= 0) return "\u2591".repeat(width);
@@ -20637,7 +20613,7 @@ function barStr2(value, max, width) {
20637
20613
  function colorBar2(value, max, width) {
20638
20614
  const s = barStr2(value, max, width);
20639
20615
  const filled = Math.max(1, Math.round(max > 0 ? value / max * width : 0));
20640
- return import_chalk25.default.cyan(s.slice(0, filled)) + import_chalk25.default.dim(s.slice(filled));
20616
+ return import_chalk24.default.cyan(s.slice(0, filled)) + import_chalk24.default.dim(s.slice(filled));
20641
20617
  }
20642
20618
  function renderSummary(summaries) {
20643
20619
  const totalTools = summaries.reduce((n, s) => n + s.toolCalls.length, 0);
@@ -20667,45 +20643,45 @@ function renderSummary(summaries) {
20667
20643
  }
20668
20644
  const topProjects = [...projCosts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 3);
20669
20645
  const W = 20;
20670
- console.log(import_chalk25.default.dim(" " + "\u2500".repeat(70)));
20646
+ console.log(import_chalk24.default.dim(" " + "\u2500".repeat(70)));
20671
20647
  console.log(
20672
- " " + import_chalk25.default.bold.white(String(summaries.length).padEnd(4)) + import_chalk25.default.dim("sessions ") + import_chalk25.default.bold.yellow(fmtCost3(totalCost).padEnd(10)) + import_chalk25.default.dim("total ") + import_chalk25.default.bold.white(String(totalTools).padEnd(6)) + import_chalk25.default.dim("tool calls ") + import_chalk25.default.bold.white(String(totalFiles)) + import_chalk25.default.dim(" files modified") + (totalBlocked > 0 ? import_chalk25.default.dim(" ") + import_chalk25.default.red.bold(String(totalBlocked)) + import_chalk25.default.dim(" blocked by node9") : "")
20648
+ " " + import_chalk24.default.bold.white(String(summaries.length).padEnd(4)) + import_chalk24.default.dim("sessions ") + import_chalk24.default.bold.yellow(fmtCost3(totalCost).padEnd(10)) + import_chalk24.default.dim("total ") + import_chalk24.default.bold.white(String(totalTools).padEnd(6)) + import_chalk24.default.dim("tool calls ") + import_chalk24.default.bold.white(String(totalFiles)) + import_chalk24.default.dim(" files modified") + (totalBlocked > 0 ? import_chalk24.default.dim(" ") + import_chalk24.default.red.bold(String(totalBlocked)) + import_chalk24.default.dim(" blocked by node9") : "")
20673
20649
  );
20674
20650
  console.log(
20675
- " " + import_chalk25.default.dim("avg ") + import_chalk25.default.white(fmtCost3(avgCost).padEnd(10)) + import_chalk25.default.dim("/session ") + import_chalk25.default.green(String(snapshots)) + import_chalk25.default.dim(` of ${summaries.length} sessions had snapshots`)
20651
+ " " + import_chalk24.default.dim("avg ") + import_chalk24.default.white(fmtCost3(avgCost).padEnd(10)) + import_chalk24.default.dim("/session ") + import_chalk24.default.green(String(snapshots)) + import_chalk24.default.dim(` of ${summaries.length} sessions had snapshots`)
20676
20652
  );
20677
20653
  console.log("");
20678
- console.log(" " + import_chalk25.default.dim("Tool breakdown:"));
20654
+ console.log(" " + import_chalk24.default.dim("Tool breakdown:"));
20679
20655
  const maxGroup = Math.max(...Object.values(groups));
20680
20656
  for (const [label, count] of Object.entries(groups)) {
20681
20657
  if (count === 0) continue;
20682
20658
  const pct = totalTools > 0 ? Math.round(count / totalTools * 100) : 0;
20683
20659
  console.log(
20684
- " " + label.padEnd(6) + " " + colorBar2(count, maxGroup, W) + " " + import_chalk25.default.white(String(count).padStart(4)) + import_chalk25.default.dim(` (${String(pct)}%)`)
20660
+ " " + label.padEnd(6) + " " + colorBar2(count, maxGroup, W) + " " + import_chalk24.default.white(String(count).padStart(4)) + import_chalk24.default.dim(` (${String(pct)}%)`)
20685
20661
  );
20686
20662
  }
20687
20663
  console.log("");
20688
20664
  if (topProjects.length > 1) {
20689
- console.log(" " + import_chalk25.default.dim("Cost by project:"));
20665
+ console.log(" " + import_chalk24.default.dim("Cost by project:"));
20690
20666
  const maxProjCost = topProjects[0][1];
20691
20667
  for (const [proj, cost] of topProjects) {
20692
20668
  console.log(
20693
- " " + proj.slice(0, 28).padEnd(28) + " " + colorBar2(cost, maxProjCost, W) + " " + import_chalk25.default.yellow(fmtCost3(cost))
20669
+ " " + proj.slice(0, 28).padEnd(28) + " " + colorBar2(cost, maxProjCost, W) + " " + import_chalk24.default.yellow(fmtCost3(cost))
20694
20670
  );
20695
20671
  }
20696
20672
  console.log("");
20697
20673
  }
20698
- console.log(import_chalk25.default.dim(" " + "\u2500".repeat(70)));
20674
+ console.log(import_chalk24.default.dim(" " + "\u2500".repeat(70)));
20699
20675
  console.log("");
20700
20676
  }
20701
20677
  function renderList(summaries, totalCost) {
20702
20678
  if (summaries.length === 0) {
20703
- console.log(import_chalk25.default.yellow(" No sessions found in the requested range.\n"));
20679
+ console.log(import_chalk24.default.yellow(" No sessions found in the requested range.\n"));
20704
20680
  return;
20705
20681
  }
20706
- const totalLabel = totalCost > 0 ? import_chalk25.default.dim(" ~" + fmtCost3(totalCost) + " total") : "";
20682
+ const totalLabel = totalCost > 0 ? import_chalk24.default.dim(" ~" + fmtCost3(totalCost) + " total") : "";
20707
20683
  console.log(
20708
- " " + import_chalk25.default.white(String(summaries.length)) + import_chalk25.default.dim(` session${summaries.length !== 1 ? "s" : ""}`) + totalLabel
20684
+ " " + import_chalk24.default.white(String(summaries.length)) + import_chalk24.default.dim(` session${summaries.length !== 1 ? "s" : ""}`) + totalLabel
20709
20685
  );
20710
20686
  console.log("");
20711
20687
  let lastGroup = "";
@@ -20713,49 +20689,49 @@ function renderList(summaries, totalCost) {
20713
20689
  const activeDate = fmtDate2(s.lastActiveTime);
20714
20690
  const group = activeDate + " " + s.projectLabel;
20715
20691
  if (group !== lastGroup) {
20716
- console.log(import_chalk25.default.dim(" \u2500\u2500\u2500 ") + import_chalk25.default.bold(activeDate) + import_chalk25.default.dim(" " + s.projectLabel));
20692
+ console.log(import_chalk24.default.dim(" \u2500\u2500\u2500 ") + import_chalk24.default.bold(activeDate) + import_chalk24.default.dim(" " + s.projectLabel));
20717
20693
  lastGroup = group;
20718
20694
  }
20719
20695
  const startDate = fmtDate2(s.startTime);
20720
- const dateRange = startDate !== activeDate ? import_chalk25.default.dim(" (" + startDate + " \u2192 " + activeDate + ")") : "";
20721
- const timeStr = import_chalk25.default.dim(fmtTime(s.startTime));
20722
- const prompt = import_chalk25.default.white(truncate(s.firstPrompt.replace(/\n/g, " "), 50).padEnd(50));
20723
- const tools = s.toolCalls.length > 0 ? import_chalk25.default.dim(String(s.toolCalls.length).padStart(3) + " tools") : import_chalk25.default.dim(" 0 tools");
20724
- const cost = s.costUSD > 0 ? import_chalk25.default.dim(" " + fmtCost3(s.costUSD).padEnd(8)) : " ";
20725
- const blocked = s.blockedCalls.length > 0 ? import_chalk25.default.red(" \u{1F6D1} " + String(s.blockedCalls.length)) : "";
20726
- const snap = s.hasSnapshot ? import_chalk25.default.green(" \u{1F4F8}") : "";
20727
- const agentBadge = s.agent === "gemini" ? import_chalk25.default.blue(" [Gemini]") : s.agent === "codex" ? import_chalk25.default.magenta(" [Codex]") : import_chalk25.default.cyan(" [Claude]");
20728
- const sid = import_chalk25.default.dim(" " + s.sessionId.slice(0, 8));
20696
+ const dateRange = startDate !== activeDate ? import_chalk24.default.dim(" (" + startDate + " \u2192 " + activeDate + ")") : "";
20697
+ const timeStr = import_chalk24.default.dim(fmtTime(s.startTime));
20698
+ const prompt = import_chalk24.default.white(truncate(s.firstPrompt.replace(/\n/g, " "), 50).padEnd(50));
20699
+ const tools = s.toolCalls.length > 0 ? import_chalk24.default.dim(String(s.toolCalls.length).padStart(3) + " tools") : import_chalk24.default.dim(" 0 tools");
20700
+ const cost = s.costUSD > 0 ? import_chalk24.default.dim(" " + fmtCost3(s.costUSD).padEnd(8)) : " ";
20701
+ const blocked = s.blockedCalls.length > 0 ? import_chalk24.default.red(" \u{1F6D1} " + String(s.blockedCalls.length)) : "";
20702
+ const snap = s.hasSnapshot ? import_chalk24.default.green(" \u{1F4F8}") : "";
20703
+ const agentBadge = s.agent === "gemini" ? import_chalk24.default.blue(" [Gemini]") : s.agent === "codex" ? import_chalk24.default.magenta(" [Codex]") : import_chalk24.default.cyan(" [Claude]");
20704
+ const sid = import_chalk24.default.dim(" " + s.sessionId.slice(0, 8));
20729
20705
  console.log(
20730
20706
  ` ${timeStr} ${prompt} ${tools}${cost}${blocked}${snap}${agentBadge}${sid}${dateRange}`
20731
20707
  );
20732
20708
  }
20733
20709
  console.log("");
20734
20710
  console.log(
20735
- import_chalk25.default.dim(" Run") + " " + import_chalk25.default.cyan("node9 sessions --detail <session-id>") + import_chalk25.default.dim(" for full tool trace.")
20711
+ import_chalk24.default.dim(" Run") + " " + import_chalk24.default.cyan("node9 sessions --detail <session-id>") + import_chalk24.default.dim(" for full tool trace.")
20736
20712
  );
20737
20713
  console.log("");
20738
20714
  }
20739
20715
  function renderDetail(s) {
20740
20716
  console.log("");
20741
- console.log(import_chalk25.default.bold(" Session ") + import_chalk25.default.dim(s.sessionId));
20717
+ console.log(import_chalk24.default.bold(" Session ") + import_chalk24.default.dim(s.sessionId));
20742
20718
  console.log(
20743
- import_chalk25.default.bold(" Prompt ") + import_chalk25.default.white(s.firstPrompt.replace(/\n/g, " ").slice(0, 120))
20719
+ import_chalk24.default.bold(" Prompt ") + import_chalk24.default.white(s.firstPrompt.replace(/\n/g, " ").slice(0, 120))
20744
20720
  );
20745
- console.log(import_chalk25.default.bold(" Project ") + import_chalk25.default.white(s.projectLabel));
20721
+ console.log(import_chalk24.default.bold(" Project ") + import_chalk24.default.white(s.projectLabel));
20746
20722
  if (s.agent) {
20747
- const agentLabel2 = s.agent === "gemini" ? import_chalk25.default.blue("Gemini CLI") : s.agent === "codex" ? import_chalk25.default.magenta("Codex") : import_chalk25.default.cyan("Claude Code");
20748
- console.log(import_chalk25.default.bold(" Agent ") + agentLabel2);
20723
+ const agentLabel2 = s.agent === "gemini" ? import_chalk24.default.blue("Gemini CLI") : s.agent === "codex" ? import_chalk24.default.magenta("Codex") : import_chalk24.default.cyan("Claude Code");
20724
+ console.log(import_chalk24.default.bold(" Agent ") + agentLabel2);
20749
20725
  }
20750
- console.log(import_chalk25.default.bold(" When ") + import_chalk25.default.white(fmtDateTime(s.startTime)));
20726
+ console.log(import_chalk24.default.bold(" When ") + import_chalk24.default.white(fmtDateTime(s.startTime)));
20751
20727
  if (s.costUSD > 0)
20752
- console.log(import_chalk25.default.bold(" Cost ") + import_chalk25.default.yellow("~" + fmtCost3(s.costUSD)));
20728
+ console.log(import_chalk24.default.bold(" Cost ") + import_chalk24.default.yellow("~" + fmtCost3(s.costUSD)));
20753
20729
  console.log(
20754
- import_chalk25.default.bold(" Snapshot ") + (s.hasSnapshot ? import_chalk25.default.green("\u2713 taken") : import_chalk25.default.dim("none"))
20730
+ import_chalk24.default.bold(" Snapshot ") + (s.hasSnapshot ? import_chalk24.default.green("\u2713 taken") : import_chalk24.default.dim("none"))
20755
20731
  );
20756
20732
  console.log("");
20757
20733
  if (s.toolCalls.length === 0 && s.blockedCalls.length === 0) {
20758
- console.log(import_chalk25.default.dim(" No tool calls recorded.\n"));
20734
+ console.log(import_chalk24.default.dim(" No tool calls recorded.\n"));
20759
20735
  return;
20760
20736
  }
20761
20737
  const timeline = [
@@ -20768,32 +20744,32 @@ function renderDetail(s) {
20768
20744
  });
20769
20745
  const headerParts = [`Tool calls (${s.toolCalls.length})`];
20770
20746
  if (s.blockedCalls.length > 0)
20771
- headerParts.push(import_chalk25.default.red(`${s.blockedCalls.length} blocked by node9`));
20772
- console.log(import_chalk25.default.bold(" " + headerParts.join(" \xB7 ")));
20747
+ headerParts.push(import_chalk24.default.red(`${s.blockedCalls.length} blocked by node9`));
20748
+ console.log(import_chalk24.default.bold(" " + headerParts.join(" \xB7 ")));
20773
20749
  console.log("");
20774
20750
  for (const entry of timeline) {
20775
20751
  if (entry.kind === "tool") {
20776
20752
  const tc = entry.tc;
20777
20753
  const colorFn = toolColor(tc.tool);
20778
20754
  const toolPad = colorFn(tc.tool.padEnd(16));
20779
- const detail = import_chalk25.default.gray(truncate(toolInputSummary(tc.tool, tc.input), 70));
20780
- const ts = tc.timestamp ? import_chalk25.default.dim(fmtTime(tc.timestamp) + " ") : " ";
20755
+ const detail = import_chalk24.default.gray(truncate(toolInputSummary(tc.tool, tc.input), 70));
20756
+ const ts = tc.timestamp ? import_chalk24.default.dim(fmtTime(tc.timestamp) + " ") : " ";
20781
20757
  console.log(` ${ts}${toolPad} ${detail}`);
20782
20758
  } else {
20783
20759
  const bc = entry.bc;
20784
- const ts = bc.timestamp ? import_chalk25.default.dim(fmtTime(bc.timestamp) + " ") : " ";
20785
- const label = import_chalk25.default.red("\u{1F6D1} BLOCKED".padEnd(16));
20786
- const toolName = import_chalk25.default.red(bc.tool.padEnd(10));
20787
- const argsSummary = bc.args ? import_chalk25.default.gray(truncate(toolInputSummary(bc.tool, bc.args), 40)) : import_chalk25.default.dim("[args not logged]");
20788
- const reason = bc.checkedBy ? import_chalk25.default.dim(" \u2190 " + bc.checkedBy) : "";
20760
+ const ts = bc.timestamp ? import_chalk24.default.dim(fmtTime(bc.timestamp) + " ") : " ";
20761
+ const label = import_chalk24.default.red("\u{1F6D1} BLOCKED".padEnd(16));
20762
+ const toolName = import_chalk24.default.red(bc.tool.padEnd(10));
20763
+ const argsSummary = bc.args ? import_chalk24.default.gray(truncate(toolInputSummary(bc.tool, bc.args), 40)) : import_chalk24.default.dim("[args not logged]");
20764
+ const reason = bc.checkedBy ? import_chalk24.default.dim(" \u2190 " + bc.checkedBy) : "";
20789
20765
  console.log(` ${ts}${label} ${toolName} ${argsSummary}${reason}`);
20790
20766
  }
20791
20767
  }
20792
20768
  console.log("");
20793
20769
  if (s.modifiedFiles.length > 0) {
20794
- console.log(import_chalk25.default.bold(` Files modified (${s.modifiedFiles.length}):`));
20770
+ console.log(import_chalk24.default.bold(` Files modified (${s.modifiedFiles.length}):`));
20795
20771
  for (const f of s.modifiedFiles) {
20796
- console.log(" " + import_chalk25.default.yellow(f));
20772
+ console.log(" " + import_chalk24.default.yellow(f));
20797
20773
  }
20798
20774
  console.log("");
20799
20775
  }
@@ -20801,19 +20777,19 @@ function renderDetail(s) {
20801
20777
  function registerSessionsCommand(program2) {
20802
20778
  program2.command("sessions").description("Show what your AI agent did \u2014 sessions, tool calls, cost, and file changes").option("--all", "Show all sessions (default: last 7 days)").option("--days <n>", "Show last N days of sessions", "7").option("--detail <sessionId>", "Show full tool trace for a session").action((options) => {
20803
20779
  console.log("");
20804
- console.log(import_chalk25.default.cyan.bold("\u{1F4CB} node9 sessions") + import_chalk25.default.dim(" \u2014 what your AI agent did"));
20780
+ console.log(import_chalk24.default.cyan.bold("\u{1F4CB} node9 sessions") + import_chalk24.default.dim(" \u2014 what your AI agent did"));
20805
20781
  console.log("");
20806
20782
  const historyPath = import_path42.default.join(import_os36.default.homedir(), ".claude", "history.jsonl");
20807
20783
  if (!import_fs40.default.existsSync(historyPath)) {
20808
- console.log(import_chalk25.default.yellow(" No Claude session history found at ~/.claude/history.jsonl"));
20809
- console.log(import_chalk25.default.gray(" Install Claude Code, run a few sessions, then try again.\n"));
20784
+ console.log(import_chalk24.default.yellow(" No Claude session history found at ~/.claude/history.jsonl"));
20785
+ console.log(import_chalk24.default.gray(" Install Claude Code, run a few sessions, then try again.\n"));
20810
20786
  return;
20811
20787
  }
20812
20788
  const days = options.detail || options.all ? null : Math.max(1, parseInt(options.days, 10) || 7);
20813
20789
  const rangeLabel = options.detail ? "all time" : options.all ? "all time" : `last ${String(days)} days`;
20814
- console.log(import_chalk25.default.dim(" " + rangeLabel));
20790
+ console.log(import_chalk24.default.dim(" " + rangeLabel));
20815
20791
  console.log("");
20816
- process.stdout.write(import_chalk25.default.dim(" Loading\u2026"));
20792
+ process.stdout.write(import_chalk24.default.dim(" Loading\u2026"));
20817
20793
  const summaries = buildSessions(days);
20818
20794
  if (process.stdout.isTTY) {
20819
20795
  process.stdout.clearLine(0);
@@ -20826,8 +20802,8 @@ function registerSessionsCommand(program2) {
20826
20802
  (s) => s.sessionId === options.detail || s.sessionId.startsWith(options.detail)
20827
20803
  );
20828
20804
  if (!target) {
20829
- console.log(import_chalk25.default.red(` Session not found: ${options.detail}`));
20830
- console.log(import_chalk25.default.dim(" Run `node9 sessions` to list recent sessions.\n"));
20805
+ console.log(import_chalk24.default.red(` Session not found: ${options.detail}`));
20806
+ console.log(import_chalk24.default.dim(" Run `node9 sessions` to list recent sessions.\n"));
20831
20807
  return;
20832
20808
  }
20833
20809
  renderDetail(target);
@@ -20840,7 +20816,7 @@ function registerSessionsCommand(program2) {
20840
20816
  }
20841
20817
 
20842
20818
  // src/cli/commands/skill-pin.ts
20843
- var import_chalk26 = __toESM(require("chalk"));
20819
+ var import_chalk25 = __toESM(require("chalk"));
20844
20820
  var import_fs41 = __toESM(require("fs"));
20845
20821
  var import_os37 = __toESM(require("os"));
20846
20822
  var import_path43 = __toESM(require("path"));
@@ -20860,29 +20836,29 @@ function registerSkillPinCommand(program2) {
20860
20836
  const result = readSkillPinsSafe();
20861
20837
  if (!result.ok) {
20862
20838
  if (result.reason === "missing") {
20863
- console.log(import_chalk26.default.gray("\nNo skill roots are pinned yet."));
20839
+ console.log(import_chalk25.default.gray("\nNo skill roots are pinned yet."));
20864
20840
  console.log(
20865
- import_chalk26.default.gray("Pins are created automatically on the first tool call of each session.\n")
20841
+ import_chalk25.default.gray("Pins are created automatically on the first tool call of each session.\n")
20866
20842
  );
20867
20843
  return;
20868
20844
  }
20869
- console.error(import_chalk26.default.red(`
20845
+ console.error(import_chalk25.default.red(`
20870
20846
  \u274C Pin file is corrupt: ${result.detail}`));
20871
- console.error(import_chalk26.default.yellow(" Run: node9 skill pin reset\n"));
20847
+ console.error(import_chalk25.default.yellow(" Run: node9 skill pin reset\n"));
20872
20848
  process.exit(1);
20873
20849
  }
20874
20850
  const entries = Object.entries(result.pins.roots);
20875
20851
  if (entries.length === 0) {
20876
- console.log(import_chalk26.default.gray("\nNo skill roots are pinned yet.\n"));
20852
+ console.log(import_chalk25.default.gray("\nNo skill roots are pinned yet.\n"));
20877
20853
  return;
20878
20854
  }
20879
- console.log(import_chalk26.default.bold("\n\u{1F512} Pinned Skill Roots\n"));
20855
+ console.log(import_chalk25.default.bold("\n\u{1F512} Pinned Skill Roots\n"));
20880
20856
  for (const [key, entry] of entries) {
20881
- const missing = entry.exists ? "" : import_chalk26.default.yellow(" (not present at pin time)");
20882
- console.log(` ${import_chalk26.default.cyan(key)} ${import_chalk26.default.gray(entry.rootPath)}${missing}`);
20857
+ const missing = entry.exists ? "" : import_chalk25.default.yellow(" (not present at pin time)");
20858
+ console.log(` ${import_chalk25.default.cyan(key)} ${import_chalk25.default.gray(entry.rootPath)}${missing}`);
20883
20859
  console.log(` Files (${entry.fileCount})`);
20884
- console.log(` Hash: ${import_chalk26.default.gray(entry.contentHash.slice(0, 16))}...`);
20885
- console.log(` Pinned: ${import_chalk26.default.gray(entry.pinnedAt)}
20860
+ console.log(` Hash: ${import_chalk25.default.gray(entry.contentHash.slice(0, 16))}...`);
20861
+ console.log(` Pinned: ${import_chalk25.default.gray(entry.pinnedAt)}
20886
20862
  `);
20887
20863
  }
20888
20864
  });
@@ -20891,39 +20867,39 @@ function registerSkillPinCommand(program2) {
20891
20867
  try {
20892
20868
  pins = readSkillPins();
20893
20869
  } catch {
20894
- console.error(import_chalk26.default.red("\n\u274C Pin file is corrupt."));
20895
- console.error(import_chalk26.default.yellow(" Run: node9 skill pin reset\n"));
20870
+ console.error(import_chalk25.default.red("\n\u274C Pin file is corrupt."));
20871
+ console.error(import_chalk25.default.yellow(" Run: node9 skill pin reset\n"));
20896
20872
  process.exit(1);
20897
20873
  }
20898
20874
  if (!pins.roots[rootKey]) {
20899
- console.error(import_chalk26.default.red(`
20875
+ console.error(import_chalk25.default.red(`
20900
20876
  \u274C No pin found for root key "${rootKey}"
20901
20877
  `));
20902
- console.error(`Run ${import_chalk26.default.cyan("node9 skill pin list")} to see pinned roots.
20878
+ console.error(`Run ${import_chalk25.default.cyan("node9 skill pin list")} to see pinned roots.
20903
20879
  `);
20904
20880
  process.exit(1);
20905
20881
  }
20906
20882
  const rootPath = pins.roots[rootKey].rootPath;
20907
20883
  removePin(rootKey);
20908
20884
  wipeSkillSessions();
20909
- console.log(import_chalk26.default.green(`
20910
- \u{1F513} Pin removed for ${import_chalk26.default.cyan(rootKey)}`));
20911
- console.log(import_chalk26.default.gray(` ${rootPath}`));
20912
- console.log(import_chalk26.default.gray(" Next session will re-pin with current state.\n"));
20885
+ console.log(import_chalk25.default.green(`
20886
+ \u{1F513} Pin removed for ${import_chalk25.default.cyan(rootKey)}`));
20887
+ console.log(import_chalk25.default.gray(` ${rootPath}`));
20888
+ console.log(import_chalk25.default.gray(" Next session will re-pin with current state.\n"));
20913
20889
  });
20914
20890
  pinSubCmd.command("reset").description("Clear all skill pins and wipe session verification flags").action(() => {
20915
20891
  const result = readSkillPinsSafe();
20916
20892
  if (!result.ok && result.reason === "missing") {
20917
20893
  wipeSkillSessions();
20918
- console.log(import_chalk26.default.gray("\nNo pins to clear.\n"));
20894
+ console.log(import_chalk25.default.gray("\nNo pins to clear.\n"));
20919
20895
  return;
20920
20896
  }
20921
20897
  const count = result.ok ? Object.keys(result.pins.roots).length : "?";
20922
20898
  clearAllPins();
20923
20899
  wipeSkillSessions();
20924
- console.log(import_chalk26.default.green(`
20900
+ console.log(import_chalk25.default.green(`
20925
20901
  \u{1F513} Cleared ${count} skill pin(s).`));
20926
- console.log(import_chalk26.default.gray(" Next session will re-pin with current state.\n"));
20902
+ console.log(import_chalk25.default.gray(" Next session will re-pin with current state.\n"));
20927
20903
  });
20928
20904
  }
20929
20905
 
@@ -20931,7 +20907,7 @@ function registerSkillPinCommand(program2) {
20931
20907
  var import_fs42 = __toESM(require("fs"));
20932
20908
  var import_os38 = __toESM(require("os"));
20933
20909
  var import_path44 = __toESM(require("path"));
20934
- var import_chalk27 = __toESM(require("chalk"));
20910
+ var import_chalk26 = __toESM(require("chalk"));
20935
20911
  var DECISIONS_FILE2 = import_path44.default.join(import_os38.default.homedir(), ".node9", "decisions.json");
20936
20912
  function readDecisions() {
20937
20913
  try {
@@ -20960,55 +20936,55 @@ function registerDecisionsCommand(program2) {
20960
20936
  const decisions = readDecisions();
20961
20937
  const entries = Object.entries(decisions);
20962
20938
  if (entries.length === 0) {
20963
- console.log(import_chalk27.default.gray(" No persistent decisions stored."));
20939
+ console.log(import_chalk26.default.gray(" No persistent decisions stored."));
20964
20940
  console.log(
20965
- import_chalk27.default.gray(` File: ${DECISIONS_FILE2}
20966
- `) + import_chalk27.default.gray(' Decisions are written when you click "Always Allow" or')
20941
+ import_chalk26.default.gray(` File: ${DECISIONS_FILE2}
20942
+ `) + import_chalk26.default.gray(' Decisions are written when you click "Always Allow" or')
20967
20943
  );
20968
- console.log(import_chalk27.default.gray(' "Always Deny" in node9 tail or the native popup.'));
20944
+ console.log(import_chalk26.default.gray(' "Always Deny" in node9 tail or the native popup.'));
20969
20945
  return;
20970
20946
  }
20971
- console.log(import_chalk27.default.bold(`
20947
+ console.log(import_chalk26.default.bold(`
20972
20948
  Persistent decisions (${entries.length})
20973
20949
  `));
20974
20950
  const w = Math.max(...entries.map(([k]) => k.length));
20975
20951
  for (const [tool, verdict] of entries.sort()) {
20976
- const colored = verdict === "allow" ? import_chalk27.default.green(verdict) : import_chalk27.default.red(verdict);
20952
+ const colored = verdict === "allow" ? import_chalk26.default.green(verdict) : import_chalk26.default.red(verdict);
20977
20953
  console.log(` ${tool.padEnd(w)} ${colored}`);
20978
20954
  }
20979
20955
  console.log(
20980
- import_chalk27.default.gray(`
20956
+ import_chalk26.default.gray(`
20981
20957
  Stored in ${DECISIONS_FILE2}
20982
- `) + import_chalk27.default.gray(" Run `node9 decisions clear <tool>` to remove an entry.")
20958
+ `) + import_chalk26.default.gray(" Run `node9 decisions clear <tool>` to remove an entry.")
20983
20959
  );
20984
20960
  });
20985
20961
  cmd.command("clear <toolName>").description("Remove a persistent decision for one tool").action((toolName) => {
20986
20962
  const decisions = readDecisions();
20987
20963
  if (!(toolName in decisions)) {
20988
- console.log(import_chalk27.default.yellow(` No persistent decision for "${toolName}". Nothing to clear.`));
20964
+ console.log(import_chalk26.default.yellow(` No persistent decision for "${toolName}". Nothing to clear.`));
20989
20965
  process.exitCode = 1;
20990
20966
  return;
20991
20967
  }
20992
20968
  delete decisions[toolName];
20993
20969
  writeDecisions(decisions);
20994
- console.log(import_chalk27.default.green(` \u2713 Cleared persistent decision for "${toolName}".`));
20970
+ console.log(import_chalk26.default.green(` \u2713 Cleared persistent decision for "${toolName}".`));
20995
20971
  });
20996
20972
  cmd.command("clear-all").description("Remove every persistent decision (irreversible)").action(() => {
20997
20973
  const decisions = readDecisions();
20998
20974
  const count = Object.keys(decisions).length;
20999
20975
  if (count === 0) {
21000
- console.log(import_chalk27.default.gray(" Nothing to clear \u2014 no persistent decisions stored."));
20976
+ console.log(import_chalk26.default.gray(" Nothing to clear \u2014 no persistent decisions stored."));
21001
20977
  return;
21002
20978
  }
21003
20979
  writeDecisions({});
21004
20980
  console.log(
21005
- import_chalk27.default.green(` \u2713 Cleared ${count} persistent decision${count === 1 ? "" : "s"}.`)
20981
+ import_chalk26.default.green(` \u2713 Cleared ${count} persistent decision${count === 1 ? "" : "s"}.`)
21006
20982
  );
21007
20983
  });
21008
20984
  }
21009
20985
 
21010
20986
  // src/cli/commands/dlp.ts
21011
- var import_chalk28 = __toESM(require("chalk"));
20987
+ var import_chalk27 = __toESM(require("chalk"));
21012
20988
  var import_fs43 = __toESM(require("fs"));
21013
20989
  var import_path45 = __toESM(require("path"));
21014
20990
  var import_os39 = __toESM(require("os"));
@@ -21063,14 +21039,14 @@ function registerDlpCommand(program2) {
21063
21039
  cmd.command("resolve").description("Mark all current DLP findings as resolved").action(() => {
21064
21040
  const findings = loadDlpFindings();
21065
21041
  if (findings.length === 0) {
21066
- console.log(import_chalk28.default.green("\n \u2705 No response-DLP findings to resolve.\n"));
21042
+ console.log(import_chalk27.default.green("\n \u2705 No response-DLP findings to resolve.\n"));
21067
21043
  return;
21068
21044
  }
21069
21045
  const resolved = loadResolved();
21070
21046
  for (const e of findings) resolved.add(entryKey(e));
21071
21047
  saveResolved(resolved);
21072
21048
  console.log(
21073
- import_chalk28.default.green(
21049
+ import_chalk27.default.green(
21074
21050
  `
21075
21051
  \u2705 ${findings.length} finding${findings.length !== 1 ? "s" : ""} marked as resolved.
21076
21052
  `
@@ -21084,54 +21060,54 @@ function registerDlpCommand(program2) {
21084
21060
  const resolvedCount = findings.length - open.length;
21085
21061
  console.log("");
21086
21062
  console.log(
21087
- import_chalk28.default.bold.cyan("\u{1F510} node9 dlp") + import_chalk28.default.dim(" \u2014 secrets found in Claude response text")
21063
+ import_chalk27.default.bold.cyan("\u{1F510} node9 dlp") + import_chalk27.default.dim(" \u2014 secrets found in Claude response text")
21088
21064
  );
21089
21065
  console.log("");
21090
21066
  if (open.length === 0) {
21091
21067
  if (resolvedCount > 0) {
21092
- console.log(import_chalk28.default.green(` \u2705 No open findings \xB7 ${resolvedCount} previously resolved`));
21068
+ console.log(import_chalk27.default.green(` \u2705 No open findings \xB7 ${resolvedCount} previously resolved`));
21093
21069
  } else {
21094
21070
  console.log(
21095
- import_chalk28.default.green(" \u2705 No findings \u2014 Claude has not leaked secrets in response text")
21071
+ import_chalk27.default.green(" \u2705 No findings \u2014 Claude has not leaked secrets in response text")
21096
21072
  );
21097
21073
  }
21098
21074
  console.log("");
21099
21075
  return;
21100
21076
  }
21101
21077
  console.log(
21102
- import_chalk28.default.bgRed.white.bold(` \u26A0\uFE0F ${open.length} open finding${open.length !== 1 ? "s" : ""} `) + import_chalk28.default.dim(resolvedCount > 0 ? ` (${resolvedCount} resolved)` : "")
21078
+ import_chalk27.default.bgRed.white.bold(` \u26A0\uFE0F ${open.length} open finding${open.length !== 1 ? "s" : ""} `) + import_chalk27.default.dim(resolvedCount > 0 ? ` (${resolvedCount} resolved)` : "")
21103
21079
  );
21104
21080
  console.log("");
21105
21081
  console.log(
21106
- import_chalk28.default.dim(" These secrets were included in Claude's response text \u2014 NOT blocked.")
21082
+ import_chalk27.default.dim(" These secrets were included in Claude's response text \u2014 NOT blocked.")
21107
21083
  );
21108
- console.log(import_chalk28.default.dim(" Rotate each affected key immediately.\n"));
21084
+ console.log(import_chalk27.default.dim(" Rotate each affected key immediately.\n"));
21109
21085
  for (const e of open) {
21110
21086
  console.log(
21111
- " " + import_chalk28.default.red("\u25CF") + " " + import_chalk28.default.white(e.dlpPattern ?? "Secret") + import_chalk28.default.dim(" " + fmtDate3(e.ts))
21087
+ " " + import_chalk27.default.red("\u25CF") + " " + import_chalk27.default.white(e.dlpPattern ?? "Secret") + import_chalk27.default.dim(" " + fmtDate3(e.ts))
21112
21088
  );
21113
21089
  if (e.dlpSample) {
21114
- console.log(" " + import_chalk28.default.dim("Sample: ") + import_chalk28.default.yellow(stripAnsi(e.dlpSample)));
21090
+ console.log(" " + import_chalk27.default.dim("Sample: ") + import_chalk27.default.yellow(stripAnsi(e.dlpSample)));
21115
21091
  }
21116
21092
  if (e.project) {
21117
- console.log(" " + import_chalk28.default.dim("Project: ") + import_chalk28.default.dim(stripAnsi(e.project)));
21093
+ console.log(" " + import_chalk27.default.dim("Project: ") + import_chalk27.default.dim(stripAnsi(e.project)));
21118
21094
  }
21119
21095
  console.log("");
21120
21096
  }
21121
- console.log(" " + import_chalk28.default.bold("Next steps:"));
21122
- console.log(" " + import_chalk28.default.cyan("1.") + " Rotate any exposed keys shown above");
21097
+ console.log(" " + import_chalk27.default.bold("Next steps:"));
21098
+ console.log(" " + import_chalk27.default.cyan("1.") + " Rotate any exposed keys shown above");
21123
21099
  console.log(
21124
- " " + import_chalk28.default.cyan("2.") + " Run " + import_chalk28.default.white("node9 dlp resolve") + " to acknowledge"
21100
+ " " + import_chalk27.default.cyan("2.") + " Run " + import_chalk27.default.white("node9 dlp resolve") + " to acknowledge"
21125
21101
  );
21126
21102
  console.log(
21127
- " " + import_chalk28.default.cyan("3.") + " Run " + import_chalk28.default.white("node9 report") + " for full audit history"
21103
+ " " + import_chalk27.default.cyan("3.") + " Run " + import_chalk27.default.white("node9 report") + " for full audit history"
21128
21104
  );
21129
21105
  console.log("");
21130
21106
  });
21131
21107
  }
21132
21108
 
21133
21109
  // src/cli/commands/mask.ts
21134
- var import_chalk29 = __toESM(require("chalk"));
21110
+ var import_chalk28 = __toESM(require("chalk"));
21135
21111
  var import_fs44 = __toESM(require("fs"));
21136
21112
  var import_path46 = __toESM(require("path"));
21137
21113
  var import_os40 = __toESM(require("os"));
@@ -21268,12 +21244,12 @@ function registerMaskCommand(program2) {
21268
21244
  }
21269
21245
  }) : allFiles;
21270
21246
  if (filtered.length === 0) {
21271
- console.log(import_chalk29.default.yellow(" No session files found."));
21247
+ console.log(import_chalk28.default.yellow(" No session files found."));
21272
21248
  return;
21273
21249
  }
21274
21250
  console.log("");
21275
21251
  if (dryRun) {
21276
- console.log(import_chalk29.default.dim(" Dry run \u2014 no files will be modified.\n"));
21252
+ console.log(import_chalk28.default.dim(" Dry run \u2014 no files will be modified.\n"));
21277
21253
  }
21278
21254
  let totalFiles = 0;
21279
21255
  let totalLines = 0;
@@ -21289,23 +21265,23 @@ function registerMaskCommand(program2) {
21289
21265
  });
21290
21266
  const verb = dryRun ? "Would redact" : "Redacted";
21291
21267
  console.log(
21292
- " " + import_chalk29.default.dim(shortPath.slice(0, 60).padEnd(62)) + import_chalk29.default.red(`${verb}: `) + import_chalk29.default.yellow(patterns.join(", ")) + import_chalk29.default.dim(` (${redactedLines} line${redactedLines !== 1 ? "s" : ""})`)
21268
+ " " + import_chalk28.default.dim(shortPath.slice(0, 60).padEnd(62)) + import_chalk28.default.red(`${verb}: `) + import_chalk28.default.yellow(patterns.join(", ")) + import_chalk28.default.dim(` (${redactedLines} line${redactedLines !== 1 ? "s" : ""})`)
21293
21269
  );
21294
21270
  }
21295
21271
  }
21296
21272
  console.log("");
21297
21273
  if (totalFiles === 0) {
21298
- console.log(import_chalk29.default.green(" No secrets found in session history."));
21274
+ console.log(import_chalk28.default.green(" No secrets found in session history."));
21299
21275
  } else {
21300
21276
  const verb = dryRun ? "would be modified" : "modified";
21301
21277
  console.log(
21302
- import_chalk29.default.bold(` ${totalFiles} file${totalFiles !== 1 ? "s" : ""} ${verb}`) + import_chalk29.default.dim(`, ${totalLines} line${totalLines !== 1 ? "s" : ""} redacted`)
21278
+ import_chalk28.default.bold(` ${totalFiles} file${totalFiles !== 1 ? "s" : ""} ${verb}`) + import_chalk28.default.dim(`, ${totalLines} line${totalLines !== 1 ? "s" : ""} redacted`)
21303
21279
  );
21304
- console.log(" Patterns: " + import_chalk29.default.yellow(totalPatterns.join(", ")));
21280
+ console.log(" Patterns: " + import_chalk28.default.yellow(totalPatterns.join(", ")));
21305
21281
  if (!dryRun) {
21306
21282
  console.log("");
21307
21283
  console.log(
21308
- import_chalk29.default.dim(
21284
+ import_chalk28.default.dim(
21309
21285
  " Note: secrets were already sent to the AI provider during the active session.\n This cleans your local disk only. Rotate any exposed keys."
21310
21286
  )
21311
21287
  );
@@ -21369,17 +21345,17 @@ program.command("login").argument("<apiKey>").option("--local", "Save key for au
21369
21345
  import_fs47.default.writeFileSync(configPath, JSON.stringify(config, null, 2), { mode: 384 });
21370
21346
  }
21371
21347
  if (options.profile && profileName !== "default") {
21372
- console.log(import_chalk31.default.green(`\u2705 Profile "${profileName}" saved`));
21373
- console.log(import_chalk31.default.gray(` Switch to it per-session: NODE9_PROFILE=${profileName} claude`));
21348
+ console.log(import_chalk30.default.green(`\u2705 Profile "${profileName}" saved`));
21349
+ console.log(import_chalk30.default.gray(` Switch to it per-session: NODE9_PROFILE=${profileName} claude`));
21374
21350
  } else if (options.local) {
21375
- console.log(import_chalk31.default.green(`\u2705 Privacy mode \u{1F6E1}\uFE0F`));
21376
- console.log(import_chalk31.default.gray(` All decisions stay on this machine.`));
21351
+ console.log(import_chalk30.default.green(`\u2705 Privacy mode \u{1F6E1}\uFE0F`));
21352
+ console.log(import_chalk30.default.gray(` All decisions stay on this machine.`));
21377
21353
  } else {
21378
- console.log(import_chalk31.default.green(`\u2705 Logged in \u2014 agent mode`));
21379
- console.log(import_chalk31.default.gray(` Team policy enforced for all calls via Node9 cloud.`));
21354
+ console.log(import_chalk30.default.green(`\u2705 Logged in \u2014 agent mode`));
21355
+ console.log(import_chalk30.default.gray(` Team policy enforced for all calls via Node9 cloud.`));
21380
21356
  }
21381
21357
  });
21382
- program.command("addto").description("Integrate Node9 with an AI agent").addHelpText(
21358
+ program.command("addto", { hidden: true }).description("Integrate Node9 with an AI agent").addHelpText(
21383
21359
  "after",
21384
21360
  "\n Supported targets: claude gemini cursor codex windsurf vscode hud"
21385
21361
  ).argument(
@@ -21394,13 +21370,13 @@ program.command("addto").description("Integrate Node9 with an AI agent").addHelp
21394
21370
  if (target === "vscode") return await setupVSCode();
21395
21371
  if (target === "hud") return setupHud();
21396
21372
  console.error(
21397
- import_chalk31.default.red(
21373
+ import_chalk30.default.red(
21398
21374
  `Unknown target: "${target}". Supported: claude, gemini, cursor, codex, windsurf, vscode, hud`
21399
21375
  )
21400
21376
  );
21401
21377
  process.exit(1);
21402
21378
  });
21403
- program.command("setup").description('Alias for "addto" \u2014 integrate Node9 with an AI agent').addHelpText(
21379
+ program.command("setup", { hidden: true }).description('Alias for "addto" \u2014 integrate Node9 with an AI agent').addHelpText(
21404
21380
  "after",
21405
21381
  "\n Supported targets: claude gemini cursor codex windsurf vscode hud"
21406
21382
  ).argument(
@@ -21408,17 +21384,17 @@ program.command("setup").description('Alias for "addto" \u2014 integrate Node9 w
21408
21384
  "The agent to protect: claude | gemini | cursor | codex | windsurf | vscode | hud"
21409
21385
  ).action(async (target) => {
21410
21386
  if (!target) {
21411
- console.log(import_chalk31.default.cyan("\n\u{1F6E1}\uFE0F Node9 Setup \u2014 integrate with your AI agent\n"));
21412
- console.log(" Usage: " + import_chalk31.default.white("node9 setup <target>") + "\n");
21387
+ console.log(import_chalk30.default.cyan("\n\u{1F6E1}\uFE0F Node9 Setup \u2014 integrate with your AI agent\n"));
21388
+ console.log(" Usage: " + import_chalk30.default.white("node9 setup <target>") + "\n");
21413
21389
  console.log(" Targets:");
21414
- console.log(" " + import_chalk31.default.green("claude") + " \u2014 Claude Code (hook mode)");
21415
- console.log(" " + import_chalk31.default.green("gemini") + " \u2014 Gemini CLI (hook mode)");
21416
- console.log(" " + import_chalk31.default.green("cursor") + " \u2014 Cursor (MCP proxy)");
21417
- console.log(" " + import_chalk31.default.green("codex") + " \u2014 OpenAI Codex CLI (MCP proxy)");
21418
- console.log(" " + import_chalk31.default.green("windsurf") + " \u2014 Windsurf (MCP proxy)");
21419
- console.log(" " + import_chalk31.default.green("vscode") + " \u2014 VSCode / Copilot (MCP proxy)");
21390
+ console.log(" " + import_chalk30.default.green("claude") + " \u2014 Claude Code (hook mode)");
21391
+ console.log(" " + import_chalk30.default.green("gemini") + " \u2014 Gemini CLI (hook mode)");
21392
+ console.log(" " + import_chalk30.default.green("cursor") + " \u2014 Cursor (MCP proxy)");
21393
+ console.log(" " + import_chalk30.default.green("codex") + " \u2014 OpenAI Codex CLI (MCP proxy)");
21394
+ console.log(" " + import_chalk30.default.green("windsurf") + " \u2014 Windsurf (MCP proxy)");
21395
+ console.log(" " + import_chalk30.default.green("vscode") + " \u2014 VSCode / Copilot (MCP proxy)");
21420
21396
  process.stdout.write(
21421
- " " + import_chalk31.default.green("hud") + " \u2014 Claude Code security statusline\n"
21397
+ " " + import_chalk30.default.green("hud") + " \u2014 Claude Code security statusline\n"
21422
21398
  );
21423
21399
  console.log("");
21424
21400
  return;
@@ -21432,13 +21408,13 @@ program.command("setup").description('Alias for "addto" \u2014 integrate Node9 w
21432
21408
  if (t === "vscode") return await setupVSCode();
21433
21409
  if (t === "hud") return setupHud();
21434
21410
  console.error(
21435
- import_chalk31.default.red(
21411
+ import_chalk30.default.red(
21436
21412
  `Unknown target: "${target}". Supported: claude, gemini, cursor, codex, windsurf, vscode, hud`
21437
21413
  )
21438
21414
  );
21439
21415
  process.exit(1);
21440
21416
  });
21441
- program.command("removefrom").description("Remove Node9 hooks from an AI agent configuration").addHelpText(
21417
+ program.command("removefrom", { hidden: true }).description("Remove Node9 hooks from an AI agent configuration").addHelpText(
21442
21418
  "after",
21443
21419
  "\n Supported targets: claude gemini cursor codex windsurf vscode hud"
21444
21420
  ).argument(
@@ -21455,33 +21431,33 @@ program.command("removefrom").description("Remove Node9 hooks from an AI agent c
21455
21431
  else if (target === "hud") fn = teardownHud;
21456
21432
  else {
21457
21433
  console.error(
21458
- import_chalk31.default.red(
21434
+ import_chalk30.default.red(
21459
21435
  `Unknown target: "${target}". Supported: claude, gemini, cursor, codex, windsurf, vscode, hud`
21460
21436
  )
21461
21437
  );
21462
21438
  process.exit(1);
21463
21439
  }
21464
- console.log(import_chalk31.default.cyan(`
21440
+ console.log(import_chalk30.default.cyan(`
21465
21441
  \u{1F6E1}\uFE0F Node9: removing hooks from ${target}...
21466
21442
  `));
21467
21443
  try {
21468
21444
  fn();
21469
21445
  } catch (err2) {
21470
- console.error(import_chalk31.default.red(` \u26A0\uFE0F Failed: ${err2 instanceof Error ? err2.message : String(err2)}`));
21446
+ console.error(import_chalk30.default.red(` \u26A0\uFE0F Failed: ${err2 instanceof Error ? err2.message : String(err2)}`));
21471
21447
  process.exit(1);
21472
21448
  }
21473
- console.log(import_chalk31.default.gray("\n Restart the agent for changes to take effect."));
21449
+ console.log(import_chalk30.default.gray("\n Restart the agent for changes to take effect."));
21474
21450
  });
21475
21451
  program.command("uninstall").description("Remove all Node9 hooks and optionally delete config files").option("--purge", "Also delete ~/.node9/ directory (config, audit log, credentials)").action(async (options) => {
21476
- console.log(import_chalk31.default.cyan("\n\u{1F6E1}\uFE0F Node9 Uninstall\n"));
21477
- console.log(import_chalk31.default.bold("Stopping daemon..."));
21452
+ console.log(import_chalk30.default.cyan("\n\u{1F6E1}\uFE0F Node9 Uninstall\n"));
21453
+ console.log(import_chalk30.default.bold("Stopping daemon..."));
21478
21454
  try {
21479
21455
  stopDaemon();
21480
- console.log(import_chalk31.default.green(" \u2705 Daemon stopped"));
21456
+ console.log(import_chalk30.default.green(" \u2705 Daemon stopped"));
21481
21457
  } catch {
21482
- console.log(import_chalk31.default.blue(" \u2139\uFE0F Daemon was not running"));
21458
+ console.log(import_chalk30.default.blue(" \u2139\uFE0F Daemon was not running"));
21483
21459
  }
21484
- console.log(import_chalk31.default.bold("\nRemoving hooks..."));
21460
+ console.log(import_chalk30.default.bold("\nRemoving hooks..."));
21485
21461
  let teardownFailed = false;
21486
21462
  for (const [label, fn] of [
21487
21463
  ["Claude", teardownClaude],
@@ -21496,7 +21472,7 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
21496
21472
  } catch (err2) {
21497
21473
  teardownFailed = true;
21498
21474
  console.error(
21499
- import_chalk31.default.red(
21475
+ import_chalk30.default.red(
21500
21476
  ` \u26A0\uFE0F Failed to remove ${label} hooks: ${err2 instanceof Error ? err2.message : String(err2)}`
21501
21477
  )
21502
21478
  );
@@ -21513,28 +21489,28 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
21513
21489
  import_fs47.default.rmSync(node9Dir, { recursive: true });
21514
21490
  if (import_fs47.default.existsSync(node9Dir)) {
21515
21491
  console.error(
21516
- import_chalk31.default.red("\n \u26A0\uFE0F ~/.node9/ could not be fully deleted \u2014 remove it manually.")
21492
+ import_chalk30.default.red("\n \u26A0\uFE0F ~/.node9/ could not be fully deleted \u2014 remove it manually.")
21517
21493
  );
21518
21494
  } else {
21519
- console.log(import_chalk31.default.green("\n \u2705 Deleted ~/.node9/ (config, audit log, credentials)"));
21495
+ console.log(import_chalk30.default.green("\n \u2705 Deleted ~/.node9/ (config, audit log, credentials)"));
21520
21496
  }
21521
21497
  } else {
21522
- console.log(import_chalk31.default.yellow("\n Skipped \u2014 ~/.node9/ was not deleted."));
21498
+ console.log(import_chalk30.default.yellow("\n Skipped \u2014 ~/.node9/ was not deleted."));
21523
21499
  }
21524
21500
  } else {
21525
- console.log(import_chalk31.default.blue("\n \u2139\uFE0F ~/.node9/ not found \u2014 nothing to delete"));
21501
+ console.log(import_chalk30.default.blue("\n \u2139\uFE0F ~/.node9/ not found \u2014 nothing to delete"));
21526
21502
  }
21527
21503
  } else {
21528
21504
  console.log(
21529
- import_chalk31.default.gray("\n ~/.node9/ kept \u2014 run with --purge to delete config and audit log")
21505
+ import_chalk30.default.gray("\n ~/.node9/ kept \u2014 run with --purge to delete config and audit log")
21530
21506
  );
21531
21507
  }
21532
21508
  if (teardownFailed) {
21533
- console.error(import_chalk31.default.red("\n \u26A0\uFE0F Some hooks could not be removed \u2014 see errors above."));
21509
+ console.error(import_chalk30.default.red("\n \u26A0\uFE0F Some hooks could not be removed \u2014 see errors above."));
21534
21510
  process.exit(1);
21535
21511
  }
21536
- console.log(import_chalk31.default.green.bold("\n\u{1F6E1}\uFE0F Node9 removed. Run: npm uninstall -g @node9/proxy"));
21537
- console.log(import_chalk31.default.gray(" Restart any open AI agent sessions for changes to take effect.\n"));
21512
+ console.log(import_chalk30.default.green.bold("\n\u{1F6E1}\uFE0F Node9 removed. Run: npm uninstall -g @node9/proxy"));
21513
+ console.log(import_chalk30.default.gray(" Restart any open AI agent sessions for changes to take effect.\n"));
21538
21514
  });
21539
21515
  registerDoctorCommand(program, version);
21540
21516
  program.command("explain").description(
@@ -21547,7 +21523,7 @@ program.command("explain").description(
21547
21523
  try {
21548
21524
  args = JSON.parse(trimmed);
21549
21525
  } catch {
21550
- console.error(import_chalk31.default.red(`
21526
+ console.error(import_chalk30.default.red(`
21551
21527
  \u274C Invalid JSON: ${trimmed}
21552
21528
  `));
21553
21529
  process.exit(1);
@@ -21558,54 +21534,54 @@ program.command("explain").description(
21558
21534
  }
21559
21535
  const result = await explainPolicy(tool, args);
21560
21536
  console.log("");
21561
- console.log(import_chalk31.default.cyan.bold("\u{1F6E1}\uFE0F Node9 Explain"));
21537
+ console.log(import_chalk30.default.cyan.bold("\u{1F6E1}\uFE0F Node9 Explain"));
21562
21538
  console.log("");
21563
- console.log(` ${import_chalk31.default.bold("Tool:")} ${import_chalk31.default.white(result.tool)}`);
21539
+ console.log(` ${import_chalk30.default.bold("Tool:")} ${import_chalk30.default.white(result.tool)}`);
21564
21540
  if (argsRaw) {
21565
21541
  const preview2 = argsRaw.length > 80 ? argsRaw.slice(0, 77) + "\u2026" : argsRaw;
21566
- console.log(` ${import_chalk31.default.bold("Input:")} ${import_chalk31.default.gray(preview2)}`);
21542
+ console.log(` ${import_chalk30.default.bold("Input:")} ${import_chalk30.default.gray(preview2)}`);
21567
21543
  }
21568
21544
  console.log("");
21569
- console.log(import_chalk31.default.bold("Config Sources (Waterfall):"));
21545
+ console.log(import_chalk30.default.bold("Config Sources (Waterfall):"));
21570
21546
  for (const tier of result.waterfall) {
21571
- const num3 = import_chalk31.default.gray(` ${tier.tier}.`);
21547
+ const num3 = import_chalk30.default.gray(` ${tier.tier}.`);
21572
21548
  const label = tier.label.padEnd(16);
21573
21549
  let statusStr;
21574
21550
  if (tier.tier === 1) {
21575
- statusStr = import_chalk31.default.gray(tier.note ?? "");
21551
+ statusStr = import_chalk30.default.gray(tier.note ?? "");
21576
21552
  } else if (tier.status === "active") {
21577
- const loc = tier.path ? import_chalk31.default.gray(tier.path) : "";
21578
- const note = tier.note ? import_chalk31.default.gray(`(${tier.note})`) : "";
21579
- statusStr = import_chalk31.default.green("\u2713 active") + (loc ? " " + loc : "") + (note ? " " + note : "");
21553
+ const loc = tier.path ? import_chalk30.default.gray(tier.path) : "";
21554
+ const note = tier.note ? import_chalk30.default.gray(`(${tier.note})`) : "";
21555
+ statusStr = import_chalk30.default.green("\u2713 active") + (loc ? " " + loc : "") + (note ? " " + note : "");
21580
21556
  } else {
21581
- statusStr = import_chalk31.default.gray("\u25CB " + (tier.note ?? "not found"));
21557
+ statusStr = import_chalk30.default.gray("\u25CB " + (tier.note ?? "not found"));
21582
21558
  }
21583
- console.log(`${num3} ${import_chalk31.default.white(label)} ${statusStr}`);
21559
+ console.log(`${num3} ${import_chalk30.default.white(label)} ${statusStr}`);
21584
21560
  }
21585
21561
  console.log("");
21586
- console.log(import_chalk31.default.bold("Policy Evaluation:"));
21562
+ console.log(import_chalk30.default.bold("Policy Evaluation:"));
21587
21563
  for (const step of result.steps) {
21588
21564
  const isFinal = step.isFinal;
21589
21565
  let icon;
21590
- if (step.outcome === "allow") icon = import_chalk31.default.green(" \u2705");
21591
- else if (step.outcome === "review") icon = import_chalk31.default.red(" \u{1F534}");
21592
- else if (step.outcome === "skip") icon = import_chalk31.default.gray(" \u2500 ");
21593
- else icon = import_chalk31.default.gray(" \u25CB ");
21566
+ if (step.outcome === "allow") icon = import_chalk30.default.green(" \u2705");
21567
+ else if (step.outcome === "review") icon = import_chalk30.default.red(" \u{1F534}");
21568
+ else if (step.outcome === "skip") icon = import_chalk30.default.gray(" \u2500 ");
21569
+ else icon = import_chalk30.default.gray(" \u25CB ");
21594
21570
  const name = step.name.padEnd(18);
21595
- const nameStr = isFinal ? import_chalk31.default.white.bold(name) : import_chalk31.default.white(name);
21596
- const detail = isFinal ? import_chalk31.default.white(step.detail) : import_chalk31.default.gray(step.detail);
21597
- const arrow = isFinal ? import_chalk31.default.yellow(" \u2190 STOP") : "";
21571
+ const nameStr = isFinal ? import_chalk30.default.white.bold(name) : import_chalk30.default.white(name);
21572
+ const detail = isFinal ? import_chalk30.default.white(step.detail) : import_chalk30.default.gray(step.detail);
21573
+ const arrow = isFinal ? import_chalk30.default.yellow(" \u2190 STOP") : "";
21598
21574
  console.log(`${icon} ${nameStr} ${detail}${arrow}`);
21599
21575
  }
21600
21576
  console.log("");
21601
21577
  if (result.decision === "allow") {
21602
- console.log(import_chalk31.default.green.bold(" Decision: \u2705 ALLOW") + import_chalk31.default.gray(" \u2014 no approval needed"));
21578
+ console.log(import_chalk30.default.green.bold(" Decision: \u2705 ALLOW") + import_chalk30.default.gray(" \u2014 no approval needed"));
21603
21579
  } else {
21604
21580
  console.log(
21605
- import_chalk31.default.red.bold(" Decision: \u{1F534} REVIEW") + import_chalk31.default.gray(" \u2014 human approval required")
21581
+ import_chalk30.default.red.bold(" Decision: \u{1F534} REVIEW") + import_chalk30.default.gray(" \u2014 human approval required")
21606
21582
  );
21607
21583
  if (result.blockedByLabel) {
21608
- console.log(import_chalk31.default.gray(` Reason: ${result.blockedByLabel}`));
21584
+ console.log(import_chalk30.default.gray(` Reason: ${result.blockedByLabel}`));
21609
21585
  }
21610
21586
  }
21611
21587
  console.log("");
@@ -21620,7 +21596,7 @@ program.command("tail").description("Stream live agent activity to the terminal"
21620
21596
  try {
21621
21597
  await startTail2(options);
21622
21598
  } catch (err2) {
21623
- console.error(import_chalk31.default.red(`\u274C ${err2 instanceof Error ? err2.message : String(err2)}`));
21599
+ console.error(import_chalk30.default.red(`\u274C ${err2 instanceof Error ? err2.message : String(err2)}`));
21624
21600
  process.exit(1);
21625
21601
  }
21626
21602
  });
@@ -21631,11 +21607,10 @@ program.command("monitor").description("Live interactive dashboard \u2014 activi
21631
21607
  const mod = await dynamicImport(`file://${dashboardPath}`);
21632
21608
  await mod.startMonitor();
21633
21609
  } catch (err2) {
21634
- console.error(import_chalk31.default.red(`\u274C ${err2 instanceof Error ? err2.message : String(err2)}`));
21610
+ console.error(import_chalk30.default.red(`\u274C ${err2 instanceof Error ? err2.message : String(err2)}`));
21635
21611
  process.exit(1);
21636
21612
  }
21637
21613
  });
21638
- registerWatchCommand(program);
21639
21614
  registerMcpGatewayCommand(program);
21640
21615
  registerMcpServerCommand(program);
21641
21616
  registerMcpPinCommand(program);
@@ -21643,7 +21618,7 @@ registerSkillPinCommand(program);
21643
21618
  registerDecisionsCommand(program);
21644
21619
  registerCheckCommand(program);
21645
21620
  registerLogCommand(program);
21646
- program.command("hud").description("Render node9 security statusline (spawned by Claude Code statusLine)").addHelpText(
21621
+ program.command("hud", { hidden: true }).description("Render node9 security statusline (spawned by Claude Code statusLine)").addHelpText(
21647
21622
  "after",
21648
21623
  `
21649
21624
  Outputs up to 3 lines to stdout, then exits:
@@ -21687,7 +21662,7 @@ program.command("pause").description("Temporarily disable Node9 protection for a
21687
21662
  const ms = parseDuration(options.duration);
21688
21663
  if (ms === null) {
21689
21664
  console.error(
21690
- import_chalk31.default.red(`
21665
+ import_chalk30.default.red(`
21691
21666
  \u274C Invalid duration: "${options.duration}". Use format like 15m, 1h, 30s.
21692
21667
  `)
21693
21668
  );
@@ -21695,20 +21670,20 @@ program.command("pause").description("Temporarily disable Node9 protection for a
21695
21670
  }
21696
21671
  pauseNode9(ms, options.duration);
21697
21672
  const expiresAt = new Date(Date.now() + ms).toLocaleTimeString();
21698
- console.log(import_chalk31.default.yellow(`
21673
+ console.log(import_chalk30.default.yellow(`
21699
21674
  \u23F8 Node9 paused until ${expiresAt}`));
21700
- console.log(import_chalk31.default.gray(` All tool calls will be allowed without review.`));
21701
- console.log(import_chalk31.default.gray(` Run "node9 resume" to re-enable early.
21675
+ console.log(import_chalk30.default.gray(` All tool calls will be allowed without review.`));
21676
+ console.log(import_chalk30.default.gray(` Run "node9 resume" to re-enable early.
21702
21677
  `));
21703
21678
  });
21704
21679
  program.command("resume").description("Re-enable Node9 protection immediately").action(() => {
21705
21680
  const { paused } = checkPause();
21706
21681
  if (!paused) {
21707
- console.log(import_chalk31.default.gray("\nNode9 is already active \u2014 nothing to resume.\n"));
21682
+ console.log(import_chalk30.default.gray("\nNode9 is already active \u2014 nothing to resume.\n"));
21708
21683
  return;
21709
21684
  }
21710
21685
  resumeNode9();
21711
- console.log(import_chalk31.default.green("\n\u25B6 Node9 resumed \u2014 protection is active.\n"));
21686
+ console.log(import_chalk30.default.green("\n\u25B6 Node9 resumed \u2014 protection is active.\n"));
21712
21687
  });
21713
21688
  var HOOK_BASED_AGENTS = {
21714
21689
  claude: "claude",
@@ -21721,15 +21696,15 @@ program.argument("[command...]", "The agent command to run (e.g., gemini)").acti
21721
21696
  if (HOOK_BASED_AGENTS[firstArg2] !== void 0) {
21722
21697
  const target = HOOK_BASED_AGENTS[firstArg2];
21723
21698
  console.error(
21724
- import_chalk31.default.yellow(`
21699
+ import_chalk30.default.yellow(`
21725
21700
  \u26A0\uFE0F Node9 proxy mode does not support "${target}" directly.`)
21726
21701
  );
21727
- console.error(import_chalk31.default.white(`
21702
+ console.error(import_chalk30.default.white(`
21728
21703
  "${target}" uses its own hook system. Use:`));
21729
21704
  console.error(
21730
- import_chalk31.default.green(` node9 addto ${target} `) + import_chalk31.default.gray("# one-time setup")
21705
+ import_chalk30.default.green(` node9 addto ${target} `) + import_chalk30.default.gray("# one-time setup")
21731
21706
  );
21732
- console.error(import_chalk31.default.green(` ${target} `) + import_chalk31.default.gray("# run normally"));
21707
+ console.error(import_chalk30.default.green(` ${target} `) + import_chalk30.default.gray("# run normally"));
21733
21708
  process.exit(1);
21734
21709
  }
21735
21710
  const runArgs = firstArg2 === "shell" ? commandArgs.slice(1) : commandArgs;
@@ -21746,7 +21721,7 @@ program.argument("[command...]", "The agent command to run (e.g., gemini)").acti
21746
21721
  }
21747
21722
  );
21748
21723
  if (result.noApprovalMechanism && !isDaemonRunning() && !process.env.NODE9_NO_AUTO_DAEMON && getConfig().settings.autoStartDaemon) {
21749
- console.error(import_chalk31.default.cyan("\n\u{1F6E1}\uFE0F Node9: Starting approval daemon automatically..."));
21724
+ console.error(import_chalk30.default.cyan("\n\u{1F6E1}\uFE0F Node9: Starting approval daemon automatically..."));
21750
21725
  const daemonReady = await autoStartDaemonAndWait();
21751
21726
  if (daemonReady) result = await authorizeHeadless("shell", { command: fullCommand });
21752
21727
  }
@@ -21759,12 +21734,12 @@ program.argument("[command...]", "The agent command to run (e.g., gemini)").acti
21759
21734
  }
21760
21735
  if (!result.approved) {
21761
21736
  console.error(
21762
- import_chalk31.default.red(`
21737
+ import_chalk30.default.red(`
21763
21738
  \u274C Node9 Blocked: ${result.reason || "Dangerous command detected."}`)
21764
21739
  );
21765
21740
  process.exit(1);
21766
21741
  }
21767
- console.error(import_chalk31.default.green("\n\u2705 Approved \u2014 running command...\n"));
21742
+ console.error(import_chalk30.default.green("\n\u2705 Approved \u2014 running command...\n"));
21768
21743
  await runProxy(fullCommand);
21769
21744
  } else {
21770
21745
  program.help();