@node9/proxy 2.47.1 → 2.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli-main.js CHANGED
@@ -19279,8 +19279,8 @@ var init_audit = __esm({
19279
19279
  // src/config-schema.ts
19280
19280
  function formatIssues(issues) {
19281
19281
  const lines = issues.map((issue) => {
19282
- const path108 = issue.path.length > 0 ? issue.path.map(String).join(".") : "root";
19283
- return ` \u2022 ${path108}: ${issue.message}`;
19282
+ const path110 = issue.path.length > 0 ? issue.path.map(String).join(".") : "root";
19283
+ return ` \u2022 ${path110}: ${issue.message}`;
19284
19284
  });
19285
19285
  return `Invalid config:
19286
19286
  ${lines.join("\n")}`;
@@ -19293,9 +19293,9 @@ function prunePaths(root, paths) {
19293
19293
  const yi = y[y.length - 1];
19294
19294
  return typeof xi === "number" && typeof yi === "number" ? yi - xi : 0;
19295
19295
  });
19296
- for (const path108 of ordered) {
19296
+ for (const path110 of ordered) {
19297
19297
  let cur = root;
19298
- for (const key of path108.slice(0, -1)) {
19298
+ for (const key of path110.slice(0, -1)) {
19299
19299
  if (cur === null || typeof cur !== "object") {
19300
19300
  cur = void 0;
19301
19301
  break;
@@ -19303,7 +19303,7 @@ function prunePaths(root, paths) {
19303
19303
  cur = cur[key];
19304
19304
  }
19305
19305
  if (cur === null || typeof cur !== "object") continue;
19306
- const last = path108[path108.length - 1];
19306
+ const last = path110[path110.length - 1];
19307
19307
  if (Array.isArray(cur)) {
19308
19308
  const i = Number(last);
19309
19309
  if (Number.isInteger(i) && i >= 0 && i < cur.length) {
@@ -19339,7 +19339,7 @@ function sanitizeConfig(raw) {
19339
19339
  return issue.keys.map((k) => [...at, k]);
19340
19340
  }
19341
19341
  return [at.slice(0, -level || void 0)];
19342
- }).filter((path108) => path108.length > 0);
19342
+ }).filter((path110) => path110.length > 0);
19343
19343
  if (paths.length === 0 || !prunePaths(working, paths)) break;
19344
19344
  }
19345
19345
  if (ConfigFileSchema.safeParse(working).success) break;
@@ -20933,13 +20933,13 @@ function getConfig(cwd) {
20933
20933
  }
20934
20934
  if (Array.isArray(mc.jailPaths)) {
20935
20935
  for (const jp of mc.jailPaths) {
20936
- const path108 = typeof jp?.path === "string" ? jp.path.trim() : "";
20937
- if (!path108) continue;
20936
+ const path110 = typeof jp?.path === "string" ? jp.path.trim() : "";
20937
+ if (!path110) continue;
20938
20938
  const verdict = jp?.verdict === "review" ? "review" : "block";
20939
- for (const r of pathRules(path108, verdict, "org-managed jail")) {
20939
+ for (const r of pathRules(path110, verdict, "org-managed jail")) {
20940
20940
  mergedPolicy.smartRules.push({ ...r, name: `org:${r.name}` });
20941
20941
  }
20942
- mergedPolicy.managedJailPaths.push({ path: path108, verdict });
20942
+ mergedPolicy.managedJailPaths.push({ path: path110, verdict });
20943
20943
  }
20944
20944
  }
20945
20945
  if (Array.isArray(mc.trustedHosts)) {
@@ -24007,19 +24007,29 @@ var init_decision_record = __esm({
24007
24007
  });
24008
24008
 
24009
24009
  // src/auth/daemon.ts
24010
- function notifyActivitySocket(data) {
24010
+ function notifyActivitySocket(data, opts = {}) {
24011
24011
  if (forecastRun()) return Promise.resolve(false);
24012
24012
  return new Promise((resolve2) => {
24013
+ let settled = false;
24014
+ let sock = null;
24015
+ const finish = (ok2) => {
24016
+ if (settled) return;
24017
+ settled = true;
24018
+ clearTimeout(timer);
24019
+ if (!ok2) sock?.destroy();
24020
+ resolve2(ok2);
24021
+ };
24022
+ const timer = setTimeout(() => finish(false), opts.timeoutMs ?? ACTIVITY_SOCKET_TIMEOUT_MS);
24013
24023
  try {
24014
24024
  const payload = JSON.stringify(data);
24015
- const sock = import_net4.default.createConnection(ACTIVITY_SOCKET_PATH);
24025
+ sock = import_net4.default.createConnection(opts.socketPath ?? ACTIVITY_SOCKET_PATH);
24016
24026
  sock.on("connect", () => {
24017
- sock.on("close", () => resolve2(true));
24027
+ sock.on("close", () => finish(true));
24018
24028
  sock.end(payload);
24019
24029
  });
24020
- sock.on("error", () => resolve2(false));
24030
+ sock.on("error", () => finish(false));
24021
24031
  } catch {
24022
- resolve2(false);
24032
+ finish(false);
24023
24033
  }
24024
24034
  });
24025
24035
  }
@@ -24554,7 +24564,7 @@ async function resolveViaDaemon(id, decision, internalToken, source, record2) {
24554
24564
  const winner = parseDecisionRecord(body?.record);
24555
24565
  return winner && typeof body?.won === "boolean" ? { won: body.won, record: winner } : null;
24556
24566
  }
24557
- var import_fs15, import_http, import_net4, import_path15, import_os11, ACTIVITY_SOCKET_PATH, DEFAULT_DAEMON_PORT, DAEMON_PORT, DAEMON_HOST;
24567
+ var import_fs15, import_http, import_net4, import_path15, import_os11, ACTIVITY_SOCKET_PATH, ACTIVITY_SOCKET_TIMEOUT_MS, DEFAULT_DAEMON_PORT, DAEMON_PORT, DAEMON_HOST;
24558
24568
  var init_daemon = __esm({
24559
24569
  "src/auth/daemon.ts"() {
24560
24570
  "use strict";
@@ -24567,6 +24577,7 @@ var init_daemon = __esm({
24567
24577
  init_forecast_context();
24568
24578
  init_decision_record();
24569
24579
  ACTIVITY_SOCKET_PATH = process.platform === "win32" ? "\\\\.\\pipe\\node9-activity" : import_path15.default.join(import_os11.default.tmpdir(), "node9-activity.sock");
24580
+ ACTIVITY_SOCKET_TIMEOUT_MS = 500;
24570
24581
  DEFAULT_DAEMON_PORT = 7391;
24571
24582
  DAEMON_PORT = resolveDaemonPort();
24572
24583
  DAEMON_HOST = "127.0.0.1";
@@ -26712,6 +26723,70 @@ var init_loop_detector = __esm({
26712
26723
  });
26713
26724
 
26714
26725
  // src/policy/negotiation.ts
26726
+ function oneLine(text) {
26727
+ return stripTerminalEscapes(text.slice(0, ONE_LINE_INPUT_MAX)).replace(/\s*\u2014\s*/g, ", ").replace(/\s+/g, " ").trim();
26728
+ }
26729
+ function bounded(text, max2 = USER_LINE_PART_MAX) {
26730
+ return text.length > max2 ? `${text.slice(0, max2 - 3).trimEnd()}...` : text;
26731
+ }
26732
+ function userLinePart(text) {
26733
+ return bounded(oneLine(text).replace(/[.\s]+$/, ""));
26734
+ }
26735
+ function userLineValue(text, max2 = 80) {
26736
+ const v = bounded(oneLine(text).replace(/`/g, "'"), max2);
26737
+ return v ? `\`${v}\`` : "";
26738
+ }
26739
+ function userLineOf(message) {
26740
+ const first = message.split("\n", 1)[0];
26741
+ return first.startsWith(USER_LINE_ICON) ? first : void 0;
26742
+ }
26743
+ function withUserLine(line, body) {
26744
+ return `${USER_LINE_ICON} ${line}
26745
+ ${QUOTE_INSTRUCTION}
26746
+ ${body}`;
26747
+ }
26748
+ function blockedLine(context, fallback) {
26749
+ return `Node9 blocked: ${ruleWhat(context?.ruleDescription) || fallback}`;
26750
+ }
26751
+ function firstSentence(text) {
26752
+ const plain = oneLine(text.replace(PICTOGRAPHS, ""));
26753
+ return plain.split(/(?<=[.!?])\s+(?=[A-Z])/)[0] ?? plain;
26754
+ }
26755
+ function withoutLeadingVerdict(text) {
26756
+ return text.replace(/^node9\b\s*:?\s*/i, "").replace(/^blocked\b\s*:?\s*/i, "");
26757
+ }
26758
+ function ruleWhat(description) {
26759
+ if (!description) return "";
26760
+ const s = firstSentence(description).replace(/^node9\s*:\s*/i, "").replace(/^blocked\s*:\s*/i, "");
26761
+ if (!/[\p{L}\p{N}]/u.test(s)) return "";
26762
+ const by = s.match(IS_BLOCKED_BY) ?? s.match(COMMA_BLOCKED_BY);
26763
+ if (by) return userLinePart(`${by[1]} (${by[2]})`);
26764
+ const bare = s.match(IS_BLOCKED);
26765
+ return userLinePart(bare ? bare[1] : s);
26766
+ }
26767
+ function reasonSentence(reason) {
26768
+ if (!reason) return "";
26769
+ const s = withoutLeadingVerdict(firstSentence(reason));
26770
+ if (/^("[^"]*")?\.?$/.test(s)) return "";
26771
+ return userLinePart(s);
26772
+ }
26773
+ function maliciousPackageLine(reason) {
26774
+ if (!reason) return "";
26775
+ const names = [...reason.matchAll(/"([^"]+)"/g)].map((m) => {
26776
+ const spec = m[1];
26777
+ const at = spec.lastIndexOf("@");
26778
+ return at > 0 ? spec.slice(0, at) : spec;
26779
+ });
26780
+ if (names.length === 0) return "";
26781
+ const advisories = [...reason.matchAll(/\b((?:MAL|GHSA|CVE|OSV|PYSEC|RUSTSEC)-[\w-]+)/g)].map(
26782
+ (m) => m[1]
26783
+ );
26784
+ const unique2 = [...new Set(names)];
26785
+ const suffix = advisories.length ? ` (${[...new Set(advisories)].join(", ")})` : "";
26786
+ return userLinePart(
26787
+ unique2.length === 1 ? `${unique2[0]} is a known malicious package${suffix}` : `${unique2.join(", ")} are known malicious packages${suffix}`
26788
+ );
26789
+ }
26715
26790
  function buildNegotiationMessage(blockedByLabel, isHumanDecision2, humanReason, recoveryCommand, context) {
26716
26791
  if (isHumanDecision2 && context?.redirect && humanReason) {
26717
26792
  return `NODE9: The user stopped this action and gave you an instruction.
@@ -26721,88 +26796,138 @@ INSTRUCTIONS:
26721
26796
  - Retry the original action only if the instruction says you may.`;
26722
26797
  }
26723
26798
  if (isHumanDecision2) {
26724
- return `NODE9: The human user rejected this action.
26799
+ return withUserLine(
26800
+ "Node9: you blocked this action",
26801
+ `NODE9: The human user rejected this action.
26725
26802
  REASON: ${humanReason || "No specific reason provided."}
26726
26803
  INSTRUCTIONS:
26727
26804
  - Do NOT retry this exact command.
26728
26805
  - Acknowledge the block to the user and ask if there is an alternative approach.
26729
- - If you believe this action is critical, explain your reasoning and ask them to run "node9 pause 15m" to proceed.`;
26806
+ - If you believe this action is critical, explain your reasoning and ask them to run "node9 pause 15m" to proceed.`
26807
+ );
26730
26808
  }
26731
26809
  if (context?.kind === "protected-path") {
26732
26810
  const subject = context.path ? `${context.path} is a protected file` : "This file is protected";
26733
- return `NODE9: Blocked. ${subject}, and node9 stopped this call to it. The call did not run, so nothing was exposed.
26811
+ const shown = context.path ? userLineValue(context.path) : "";
26812
+ const line2 = shown ? `Node9 blocked access to ${shown} (protected file)` : "Node9 blocked access to a protected file";
26813
+ return withUserLine(
26814
+ line2,
26815
+ `NODE9: Blocked. ${subject}, and node9 stopped this call to it. The call did not run, so nothing was exposed.
26734
26816
  INSTRUCTIONS:
26735
26817
  - Do NOT retry, and do NOT reach the file another way (cat, grep, a copy, a script, a redirect).
26736
26818
  - If this step needs that file, ask the user to provide what you need or to do the step themselves.
26737
- - Tell the user node9 protected this file, then ask how to proceed.`;
26819
+ - Tell the user node9 protected this file, then ask how to proceed.`
26820
+ );
26738
26821
  }
26739
26822
  const label3 = blockedByLabel.toLowerCase();
26740
26823
  if (label3.includes("dlp") || label3.includes("secret detected") || label3.includes("credential review")) {
26741
- return `NODE9 SECURITY ALERT: A sensitive credential (API key, token, or private key) was found in your tool call arguments.
26824
+ return withUserLine(
26825
+ "Node9 blocked this command: it contains a secret",
26826
+ `NODE9 SECURITY ALERT: A sensitive credential (API key, token, or private key) was found in your tool call arguments.
26742
26827
  CRITICAL INSTRUCTION: Do NOT retry this action.
26743
26828
  REQUIRED ACTIONS:
26744
26829
  1. Remove the hardcoded credential from your command or code.
26745
26830
  2. Use an environment variable or a dedicated secrets manager instead.
26746
26831
  3. Treat the leaked credential as compromised and rotate it immediately.
26747
26832
  Do NOT attempt to bypass this check or pass the credential through another tool.
26748
- - Tell the user node9 blocked this and why, then ask how to proceed.`;
26833
+ - Tell the user node9 blocked this and why, then ask how to proceed.`
26834
+ );
26749
26835
  }
26750
26836
  if (label3.includes("package check")) {
26751
- return `NODE9: Blocked \u2014 ${humanReason || "a package in this command is known to be malicious."}
26837
+ const pkg = maliciousPackageLine(humanReason);
26838
+ return withUserLine(
26839
+ pkg ? `Node9 blocked: ${pkg}` : "Node9 blocked: this package is known to be malicious",
26840
+ `NODE9: Blocked \u2014 ${humanReason || "a package in this command is known to be malicious."}
26752
26841
  INSTRUCTIONS:
26753
26842
  - Do NOT install this package, and do NOT fetch it another way (a different package manager, a tarball URL, a git URL, a mirror).
26754
26843
  - If a dependency is needed, suggest a well-known alternative and let the user choose.
26755
- - Tell the user node9 blocked this install and name the advisory, then ask how to proceed.`;
26844
+ - Tell the user node9 blocked this install and name the advisory, then ask how to proceed.`
26845
+ );
26756
26846
  }
26757
26847
  if (label3.includes("sql safety") && label3.includes("delete without where")) {
26758
- return `NODE9: Blocked \u2014 DELETE without WHERE clause would wipe the entire table.
26848
+ return withUserLine(
26849
+ blockedLine(context, "DELETE without WHERE would wipe the whole table"),
26850
+ `NODE9: Blocked \u2014 DELETE without WHERE clause would wipe the entire table.
26759
26851
  INSTRUCTION: Add a WHERE clause to scope the deletion (e.g. WHERE id = <value>).
26760
26852
  Do NOT retry without a WHERE clause.
26761
- - Tell the user node9 blocked this and why, then ask how to proceed.`;
26853
+ - Tell the user node9 blocked this and why, then ask how to proceed.`
26854
+ );
26762
26855
  }
26763
26856
  if (label3.includes("sql safety") && label3.includes("update without where")) {
26764
- return `NODE9: Blocked \u2014 UPDATE without WHERE clause would update every row.
26857
+ return withUserLine(
26858
+ blockedLine(context, "UPDATE without WHERE would change every row"),
26859
+ `NODE9: Blocked \u2014 UPDATE without WHERE clause would update every row.
26765
26860
  INSTRUCTION: Add a WHERE clause to scope the update (e.g. WHERE id = <value>).
26766
26861
  Do NOT retry without a WHERE clause.
26767
- - Tell the user node9 blocked this and why, then ask how to proceed.`;
26862
+ - Tell the user node9 blocked this and why, then ask how to proceed.`
26863
+ );
26768
26864
  }
26769
26865
  if (label3.includes("dangerous word")) {
26770
26866
  const match = blockedByLabel.match(/dangerous word: "([^"]+)"/i);
26771
26867
  const word = match?.[1] ?? "a dangerous keyword";
26772
- return `NODE9: Blocked \u2014 command contains forbidden keyword "${word}".
26868
+ return withUserLine(
26869
+ blockedLine(context, `the command contains ${userLineValue(word)}`),
26870
+ `NODE9: Blocked \u2014 command contains forbidden keyword "${word}".
26773
26871
  INSTRUCTION: Do NOT use "${word}". Use a non-destructive alternative.
26774
26872
  Do NOT attempt to bypass this with shell tricks or aliases \u2014 it will be blocked again.
26775
- - Tell the user node9 blocked this and why, then ask how to proceed.`;
26873
+ - Tell the user node9 blocked this and why, then ask how to proceed.`
26874
+ );
26776
26875
  }
26777
26876
  if (label3.includes("path blocked") || label3.includes("sandbox")) {
26778
- return `NODE9: Blocked \u2014 operation targets a path outside the allowed sandbox.
26877
+ return withUserLine(
26878
+ blockedLine(context, "this path is outside the allowed sandbox"),
26879
+ `NODE9: Blocked \u2014 operation targets a path outside the allowed sandbox.
26779
26880
  INSTRUCTION: Move your output to an allowed directory such as /tmp/ or the project directory.
26780
26881
  Do NOT retry on the same path.
26781
- - Tell the user node9 blocked this and why, then ask how to proceed.`;
26882
+ - Tell the user node9 blocked this and why, then ask how to proceed.`
26883
+ );
26782
26884
  }
26783
26885
  if (label3.includes("inline execution")) {
26784
- return `NODE9: Blocked \u2014 inline code execution (e.g. bash -c "...") is not allowed.
26886
+ return withUserLine(
26887
+ blockedLine(context, "inline code execution is not allowed"),
26888
+ `NODE9: Blocked \u2014 inline code execution (e.g. bash -c "...") is not allowed.
26785
26889
  INSTRUCTION: Use individual tool calls instead of embedding code in a shell string.
26786
- - Tell the user node9 blocked this and why, then ask how to proceed.`;
26890
+ - Tell the user node9 blocked this and why, then ask how to proceed.`
26891
+ );
26787
26892
  }
26788
26893
  if (label3.includes("strict mode")) {
26789
- return `NODE9: Blocked \u2014 the Block all level is on. All tool calls require explicit human approval.
26790
- INSTRUCTION: Inform the user this action is pending approval. Wait for them to approve via the dashboard or run "node9 pause".`;
26894
+ return withUserLine(
26895
+ "Node9: the Block all level is on, so every action needs your approval",
26896
+ `NODE9: Blocked \u2014 the Block all level is on. All tool calls require explicit human approval.
26897
+ INSTRUCTION: Inform the user this action is pending approval. Wait for them to approve via the dashboard or run "node9 pause".`
26898
+ );
26791
26899
  }
26792
26900
  if (label3.includes("rule") && label3.includes("default block")) {
26793
26901
  const match = blockedByLabel.match(/rule "([^"]+)"/i);
26794
- const rule = match?.[1] ?? "a policy rule";
26795
- return `NODE9: Blocked \u2014 action "${rule}" is forbidden by security policy.
26796
- INSTRUCTION: Do NOT use "${rule}". Find a read-only or non-destructive alternative.
26902
+ const rule2 = match?.[1] ?? "a policy rule";
26903
+ return withUserLine(
26904
+ blockedLine(context, `${userLineValue(rule2)} is not allowed by policy`),
26905
+ `NODE9: Blocked \u2014 action "${rule2}" is forbidden by security policy.
26906
+ INSTRUCTION: Do NOT use "${rule2}". Find a read-only or non-destructive alternative.
26797
26907
  Do NOT attempt to bypass this rule.
26798
- - Tell the user node9 blocked this and why, then ask how to proceed.`;
26908
+ - Tell the user node9 blocked this and why, then ask how to proceed.`
26909
+ );
26910
+ }
26911
+ const timedOut = label3.includes("approval timeout");
26912
+ const rule = ruleWhat(context?.ruleDescription);
26913
+ let line;
26914
+ if (timedOut) {
26915
+ line = rule ? `Node9 blocked: no one approved this in time (${rule.replace(/ \(([^()]+)\)$/, ", $1")})` : "Node9 blocked: no one approved this in time";
26916
+ } else if (rule) {
26917
+ line = `Node9 blocked: ${rule}`;
26918
+ } else {
26919
+ const why = reasonSentence(humanReason);
26920
+ line = why ? `Node9 blocked: ${why}` : `Node9 blocked this action (${userLinePart(agentFacingLabel(blockedByLabel))})`;
26799
26921
  }
26800
26922
  const recovery = recoveryCommand ? `
26801
26923
  REQUIRED ACTION: Run \`${recoveryCommand}\` first, then retry your original command.` : "\n- Pivot to a non-destructive or read-only alternative.";
26802
- return `NODE9: Action blocked by security policy [${agentFacingLabel(blockedByLabel)}].
26924
+ return withUserLine(
26925
+ line,
26926
+ `NODE9: Action blocked by security policy [${agentFacingLabel(blockedByLabel)}].
26803
26927
  INSTRUCTIONS:
26804
26928
  - Do NOT retry this exact command or attempt to bypass the rule.${recovery}
26805
- - Inform the user which security rule was triggered and ask how to proceed.`;
26929
+ - Inform the user which security rule was triggered and ask how to proceed.`
26930
+ );
26806
26931
  }
26807
26932
  function buildReviewMessage(blockedByLabel, ruleDescription, reason) {
26808
26933
  const why = ruleDescription || (reason && reason !== blockedByLabel ? reason : void 0) || blockedByLabel || "this action needs your review";
@@ -26817,7 +26942,7 @@ function isHumanDecision(label3, blockedBy, decidedBy) {
26817
26942
  return l.includes("user") || l.includes("daemon") || l.includes("decision");
26818
26943
  }
26819
26944
  function agentFacingLabel(label3) {
26820
- const plain = label3.replace(/[\p{Extended_Pictographic}\u200D\uFE0F]/gu, "").replace(/\bNode9\b/g, "node9").replace(/\s+/g, " ").trim();
26945
+ const plain = label3.replace(PICTOGRAPHS, "").replace(/\bNode9\b/g, "node9").replace(/\s+/g, " ").trim();
26821
26946
  return plain || "Security Policy";
26822
26947
  }
26823
26948
  function asApprovalRequest(description) {
@@ -26833,11 +26958,20 @@ function asApprovalRequest(description) {
26833
26958
  }
26834
26959
  return description;
26835
26960
  }
26836
- var BLOCKED_BY, DASH_BLOCKED_BY, SHIELD;
26961
+ var USER_LINE_ICON, QUOTE_INSTRUCTION, USER_LINE_PART_MAX, ONE_LINE_INPUT_MAX, PICTOGRAPHS, IS_BLOCKED_BY, IS_BLOCKED, COMMA_BLOCKED_BY, BLOCKED_BY, DASH_BLOCKED_BY, SHIELD;
26837
26962
  var init_negotiation = __esm({
26838
26963
  "src/policy/negotiation.ts"() {
26839
26964
  "use strict";
26840
26965
  init_cjs_shims();
26966
+ init_dist();
26967
+ USER_LINE_ICON = "\u{1F6E1}\uFE0F";
26968
+ QUOTE_INSTRUCTION = "Start your reply with the line above, exactly as written, on its own line.";
26969
+ USER_LINE_PART_MAX = 160;
26970
+ ONE_LINE_INPUT_MAX = 1e3;
26971
+ PICTOGRAPHS = /[\p{Extended_Pictographic}\u200D\uFE0F]/gu;
26972
+ IS_BLOCKED_BY = /^(.+?) (?:is|are) blocked by (.+?)\.?$/i;
26973
+ IS_BLOCKED = /^(.+?) (?:is|are) blocked\.?$/i;
26974
+ COMMA_BLOCKED_BY = /^(.+?), blocked by (.+?)\.?$/i;
26841
26975
  BLOCKED_BY = " is blocked by ";
26842
26976
  DASH_BLOCKED_BY = " \u2014 blocked by ";
26843
26977
  SHIELD = " shield";
@@ -45905,21 +46039,21 @@ function patchConfig(configPath2, patch) {
45905
46039
  throw err2;
45906
46040
  }
45907
46041
  }
45908
- var import_path84, import_os71, GLOBAL_CONFIG_PATH;
46042
+ var import_path86, import_os72, GLOBAL_CONFIG_PATH;
45909
46043
  var init_patch = __esm({
45910
46044
  "src/config/patch.ts"() {
45911
46045
  "use strict";
45912
46046
  init_cjs_shims();
45913
- import_path84 = __toESM(require("path"));
45914
- import_os71 = __toESM(require("os"));
46047
+ import_path86 = __toESM(require("path"));
46048
+ import_os72 = __toESM(require("os"));
45915
46049
  init_write();
45916
- GLOBAL_CONFIG_PATH = import_path84.default.join(import_os71.default.homedir(), ".node9", "config.json");
46050
+ GLOBAL_CONFIG_PATH = import_path86.default.join(import_os72.default.homedir(), ".node9", "config.json");
45917
46051
  }
45918
46052
  });
45919
46053
 
45920
46054
  // src/auth/egress-config.ts
45921
46055
  function egressConfigPath() {
45922
- return import_path85.default.join(import_os72.default.homedir(), ".node9", "config.json");
46056
+ return import_path87.default.join(import_os73.default.homedir(), ".node9", "config.json");
45923
46057
  }
45924
46058
  function readEgressRawConfig() {
45925
46059
  return readConfigFileLegacy(egressConfigPath());
@@ -45979,14 +46113,14 @@ function normalizeEgressHost(host2) {
45979
46113
  function isValidEgressHost(host2) {
45980
46114
  return EGRESS_HOST_RE.test(host2);
45981
46115
  }
45982
- var import_os72, import_path85, DEFAULT_EGRESS, EGRESS_HOST_RE;
46116
+ var import_os73, import_path87, DEFAULT_EGRESS, EGRESS_HOST_RE;
45983
46117
  var init_egress_config = __esm({
45984
46118
  "src/auth/egress-config.ts"() {
45985
46119
  "use strict";
45986
46120
  init_cjs_shims();
45987
46121
  init_write();
45988
- import_os72 = __toESM(require("os"));
45989
- import_path85 = __toESM(require("path"));
46122
+ import_os73 = __toESM(require("os"));
46123
+ import_path87 = __toESM(require("path"));
45990
46124
  init_dist();
45991
46125
  DEFAULT_EGRESS = {
45992
46126
  enabled: false,
@@ -46014,27 +46148,27 @@ __export(local_setup_exports, {
46014
46148
  runLocalSetup: () => runLocalSetup
46015
46149
  });
46016
46150
  function configPath() {
46017
- return import_path86.default.join(import_os73.default.homedir(), ".node9", "config.json");
46151
+ return import_path88.default.join(import_os74.default.homedir(), ".node9", "config.json");
46018
46152
  }
46019
46153
  function combined(values) {
46020
46154
  return values.every(Boolean) ? "on" : values.some(Boolean) ? "partial" : "off";
46021
46155
  }
46022
46156
  function readLocalState(opts = {}) {
46023
46157
  const file2 = configPath();
46024
- if (import_fs86.default.existsSync(file2) && !opts.replaceConfig) {
46158
+ if (import_fs88.default.existsSync(file2) && !opts.replaceConfig) {
46025
46159
  let raw;
46026
46160
  try {
46027
- raw = JSON.parse(import_fs86.default.readFileSync(file2, "utf8"));
46161
+ raw = JSON.parse(import_fs88.default.readFileSync(file2, "utf8"));
46028
46162
  } catch {
46029
46163
  raw = void 0;
46030
46164
  }
46031
46165
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) throw invalidConfig();
46032
46166
  }
46033
- const config = getConfig(import_path86.default.join(import_os73.default.homedir(), ".node9"));
46167
+ const config = getConfig(import_path88.default.join(import_os74.default.homedir(), ".node9"));
46034
46168
  const active = readActiveShields();
46035
46169
  const installed = isDaemonServiceInstalled();
46036
46170
  return {
46037
- fresh: !import_fs86.default.existsSync(file2),
46171
+ fresh: !import_fs88.default.existsSync(file2),
46038
46172
  managed: config.policySource === "workspace",
46039
46173
  shields: combined(DEFAULT_SHIELDS.map((s) => active.includes(s))),
46040
46174
  dlp: combined([config.policy.dlp.enabled, config.policy.dlp.pii !== "off"]),
@@ -46082,7 +46216,7 @@ function diffChoices(state, selected, partial = {}) {
46082
46216
  }
46083
46217
  function setAutostart(enabled) {
46084
46218
  const file2 = configPath();
46085
- const raw = JSON.parse(import_fs86.default.readFileSync(file2, "utf8"));
46219
+ const raw = JSON.parse(import_fs88.default.readFileSync(file2, "utf8"));
46086
46220
  if (raw.settings?.autoStartDaemon === enabled) return;
46087
46221
  raw.settings = { ...raw.settings, autoStartDaemon: enabled };
46088
46222
  atomicWriteSync(file2, JSON.stringify(raw, null, 2) + "\n", { mode: 384 });
@@ -46249,14 +46383,14 @@ async function runLocalSetup(opts) {
46249
46383
  if (interactive && !state.managed && !opts.skipSetup) await askTelemetry(agents, firstInstall);
46250
46384
  return collectSummary(applied);
46251
46385
  }
46252
- var import_fs86, import_os73, import_path86, DEFAULT_SHIELDS;
46386
+ var import_fs88, import_os74, import_path88, DEFAULT_SHIELDS;
46253
46387
  var init_local_setup = __esm({
46254
46388
  "src/cli/local-setup.ts"() {
46255
46389
  "use strict";
46256
46390
  init_cjs_shims();
46257
- import_fs86 = __toESM(require("fs"));
46258
- import_os73 = __toESM(require("os"));
46259
- import_path86 = __toESM(require("path"));
46391
+ import_fs88 = __toESM(require("fs"));
46392
+ import_os74 = __toESM(require("os"));
46393
+ import_path88 = __toESM(require("path"));
46260
46394
  init_config();
46261
46395
  init_patch();
46262
46396
  init_keyed_guard();
@@ -46319,8 +46453,8 @@ async function askTelemetry(agents, firstInstall) {
46319
46453
  }
46320
46454
  }
46321
46455
  function ensureConfig(mode, force = false) {
46322
- const file2 = import_path87.default.join(import_os74.default.homedir(), ".node9", "config.json");
46323
- const firstInstall = !import_fs87.default.existsSync(file2);
46456
+ const file2 = import_path89.default.join(import_os75.default.homedir(), ".node9", "config.json");
46457
+ const firstInstall = !import_fs89.default.existsSync(file2);
46324
46458
  if (firstInstall || force) {
46325
46459
  const body = legacyToV2(
46326
46460
  mode !== void 0 && mode !== DEFAULT_CONFIG.settings.mode ? { settings: { mode } } : {}
@@ -46372,16 +46506,16 @@ function registerInitCommand(program2) {
46372
46506
  }
46373
46507
  );
46374
46508
  }
46375
- var import_fs87, import_path87, import_os74, import_https6, TELEMETRY_PROMPT;
46509
+ var import_fs89, import_path89, import_os75, import_https6, TELEMETRY_PROMPT;
46376
46510
  var init_init = __esm({
46377
46511
  "src/cli/commands/init.ts"() {
46378
46512
  "use strict";
46379
46513
  init_cjs_shims();
46380
46514
  init_v2();
46381
46515
  init_write();
46382
- import_fs87 = __toESM(require("fs"));
46383
- import_path87 = __toESM(require("path"));
46384
- import_os74 = __toESM(require("os"));
46516
+ import_fs89 = __toESM(require("fs"));
46517
+ import_path89 = __toESM(require("path"));
46518
+ import_os75 = __toESM(require("os"));
46385
46519
  import_https6 = __toESM(require("https"));
46386
46520
  init_config();
46387
46521
  init_setup();
@@ -47508,14 +47642,14 @@ var require_util = __commonJS({
47508
47642
  }
47509
47643
  const port = url.port != null ? url.port : url.protocol === "https:" ? 443 : 80;
47510
47644
  let origin = url.origin != null ? url.origin : `${url.protocol || ""}//${url.hostname || ""}:${port}`;
47511
- let path108 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`;
47645
+ let path110 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`;
47512
47646
  if (origin[origin.length - 1] === "/") {
47513
47647
  origin = origin.slice(0, origin.length - 1);
47514
47648
  }
47515
- if (path108 && path108[0] !== "/") {
47516
- path108 = `/${path108}`;
47649
+ if (path110 && path110[0] !== "/") {
47650
+ path110 = `/${path110}`;
47517
47651
  }
47518
- return new URL(`${origin}${path108}`);
47652
+ return new URL(`${origin}${path110}`);
47519
47653
  }
47520
47654
  if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) {
47521
47655
  throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`.");
@@ -48338,9 +48472,9 @@ var require_diagnostics = __commonJS({
48338
48472
  "undici:client:sendHeaders",
48339
48473
  (evt) => {
48340
48474
  const {
48341
- request: { method, path: path108, origin }
48475
+ request: { method, path: path110, origin }
48342
48476
  } = evt;
48343
- debugLog2("sending request to %s %s%s", method, origin, path108);
48477
+ debugLog2("sending request to %s %s%s", method, origin, path110);
48344
48478
  }
48345
48479
  );
48346
48480
  }
@@ -48358,14 +48492,14 @@ var require_diagnostics = __commonJS({
48358
48492
  "undici:request:headers",
48359
48493
  (evt) => {
48360
48494
  const {
48361
- request: { method, path: path108, origin },
48495
+ request: { method, path: path110, origin },
48362
48496
  response: { statusCode }
48363
48497
  } = evt;
48364
48498
  debugLog2(
48365
48499
  "received response to %s %s%s - HTTP %d",
48366
48500
  method,
48367
48501
  origin,
48368
- path108,
48502
+ path110,
48369
48503
  statusCode
48370
48504
  );
48371
48505
  }
@@ -48374,23 +48508,23 @@ var require_diagnostics = __commonJS({
48374
48508
  "undici:request:trailers",
48375
48509
  (evt) => {
48376
48510
  const {
48377
- request: { method, path: path108, origin }
48511
+ request: { method, path: path110, origin }
48378
48512
  } = evt;
48379
- debugLog2("trailers received from %s %s%s", method, origin, path108);
48513
+ debugLog2("trailers received from %s %s%s", method, origin, path110);
48380
48514
  }
48381
48515
  );
48382
48516
  diagnosticsChannel.subscribe(
48383
48517
  "undici:request:error",
48384
48518
  (evt) => {
48385
48519
  const {
48386
- request: { method, path: path108, origin },
48520
+ request: { method, path: path110, origin },
48387
48521
  error
48388
48522
  } = evt;
48389
48523
  debugLog2(
48390
48524
  "request to %s %s%s errored - %s",
48391
48525
  method,
48392
48526
  origin,
48393
- path108,
48527
+ path110,
48394
48528
  error.message
48395
48529
  );
48396
48530
  }
@@ -48506,7 +48640,7 @@ var require_request = __commonJS({
48506
48640
  var kHandler = /* @__PURE__ */ Symbol("handler");
48507
48641
  var Request = class {
48508
48642
  constructor(origin, {
48509
- path: path108,
48643
+ path: path110,
48510
48644
  method,
48511
48645
  body,
48512
48646
  headers,
@@ -48523,11 +48657,11 @@ var require_request = __commonJS({
48523
48657
  maxRedirections,
48524
48658
  typeOfService
48525
48659
  }, handler) {
48526
- if (typeof path108 !== "string") {
48660
+ if (typeof path110 !== "string") {
48527
48661
  throw new InvalidArgumentError("path must be a string");
48528
- } else if (path108[0] !== "/" && !(path108.startsWith("http://") || path108.startsWith("https://")) && method !== "CONNECT") {
48662
+ } else if (path110[0] !== "/" && !(path110.startsWith("http://") || path110.startsWith("https://")) && method !== "CONNECT") {
48529
48663
  throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
48530
- } else if (invalidPathRegex.test(path108)) {
48664
+ } else if (invalidPathRegex.test(path110)) {
48531
48665
  throw new InvalidArgumentError("invalid request path");
48532
48666
  }
48533
48667
  if (typeof method !== "string") {
@@ -48602,7 +48736,7 @@ var require_request = __commonJS({
48602
48736
  this.completed = false;
48603
48737
  this.aborted = false;
48604
48738
  this.upgrade = upgrade || null;
48605
- this.path = query ? serializePathWithQuery(path108, query) : path108;
48739
+ this.path = query ? serializePathWithQuery(path110, query) : path110;
48606
48740
  this.origin = origin;
48607
48741
  this.protocol = getProtocolFromUrlString(origin);
48608
48742
  this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent;
@@ -53849,7 +53983,7 @@ var require_client_h1 = __commonJS({
53849
53983
  return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT";
53850
53984
  }
53851
53985
  function writeH1(client, request2) {
53852
- const { method, path: path108, host: host2, upgrade, blocking, reset } = request2;
53986
+ const { method, path: path110, host: host2, upgrade, blocking, reset } = request2;
53853
53987
  let { body, headers, contentLength } = request2;
53854
53988
  const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH" || method === "QUERY" || method === "PROPFIND" || method === "PROPPATCH";
53855
53989
  if (util.isFormDataLike(body)) {
@@ -53927,7 +54061,7 @@ var require_client_h1 = __commonJS({
53927
54061
  if (socket.setTypeOfService) {
53928
54062
  socket.setTypeOfService(request2.typeOfService);
53929
54063
  }
53930
- let header = `${method} ${path108} HTTP/1.1\r
54064
+ let header = `${method} ${path110} HTTP/1.1\r
53931
54065
  `;
53932
54066
  if (typeof host2 === "string") {
53933
54067
  header += `host: ${host2}\r
@@ -54605,7 +54739,7 @@ var require_client_h2 = __commonJS({
54605
54739
  const headersTimeout = request2.headersTimeout ?? client[kHeadersTimeout];
54606
54740
  const bodyTimeout = request2.bodyTimeout ?? client[kBodyTimeout];
54607
54741
  const session = client[kHTTP2Session];
54608
- const { method, path: path108, host: host2, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request2;
54742
+ const { method, path: path110, host: host2, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request2;
54609
54743
  let { body } = request2;
54610
54744
  if (upgrade != null && upgrade !== "websocket") {
54611
54745
  util.errorRequest(client, request2, new InvalidArgumentError(`Custom upgrade "${upgrade}" not supported over HTTP/2`));
@@ -54674,7 +54808,7 @@ var require_client_h2 = __commonJS({
54674
54808
  }
54675
54809
  headers[HTTP2_HEADER_METHOD] = "CONNECT";
54676
54810
  headers[HTTP2_HEADER_PROTOCOL] = "websocket";
54677
- headers[HTTP2_HEADER_PATH] = path108;
54811
+ headers[HTTP2_HEADER_PATH] = path110;
54678
54812
  if (protocol === "ws:" || protocol === "wss:") {
54679
54813
  headers[HTTP2_HEADER_SCHEME] = protocol === "ws:" ? "http" : "https";
54680
54814
  } else {
@@ -54726,7 +54860,7 @@ var require_client_h2 = __commonJS({
54726
54860
  stream.setTimeout(headersTimeout);
54727
54861
  return true;
54728
54862
  }
54729
- headers[HTTP2_HEADER_PATH] = path108;
54863
+ headers[HTTP2_HEADER_PATH] = path110;
54730
54864
  headers[HTTP2_HEADER_SCHEME] = protocol === "http:" ? "http" : "https";
54731
54865
  const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
54732
54866
  if (body && typeof body.read === "function") {
@@ -57093,10 +57227,10 @@ var require_proxy_agent = __commonJS({
57093
57227
  };
57094
57228
  const {
57095
57229
  origin,
57096
- path: path108 = "/",
57230
+ path: path110 = "/",
57097
57231
  headers = {}
57098
57232
  } = opts;
57099
- opts.path = origin + path108;
57233
+ opts.path = origin + path110;
57100
57234
  if (!("host" in headers) && !("Host" in headers)) {
57101
57235
  const { host: host2 } = new URL(origin);
57102
57236
  headers.host = host2;
@@ -59271,20 +59405,20 @@ var require_mock_utils = __commonJS({
59271
59405
  }
59272
59406
  return normalizedQp;
59273
59407
  }
59274
- function safeUrl(path108) {
59275
- if (typeof path108 !== "string") {
59276
- return path108;
59408
+ function safeUrl(path110) {
59409
+ if (typeof path110 !== "string") {
59410
+ return path110;
59277
59411
  }
59278
- const pathSegments = path108.split("?", 3);
59412
+ const pathSegments = path110.split("?", 3);
59279
59413
  if (pathSegments.length !== 2) {
59280
- return path108;
59414
+ return path110;
59281
59415
  }
59282
59416
  const qp = new URLSearchParams(pathSegments.pop());
59283
59417
  qp.sort();
59284
59418
  return [...pathSegments, qp.toString()].join("?");
59285
59419
  }
59286
- function matchKey(mockDispatch2, { path: path108, method, body, headers }) {
59287
- const pathMatch = matchValue(mockDispatch2.path, path108);
59420
+ function matchKey(mockDispatch2, { path: path110, method, body, headers }) {
59421
+ const pathMatch = matchValue(mockDispatch2.path, path110);
59288
59422
  const methodMatch = matchValue(mockDispatch2.method, method);
59289
59423
  const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true;
59290
59424
  const headersMatch = matchHeaders(mockDispatch2, headers);
@@ -59309,8 +59443,8 @@ var require_mock_utils = __commonJS({
59309
59443
  const basePath = key.query ? serializePathWithQuery(key.path, key.query) : key.path;
59310
59444
  const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
59311
59445
  const resolvedPathWithoutTrailingSlash = removeTrailingSlash(resolvedPath);
59312
- let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path108, ignoreTrailingSlash }) => {
59313
- return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(path108)), resolvedPathWithoutTrailingSlash) : matchValue(safeUrl(path108), resolvedPath);
59446
+ let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path110, ignoreTrailingSlash }) => {
59447
+ return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(path110)), resolvedPathWithoutTrailingSlash) : matchValue(safeUrl(path110), resolvedPath);
59314
59448
  });
59315
59449
  if (matchedMockDispatches.length === 0) {
59316
59450
  throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
@@ -59349,19 +59483,19 @@ var require_mock_utils = __commonJS({
59349
59483
  mockDispatches.splice(index, 1);
59350
59484
  }
59351
59485
  }
59352
- function removeTrailingSlash(path108) {
59353
- while (path108.endsWith("/")) {
59354
- path108 = path108.slice(0, -1);
59486
+ function removeTrailingSlash(path110) {
59487
+ while (path110.endsWith("/")) {
59488
+ path110 = path110.slice(0, -1);
59355
59489
  }
59356
- if (path108.length === 0) {
59357
- path108 = "/";
59490
+ if (path110.length === 0) {
59491
+ path110 = "/";
59358
59492
  }
59359
- return path108;
59493
+ return path110;
59360
59494
  }
59361
59495
  function buildKey(opts) {
59362
- const { path: path108, method, body, headers, query } = opts;
59496
+ const { path: path110, method, body, headers, query } = opts;
59363
59497
  return {
59364
- path: path108,
59498
+ path: path110,
59365
59499
  method,
59366
59500
  body,
59367
59501
  headers,
@@ -60056,10 +60190,10 @@ var require_pending_interceptors_formatter = __commonJS({
60056
60190
  }
60057
60191
  format(pendingInterceptors) {
60058
60192
  const withPrettyHeaders = pendingInterceptors.map(
60059
- ({ method, path: path108, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
60193
+ ({ method, path: path110, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
60060
60194
  Method: method,
60061
60195
  Origin: origin,
60062
- Path: path108,
60196
+ Path: path110,
60063
60197
  "Status code": statusCode,
60064
60198
  Persistent: persist ? PERSISTENT : NOT_PERSISTENT,
60065
60199
  Invocations: timesInvoked,
@@ -60142,9 +60276,9 @@ var require_mock_agent = __commonJS({
60142
60276
  const acceptNonStandardSearchParameters = this[kMockAgentAcceptsNonStandardSearchParameters];
60143
60277
  const dispatchOpts = { ...opts };
60144
60278
  if (acceptNonStandardSearchParameters && dispatchOpts.path) {
60145
- const [path108, searchParams] = dispatchOpts.path.split("?");
60279
+ const [path110, searchParams] = dispatchOpts.path.split("?");
60146
60280
  const normalizedSearchParams = normalizeSearchParams(searchParams, acceptNonStandardSearchParameters);
60147
- dispatchOpts.path = `${path108}?${normalizedSearchParams}`;
60281
+ dispatchOpts.path = `${path110}?${normalizedSearchParams}`;
60148
60282
  }
60149
60283
  return this[kAgent].dispatch(dispatchOpts, handler);
60150
60284
  }
@@ -60547,12 +60681,12 @@ var require_snapshot_recorder = __commonJS({
60547
60681
  * @return {Promise<void>} - Resolves when snapshots are loaded
60548
60682
  */
60549
60683
  async loadSnapshots(filePath) {
60550
- const path108 = filePath || this.#snapshotPath;
60551
- if (!path108) {
60684
+ const path110 = filePath || this.#snapshotPath;
60685
+ if (!path110) {
60552
60686
  throw new InvalidArgumentError("Snapshot path is required");
60553
60687
  }
60554
60688
  try {
60555
- const data = await readFile(resolve2(path108), "utf8");
60689
+ const data = await readFile(resolve2(path110), "utf8");
60556
60690
  const parsed = JSON.parse(data);
60557
60691
  if (Array.isArray(parsed)) {
60558
60692
  this.#snapshots.clear();
@@ -60566,7 +60700,7 @@ var require_snapshot_recorder = __commonJS({
60566
60700
  if (error.code === "ENOENT") {
60567
60701
  this.#snapshots.clear();
60568
60702
  } else {
60569
- throw new UndiciError(`Failed to load snapshots from ${path108}`, { cause: error });
60703
+ throw new UndiciError(`Failed to load snapshots from ${path110}`, { cause: error });
60570
60704
  }
60571
60705
  }
60572
60706
  }
@@ -60577,11 +60711,11 @@ var require_snapshot_recorder = __commonJS({
60577
60711
  * @returns {Promise<void>} - Resolves when snapshots are saved
60578
60712
  */
60579
60713
  async saveSnapshots(filePath) {
60580
- const path108 = filePath || this.#snapshotPath;
60581
- if (!path108) {
60714
+ const path110 = filePath || this.#snapshotPath;
60715
+ if (!path110) {
60582
60716
  throw new InvalidArgumentError("Snapshot path is required");
60583
60717
  }
60584
- const resolvedPath = resolve2(path108);
60718
+ const resolvedPath = resolve2(path110);
60585
60719
  await mkdir(dirname3(resolvedPath), { recursive: true });
60586
60720
  const data = Array.from(this.#snapshots.entries()).map(([hash2, snapshot]) => ({
60587
60721
  hash: hash2,
@@ -61222,15 +61356,15 @@ var require_redirect_handler = __commonJS({
61222
61356
  }
61223
61357
  this.history[kRedirectCacheControl].push(headers["cache-control"]);
61224
61358
  const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)));
61225
- const path108 = search ? `${pathname}${search}` : pathname;
61226
- const redirectUrlString = `${origin}${path108}`;
61359
+ const path110 = search ? `${pathname}${search}` : pathname;
61360
+ const redirectUrlString = `${origin}${path110}`;
61227
61361
  for (const historyUrl of this.history) {
61228
61362
  if (historyUrl.toString() === redirectUrlString) {
61229
61363
  throw new InvalidArgumentError(`Redirect loop detected. Cannot redirect to ${origin}. This typically happens when using a Client or Pool with cross-origin redirects. Use an Agent for cross-origin redirects.`);
61230
61364
  }
61231
61365
  }
61232
61366
  this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin);
61233
- this.opts.path = path108;
61367
+ this.opts.path = path110;
61234
61368
  this.opts.origin = origin;
61235
61369
  this.opts.query = null;
61236
61370
  }
@@ -63006,10 +63140,10 @@ var require_cache_handler = __commonJS({
63006
63140
  }
63007
63141
  return locationUrl.pathname + locationUrl.search;
63008
63142
  }
63009
- function deleteCachedUri(store, cacheKey, path108) {
63143
+ function deleteCachedUri(store, cacheKey, path110) {
63010
63144
  deleteCachedValue(store, {
63011
63145
  ...cacheKey,
63012
- path: path108
63146
+ path: path110
63013
63147
  });
63014
63148
  for (let i = 0; i < util.safeHTTPMethods.length; i++) {
63015
63149
  const method = util.safeHTTPMethods[i];
@@ -63017,7 +63151,7 @@ var require_cache_handler = __commonJS({
63017
63151
  deleteCachedValue(store, {
63018
63152
  ...cacheKey,
63019
63153
  method,
63020
- path: path108
63154
+ path: path110
63021
63155
  });
63022
63156
  }
63023
63157
  }
@@ -63028,9 +63162,9 @@ var require_cache_handler = __commonJS({
63028
63162
  }
63029
63163
  const values = Array.isArray(headerValue) ? headerValue : [headerValue];
63030
63164
  for (let i = 0; i < values.length; i++) {
63031
- const path108 = getSameOriginPath(cacheKey, values[i]);
63032
- if (path108 !== void 0) {
63033
- deleteCachedUri(store, cacheKey, path108);
63165
+ const path110 = getSameOriginPath(cacheKey, values[i]);
63166
+ if (path110 !== void 0) {
63167
+ deleteCachedUri(store, cacheKey, path110);
63034
63168
  }
63035
63169
  }
63036
63170
  }
@@ -68253,11 +68387,11 @@ var require_fetch = __commonJS({
68253
68387
  function dispatch({ body }) {
68254
68388
  const url = requestCurrentURL(request2);
68255
68389
  const agent = fetchParams.controller.dispatcher;
68256
- const path108 = url.pathname + url.search;
68390
+ const path110 = url.pathname + url.search;
68257
68391
  const hasTrailingQuestionMark = url.search.length === 0 && url.href[url.href.length - url.hash.length - 1] === "?";
68258
68392
  return new Promise((resolve2, reject) => agent.dispatch(
68259
68393
  {
68260
- path: hasTrailingQuestionMark ? `${path108}?` : path108,
68394
+ path: hasTrailingQuestionMark ? `${path110}?` : path110,
68261
68395
  origin: url.origin,
68262
68396
  method: request2.method,
68263
68397
  body: agent.isMockActive ? request2.body && (request2.body.source || request2.body.stream) : body,
@@ -69209,9 +69343,9 @@ var require_util4 = __commonJS({
69209
69343
  }
69210
69344
  }
69211
69345
  }
69212
- function validateCookiePath(path108) {
69213
- for (let i = 0; i < path108.length; ++i) {
69214
- const code2 = path108.charCodeAt(i);
69346
+ function validateCookiePath(path110) {
69347
+ for (let i = 0; i < path110.length; ++i) {
69348
+ const code2 = path110.charCodeAt(i);
69215
69349
  if (code2 < 32 || // exclude CTLs (0-31)
69216
69350
  code2 > 126 || // exclude DEL and non-ascii
69217
69351
  code2 === 59) {
@@ -72664,11 +72798,11 @@ var require_undici = __commonJS({
72664
72798
  if (typeof opts.path !== "string") {
72665
72799
  throw new InvalidArgumentError("invalid opts.path");
72666
72800
  }
72667
- let path108 = opts.path;
72801
+ let path110 = opts.path;
72668
72802
  if (!opts.path.startsWith("/")) {
72669
- path108 = `/${path108}`;
72803
+ path110 = `/${path110}`;
72670
72804
  }
72671
- url = new URL(util.parseOrigin(url).origin + path108);
72805
+ url = new URL(util.parseOrigin(url).origin + path110);
72672
72806
  } else {
72673
72807
  if (!opts) {
72674
72808
  opts = typeof url === "object" ? url : {};
@@ -72790,10 +72924,10 @@ function readFirstRunEnv() {
72790
72924
  stdinTTY: !!process.stdin.isTTY,
72791
72925
  stdoutTTY: !!process.stdout.isTTY,
72792
72926
  ci: isCI() || process.env.NODE9_NONINTERACTIVE === "1",
72793
- hasConfig: import_fs101.default.existsSync(import_path100.default.join(import_os82.default.homedir(), ".node9/config.json")),
72927
+ hasConfig: import_fs103.default.existsSync(import_path102.default.join(import_os83.default.homedir(), ".node9/config.json")),
72794
72928
  // Any stored profile means this is not a never-configured machine. Treat
72795
72929
  // malformed credential files conservatively and leave repair to explicit setup.
72796
- hasCredentials: !!getCredentials() || import_fs101.default.existsSync(import_path100.default.join(import_os82.default.homedir(), ".node9/credentials.json"))
72930
+ hasCredentials: !!getCredentials() || import_fs103.default.existsSync(import_path102.default.join(import_os83.default.homedir(), ".node9/credentials.json"))
72797
72931
  };
72798
72932
  }
72799
72933
  function shouldOfferFirstRun(env) {
@@ -72898,14 +73032,14 @@ async function runSetupWizard(opts) {
72898
73032
  process.exitCode = 130;
72899
73033
  }
72900
73034
  }
72901
- var import_fs101, import_os82, import_path100;
73035
+ var import_fs103, import_os83, import_path102;
72902
73036
  var init_first_run = __esm({
72903
73037
  "src/cli/first-run.ts"() {
72904
73038
  "use strict";
72905
73039
  init_cjs_shims();
72906
- import_fs101 = __toESM(require("fs"));
72907
- import_os82 = __toESM(require("os"));
72908
- import_path100 = __toESM(require("path"));
73040
+ import_fs103 = __toESM(require("fs"));
73041
+ import_os83 = __toESM(require("os"));
73042
+ import_path102 = __toESM(require("path"));
72909
73043
  init_config();
72910
73044
  init_agent_wiring();
72911
73045
  init_browser_login();
@@ -72951,20 +73085,20 @@ function getModelContextLimit(model) {
72951
73085
  return 2e5;
72952
73086
  }
72953
73087
  function readSessionUsage() {
72954
- const projectsDir = import_path101.default.join(import_os83.default.homedir(), ".claude", "projects");
72955
- if (!import_fs102.default.existsSync(projectsDir)) return null;
73088
+ const projectsDir = import_path103.default.join(import_os84.default.homedir(), ".claude", "projects");
73089
+ if (!import_fs104.default.existsSync(projectsDir)) return null;
72956
73090
  let latestFile = null;
72957
73091
  let latestMtime = 0;
72958
73092
  try {
72959
- for (const dir2 of import_fs102.default.readdirSync(projectsDir)) {
72960
- const dirPath = import_path101.default.join(projectsDir, dir2);
73093
+ for (const dir2 of import_fs104.default.readdirSync(projectsDir)) {
73094
+ const dirPath = import_path103.default.join(projectsDir, dir2);
72961
73095
  try {
72962
- if (!import_fs102.default.statSync(dirPath).isDirectory()) continue;
72963
- for (const file2 of import_fs102.default.readdirSync(dirPath)) {
73096
+ if (!import_fs104.default.statSync(dirPath).isDirectory()) continue;
73097
+ for (const file2 of import_fs104.default.readdirSync(dirPath)) {
72964
73098
  if (!file2.endsWith(".jsonl") || file2.startsWith("agent-")) continue;
72965
- const filePath = import_path101.default.join(dirPath, file2);
73099
+ const filePath = import_path103.default.join(dirPath, file2);
72966
73100
  try {
72967
- const mtime = import_fs102.default.statSync(filePath).mtimeMs;
73101
+ const mtime = import_fs104.default.statSync(filePath).mtimeMs;
72968
73102
  if (mtime > latestMtime) {
72969
73103
  latestMtime = mtime;
72970
73104
  latestFile = filePath;
@@ -72979,7 +73113,7 @@ function readSessionUsage() {
72979
73113
  }
72980
73114
  if (!latestFile) return null;
72981
73115
  try {
72982
- const lines = import_fs102.default.readFileSync(latestFile, "utf-8").split("\n");
73116
+ const lines = import_fs104.default.readFileSync(latestFile, "utf-8").split("\n");
72983
73117
  let lastModel = "";
72984
73118
  let lastInput = 0;
72985
73119
  let lastOutput = 0;
@@ -73040,7 +73174,7 @@ function formatBase(activity) {
73040
73174
  const time = new Date(activity.ts).toLocaleTimeString([], { hour12: false });
73041
73175
  const icon = getIcon(activity.tool);
73042
73176
  const toolName = activity.tool.slice(0, 16).padEnd(16);
73043
- const argsStr = JSON.stringify(activity.args ?? {}).replace(/\s+/g, " ").replaceAll(import_os83.default.homedir(), "~");
73177
+ const argsStr = JSON.stringify(activity.args ?? {}).replace(/\s+/g, " ").replaceAll(import_os84.default.homedir(), "~");
73044
73178
  const argsPreview = argsStr.length > 70 ? argsStr.slice(0, 70) + "\u2026" : argsStr;
73045
73179
  return `${import_chalk49.default.gray(time)} ${icon} ${agentLabel(activity.agent, activity.mcpServer, activity.sessionId)}${import_chalk49.default.white.bold(toolName)} ${import_chalk49.default.dim(argsPreview)}`;
73046
73180
  }
@@ -73079,9 +73213,9 @@ function renderPending(activity) {
73079
73213
  }
73080
73214
  async function ensureDaemon() {
73081
73215
  let pidPort = null;
73082
- if (import_fs102.default.existsSync(PID_FILE)) {
73216
+ if (import_fs104.default.existsSync(PID_FILE)) {
73083
73217
  try {
73084
- const { port } = JSON.parse(import_fs102.default.readFileSync(PID_FILE, "utf-8"));
73218
+ const { port } = JSON.parse(import_fs104.default.readFileSync(PID_FILE, "utf-8"));
73085
73219
  pidPort = port;
73086
73220
  } catch {
73087
73221
  console.error(import_chalk49.default.dim("\u26A0\uFE0F Could not read PID file; falling back to default port."));
@@ -73107,7 +73241,7 @@ async function ensureDaemon() {
73107
73241
  child.unref();
73108
73242
  if (startupFd !== void 0) {
73109
73243
  try {
73110
- import_fs102.default.closeSync(startupFd);
73244
+ import_fs104.default.closeSync(startupFd);
73111
73245
  } catch {
73112
73246
  }
73113
73247
  }
@@ -73477,8 +73611,8 @@ async function startTail(options = {}) {
73477
73611
  );
73478
73612
  }).catch((err2) => {
73479
73613
  try {
73480
- import_fs102.default.appendFileSync(
73481
- import_path101.default.join(import_os83.default.homedir(), ".node9", "hook-debug.log"),
73614
+ import_fs104.default.appendFileSync(
73615
+ import_path103.default.join(import_os84.default.homedir(), ".node9", "hook-debug.log"),
73482
73616
  `[tail] POST /decision failed: ${String(err2)}
73483
73617
  `
73484
73618
  );
@@ -73544,9 +73678,9 @@ async function startTail(options = {}) {
73544
73678
  };
73545
73679
  process.stdin.on("keypress", onKeypress);
73546
73680
  }
73547
- const auditLog = import_path101.default.join(import_os83.default.homedir(), ".node9", "audit.log");
73681
+ const auditLog = import_path103.default.join(import_os84.default.homedir(), ".node9", "audit.log");
73548
73682
  try {
73549
- const unackedDlp = import_fs102.default.readFileSync(auditLog, "utf-8").split("\n").filter((l) => l.includes('"response-dlp"')).length;
73683
+ const unackedDlp = import_fs104.default.readFileSync(auditLog, "utf-8").split("\n").filter((l) => l.includes('"response-dlp"')).length;
73550
73684
  if (unackedDlp > 0) {
73551
73685
  console.log("");
73552
73686
  console.log(
@@ -73586,7 +73720,7 @@ async function startTail(options = {}) {
73586
73720
  if (stallWarned) return;
73587
73721
  if (Date.now() - lastActivityFromDaemon < STALL_THRESHOLD_MS) return;
73588
73722
  try {
73589
- const auditMtime = import_fs102.default.statSync(auditLog).mtimeMs;
73723
+ const auditMtime = import_fs104.default.statSync(auditLog).mtimeMs;
73590
73724
  if (Date.now() - auditMtime >= STALL_THRESHOLD_MS) return;
73591
73725
  console.log("");
73592
73726
  console.log(
@@ -73758,7 +73892,7 @@ async function startTail(options = {}) {
73758
73892
  process.exit(1);
73759
73893
  });
73760
73894
  }
73761
- var import_http6, import_chalk49, import_fs102, import_os83, import_path101, import_readline5, import_child_process17, PID_FILE, ICONS, MODEL_CONTEXT_LIMITS, RESET, BOLD, RED, YELLOW, CYAN, GRAY, GREEN, HIDE_CURSOR, SHOW_CURSOR, ERASE_DOWN, pendingShownForId, pendingWrappedLines, DIVIDER;
73895
+ var import_http6, import_chalk49, import_fs104, import_os84, import_path103, import_readline5, import_child_process17, PID_FILE, ICONS, MODEL_CONTEXT_LIMITS, RESET, BOLD, RED, YELLOW, CYAN, GRAY, GREEN, HIDE_CURSOR, SHOW_CURSOR, ERASE_DOWN, pendingShownForId, pendingWrappedLines, DIVIDER;
73762
73896
  var init_tail = __esm({
73763
73897
  "src/tui/tail.ts"() {
73764
73898
  "use strict";
@@ -73766,16 +73900,16 @@ var init_tail = __esm({
73766
73900
  import_http6 = __toESM(require("http"));
73767
73901
  init_write();
73768
73902
  import_chalk49 = __toESM(require("chalk"));
73769
- import_fs102 = __toESM(require("fs"));
73770
- import_os83 = __toESM(require("os"));
73771
- import_path101 = __toESM(require("path"));
73903
+ import_fs104 = __toESM(require("fs"));
73904
+ import_os84 = __toESM(require("os"));
73905
+ import_path103 = __toESM(require("path"));
73772
73906
  import_readline5 = __toESM(require("readline"));
73773
73907
  import_child_process17 = require("child_process");
73774
73908
  init_startup_log();
73775
73909
  init_daemon3();
73776
73910
  init_daemon();
73777
73911
  init_safe_text();
73778
- PID_FILE = import_path101.default.join(import_os83.default.homedir(), ".node9", "daemon.pid");
73912
+ PID_FILE = import_path103.default.join(import_os84.default.homedir(), ".node9", "daemon.pid");
73779
73913
  ICONS = {
73780
73914
  bash: "\u{1F4BB}",
73781
73915
  shell: "\u{1F4BB}",
@@ -73897,9 +74031,9 @@ function formatTimeLeft(resetsAt) {
73897
74031
  return ` (${m}m left)`;
73898
74032
  }
73899
74033
  function safeReadJson(filePath) {
73900
- if (!import_fs103.default.existsSync(filePath)) return null;
74034
+ if (!import_fs105.default.existsSync(filePath)) return null;
73901
74035
  try {
73902
- return JSON.parse(import_fs103.default.readFileSync(filePath, "utf-8"));
74036
+ return JSON.parse(import_fs105.default.readFileSync(filePath, "utf-8"));
73903
74037
  } catch {
73904
74038
  return null;
73905
74039
  }
@@ -73920,12 +74054,12 @@ function countHooksInFile(filePath) {
73920
74054
  return Object.keys(cfg.hooks).length;
73921
74055
  }
73922
74056
  function countRulesInDir(rulesDir) {
73923
- if (!import_fs103.default.existsSync(rulesDir)) return 0;
74057
+ if (!import_fs105.default.existsSync(rulesDir)) return 0;
73924
74058
  let count = 0;
73925
74059
  try {
73926
- for (const entry of import_fs103.default.readdirSync(rulesDir, { withFileTypes: true })) {
74060
+ for (const entry of import_fs105.default.readdirSync(rulesDir, { withFileTypes: true })) {
73927
74061
  if (entry.isDirectory()) {
73928
- count += countRulesInDir(import_path102.default.join(rulesDir, entry.name));
74062
+ count += countRulesInDir(import_path104.default.join(rulesDir, entry.name));
73929
74063
  } else if (entry.isFile() && entry.name.endsWith(".md")) {
73930
74064
  count++;
73931
74065
  }
@@ -73936,46 +74070,46 @@ function countRulesInDir(rulesDir) {
73936
74070
  }
73937
74071
  function isSamePath(a, b) {
73938
74072
  try {
73939
- return import_path102.default.resolve(a) === import_path102.default.resolve(b);
74073
+ return import_path104.default.resolve(a) === import_path104.default.resolve(b);
73940
74074
  } catch {
73941
74075
  return false;
73942
74076
  }
73943
74077
  }
73944
74078
  function countConfigs(cwd) {
73945
- const homeDir2 = import_os84.default.homedir();
73946
- const claudeDir = import_path102.default.join(homeDir2, ".claude");
74079
+ const homeDir2 = import_os85.default.homedir();
74080
+ const claudeDir = import_path104.default.join(homeDir2, ".claude");
73947
74081
  let claudeMdCount = 0;
73948
74082
  let rulesCount = 0;
73949
74083
  let hooksCount = 0;
73950
74084
  const userMcpServers = /* @__PURE__ */ new Set();
73951
74085
  const projectMcpServers = /* @__PURE__ */ new Set();
73952
- if (import_fs103.default.existsSync(import_path102.default.join(claudeDir, "CLAUDE.md"))) claudeMdCount++;
73953
- rulesCount += countRulesInDir(import_path102.default.join(claudeDir, "rules"));
73954
- const userSettings = import_path102.default.join(claudeDir, "settings.json");
74086
+ if (import_fs105.default.existsSync(import_path104.default.join(claudeDir, "CLAUDE.md"))) claudeMdCount++;
74087
+ rulesCount += countRulesInDir(import_path104.default.join(claudeDir, "rules"));
74088
+ const userSettings = import_path104.default.join(claudeDir, "settings.json");
73955
74089
  for (const name of getMcpServerNames(userSettings)) userMcpServers.add(name);
73956
74090
  hooksCount += countHooksInFile(userSettings);
73957
- const userClaudeJson = import_path102.default.join(homeDir2, ".claude.json");
74091
+ const userClaudeJson = import_path104.default.join(homeDir2, ".claude.json");
73958
74092
  for (const name of getMcpServerNames(userClaudeJson)) userMcpServers.add(name);
73959
74093
  for (const name of getDisabledMcpServers(userClaudeJson, "disabledMcpServers")) {
73960
74094
  userMcpServers.delete(name);
73961
74095
  }
73962
74096
  if (cwd) {
73963
- if (import_fs103.default.existsSync(import_path102.default.join(cwd, "CLAUDE.md"))) claudeMdCount++;
73964
- if (import_fs103.default.existsSync(import_path102.default.join(cwd, "CLAUDE.local.md"))) claudeMdCount++;
73965
- const projectClaudeDir = import_path102.default.join(cwd, ".claude");
74097
+ if (import_fs105.default.existsSync(import_path104.default.join(cwd, "CLAUDE.md"))) claudeMdCount++;
74098
+ if (import_fs105.default.existsSync(import_path104.default.join(cwd, "CLAUDE.local.md"))) claudeMdCount++;
74099
+ const projectClaudeDir = import_path104.default.join(cwd, ".claude");
73966
74100
  const overlapsUserScope = isSamePath(projectClaudeDir, claudeDir);
73967
74101
  if (!overlapsUserScope) {
73968
- if (import_fs103.default.existsSync(import_path102.default.join(projectClaudeDir, "CLAUDE.md"))) claudeMdCount++;
73969
- rulesCount += countRulesInDir(import_path102.default.join(projectClaudeDir, "rules"));
73970
- const projSettings = import_path102.default.join(projectClaudeDir, "settings.json");
74102
+ if (import_fs105.default.existsSync(import_path104.default.join(projectClaudeDir, "CLAUDE.md"))) claudeMdCount++;
74103
+ rulesCount += countRulesInDir(import_path104.default.join(projectClaudeDir, "rules"));
74104
+ const projSettings = import_path104.default.join(projectClaudeDir, "settings.json");
73971
74105
  for (const name of getMcpServerNames(projSettings)) projectMcpServers.add(name);
73972
74106
  hooksCount += countHooksInFile(projSettings);
73973
74107
  }
73974
- if (import_fs103.default.existsSync(import_path102.default.join(projectClaudeDir, "CLAUDE.local.md"))) claudeMdCount++;
73975
- const localSettings = import_path102.default.join(projectClaudeDir, "settings.local.json");
74108
+ if (import_fs105.default.existsSync(import_path104.default.join(projectClaudeDir, "CLAUDE.local.md"))) claudeMdCount++;
74109
+ const localSettings = import_path104.default.join(projectClaudeDir, "settings.local.json");
73976
74110
  for (const name of getMcpServerNames(localSettings)) projectMcpServers.add(name);
73977
74111
  hooksCount += countHooksInFile(localSettings);
73978
- const mcpJsonServers = getMcpServerNames(import_path102.default.join(cwd, ".mcp.json"));
74112
+ const mcpJsonServers = getMcpServerNames(import_path104.default.join(cwd, ".mcp.json"));
73979
74113
  const disabledMcpJson = getDisabledMcpServers(localSettings, "disabledMcpjsonServers");
73980
74114
  for (const name of disabledMcpJson) mcpJsonServers.delete(name);
73981
74115
  for (const name of mcpJsonServers) projectMcpServers.add(name);
@@ -74008,12 +74142,12 @@ function readActiveShieldsHud() {
74008
74142
  return shieldsCache.value;
74009
74143
  }
74010
74144
  try {
74011
- const shieldsPath = import_path102.default.join(import_os84.default.homedir(), ".node9", "shields.json");
74012
- if (!import_fs103.default.existsSync(shieldsPath)) {
74145
+ const shieldsPath = import_path104.default.join(import_os85.default.homedir(), ".node9", "shields.json");
74146
+ if (!import_fs105.default.existsSync(shieldsPath)) {
74013
74147
  shieldsCache = { value: [], ts: now };
74014
74148
  return [];
74015
74149
  }
74016
- const parsed = JSON.parse(import_fs103.default.readFileSync(shieldsPath, "utf-8"));
74150
+ const parsed = JSON.parse(import_fs105.default.readFileSync(shieldsPath, "utf-8"));
74017
74151
  if (!Array.isArray(parsed.active)) {
74018
74152
  shieldsCache = { value: [], ts: now };
74019
74153
  return [];
@@ -74115,17 +74249,17 @@ function renderContextLine(stdin) {
74115
74249
  async function main() {
74116
74250
  try {
74117
74251
  const [stdin, daemonStatus2] = await Promise.all([readStdin(), queryDaemon()]);
74118
- if (import_fs103.default.existsSync(import_path102.default.join(import_os84.default.homedir(), ".node9", "hud-debug"))) {
74252
+ if (import_fs105.default.existsSync(import_path104.default.join(import_os85.default.homedir(), ".node9", "hud-debug"))) {
74119
74253
  try {
74120
- const logPath = import_path102.default.join(import_os84.default.homedir(), ".node9", "hud-debug.log");
74254
+ const logPath = import_path104.default.join(import_os85.default.homedir(), ".node9", "hud-debug.log");
74121
74255
  const MAX_LOG_SIZE = 10 * 1024 * 1024;
74122
74256
  let size = 0;
74123
74257
  try {
74124
- size = import_fs103.default.statSync(logPath).size;
74258
+ size = import_fs105.default.statSync(logPath).size;
74125
74259
  } catch {
74126
74260
  }
74127
74261
  if (size < MAX_LOG_SIZE) {
74128
- import_fs103.default.appendFileSync(
74262
+ import_fs105.default.appendFileSync(
74129
74263
  logPath,
74130
74264
  JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), stdin }) + "\n"
74131
74265
  );
@@ -74146,11 +74280,11 @@ async function main() {
74146
74280
  try {
74147
74281
  const cwd = stdin.cwd ?? process.cwd();
74148
74282
  for (const configPath2 of [
74149
- import_path102.default.join(cwd, "node9.config.json"),
74150
- import_path102.default.join(import_os84.default.homedir(), ".node9", "config.json")
74283
+ import_path104.default.join(cwd, "node9.config.json"),
74284
+ import_path104.default.join(import_os85.default.homedir(), ".node9", "config.json")
74151
74285
  ]) {
74152
- if (!import_fs103.default.existsSync(configPath2)) continue;
74153
- const cfg = JSON.parse(import_fs103.default.readFileSync(configPath2, "utf-8"));
74286
+ if (!import_fs105.default.existsSync(configPath2)) continue;
74287
+ const cfg = JSON.parse(import_fs105.default.readFileSync(configPath2, "utf-8"));
74154
74288
  const hud = cfg.settings?.hud;
74155
74289
  if (hud && "showEnvironmentCounts" in hud) return hud.showEnvironmentCounts !== false;
74156
74290
  }
@@ -74168,14 +74302,14 @@ async function main() {
74168
74302
  renderOffline();
74169
74303
  }
74170
74304
  }
74171
- var import_fs103, import_path102, import_os84, import_http7, RESET2, BOLD2, DIM, RED2, GREEN2, YELLOW2, BLUE, MAGENTA, CYAN2, WHITE, BAR_FILLED, BAR_EMPTY, BAR_WIDTH, shieldsCache, SHIELDS_CACHE_TTL_MS;
74305
+ var import_fs105, import_path104, import_os85, import_http7, RESET2, BOLD2, DIM, RED2, GREEN2, YELLOW2, BLUE, MAGENTA, CYAN2, WHITE, BAR_FILLED, BAR_EMPTY, BAR_WIDTH, shieldsCache, SHIELDS_CACHE_TTL_MS;
74172
74306
  var init_hud = __esm({
74173
74307
  "src/cli/hud.ts"() {
74174
74308
  "use strict";
74175
74309
  init_cjs_shims();
74176
- import_fs103 = __toESM(require("fs"));
74177
- import_path102 = __toESM(require("path"));
74178
- import_os84 = __toESM(require("os"));
74310
+ import_fs105 = __toESM(require("fs"));
74311
+ import_path104 = __toESM(require("path"));
74312
+ import_os85 = __toESM(require("os"));
74179
74313
  import_http7 = __toESM(require("http"));
74180
74314
  init_daemon();
74181
74315
  init_dist();
@@ -74240,9 +74374,9 @@ init_agent_wiring();
74240
74374
  init_credentials();
74241
74375
  init_daemon3();
74242
74376
  var import_chalk50 = __toESM(require("chalk"));
74243
- var import_fs104 = __toESM(require("fs"));
74244
- var import_path103 = __toESM(require("path"));
74245
- var import_os85 = __toESM(require("os"));
74377
+ var import_fs106 = __toESM(require("fs"));
74378
+ var import_path105 = __toESM(require("path"));
74379
+ var import_os86 = __toESM(require("os"));
74246
74380
  var import_prompts4 = require("@inquirer/prompts");
74247
74381
 
74248
74382
  // src/utils/duration.ts
@@ -74330,7 +74464,8 @@ async function runProxy(targetCommand) {
74330
74464
  {
74331
74465
  kind: result.blockKind,
74332
74466
  path: result.blockedPath,
74333
- redirect: !!result.redirect
74467
+ redirect: !!result.redirect,
74468
+ ruleDescription: result.ruleDescription
74334
74469
  }
74335
74470
  );
74336
74471
  const errorResponse = {
@@ -74450,10 +74585,10 @@ function buildExplainJsonError(message) {
74450
74585
  // src/cli/commands/check.ts
74451
74586
  init_cjs_shims();
74452
74587
  var import_chalk14 = __toESM(require("chalk"));
74453
- var import_fs73 = __toESM(require("fs"));
74588
+ var import_fs75 = __toESM(require("fs"));
74454
74589
  var import_child_process9 = require("child_process");
74455
- var import_path73 = __toESM(require("path"));
74456
- var import_os61 = __toESM(require("os"));
74590
+ var import_path75 = __toESM(require("path"));
74591
+ var import_os62 = __toESM(require("os"));
74457
74592
  init_orchestrator();
74458
74593
  init_state();
74459
74594
  init_daemon();
@@ -74739,6 +74874,112 @@ function discardPendingReview(key, now = Date.now()) {
74739
74874
  // src/cli/commands/check.ts
74740
74875
  init_hook_payload();
74741
74876
  init_safe_text();
74877
+ init_atomic_write();
74878
+
74879
+ // src/utils/own-dir.ts
74880
+ init_cjs_shims();
74881
+ var import_fs73 = __toESM(require("fs"));
74882
+ var import_path73 = __toESM(require("path"));
74883
+ var SESSION_FLAG_SUFFIX = ".node9-flag";
74884
+ var SESSION_FLAG_NAME = /^[A-Za-z0-9_-]{1,128}\.node9-flag$/;
74885
+ function isSessionFlagName(name) {
74886
+ return SESSION_FLAG_NAME.test(name);
74887
+ }
74888
+ function ownRealDir(st) {
74889
+ if (st.isSymbolicLink() || !st.isDirectory()) return false;
74890
+ return typeof process.getuid !== "function" || st.uid === process.getuid();
74891
+ }
74892
+ function ensureOwnDir(dir2) {
74893
+ try {
74894
+ import_fs73.default.mkdirSync(dir2, { recursive: true, mode: 448 });
74895
+ const st = import_fs73.default.lstatSync(dir2);
74896
+ return ownRealDir(st) ? { dev: st.dev, ino: st.ino } : null;
74897
+ } catch {
74898
+ return null;
74899
+ }
74900
+ }
74901
+ function isSameOwnDir(dir2, seen) {
74902
+ try {
74903
+ const st = import_fs73.default.lstatSync(dir2);
74904
+ return ownRealDir(st) && st.dev === seen.dev && st.ino === seen.ino;
74905
+ } catch {
74906
+ return false;
74907
+ }
74908
+ }
74909
+ function removeOldFlag(dir2, seen, name, cutoffMs) {
74910
+ if (!isSessionFlagName(name)) return;
74911
+ const p = import_path73.default.join(dir2, name);
74912
+ try {
74913
+ const st = import_fs73.default.lstatSync(p);
74914
+ if (!st.isFile() || st.mtimeMs >= cutoffMs) return;
74915
+ if (!isSameOwnDir(dir2, seen)) return;
74916
+ import_fs73.default.unlinkSync(p);
74917
+ } catch {
74918
+ }
74919
+ }
74920
+
74921
+ // src/notices/session-notice.ts
74922
+ init_cjs_shims();
74923
+ var import_fs74 = __toESM(require("fs"));
74924
+ var import_os61 = __toESM(require("os"));
74925
+ var import_path74 = __toESM(require("path"));
74926
+ init_dist();
74927
+ var ICON2 = "\u{1F6E1}\uFE0F";
74928
+ var LEVEL_NAMES = {
74929
+ audit: "Audit",
74930
+ soft: "Soft",
74931
+ standard: "Standard",
74932
+ strict: "Strict",
74933
+ "block-all": "Block all"
74934
+ };
74935
+ var SESSION_NOTICE_INSTRUCTION = "Start your next reply to the user with the line above, exactly as written, on its own line.";
74936
+ var FLAG_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
74937
+ var SAFE_SESSION_ID = /^[A-Za-z0-9_-]{1,128}$/;
74938
+ function sessionNoticeLine(mode) {
74939
+ const level = levelOf(mode);
74940
+ if (level === "audit") {
74941
+ return `${ICON2} Node9 is in Audit mode: actions are logged, nothing is blocked.`;
74942
+ }
74943
+ return `${ICON2} Node9 is on (${LEVEL_NAMES[level]}). Every action in this session is checked.`;
74944
+ }
74945
+ function sessionNoticeOutput(mode) {
74946
+ const line = sessionNoticeLine(mode);
74947
+ return JSON.stringify({
74948
+ hookSpecificOutput: {
74949
+ hookEventName: "PreToolUse",
74950
+ additionalContext: `${line}
74951
+ ${SESSION_NOTICE_INSTRUCTION}`
74952
+ },
74953
+ systemMessage: line
74954
+ });
74955
+ }
74956
+ function sessionNoticeEnabled(env = process.env) {
74957
+ if (env.NODE9_SESSION_NOTICE === "1") return true;
74958
+ return env.NODE9_TESTING !== "1";
74959
+ }
74960
+ function claimSessionNotice(sessionId, home = import_os61.default.homedir()) {
74961
+ if (!sessionId || !SAFE_SESSION_ID.test(sessionId)) return false;
74962
+ const dir2 = import_path74.default.join(home, ".node9", "notice-sessions");
74963
+ const seen = ensureOwnDir(dir2);
74964
+ if (!seen) return false;
74965
+ try {
74966
+ if (!isSameOwnDir(dir2, seen)) return false;
74967
+ import_fs74.default.closeSync(import_fs74.default.openSync(import_path74.default.join(dir2, sessionId + SESSION_FLAG_SUFFIX), "wx"));
74968
+ } catch {
74969
+ return false;
74970
+ }
74971
+ removeOldFlags(dir2, seen);
74972
+ return true;
74973
+ }
74974
+ function removeOldFlags(dir2, seen) {
74975
+ const cutoff = Date.now() - FLAG_TTL_MS;
74976
+ try {
74977
+ for (const name of import_fs74.default.readdirSync(dir2)) removeOldFlag(dir2, seen, name, cutoff);
74978
+ } catch {
74979
+ }
74980
+ }
74981
+
74982
+ // src/cli/commands/check.ts
74742
74983
  function detectAiAgent(payload) {
74743
74984
  const meta = payload.meta;
74744
74985
  if (meta && typeof meta === "object") {
@@ -74816,9 +75057,9 @@ function registerCheckCommand(program2) {
74816
75057
  } catch (err2) {
74817
75058
  const tempConfig = getConfig();
74818
75059
  if (process.env.NODE9_DEBUG === "1" || tempConfig.settings.enableHookLogDebug) {
74819
- const logPath = import_path73.default.join(import_os61.default.homedir(), ".node9", "hook-debug.log");
75060
+ const logPath = import_path75.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
74820
75061
  const errMsg = err2 instanceof Error ? err2.message : String(err2);
74821
- import_fs73.default.appendFileSync(
75062
+ import_fs75.default.appendFileSync(
74822
75063
  logPath,
74823
75064
  `[${(/* @__PURE__ */ new Date()).toISOString()}] JSON_PARSE_ERROR: ${errMsg}
74824
75065
  RAW: ${raw}
@@ -74831,14 +75072,14 @@ RAW: ${raw}
74831
75072
  const prompt = typeof payload.prompt === "string" ? payload.prompt : "";
74832
75073
  if (process.env.NODE9_DEBUG === "1") {
74833
75074
  try {
74834
- const logPath = import_path73.default.join(import_os61.default.homedir(), ".node9", "hook-debug.log");
74835
- if (!import_fs73.default.existsSync(import_path73.default.dirname(logPath)))
74836
- import_fs73.default.mkdirSync(import_path73.default.dirname(logPath), { recursive: true });
75075
+ const logPath = import_path75.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
75076
+ if (!import_fs75.default.existsSync(import_path75.default.dirname(logPath)))
75077
+ import_fs75.default.mkdirSync(import_path75.default.dirname(logPath), { recursive: true });
74837
75078
  const sanitized = JSON.stringify({
74838
75079
  ...payload,
74839
75080
  prompt: `<redacted, ${prompt.length} bytes>`
74840
75081
  });
74841
- import_fs73.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] STDIN: ${sanitized}
75082
+ import_fs75.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] STDIN: ${sanitized}
74842
75083
  `);
74843
75084
  } catch {
74844
75085
  }
@@ -74856,7 +75097,7 @@ RAW: ${raw}
74856
75097
  if (!dlpMatch && !canaryHit) {
74857
75098
  try {
74858
75099
  const sid = typeof payload.session_id === "string" ? payload.session_id : typeof payload.conversationId === "string" ? payload.conversationId : "";
74859
- const promptCwd = typeof payload.cwd === "string" && import_path73.default.isAbsolute(payload.cwd) ? payload.cwd : void 0;
75100
+ const promptCwd = typeof payload.cwd === "string" && import_path75.default.isAbsolute(payload.cwd) ? payload.cwd : void 0;
74860
75101
  if (sid && getConfig(promptCwd).policy.untrustedContent?.enabled) {
74861
75102
  await notifyUserMentions(sid, extractContentDestinations(prompt));
74862
75103
  }
@@ -74897,8 +75138,8 @@ RAW: ${raw}
74897
75138
  );
74898
75139
  const reason = `\u{1F6A8} Node9 DLP: ${shownPattern} detected in prompt (${shownSample}). Prompt was not submitted \u2014 remove the credential and try again.`;
74899
75140
  try {
74900
- const ttyFd = import_fs73.default.openSync("/dev/tty", "w");
74901
- import_fs73.default.writeSync(
75141
+ const ttyFd = import_fs75.default.openSync("/dev/tty", "w");
75142
+ import_fs75.default.writeSync(
74902
75143
  ttyFd,
74903
75144
  import_chalk14.default.bgRed.white.bold(`
74904
75145
  \u{1F6A8} NODE9 DLP \u2014 PROMPT BLOCKED
@@ -74908,7 +75149,7 @@ RAW: ${raw}
74908
75149
 
74909
75150
  `)
74910
75151
  );
74911
- import_fs73.default.closeSync(ttyFd);
75152
+ import_fs75.default.closeSync(ttyFd);
74912
75153
  } catch {
74913
75154
  }
74914
75155
  const isCodex = agent2 === "Codex";
@@ -74927,17 +75168,17 @@ RAW: ${raw}
74927
75168
  process.exit(2);
74928
75169
  }
74929
75170
  const payloadCwd = typeof payload.cwd === "string" ? payload.cwd : Array.isArray(payload.workspacePaths) && typeof payload.workspacePaths[0] === "string" ? payload.workspacePaths[0] : void 0;
74930
- const safeCwdForConfig = typeof payloadCwd === "string" && import_path73.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
75171
+ const safeCwdForConfig = typeof payloadCwd === "string" && import_path75.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
74931
75172
  const config = getConfig(safeCwdForConfig);
74932
75173
  const daemonDown = !isDaemonRunning();
74933
75174
  if (config.settings.autoStartDaemon && daemonDown && !process.env.NODE9_NO_AUTO_DAEMON) {
74934
75175
  try {
74935
75176
  const scriptPath = process.argv[1];
74936
- if (typeof scriptPath !== "string" || !import_path73.default.isAbsolute(scriptPath))
75177
+ if (typeof scriptPath !== "string" || !import_path75.default.isAbsolute(scriptPath))
74937
75178
  throw new Error("node9: argv[1] is not an absolute path");
74938
- const resolvedScript = import_fs73.default.realpathSync(scriptPath);
74939
- const packageDist = import_fs73.default.realpathSync(import_path73.default.resolve(__dirname, "../.."));
74940
- if (!resolvedScript.startsWith(packageDist + import_path73.default.sep) && resolvedScript !== packageDist)
75179
+ const resolvedScript = import_fs75.default.realpathSync(scriptPath);
75180
+ const packageDist = import_fs75.default.realpathSync(import_path75.default.resolve(__dirname, "../.."));
75181
+ if (!resolvedScript.startsWith(packageDist + import_path75.default.sep) && resolvedScript !== packageDist)
74941
75182
  throw new Error(
74942
75183
  `node9: daemon spawn aborted \u2014 argv[1] (${resolvedScript}) is outside package dist (${packageDist})`
74943
75184
  );
@@ -74967,17 +75208,17 @@ RAW: ${raw}
74967
75208
  } finally {
74968
75209
  if (startupFd !== void 0) {
74969
75210
  try {
74970
- import_fs73.default.closeSync(startupFd);
75211
+ import_fs75.default.closeSync(startupFd);
74971
75212
  } catch {
74972
75213
  }
74973
75214
  }
74974
75215
  }
74975
75216
  } catch (spawnErr) {
74976
- const logPath = import_path73.default.join(import_os61.default.homedir(), ".node9", "hook-debug.log");
75217
+ const logPath = import_path75.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
74977
75218
  const msg = spawnErr instanceof Error ? spawnErr.message : String(spawnErr);
74978
75219
  recordStartupState("failed", "spawn-aborted", msg);
74979
75220
  try {
74980
- import_fs73.default.appendFileSync(
75221
+ import_fs75.default.appendFileSync(
74981
75222
  logPath,
74982
75223
  `[${(/* @__PURE__ */ new Date()).toISOString()}] daemon-autostart-failed: ${msg}
74983
75224
  `
@@ -74991,10 +75232,10 @@ RAW: ${raw}
74991
75232
  );
74992
75233
  }
74993
75234
  if (process.env.NODE9_DEBUG === "1" || config.settings.enableHookLogDebug) {
74994
- const logPath = import_path73.default.join(import_os61.default.homedir(), ".node9", "hook-debug.log");
74995
- if (!import_fs73.default.existsSync(import_path73.default.dirname(logPath)))
74996
- import_fs73.default.mkdirSync(import_path73.default.dirname(logPath), { recursive: true });
74997
- import_fs73.default.appendFileSync(
75235
+ const logPath = import_path75.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
75236
+ if (!import_fs75.default.existsSync(import_path75.default.dirname(logPath)))
75237
+ import_fs75.default.mkdirSync(import_path75.default.dirname(logPath), { recursive: true });
75238
+ import_fs75.default.appendFileSync(
74998
75239
  logPath,
74999
75240
  `[${(/* @__PURE__ */ new Date()).toISOString()}] STDIN: ${JSON.stringify(raw)}
75000
75241
  `
@@ -75015,8 +75256,8 @@ RAW: ${raw}
75015
75256
  );
75016
75257
  let ttyFd = null;
75017
75258
  try {
75018
- ttyFd = import_fs73.default.openSync("/dev/tty", "w");
75019
- const writeTty = (line) => import_fs73.default.writeSync(ttyFd, line + "\n");
75259
+ ttyFd = import_fs75.default.openSync("/dev/tty", "w");
75260
+ const writeTty = (line) => import_fs75.default.writeSync(ttyFd, line + "\n");
75020
75261
  if (result2?.blockKind === "protected-path") {
75021
75262
  writeTty(
75022
75263
  import_chalk14.default.red.bold(
@@ -75043,7 +75284,7 @@ RAW: ${raw}
75043
75284
  } finally {
75044
75285
  if (ttyFd !== null)
75045
75286
  try {
75046
- import_fs73.default.closeSync(ttyFd);
75287
+ import_fs75.default.closeSync(ttyFd);
75047
75288
  } catch {
75048
75289
  }
75049
75290
  }
@@ -75052,7 +75293,12 @@ RAW: ${raw}
75052
75293
  humanDecision,
75053
75294
  msg,
75054
75295
  result2?.recoveryCommand,
75055
- { kind: result2?.blockKind, path: result2?.blockedPath, redirect: !!result2?.redirect }
75296
+ {
75297
+ kind: result2?.blockKind,
75298
+ path: result2?.blockedPath,
75299
+ redirect: !!result2?.redirect,
75300
+ ruleDescription: result2?.ruleDescription
75301
+ }
75056
75302
  );
75057
75303
  if (agent === "Antigravity") {
75058
75304
  process.stdout.write(
@@ -75069,11 +75315,13 @@ RAW: ${raw}
75069
75315
  );
75070
75316
  process.exit(0);
75071
75317
  }
75318
+ const userLine = userLineOf(aiFeedbackMessage);
75072
75319
  process.stdout.write(
75073
75320
  JSON.stringify({
75074
75321
  decision: "block",
75075
75322
  reason: aiFeedbackMessage,
75076
75323
  // This is the core instruction
75324
+ ...agent === "Claude Code" && userLine ? { systemMessage: userLine } : {},
75077
75325
  hookSpecificOutput: {
75078
75326
  hookEventName: "PreToolUse",
75079
75327
  permissionDecision: "deny",
@@ -75107,8 +75355,8 @@ RAW: ${raw}
75107
75355
  } catch {
75108
75356
  }
75109
75357
  try {
75110
- const ttyFd = import_fs73.default.openSync("/dev/tty", "w");
75111
- import_fs73.default.writeSync(
75358
+ const ttyFd = import_fs75.default.openSync("/dev/tty", "w");
75359
+ import_fs75.default.writeSync(
75112
75360
  ttyFd,
75113
75361
  import_chalk14.default.yellow(
75114
75362
  `
@@ -75116,7 +75364,7 @@ RAW: ${raw}
75116
75364
  `
75117
75365
  )
75118
75366
  );
75119
- import_fs73.default.closeSync(ttyFd);
75367
+ import_fs75.default.closeSync(ttyFd);
75120
75368
  } catch {
75121
75369
  }
75122
75370
  if (agent === "GitHub Copilot") {
@@ -75148,17 +75396,20 @@ RAW: ${raw}
75148
75396
  const safeSessionId = /^[A-Za-z0-9_\-]{1,128}$/.test(rawSessionId) ? rawSessionId : "";
75149
75397
  if (skillPinCfg.enabled && safeSessionId) {
75150
75398
  try {
75151
- const sessionsDir = import_path73.default.join(import_os61.default.homedir(), ".node9", "skill-sessions");
75152
- const flagPath = import_path73.default.join(sessionsDir, `${safeSessionId}.json`);
75399
+ const sessionsDir = import_path75.default.join(import_os62.default.homedir(), ".node9", "skill-sessions");
75400
+ const flagPath = import_path75.default.join(sessionsDir, `${safeSessionId}${SESSION_FLAG_SUFFIX}`);
75401
+ const memo = ensureOwnDir(sessionsDir);
75153
75402
  let flag = null;
75154
75403
  try {
75155
- flag = JSON.parse(import_fs73.default.readFileSync(flagPath, "utf-8"));
75404
+ const st = memo ? import_fs75.default.lstatSync(flagPath) : null;
75405
+ if (st && st.isFile() && st.nlink === 1)
75406
+ flag = JSON.parse(import_fs75.default.readFileSync(flagPath, "utf-8"));
75156
75407
  } catch {
75157
75408
  }
75158
75409
  const writeFlag = (data2) => {
75410
+ if (!memo || !isSameOwnDir(sessionsDir, memo)) return;
75159
75411
  try {
75160
- import_fs73.default.mkdirSync(sessionsDir, { recursive: true });
75161
- import_fs73.default.writeFileSync(
75412
+ atomicWriteSync(
75162
75413
  flagPath,
75163
75414
  JSON.stringify({ ...data2, timestamp: (/* @__PURE__ */ new Date()).toISOString() }, null, 2),
75164
75415
  { mode: 384 }
@@ -75169,8 +75420,8 @@ RAW: ${raw}
75169
75420
  const sendSkillWarn = (detail, recoveryCmd) => {
75170
75421
  let ttyFd = null;
75171
75422
  try {
75172
- ttyFd = import_fs73.default.openSync("/dev/tty", "w");
75173
- const w = (line) => import_fs73.default.writeSync(ttyFd, line + "\n");
75423
+ ttyFd = import_fs75.default.openSync("/dev/tty", "w");
75424
+ const w = (line) => import_fs75.default.writeSync(ttyFd, line + "\n");
75174
75425
  w(import_chalk14.default.yellow(`
75175
75426
  \u26A0\uFE0F Node9: installed skill drift detected`));
75176
75427
  w(import_chalk14.default.gray(` ${detail}`));
@@ -75185,7 +75436,7 @@ RAW: ${raw}
75185
75436
  } finally {
75186
75437
  if (ttyFd !== null)
75187
75438
  try {
75188
- import_fs73.default.closeSync(ttyFd);
75439
+ import_fs75.default.closeSync(ttyFd);
75189
75440
  } catch {
75190
75441
  }
75191
75442
  }
@@ -75201,7 +75452,7 @@ RAW: ${raw}
75201
75452
  return;
75202
75453
  }
75203
75454
  if (!flag || flag.state !== "verified" && flag.state !== "warned") {
75204
- const absoluteCwd = typeof payloadCwd === "string" && import_path73.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
75455
+ const absoluteCwd = typeof payloadCwd === "string" && import_path75.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
75205
75456
  const extraRoots = skillPinCfg.roots;
75206
75457
  const resolvedExtra = extraRoots.map((r) => resolveUserSkillRoot(r, absoluteCwd)).filter((r) => typeof r === "string");
75207
75458
  const roots = [...defaultSkillRoots(absoluteCwd), ...resolvedExtra];
@@ -75240,31 +75491,27 @@ RAW: ${raw}
75240
75491
  } else {
75241
75492
  writeFlag({ state: "verified" });
75242
75493
  }
75243
- try {
75244
- const cutoff = Date.now() - 7 * 24 * 60 * 60 * 1e3;
75245
- for (const name of import_fs73.default.readdirSync(sessionsDir)) {
75246
- const p = import_path73.default.join(sessionsDir, name);
75247
- try {
75248
- if (import_fs73.default.statSync(p).mtimeMs < cutoff) import_fs73.default.unlinkSync(p);
75249
- } catch {
75250
- }
75494
+ if (memo)
75495
+ try {
75496
+ const cutoff = Date.now() - 7 * 24 * 60 * 60 * 1e3;
75497
+ for (const name of import_fs75.default.readdirSync(sessionsDir))
75498
+ removeOldFlag(sessionsDir, memo, name, cutoff);
75499
+ } catch {
75251
75500
  }
75252
- } catch {
75253
- }
75254
75501
  }
75255
75502
  } catch (err2) {
75256
75503
  if (process.env.NODE9_DEBUG === "1") {
75257
75504
  try {
75258
- const dbg = import_path73.default.join(import_os61.default.homedir(), ".node9", "hook-debug.log");
75505
+ const dbg = import_path75.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
75259
75506
  const msg = err2 instanceof Error ? err2.message : String(err2);
75260
- import_fs73.default.appendFileSync(dbg, `[${(/* @__PURE__ */ new Date()).toISOString()}] SKILL_PIN_ERROR: ${msg}
75507
+ import_fs75.default.appendFileSync(dbg, `[${(/* @__PURE__ */ new Date()).toISOString()}] SKILL_PIN_ERROR: ${msg}
75261
75508
  `);
75262
75509
  } catch {
75263
75510
  }
75264
75511
  }
75265
75512
  }
75266
75513
  }
75267
- const safeCwdForAuth = typeof payloadCwd === "string" && import_path73.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
75514
+ const safeCwdForAuth = typeof payloadCwd === "string" && import_path75.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
75268
75515
  const askMode = resolveAskMode(agent, opts, config);
75269
75516
  const result = await authorizeHeadless(toolName, toolInput, meta, {
75270
75517
  cwd: safeCwdForAuth,
@@ -75277,11 +75524,21 @@ RAW: ${raw}
75277
75524
  } catch {
75278
75525
  }
75279
75526
  }
75527
+ const isSubagentCall = typeof payload.agent_id === "string" && payload.agent_id !== "";
75528
+ const allowExit = (checkedBy) => {
75529
+ if (checkedBy !== "paused" && agent === "Claude Code" && !isSubagentCall && sessionNoticeEnabled() && claimSessionNotice(safeSessionId)) {
75530
+ try {
75531
+ import_fs75.default.writeSync(1, sessionNoticeOutput(config.settings.mode) + "\n");
75532
+ } catch {
75533
+ }
75534
+ }
75535
+ process.exit(0);
75536
+ };
75280
75537
  if (result.approved) {
75281
75538
  if (result.checkedBy && process.env.NODE9_DEBUG === "1")
75282
75539
  process.stderr.write(`\u2713 node9 [${result.checkedBy}]: "${toolName}" allowed
75283
75540
  `);
75284
- process.exit(0);
75541
+ allowExit(result.checkedBy);
75285
75542
  }
75286
75543
  if (result.review) {
75287
75544
  sendAsk(result);
@@ -75289,12 +75546,12 @@ RAW: ${raw}
75289
75546
  }
75290
75547
  if (result.noApprovalMechanism && !isDaemonRunning() && !process.env.NODE9_NO_AUTO_DAEMON && !process.stdout.isTTY && config.settings.autoStartDaemon) {
75291
75548
  try {
75292
- const tty = import_fs73.default.openSync("/dev/tty", "w");
75293
- import_fs73.default.writeSync(
75549
+ const tty = import_fs75.default.openSync("/dev/tty", "w");
75550
+ import_fs75.default.writeSync(
75294
75551
  tty,
75295
75552
  import_chalk14.default.cyan("\n\u{1F6E1}\uFE0F Node9: Starting approval daemon automatically...\n")
75296
75553
  );
75297
- import_fs73.default.closeSync(tty);
75554
+ import_fs75.default.closeSync(tty);
75298
75555
  } catch {
75299
75556
  }
75300
75557
  const daemonReady = await autoStartDaemonAndWait();
@@ -75306,7 +75563,7 @@ RAW: ${raw}
75306
75563
  if (retry.checkedBy && process.env.NODE9_DEBUG === "1")
75307
75564
  process.stderr.write(`\u2713 node9 [${retry.checkedBy}]: "${toolName}" allowed
75308
75565
  `);
75309
- process.exit(0);
75566
+ allowExit(retry.checkedBy);
75310
75567
  }
75311
75568
  sendBlock(retry.reason ?? `Node9 blocked "${toolName}".`, {
75312
75569
  ...retry,
@@ -75321,9 +75578,9 @@ RAW: ${raw}
75321
75578
  });
75322
75579
  } catch (err2) {
75323
75580
  if (process.env.NODE9_DEBUG === "1") {
75324
- const logPath = import_path73.default.join(import_os61.default.homedir(), ".node9", "hook-debug.log");
75581
+ const logPath = import_path75.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
75325
75582
  const errMsg = err2 instanceof Error ? err2.message : String(err2);
75326
- import_fs73.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] ERROR: ${errMsg}
75583
+ import_fs75.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] ERROR: ${errMsg}
75327
75584
  `);
75328
75585
  }
75329
75586
  process.exit(0);
@@ -75358,9 +75615,9 @@ RAW: ${raw}
75358
75615
 
75359
75616
  // src/cli/commands/log.ts
75360
75617
  init_cjs_shims();
75361
- var import_fs74 = __toESM(require("fs"));
75362
- var import_path74 = __toESM(require("path"));
75363
- var import_os62 = __toESM(require("os"));
75618
+ var import_fs76 = __toESM(require("fs"));
75619
+ var import_path76 = __toESM(require("path"));
75620
+ var import_os63 = __toESM(require("os"));
75364
75621
  init_audit();
75365
75622
  init_config();
75366
75623
  init_daemon();
@@ -75640,12 +75897,12 @@ function registerLogCommand(program2) {
75640
75897
  if (rawToolName !== tool) entry.agentToolName = rawToolName;
75641
75898
  const payloadSessionId = payload.session_id ?? payload.conversationId;
75642
75899
  if (payloadSessionId) entry.sessionId = payloadSessionId;
75643
- const logPath = import_path74.default.join(import_os62.default.homedir(), ".node9", "audit.log");
75644
- if (!import_fs74.default.existsSync(import_path74.default.dirname(logPath)))
75645
- import_fs74.default.mkdirSync(import_path74.default.dirname(logPath), { recursive: true });
75646
- import_fs74.default.appendFileSync(logPath, JSON.stringify(entry) + "\n");
75900
+ const logPath = import_path76.default.join(import_os63.default.homedir(), ".node9", "audit.log");
75901
+ if (!import_fs76.default.existsSync(import_path76.default.dirname(logPath)))
75902
+ import_fs76.default.mkdirSync(import_path76.default.dirname(logPath), { recursive: true });
75903
+ import_fs76.default.appendFileSync(logPath, JSON.stringify(entry) + "\n");
75647
75904
  const payloadCwd = typeof payload.cwd === "string" ? payload.cwd : Array.isArray(payload.workspacePaths) && typeof payload.workspacePaths[0] === "string" ? payload.workspacePaths[0] : void 0;
75648
- const safeCwd = typeof payloadCwd === "string" && import_path74.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
75905
+ const safeCwd = typeof payloadCwd === "string" && import_path76.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
75649
75906
  if ((tool === "Bash" || tool === "bash") && isDaemonRunning()) {
75650
75907
  const command = typeof rawInput === "object" && rawInput !== null && "command" in rawInput && typeof rawInput.command === "string" ? rawInput.command : null;
75651
75908
  if (command) {
@@ -75866,9 +76123,9 @@ function registerLogCommand(program2) {
75866
76123
  const msg = err2 instanceof Error ? err2.message : String(err2);
75867
76124
  process.stderr.write(`[Node9] audit log error: ${msg}
75868
76125
  `);
75869
- const debugPath = import_path74.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
76126
+ const debugPath = import_path76.default.join(import_os63.default.homedir(), ".node9", "hook-debug.log");
75870
76127
  try {
75871
- import_fs74.default.appendFileSync(debugPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] LOG_ERROR: ${msg}
76128
+ import_fs76.default.appendFileSync(debugPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] LOG_ERROR: ${msg}
75872
76129
  `);
75873
76130
  } catch {
75874
76131
  }
@@ -75891,9 +76148,9 @@ function registerLogCommand(program2) {
75891
76148
  });
75892
76149
  }
75893
76150
  function absolutePathFor(spelled, cwd) {
75894
- const expanded = spelled === "~" || spelled.startsWith("~/") ? import_path74.default.join(import_os62.default.homedir(), spelled.slice(1)) : spelled;
75895
- if (import_path74.default.isAbsolute(expanded)) return expanded;
75896
- return cwd ? import_path74.default.resolve(cwd, expanded) : import_path74.default.resolve(expanded);
76151
+ const expanded = spelled === "~" || spelled.startsWith("~/") ? import_path76.default.join(import_os63.default.homedir(), spelled.slice(1)) : spelled;
76152
+ if (import_path76.default.isAbsolute(expanded)) return expanded;
76153
+ return cwd ? import_path76.default.resolve(cwd, expanded) : import_path76.default.resolve(expanded);
75897
76154
  }
75898
76155
  async function carryTaintAcrossWrites(command, cwd) {
75899
76156
  let pairs;
@@ -75912,23 +76169,23 @@ async function carryTaintAcrossWrites(command, cwd) {
75912
76169
  continue;
75913
76170
  }
75914
76171
  const sensitive = scanFilePath(src, cwd);
75915
- if (sensitive) await notifyTaint(dst, `copy:${sensitive.patternName}:${import_path74.default.basename(src)}`);
76172
+ if (sensitive) await notifyTaint(dst, `copy:${sensitive.patternName}:${import_path76.default.basename(src)}`);
75916
76173
  }
75917
76174
  }
75918
76175
 
75919
76176
  // src/cli/commands/shield.ts
75920
76177
  init_cjs_shims();
75921
76178
  var import_chalk16 = __toESM(require("chalk"));
75922
- var import_fs76 = __toESM(require("fs"));
75923
- var import_path76 = __toESM(require("path"));
75924
- var import_os63 = __toESM(require("os"));
76179
+ var import_fs78 = __toESM(require("fs"));
76180
+ var import_path78 = __toESM(require("path"));
76181
+ var import_os64 = __toESM(require("os"));
75925
76182
  init_shields();
75926
76183
  init_build();
75927
76184
 
75928
76185
  // src/shields/create.ts
75929
76186
  init_cjs_shims();
75930
- var import_fs75 = __toESM(require("fs"));
75931
- var import_path75 = __toESM(require("path"));
76187
+ var import_fs77 = __toESM(require("fs"));
76188
+ var import_path77 = __toESM(require("path"));
75932
76189
  init_dist();
75933
76190
  init_shields();
75934
76191
  init_audit();
@@ -75948,8 +76205,8 @@ function createShield(def, opts = {}) {
75948
76205
  error: `"${name}" is a built-in shield \u2014 choose a different name (a user shield with this name would shadow the built-in).`
75949
76206
  };
75950
76207
  }
75951
- const filePath = import_path75.default.join(USER_SHIELDS_DIR_PATH, `${name}.json`);
75952
- if (!opts.overwrite && import_fs75.default.existsSync(filePath)) {
76208
+ const filePath = import_path77.default.join(USER_SHIELDS_DIR_PATH, `${name}.json`);
76209
+ if (!opts.overwrite && import_fs77.default.existsSync(filePath)) {
75953
76210
  return {
75954
76211
  ok: false,
75955
76212
  error: `Shield "${name}" already exists at ${filePath}. Pass --overwrite to replace it.`
@@ -76047,8 +76304,8 @@ var COMMUNITY_INDEX_URL = "https://raw.githubusercontent.com/node9ai/node9-proxy
76047
76304
  function readCloudShields() {
76048
76305
  const out = /* @__PURE__ */ new Set();
76049
76306
  try {
76050
- const file2 = import_path76.default.join(import_os63.default.homedir(), ".node9", "rules-cache.json");
76051
- const raw = JSON.parse(import_fs76.default.readFileSync(file2, "utf-8"));
76307
+ const file2 = import_path78.default.join(import_os64.default.homedir(), ".node9", "rules-cache.json");
76308
+ const raw = JSON.parse(import_fs78.default.readFileSync(file2, "utf-8"));
76052
76309
  for (const r of raw.rules ?? []) {
76053
76310
  const rule = r;
76054
76311
  const fromSource = rule.source?.startsWith("SHIELD:") ? rule.source.slice("SHIELD:".length).toLowerCase() : void 0;
@@ -76385,7 +76642,7 @@ function registerShieldCommand(program2) {
76385
76642
  if (opts.fromFile) {
76386
76643
  let raw;
76387
76644
  try {
76388
- raw = JSON.parse(import_fs76.default.readFileSync(opts.fromFile, "utf-8"));
76645
+ raw = JSON.parse(import_fs78.default.readFileSync(opts.fromFile, "utf-8"));
76389
76646
  } catch (err2) {
76390
76647
  console.error(
76391
76648
  import_chalk16.default.red(`
@@ -76733,9 +76990,9 @@ init_migrate();
76733
76990
  // src/cli/commands/doctor.ts
76734
76991
  init_cjs_shims();
76735
76992
  var import_chalk19 = __toESM(require("chalk"));
76736
- var import_fs78 = __toESM(require("fs"));
76737
- var import_path78 = __toESM(require("path"));
76738
- var import_os65 = __toESM(require("os"));
76993
+ var import_fs80 = __toESM(require("fs"));
76994
+ var import_path80 = __toESM(require("path"));
76995
+ var import_os66 = __toESM(require("os"));
76739
76996
  var import_child_process10 = require("child_process");
76740
76997
  init_daemon();
76741
76998
  init_build_id();
@@ -76764,22 +77021,22 @@ init_startup_log();
76764
77021
 
76765
77022
  // src/utils/undo-leftovers.ts
76766
77023
  init_cjs_shims();
76767
- var import_fs77 = __toESM(require("fs"));
76768
- var import_os64 = __toESM(require("os"));
76769
- var import_path77 = __toESM(require("path"));
77024
+ var import_fs79 = __toESM(require("fs"));
77025
+ var import_os65 = __toESM(require("os"));
77026
+ var import_path79 = __toESM(require("path"));
76770
77027
  function candidates(homeDir2) {
76771
- const node9Dir = import_path77.default.join(homeDir2, ".node9");
77028
+ const node9Dir = import_path79.default.join(homeDir2, ".node9");
76772
77029
  return [
76773
- import_path77.default.join(node9Dir, "snapshots"),
76774
- import_path77.default.join(node9Dir, "snapshots.json"),
76775
- import_path77.default.join(node9Dir, "undo_latest.txt")
77030
+ import_path79.default.join(node9Dir, "snapshots"),
77031
+ import_path79.default.join(node9Dir, "snapshots.json"),
77032
+ import_path79.default.join(node9Dir, "undo_latest.txt")
76776
77033
  ];
76777
77034
  }
76778
- function undoLeftoverPaths(homeDir2 = import_os64.default.homedir()) {
77035
+ function undoLeftoverPaths(homeDir2 = import_os65.default.homedir()) {
76779
77036
  const found = [];
76780
77037
  for (const p of candidates(homeDir2)) {
76781
77038
  try {
76782
- import_fs77.default.lstatSync(p);
77039
+ import_fs79.default.lstatSync(p);
76783
77040
  found.push(p);
76784
77041
  } catch (err2) {
76785
77042
  if (err2.code !== "ENOENT") found.push(p);
@@ -76787,11 +77044,11 @@ function undoLeftoverPaths(homeDir2 = import_os64.default.homedir()) {
76787
77044
  }
76788
77045
  return found;
76789
77046
  }
76790
- function purgeUndoLeftovers(homeDir2 = import_os64.default.homedir()) {
77047
+ function purgeUndoLeftovers(homeDir2 = import_os65.default.homedir()) {
76791
77048
  const out = { deleted: [], skipped: [], failed: [] };
76792
77049
  for (const p of undoLeftoverPaths(homeDir2)) {
76793
77050
  try {
76794
- if (import_fs77.default.lstatSync(p).isSymbolicLink()) {
77051
+ if (import_fs79.default.lstatSync(p).isSymbolicLink()) {
76795
77052
  out.skipped.push({
76796
77053
  path: p,
76797
77054
  reason: "is a symlink \u2014 remove it yourself so nothing else is followed"
@@ -76804,11 +77061,11 @@ function purgeUndoLeftovers(homeDir2 = import_os64.default.homedir()) {
76804
77061
  }
76805
77062
  let reason = null;
76806
77063
  try {
76807
- import_fs77.default.rmSync(p, { recursive: true, force: true });
77064
+ import_fs79.default.rmSync(p, { recursive: true, force: true });
76808
77065
  } catch (err2) {
76809
77066
  reason = err2.message;
76810
77067
  }
76811
- if (import_fs77.default.existsSync(p)) {
77068
+ if (import_fs79.default.existsSync(p)) {
76812
77069
  out.failed.push({ path: p, reason: reason ?? "still present after removal" });
76813
77070
  } else {
76814
77071
  out.deleted.push(p);
@@ -76824,7 +77081,7 @@ function keyRejected(health) {
76824
77081
  }
76825
77082
  function registerDoctorCommand(program2, version2) {
76826
77083
  program2.command("doctor").description("Check that Node9 is installed and configured correctly").action(async () => {
76827
- const homeDir2 = import_os65.default.homedir();
77084
+ const homeDir2 = import_os66.default.homedir();
76828
77085
  let failures = 0;
76829
77086
  let warnings = 0;
76830
77087
  function pass(msg) {
@@ -76878,10 +77135,10 @@ function registerDoctorCommand(program2, version2) {
76878
77135
  "Policy source: workspace config (app.node9.ai) \u2014 local config files govern operational settings only"
76879
77136
  );
76880
77137
  }
76881
- const globalConfigPath2 = import_path78.default.join(homeDir2, ".node9", "config.json");
76882
- if (import_fs78.default.existsSync(globalConfigPath2)) {
77138
+ const globalConfigPath2 = import_path80.default.join(homeDir2, ".node9", "config.json");
77139
+ if (import_fs80.default.existsSync(globalConfigPath2)) {
76883
77140
  try {
76884
- JSON.parse(import_fs78.default.readFileSync(globalConfigPath2, "utf-8"));
77141
+ JSON.parse(import_fs80.default.readFileSync(globalConfigPath2, "utf-8"));
76885
77142
  pass(
76886
77143
  wsGoverned ? "~/.node9/config.json found and valid (policy fields ignored \u2014 workspace governs)" : "~/.node9/config.json found and valid"
76887
77144
  );
@@ -76900,10 +77157,10 @@ function registerDoctorCommand(program2, version2) {
76900
77157
  "Remove them when ready: node9 undo --purge"
76901
77158
  );
76902
77159
  }
76903
- const projectConfigPath = import_path78.default.join(process.cwd(), "node9.config.json");
76904
- if (import_fs78.default.existsSync(projectConfigPath)) {
77160
+ const projectConfigPath = import_path80.default.join(process.cwd(), "node9.config.json");
77161
+ if (import_fs80.default.existsSync(projectConfigPath)) {
76905
77162
  try {
76906
- JSON.parse(import_fs78.default.readFileSync(projectConfigPath, "utf-8"));
77163
+ JSON.parse(import_fs80.default.readFileSync(projectConfigPath, "utf-8"));
76907
77164
  pass("node9.config.json found and valid (project)");
76908
77165
  } catch {
76909
77166
  fail2(
@@ -76912,8 +77169,8 @@ function registerDoctorCommand(program2, version2) {
76912
77169
  );
76913
77170
  }
76914
77171
  }
76915
- const credsPath = import_path78.default.join(homeDir2, ".node9", "credentials.json");
76916
- if (import_fs78.default.existsSync(credsPath)) {
77172
+ const credsPath = import_path80.default.join(homeDir2, ".node9", "credentials.json");
77173
+ if (import_fs80.default.existsSync(credsPath)) {
76917
77174
  pass("Cloud credentials found (~/.node9/credentials.json)");
76918
77175
  } else {
76919
77176
  warn(
@@ -76967,7 +77224,7 @@ function registerDoctorCommand(program2, version2) {
76967
77224
  )
76968
77225
  );
76969
77226
  }
76970
- const cloudOn = import_fs78.default.existsSync(import_path78.default.join(homeDir2, ".node9", "credentials.json")) && !!getConfig().settings.approvers?.cloud;
77227
+ const cloudOn = import_fs80.default.existsSync(import_path80.default.join(homeDir2, ".node9", "credentials.json")) && !!getConfig().settings.approvers?.cloud;
76971
77228
  section(cloudOn ? "Daemon" : "Daemon (optional)");
76972
77229
  if (isDaemonRunning()) {
76973
77230
  pass(
@@ -77005,7 +77262,7 @@ function registerDoctorCommand(program2, version2) {
77005
77262
  cloudEnabled: !!getConfig().settings.approvers?.cloud
77006
77263
  });
77007
77264
  if (autostart) warn(autostart.message, autostart.hint);
77008
- if (import_fs78.default.existsSync(import_path78.default.join(import_os65.default.homedir(), ".node9", "credentials.json")) && getConfig().settings.approvers?.cloud) {
77265
+ if (import_fs80.default.existsSync(import_path80.default.join(import_os66.default.homedir(), ".node9", "credentials.json")) && getConfig().settings.approvers?.cloud) {
77009
77266
  section("Policy sync");
77010
77267
  const health = readSyncHealth();
77011
77268
  if (keyRejected(health)) {
@@ -77031,7 +77288,7 @@ function registerDoctorCommand(program2, version2) {
77031
77288
  try {
77032
77289
  const { shipLagBytes: shipLagBytes2, readWatermark: readWatermark2, AUDIT_SHIP_WATERMARK: AUDIT_SHIP_WATERMARK2 } = await Promise.resolve().then(() => (init_audit_shipper(), audit_shipper_exports));
77033
77290
  const cfg = getConfig();
77034
- const creds = import_fs78.default.existsSync(import_path78.default.join(import_os65.default.homedir(), ".node9", "credentials.json"));
77291
+ const creds = import_fs80.default.existsSync(import_path80.default.join(import_os66.default.homedir(), ".node9", "credentials.json"));
77035
77292
  if (!creds) {
77036
77293
  warn("Not logged in \u2014 audit rows stay local", "Run: node9 login <api-key>");
77037
77294
  } else if (!cfg.settings.approvers.cloud) {
@@ -77097,10 +77354,10 @@ function registerDoctorCommand(program2, version2) {
77097
77354
  // src/cli/commands/audit.ts
77098
77355
  init_cjs_shims();
77099
77356
  var import_chalk20 = __toESM(require("chalk"));
77100
- var import_fs79 = __toESM(require("fs"));
77101
- var import_path79 = __toESM(require("path"));
77357
+ var import_fs81 = __toESM(require("fs"));
77358
+ var import_path81 = __toESM(require("path"));
77102
77359
  init_decision();
77103
- var import_os66 = __toESM(require("os"));
77360
+ var import_os67 = __toESM(require("os"));
77104
77361
  function formatRelativeTime(timestamp2) {
77105
77362
  const diff = Date.now() - new Date(timestamp2).getTime();
77106
77363
  const sec = Math.floor(diff / 1e3);
@@ -77113,14 +77370,14 @@ function formatRelativeTime(timestamp2) {
77113
77370
  }
77114
77371
  function registerAuditCommand(program2) {
77115
77372
  program2.command("audit").description("View local execution audit log").option("--tail <n>", "Number of entries to show", "20").option("--tool <pattern>", "Filter by tool name (substring match)").option("--deny", "Show only denied actions").option("--json", "Output raw JSON").action((options) => {
77116
- const logPath = import_path79.default.join(import_os66.default.homedir(), ".node9", "audit.log");
77117
- if (!import_fs79.default.existsSync(logPath)) {
77373
+ const logPath = import_path81.default.join(import_os67.default.homedir(), ".node9", "audit.log");
77374
+ if (!import_fs81.default.existsSync(logPath)) {
77118
77375
  console.log(
77119
77376
  import_chalk20.default.yellow("No audit logs found. Run node9 with an agent to generate entries.")
77120
77377
  );
77121
77378
  return;
77122
77379
  }
77123
- const raw = import_fs79.default.readFileSync(logPath, "utf-8");
77380
+ const raw = import_fs81.default.readFileSync(logPath, "utf-8");
77124
77381
  const lines = raw.split("\n").filter((l) => l.trim() !== "");
77125
77382
  let entries = lines.flatMap((line) => {
77126
77383
  try {
@@ -77183,7 +77440,7 @@ init_cjs_shims();
77183
77440
 
77184
77441
  // src/apps/report.ts
77185
77442
  init_cjs_shims();
77186
- var import_fs80 = __toESM(require("fs"));
77443
+ var import_fs82 = __toESM(require("fs"));
77187
77444
  init_catalog();
77188
77445
  init_dist();
77189
77446
  function appsReportLines(file2, activeShields, opts = {}) {
@@ -77213,17 +77470,17 @@ var AUDIT_TAIL_BYTES2 = 5 * 1024 * 1024;
77213
77470
  function readTail2(file2) {
77214
77471
  let fd;
77215
77472
  try {
77216
- fd = import_fs80.default.openSync(file2, "r");
77217
- const size = import_fs80.default.fstatSync(fd).size;
77473
+ fd = import_fs82.default.openSync(file2, "r");
77474
+ const size = import_fs82.default.fstatSync(fd).size;
77218
77475
  const start = Math.max(0, size - AUDIT_TAIL_BYTES2);
77219
77476
  const buf = Buffer.alloc(size - start);
77220
- import_fs80.default.readSync(fd, buf, 0, buf.length, start);
77477
+ import_fs82.default.readSync(fd, buf, 0, buf.length, start);
77221
77478
  const text = buf.toString("utf8");
77222
77479
  return start > 0 ? text.slice(text.indexOf("\n") + 1) : text;
77223
77480
  } catch {
77224
77481
  return "";
77225
77482
  } finally {
77226
- if (fd !== void 0) import_fs80.default.closeSync(fd);
77483
+ if (fd !== void 0) import_fs82.default.closeSync(fd);
77227
77484
  }
77228
77485
  }
77229
77486
  function approvalsFromAudit(auditFile, sinceMs) {
@@ -77278,21 +77535,21 @@ init_detect();
77278
77535
 
77279
77536
  // src/apps/nudges.ts
77280
77537
  init_cjs_shims();
77281
- var import_fs81 = __toESM(require("fs"));
77282
- var import_os67 = __toESM(require("os"));
77283
- var import_path80 = __toESM(require("path"));
77538
+ var import_fs83 = __toESM(require("fs"));
77539
+ var import_os68 = __toESM(require("os"));
77540
+ var import_path82 = __toESM(require("path"));
77284
77541
  var import_child_process11 = require("child_process");
77285
77542
  var UNANSWERED_AT = 3;
77286
77543
  var QUESTIONS_AT = 10;
77287
77544
  var TEAM_AUTHORS_AT = 2;
77288
77545
  var TEAM_PROJECTS = 5;
77289
77546
  var GIT_TIMEOUT_MS = 2e3;
77290
- function nudgesFilePath(home = import_os67.default.homedir()) {
77291
- return import_path80.default.join(home, ".node9", "nudges.json");
77547
+ function nudgesFilePath(home = import_os68.default.homedir()) {
77548
+ return import_path82.default.join(home, ".node9", "nudges.json");
77292
77549
  }
77293
77550
  function readShownNudges(home) {
77294
77551
  try {
77295
- const raw = JSON.parse(import_fs81.default.readFileSync(nudgesFilePath(home), "utf8"));
77552
+ const raw = JSON.parse(import_fs83.default.readFileSync(nudgesFilePath(home), "utf8"));
77296
77553
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) return /* @__PURE__ */ new Set();
77297
77554
  return new Set(
77298
77555
  Object.keys(raw).filter(
@@ -77307,14 +77564,14 @@ function markNudgeShown(key, home, now = /* @__PURE__ */ new Date()) {
77307
77564
  const file2 = nudgesFilePath(home);
77308
77565
  let data = {};
77309
77566
  try {
77310
- const raw = JSON.parse(import_fs81.default.readFileSync(file2, "utf8"));
77567
+ const raw = JSON.parse(import_fs83.default.readFileSync(file2, "utf8"));
77311
77568
  if (raw && typeof raw === "object" && !Array.isArray(raw)) data = raw;
77312
77569
  } catch {
77313
77570
  }
77314
77571
  data[key] = now.toISOString();
77315
77572
  try {
77316
- import_fs81.default.mkdirSync(import_path80.default.dirname(file2), { recursive: true });
77317
- import_fs81.default.writeFileSync(file2, JSON.stringify(data, null, 2) + "\n", { mode: 384 });
77573
+ import_fs83.default.mkdirSync(import_path82.default.dirname(file2), { recursive: true });
77574
+ import_fs83.default.writeFileSync(file2, JSON.stringify(data, null, 2) + "\n", { mode: 384 });
77318
77575
  } catch {
77319
77576
  }
77320
77577
  }
@@ -77335,7 +77592,7 @@ function recentAuthorCount(dir2) {
77335
77592
  }
77336
77593
  function teamProject(dirs, countAuthors = recentAuthorCount) {
77337
77594
  for (const dir2 of dirs.slice(0, TEAM_PROJECTS)) {
77338
- if (countAuthors(dir2) >= TEAM_AUTHORS_AT) return import_path80.default.basename(dir2);
77595
+ if (countAuthors(dir2) >= TEAM_AUTHORS_AT) return import_path82.default.basename(dir2);
77339
77596
  }
77340
77597
  return void 0;
77341
77598
  }
@@ -77370,9 +77627,9 @@ var import_chalk22 = __toESM(require("chalk"));
77370
77627
 
77371
77628
  // src/cli/aggregate/report-audit.ts
77372
77629
  init_cjs_shims();
77373
- var import_fs82 = __toESM(require("fs"));
77374
- var import_os68 = __toESM(require("os"));
77375
- var import_path81 = __toESM(require("path"));
77630
+ var import_fs84 = __toESM(require("fs"));
77631
+ var import_os69 = __toESM(require("os"));
77632
+ var import_path83 = __toESM(require("path"));
77376
77633
  init_costSync();
77377
77634
  init_litellm();
77378
77635
  init_cost_codex();
@@ -77457,8 +77714,8 @@ function getDateRange(period, now) {
77457
77714
  }
77458
77715
  }
77459
77716
  function parseAuditLog(logPath) {
77460
- if (!import_fs82.default.existsSync(logPath)) return [];
77461
- const raw = import_fs82.default.readFileSync(logPath, "utf-8");
77717
+ if (!import_fs84.default.existsSync(logPath)) return [];
77718
+ const raw = import_fs84.default.readFileSync(logPath, "utf-8");
77462
77719
  return raw.split("\n").flatMap((line) => {
77463
77720
  if (!line.trim()) return [];
77464
77721
  try {
@@ -77512,10 +77769,10 @@ function freezeClaudeCost(acc) {
77512
77769
  };
77513
77770
  }
77514
77771
  function processClaudeCostProject(proj, projectsDir, start, end, acc) {
77515
- const projPath = import_path81.default.join(projectsDir, proj);
77772
+ const projPath = import_path83.default.join(projectsDir, proj);
77516
77773
  let files;
77517
77774
  try {
77518
- const stat = import_fs82.default.statSync(projPath);
77775
+ const stat = import_fs84.default.statSync(projPath);
77519
77776
  if (!stat.isDirectory()) return;
77520
77777
  files = listSessionFiles(projPath);
77521
77778
  } catch {
@@ -77523,14 +77780,14 @@ function processClaudeCostProject(proj, projectsDir, start, end, acc) {
77523
77780
  }
77524
77781
  const startMs = start.getTime();
77525
77782
  for (const file2 of files) {
77526
- const filePath = import_path81.default.join(projPath, file2);
77783
+ const filePath = import_path83.default.join(projPath, file2);
77527
77784
  try {
77528
- if (import_fs82.default.statSync(filePath).mtimeMs < startMs) continue;
77785
+ if (import_fs84.default.statSync(filePath).mtimeMs < startMs) continue;
77529
77786
  } catch {
77530
77787
  continue;
77531
77788
  }
77532
77789
  try {
77533
- const raw = import_fs82.default.readFileSync(filePath, "utf-8");
77790
+ const raw = import_fs84.default.readFileSync(filePath, "utf-8");
77534
77791
  for (const line of raw.split("\n")) {
77535
77792
  if (!line.trim()) continue;
77536
77793
  let entry;
@@ -77580,10 +77837,10 @@ function processClaudeCostProject(proj, projectsDir, start, end, acc) {
77580
77837
  }
77581
77838
  function loadClaudeCost(start, end, projectsDir) {
77582
77839
  const acc = emptyClaudeCostAccumulator();
77583
- if (!import_fs82.default.existsSync(projectsDir)) return freezeClaudeCost(acc);
77840
+ if (!import_fs84.default.existsSync(projectsDir)) return freezeClaudeCost(acc);
77584
77841
  let dirs;
77585
77842
  try {
77586
- dirs = import_fs82.default.readdirSync(projectsDir);
77843
+ dirs = import_fs84.default.readdirSync(projectsDir);
77587
77844
  } catch {
77588
77845
  return freezeClaudeCost(acc);
77589
77846
  }
@@ -77595,7 +77852,7 @@ function loadClaudeCost(start, end, projectsDir) {
77595
77852
  function processCodexCostFile(filePath, start, end, acc) {
77596
77853
  let lines;
77597
77854
  try {
77598
- lines = import_fs82.default.readFileSync(filePath, "utf-8").split("\n");
77855
+ lines = import_fs84.default.readFileSync(filePath, "utf-8").split("\n");
77599
77856
  } catch {
77600
77857
  return;
77601
77858
  }
@@ -77670,13 +77927,13 @@ function freezeGeminiCost(acc) {
77670
77927
  function processGeminiCostFile(filePath, projectKey, start, end, acc) {
77671
77928
  const startMs = start.getTime();
77672
77929
  try {
77673
- if (import_fs82.default.statSync(filePath).mtimeMs < startMs) return;
77930
+ if (import_fs84.default.statSync(filePath).mtimeMs < startMs) return;
77674
77931
  } catch {
77675
77932
  return;
77676
77933
  }
77677
77934
  let raw;
77678
77935
  try {
77679
- raw = import_fs82.default.readFileSync(filePath, "utf-8");
77936
+ raw = import_fs84.default.readFileSync(filePath, "utf-8");
77680
77937
  } catch {
77681
77938
  return;
77682
77939
  }
@@ -77725,30 +77982,30 @@ function listGeminiSessionFiles2(geminiTmpDir2) {
77725
77982
  const out = [];
77726
77983
  let dirs;
77727
77984
  try {
77728
- if (!import_fs82.default.statSync(geminiTmpDir2).isDirectory()) return out;
77729
- dirs = import_fs82.default.readdirSync(geminiTmpDir2);
77985
+ if (!import_fs84.default.statSync(geminiTmpDir2).isDirectory()) return out;
77986
+ dirs = import_fs84.default.readdirSync(geminiTmpDir2);
77730
77987
  } catch {
77731
77988
  return out;
77732
77989
  }
77733
77990
  for (const proj of dirs) {
77734
- const chatsDir = import_path81.default.join(geminiTmpDir2, proj, "chats");
77991
+ const chatsDir = import_path83.default.join(geminiTmpDir2, proj, "chats");
77735
77992
  let files;
77736
77993
  try {
77737
- if (!import_fs82.default.statSync(chatsDir).isDirectory()) continue;
77738
- files = import_fs82.default.readdirSync(chatsDir);
77994
+ if (!import_fs84.default.statSync(chatsDir).isDirectory()) continue;
77995
+ files = import_fs84.default.readdirSync(chatsDir);
77739
77996
  } catch {
77740
77997
  continue;
77741
77998
  }
77742
77999
  for (const f of files) {
77743
78000
  if (!f.endsWith(".jsonl")) continue;
77744
- out.push({ projectKey: proj, file: import_path81.default.join(chatsDir, f) });
78001
+ out.push({ projectKey: proj, file: import_path83.default.join(chatsDir, f) });
77745
78002
  }
77746
78003
  }
77747
78004
  return out;
77748
78005
  }
77749
78006
  function loadGeminiCost(start, end, geminiTmpDir2) {
77750
78007
  const acc = emptyGeminiAccumulator();
77751
- if (!import_fs82.default.existsSync(geminiTmpDir2)) return freezeGeminiCost(acc);
78008
+ if (!import_fs84.default.existsSync(geminiTmpDir2)) return freezeGeminiCost(acc);
77752
78009
  for (const { projectKey, file: file2 } of listGeminiSessionFiles2(geminiTmpDir2)) {
77753
78010
  processGeminiCostFile(file2, projectKey, start, end, acc);
77754
78011
  }
@@ -77769,11 +78026,11 @@ function dimensionOfBlock(checkedBy, ruleName) {
77769
78026
  }
77770
78027
  function aggregateReportFromAudit(period, opts = {}) {
77771
78028
  const now = opts.now ?? /* @__PURE__ */ new Date();
77772
- const auditLogPath = opts.auditLogPath ?? import_path81.default.join(import_os68.default.homedir(), ".node9", "audit.log");
77773
- const claudeProjectsDir = opts.claudeProjectsDir ?? import_path81.default.join(import_os68.default.homedir(), ".claude", "projects");
78029
+ const auditLogPath = opts.auditLogPath ?? import_path83.default.join(import_os69.default.homedir(), ".node9", "audit.log");
78030
+ const claudeProjectsDir = opts.claudeProjectsDir ?? import_path83.default.join(import_os69.default.homedir(), ".claude", "projects");
77774
78031
  const codexSessionsDir2 = opts.codexSessionsDir ?? codexSessionsDir();
77775
- const geminiTmpDir2 = opts.geminiTmpDir ?? import_path81.default.join(import_os68.default.homedir(), ".gemini", "tmp");
77776
- const hasAuditFile = import_fs82.default.existsSync(auditLogPath);
78032
+ const geminiTmpDir2 = opts.geminiTmpDir ?? import_path83.default.join(import_os69.default.homedir(), ".gemini", "tmp");
78033
+ const hasAuditFile = import_fs84.default.existsSync(auditLogPath);
77777
78034
  const allEntries = opts.preloadedAuditEntries ?? parseAuditLog(auditLogPath);
77778
78035
  const unackedDlp = allEntries.filter((e) => e.source === "response-dlp");
77779
78036
  const { start, end } = getDateRange(period, now);
@@ -78059,10 +78316,10 @@ function buildReportJson(input) {
78059
78316
  // src/cli/commands/sessions.ts
78060
78317
  init_cjs_shims();
78061
78318
  var import_chalk21 = __toESM(require("chalk"));
78062
- var import_fs83 = __toESM(require("fs"));
78063
- var import_path82 = __toESM(require("path"));
78319
+ var import_fs85 = __toESM(require("fs"));
78320
+ var import_path84 = __toESM(require("path"));
78064
78321
  init_decision();
78065
- var import_os69 = __toESM(require("os"));
78322
+ var import_os70 = __toESM(require("os"));
78066
78323
  init_scan_summary();
78067
78324
  init_litellm();
78068
78325
  init_cost_gemini();
@@ -78083,10 +78340,10 @@ function encodeProjectPath(projectPath) {
78083
78340
  }
78084
78341
  function sessionJsonlPath(projectPath, sessionId) {
78085
78342
  const encoded = encodeProjectPath(projectPath);
78086
- return import_path82.default.join(import_os69.default.homedir(), ".claude", "projects", encoded, `${sessionId}.jsonl`);
78343
+ return import_path84.default.join(import_os70.default.homedir(), ".claude", "projects", encoded, `${sessionId}.jsonl`);
78087
78344
  }
78088
78345
  function projectLabel(projectPath) {
78089
- return projectPath.replace(import_os69.default.homedir(), "~");
78346
+ return projectPath.replace(import_os70.default.homedir(), "~");
78090
78347
  }
78091
78348
  function parseHistoryLines(lines) {
78092
78349
  const entries = [];
@@ -78155,10 +78412,10 @@ function parseSessionLines(lines) {
78155
78412
  return { toolCalls, costUSD, hasSnapshot, modifiedFiles };
78156
78413
  }
78157
78414
  function loadAuditEntries(auditPath) {
78158
- const aPath = auditPath ?? import_path82.default.join(import_os69.default.homedir(), ".node9", "audit.log");
78415
+ const aPath = auditPath ?? import_path84.default.join(import_os70.default.homedir(), ".node9", "audit.log");
78159
78416
  let raw;
78160
78417
  try {
78161
- raw = import_fs83.default.readFileSync(aPath, "utf-8");
78418
+ raw = import_fs85.default.readFileSync(aPath, "utf-8");
78162
78419
  } catch {
78163
78420
  return [];
78164
78421
  }
@@ -78194,8 +78451,8 @@ function auditEntriesInWindow(entries, windowStart, windowEnd) {
78194
78451
  return result;
78195
78452
  }
78196
78453
  function buildGeminiSessions(days, allAuditEntries) {
78197
- const tmpDir = import_path82.default.join(import_os69.default.homedir(), ".gemini", "tmp");
78198
- if (!import_fs83.default.existsSync(tmpDir)) return [];
78454
+ const tmpDir = import_path84.default.join(import_os70.default.homedir(), ".gemini", "tmp");
78455
+ if (!import_fs85.default.existsSync(tmpDir)) return [];
78199
78456
  const cutoff = days !== null ? (() => {
78200
78457
  const d = /* @__PURE__ */ new Date();
78201
78458
  d.setDate(d.getDate() - days);
@@ -78204,35 +78461,35 @@ function buildGeminiSessions(days, allAuditEntries) {
78204
78461
  })() : null;
78205
78462
  let slugDirs;
78206
78463
  try {
78207
- slugDirs = import_fs83.default.readdirSync(tmpDir);
78464
+ slugDirs = import_fs85.default.readdirSync(tmpDir);
78208
78465
  } catch {
78209
78466
  return [];
78210
78467
  }
78211
78468
  const summaries = [];
78212
78469
  for (const slug2 of slugDirs) {
78213
- const slugPath = import_path82.default.join(tmpDir, slug2);
78470
+ const slugPath = import_path84.default.join(tmpDir, slug2);
78214
78471
  try {
78215
- if (!import_fs83.default.statSync(slugPath).isDirectory()) continue;
78472
+ if (!import_fs85.default.statSync(slugPath).isDirectory()) continue;
78216
78473
  } catch {
78217
78474
  continue;
78218
78475
  }
78219
- let projectRoot = import_path82.default.join(import_os69.default.homedir(), slug2);
78476
+ let projectRoot = import_path84.default.join(import_os70.default.homedir(), slug2);
78220
78477
  try {
78221
- projectRoot = import_fs83.default.readFileSync(import_path82.default.join(slugPath, ".project_root"), "utf-8").trim();
78478
+ projectRoot = import_fs85.default.readFileSync(import_path84.default.join(slugPath, ".project_root"), "utf-8").trim();
78222
78479
  } catch {
78223
78480
  }
78224
- const chatsDir = import_path82.default.join(slugPath, "chats");
78225
- if (!import_fs83.default.existsSync(chatsDir)) continue;
78481
+ const chatsDir = import_path84.default.join(slugPath, "chats");
78482
+ if (!import_fs85.default.existsSync(chatsDir)) continue;
78226
78483
  let chatFiles;
78227
78484
  try {
78228
- chatFiles = import_fs83.default.readdirSync(chatsDir).filter((f) => f.endsWith(".json"));
78485
+ chatFiles = import_fs85.default.readdirSync(chatsDir).filter((f) => f.endsWith(".json"));
78229
78486
  } catch {
78230
78487
  continue;
78231
78488
  }
78232
78489
  for (const chatFile of chatFiles) {
78233
78490
  let raw;
78234
78491
  try {
78235
- raw = import_fs83.default.readFileSync(import_path82.default.join(chatsDir, chatFile), "utf-8");
78492
+ raw = import_fs85.default.readFileSync(import_path84.default.join(chatsDir, chatFile), "utf-8");
78236
78493
  } catch {
78237
78494
  continue;
78238
78495
  }
@@ -78323,7 +78580,7 @@ function buildCodexSessions(days, allAuditEntries) {
78323
78580
  for (const filePath of jsonlFiles) {
78324
78581
  let lines;
78325
78582
  try {
78326
- lines = import_fs83.default.readFileSync(filePath, "utf-8").split("\n");
78583
+ lines = import_fs85.default.readFileSync(filePath, "utf-8").split("\n");
78327
78584
  } catch {
78328
78585
  continue;
78329
78586
  }
@@ -78394,10 +78651,10 @@ function buildCodexSessions(days, allAuditEntries) {
78394
78651
  return summaries;
78395
78652
  }
78396
78653
  function buildSessions(days, historyPath) {
78397
- const hPath = historyPath ?? import_path82.default.join(import_os69.default.homedir(), ".claude", "history.jsonl");
78654
+ const hPath = historyPath ?? import_path84.default.join(import_os70.default.homedir(), ".claude", "history.jsonl");
78398
78655
  let historyRaw = "";
78399
78656
  try {
78400
- historyRaw = import_fs83.default.readFileSync(hPath, "utf-8");
78657
+ historyRaw = import_fs85.default.readFileSync(hPath, "utf-8");
78401
78658
  } catch {
78402
78659
  }
78403
78660
  const cutoff = days !== null ? (() => {
@@ -78421,7 +78678,7 @@ function buildSessions(days, historyPath) {
78421
78678
  const jsonlFile = sessionJsonlPath(entry.project, entry.sessionId);
78422
78679
  let sessionLines = [];
78423
78680
  try {
78424
- sessionLines = import_fs83.default.readFileSync(jsonlFile, "utf-8").split("\n");
78681
+ sessionLines = import_fs85.default.readFileSync(jsonlFile, "utf-8").split("\n");
78425
78682
  } catch {
78426
78683
  }
78427
78684
  const { toolCalls, costUSD, hasSnapshot, modifiedFiles } = parseSessionLines(sessionLines);
@@ -79212,7 +79469,7 @@ init_cjs_shims();
79212
79469
  var import_chalk23 = __toESM(require("chalk"));
79213
79470
  var import_child_process12 = require("child_process");
79214
79471
  init_daemon();
79215
- var import_fs84 = __toESM(require("fs"));
79472
+ var import_fs86 = __toESM(require("fs"));
79216
79473
  init_startup_log();
79217
79474
  init_daemon3();
79218
79475
  init_service();
@@ -79289,7 +79546,7 @@ function registerDaemonCommand(program2) {
79289
79546
  child.unref();
79290
79547
  if (restartFd !== void 0) {
79291
79548
  try {
79292
- import_fs84.default.closeSync(restartFd);
79549
+ import_fs86.default.closeSync(restartFd);
79293
79550
  } catch {
79294
79551
  }
79295
79552
  }
@@ -79340,7 +79597,7 @@ function registerDaemonCommand(program2) {
79340
79597
  } finally {
79341
79598
  if (startupFd !== void 0) {
79342
79599
  try {
79343
- import_fs84.default.closeSync(startupFd);
79600
+ import_fs86.default.closeSync(startupFd);
79344
79601
  } catch {
79345
79602
  }
79346
79603
  }
@@ -79355,9 +79612,9 @@ function registerDaemonCommand(program2) {
79355
79612
  // src/cli/commands/status.ts
79356
79613
  init_cjs_shims();
79357
79614
  var import_chalk24 = __toESM(require("chalk"));
79358
- var import_fs85 = __toESM(require("fs"));
79359
- var import_path83 = __toESM(require("path"));
79360
- var import_os70 = __toESM(require("os"));
79615
+ var import_fs87 = __toESM(require("fs"));
79616
+ var import_path85 = __toESM(require("path"));
79617
+ var import_os71 = __toESM(require("os"));
79361
79618
  init_core();
79362
79619
  init_daemon();
79363
79620
  init_build_id();
@@ -79458,20 +79715,20 @@ function registerStatusCommand(program2) {
79458
79715
  console.log(` Policy: ${import_chalk24.default.cyan("Workspace config (app.node9.ai)")}`);
79459
79716
  }
79460
79717
  const ignoredLabel = import_chalk24.default.gray("Present \u2014 ignored (workspace config governs)");
79461
- const projectConfig = import_path83.default.join(process.cwd(), "node9.config.json");
79462
- const globalConfig = import_path83.default.join(import_os70.default.homedir(), ".node9", "config.json");
79718
+ const projectConfig = import_path85.default.join(process.cwd(), "node9.config.json");
79719
+ const globalConfig = import_path85.default.join(import_os71.default.homedir(), ".node9", "config.json");
79463
79720
  console.log(
79464
- ` Local: ${import_fs85.default.existsSync(projectConfig) ? wsGoverned ? ignoredLabel : import_chalk24.default.green("Active (node9.config.json)") : import_chalk24.default.gray("Not present")}`
79721
+ ` Local: ${import_fs87.default.existsSync(projectConfig) ? wsGoverned ? ignoredLabel : import_chalk24.default.green("Active (node9.config.json)") : import_chalk24.default.gray("Not present")}`
79465
79722
  );
79466
79723
  console.log(
79467
- ` Global: ${import_fs85.default.existsSync(globalConfig) ? wsGoverned ? ignoredLabel : import_chalk24.default.green("Active (~/.node9/config.json)") : import_chalk24.default.gray("Not present")}`
79724
+ ` Global: ${import_fs87.default.existsSync(globalConfig) ? wsGoverned ? ignoredLabel : import_chalk24.default.green("Active (~/.node9/config.json)") : import_chalk24.default.gray("Not present")}`
79468
79725
  );
79469
79726
  if (mergedConfig.policy.sandboxPaths.length > 0) {
79470
79727
  console.log(
79471
79728
  ` Sandbox: ${import_chalk24.default.green(`${mergedConfig.policy.sandboxPaths.length} safe zones active`)}`
79472
79729
  );
79473
79730
  }
79474
- const wiring = getAgentWiring(import_os70.default.homedir()).filter((a) => a.present);
79731
+ const wiring = getAgentWiring(import_os71.default.homedir()).filter((a) => a.present);
79475
79732
  if (wiring.length > 0) {
79476
79733
  console.log("");
79477
79734
  console.log(import_chalk24.default.bold(" Agent Wiring:"));
@@ -79490,7 +79747,7 @@ function registerStatusCommand(program2) {
79490
79747
  a.mcpServers
79491
79748
  );
79492
79749
  if (a.id === "codex" && a.hooks.some((h) => h.wired)) {
79493
- const t = assessCodexTrust(import_os70.default.homedir());
79750
+ const t = assessCodexTrust(import_os71.default.homedir());
79494
79751
  if (t.state === "observed") {
79495
79752
  console.log(
79496
79753
  import_chalk24.default.green(
@@ -79534,7 +79791,7 @@ init_init();
79534
79791
  // src/cli/commands/heal.ts
79535
79792
  init_cjs_shims();
79536
79793
  var import_chalk25 = __toESM(require("chalk"));
79537
- var import_fs88 = __toESM(require("fs"));
79794
+ var import_fs90 = __toESM(require("fs"));
79538
79795
  init_agent_wiring();
79539
79796
  init_mcp_wrap();
79540
79797
  init_setup();
@@ -79542,7 +79799,7 @@ init_hook_baseline();
79542
79799
  var hasHookSurface = (a) => a.hooks.length > 0;
79543
79800
  function backupForHeal(file2) {
79544
79801
  try {
79545
- if (file2 && import_fs88.default.existsSync(file2)) import_fs88.default.copyFileSync(file2, `${file2}.node9-heal-bak`);
79802
+ if (file2 && import_fs90.default.existsSync(file2)) import_fs90.default.copyFileSync(file2, `${file2}.node9-heal-bak`);
79546
79803
  } catch {
79547
79804
  }
79548
79805
  }
@@ -80163,7 +80420,12 @@ async function runMcpGateway(upstreamCommand, configName) {
80163
80420
  humanDecision,
80164
80421
  result.reason,
80165
80422
  void 0,
80166
- { kind: result.blockKind, path: result.blockedPath, redirect: !!result.redirect }
80423
+ {
80424
+ kind: result.blockKind,
80425
+ path: result.blockedPath,
80426
+ redirect: !!result.redirect,
80427
+ ruleDescription: result.ruleDescription
80428
+ }
80167
80429
  );
80168
80430
  const errorResponse = {
80169
80431
  jsonrpc: "2.0",
@@ -80507,9 +80769,9 @@ init_cjs_shims();
80507
80769
  init_cjs_shims();
80508
80770
  var import_readline4 = __toESM(require("readline"));
80509
80771
  init_write();
80510
- var import_fs89 = __toESM(require("fs"));
80511
- var import_os75 = __toESM(require("os"));
80512
- var import_path88 = __toESM(require("path"));
80772
+ var import_fs91 = __toESM(require("fs"));
80773
+ var import_os76 = __toESM(require("os"));
80774
+ var import_path90 = __toESM(require("path"));
80513
80775
  var import_child_process14 = require("child_process");
80514
80776
  init_decision();
80515
80777
  init_core();
@@ -81060,14 +81322,14 @@ function handleStatus() {
81060
81322
  const state = !a.installed ? "not installed" : hooked ? "wired" : a.isProtected ? "protected through MCP" : "not wired";
81061
81323
  lines.push(` ${a.label}: ${state}`);
81062
81324
  }
81063
- const projectConfig = import_path88.default.join(process.cwd(), "node9.config.json");
81064
- const globalConfig = import_path88.default.join(import_os75.default.homedir(), ".node9", "config.json");
81325
+ const projectConfig = import_path90.default.join(process.cwd(), "node9.config.json");
81326
+ const globalConfig = import_path90.default.join(import_os76.default.homedir(), ".node9", "config.json");
81065
81327
  const presentLabel = wsGoverned ? "present \u2014 ignored (workspace config governs)" : "present";
81066
81328
  lines.push(
81067
- `Project config (node9.config.json): ${import_fs89.default.existsSync(projectConfig) ? presentLabel : "not found"}`
81329
+ `Project config (node9.config.json): ${import_fs91.default.existsSync(projectConfig) ? presentLabel : "not found"}`
81068
81330
  );
81069
81331
  lines.push(
81070
- `Global config (~/.node9/config.json): ${import_fs89.default.existsSync(globalConfig) ? presentLabel : "not found"}`
81332
+ `Global config (~/.node9/config.json): ${import_fs91.default.existsSync(globalConfig) ? presentLabel : "not found"}`
81071
81333
  );
81072
81334
  return lines.join("\n");
81073
81335
  }
@@ -81204,7 +81466,7 @@ function handleEgressDeny(args) {
81204
81466
  addEgressHost("deny", host2);
81205
81467
  return `Denied egress to ${host2} (deny always wins over allow).`;
81206
81468
  }
81207
- var GLOBAL_CONFIG_PATH2 = import_path88.default.join(import_os75.default.homedir(), ".node9", "config.json");
81469
+ var GLOBAL_CONFIG_PATH2 = import_path90.default.join(import_os76.default.homedir(), ".node9", "config.json");
81208
81470
  var APPROVER_CHANNELS2 = ["native", "browser", "cloud", "terminal"];
81209
81471
  function handleApproverList() {
81210
81472
  const config = getConfig();
@@ -81245,9 +81507,9 @@ function handleApproverSet(args) {
81245
81507
  function handleAuditGet(args) {
81246
81508
  const limit = Math.min(typeof args.limit === "number" ? args.limit : 20, 100);
81247
81509
  const filter = typeof args.filter === "string" && args.filter !== "all" ? args.filter : null;
81248
- const auditPath = import_path88.default.join(import_os75.default.homedir(), ".node9", "audit.log");
81249
- if (!import_fs89.default.existsSync(auditPath)) return "No audit log found.";
81250
- const rawLines = import_fs89.default.readFileSync(auditPath, "utf-8").trim().split("\n").filter(Boolean);
81510
+ const auditPath = import_path90.default.join(import_os76.default.homedir(), ".node9", "audit.log");
81511
+ if (!import_fs91.default.existsSync(auditPath)) return "No audit log found.";
81512
+ const rawLines = import_fs91.default.readFileSync(auditPath, "utf-8").trim().split("\n").filter(Boolean);
81251
81513
  const wanted = filter === "block" ? "deny" : filter;
81252
81514
  const parsed = [];
81253
81515
  for (const line of rawLines) {
@@ -81607,7 +81869,7 @@ function registerTrustCommand(program2) {
81607
81869
  init_cjs_shims();
81608
81870
  var import_chalk32 = __toESM(require("chalk"));
81609
81871
  init_mcp_pin();
81610
- var import_fs90 = __toESM(require("fs"));
81872
+ var import_fs92 = __toESM(require("fs"));
81611
81873
 
81612
81874
  // src/cli/commands/mcp-gateway-cmd.ts
81613
81875
  init_cjs_shims();
@@ -81816,7 +82078,7 @@ function registerMcpPinCommand(program2) {
81816
82078
  let repoCorrupt = false;
81817
82079
  if (found.source === "repo") {
81818
82080
  try {
81819
- const raw = import_fs90.default.readFileSync(found.path, "utf-8");
82081
+ const raw = import_fs92.default.readFileSync(found.path, "utf-8");
81820
82082
  const parsed = JSON.parse(raw);
81821
82083
  repoEntries = parsed.servers ?? {};
81822
82084
  } catch {
@@ -82268,8 +82530,8 @@ init_cjs_shims();
82268
82530
 
82269
82531
  // src/ci-check/fetch.ts
82270
82532
  init_cjs_shims();
82271
- var import_fs91 = __toESM(require("fs"));
82272
- var import_path89 = __toESM(require("path"));
82533
+ var import_fs93 = __toESM(require("fs"));
82534
+ var import_path91 = __toESM(require("path"));
82273
82535
  var import_node_child_process = require("child_process");
82274
82536
  var import_undici = __toESM(require_undici());
82275
82537
 
@@ -82469,8 +82731,8 @@ function isOfficialInstaller(u) {
82469
82731
  if (u.username || u.password) return false;
82470
82732
  const host2 = u.hostname.toLowerCase().replace(/^www\./, "");
82471
82733
  if (OFFICIAL_HOSTS.has(host2)) return true;
82472
- const path108 = OFFICIAL_PATHS[host2];
82473
- return !!path108 && path108.test(u.pathname);
82734
+ const path110 = OFFICIAL_PATHS[host2];
82735
+ return !!path110 && path110.test(u.pathname);
82474
82736
  }
82475
82737
  function onlyOfficialInstaller(s) {
82476
82738
  const urls = s.match(URL_RE3);
@@ -82661,21 +82923,21 @@ function appSkillDirsOf(paths, skillDirs) {
82661
82923
  }
82662
82924
  return apps;
82663
82925
  }
82664
- function isSkillSupportFile(path108, skillDirs, appDirs) {
82665
- if (!path108.endsWith(".md") || /(^|\/)[Ss][Kk][Ii][Ll][Ll]\.md$/.test(path108)) return false;
82666
- for (let d = path108.lastIndexOf("/"); d > 0; d = path108.lastIndexOf("/", d - 1)) {
82667
- const dir2 = path108.slice(0, d);
82926
+ function isSkillSupportFile(path110, skillDirs, appDirs) {
82927
+ if (!path110.endsWith(".md") || /(^|\/)[Ss][Kk][Ii][Ll][Ll]\.md$/.test(path110)) return false;
82928
+ for (let d = path110.lastIndexOf("/"); d > 0; d = path110.lastIndexOf("/", d - 1)) {
82929
+ const dir2 = path110.slice(0, d);
82668
82930
  if (!skillDirs.has(dir2)) continue;
82669
- return !appDirs?.has(dir2) || SKILL_LAYOUT_RE.test(path108.slice(d + 1));
82931
+ return !appDirs?.has(dir2) || SKILL_LAYOUT_RE.test(path110.slice(d + 1));
82670
82932
  }
82671
82933
  return false;
82672
82934
  }
82673
- function isAppDoc(path108, skillDirs, appDirs) {
82674
- if (!path108.endsWith(".md") || INSTRUCTION_FILE_RE.test(path108)) return false;
82675
- for (let d = path108.lastIndexOf("/"); d > 0; d = path108.lastIndexOf("/", d - 1)) {
82676
- const dir2 = path108.slice(0, d);
82935
+ function isAppDoc(path110, skillDirs, appDirs) {
82936
+ if (!path110.endsWith(".md") || INSTRUCTION_FILE_RE.test(path110)) return false;
82937
+ for (let d = path110.lastIndexOf("/"); d > 0; d = path110.lastIndexOf("/", d - 1)) {
82938
+ const dir2 = path110.slice(0, d);
82677
82939
  if (!skillDirs.has(dir2)) continue;
82678
- return appDirs.has(dir2) && !SKILL_LAYOUT_RE.test(path108.slice(d + 1));
82940
+ return appDirs.has(dir2) && !SKILL_LAYOUT_RE.test(path110.slice(d + 1));
82679
82941
  }
82680
82942
  return false;
82681
82943
  }
@@ -82698,20 +82960,20 @@ function namedDocs(dir2, skillMd) {
82698
82960
  return out;
82699
82961
  }
82700
82962
  var SCRIPT_EXT_RE = /\.(sh|bash|zsh|py|js|mjs|cjs|ts|rb|pl|ps1)$/i;
82701
- function isHookScript(path108) {
82702
- return /(^|\/)\.claude\/hooks\/.+/.test(path108) && SCRIPT_EXT_RE.test(path108);
82703
- }
82704
- function isSkillScript(path108, skillDirs) {
82705
- if (!SCRIPT_EXT_RE.test(path108)) return false;
82706
- for (let d = path108.lastIndexOf("/"); d > 0; d = path108.lastIndexOf("/", d - 1)) {
82707
- if (!skillDirs.has(path108.slice(0, d))) continue;
82708
- const rel = path108.slice(d + 1);
82963
+ function isHookScript(path110) {
82964
+ return /(^|\/)\.claude\/hooks\/.+/.test(path110) && SCRIPT_EXT_RE.test(path110);
82965
+ }
82966
+ function isSkillScript(path110, skillDirs) {
82967
+ if (!SCRIPT_EXT_RE.test(path110)) return false;
82968
+ for (let d = path110.lastIndexOf("/"); d > 0; d = path110.lastIndexOf("/", d - 1)) {
82969
+ if (!skillDirs.has(path110.slice(0, d))) continue;
82970
+ const rel = path110.slice(d + 1);
82709
82971
  return !rel.includes("/") || /^(scripts|bin)\//.test(rel);
82710
82972
  }
82711
82973
  return false;
82712
82974
  }
82713
- function isInstructionFile(path108, skillDirs, appDirs) {
82714
- return INSTRUCTION_FILE_RE.test(path108) || isSkillSupportFile(path108, skillDirs, appDirs);
82975
+ function isInstructionFile(path110, skillDirs, appDirs) {
82976
+ return INSTRUCTION_FILE_RE.test(path110) || isSkillSupportFile(path110, skillDirs, appDirs);
82715
82977
  }
82716
82978
  var OVERRIDE_RE = /ignore\s+(all\s+)?(previous|prior|the\s+above)\s+(instructions|prompts?|rules)|disregard\s+(the\s+|your\s+)?(system\s+)?(prompt|instructions|rules)|forget\s+(everything|all\s+(previous|prior))|you\s+are\s+now\s+(a|an|the)\b|<\/?system>/i;
82717
82979
  var FETCH_WORD_RE = /\b(curl|wget|iwr|invoke-webrequest)\b/gi;
@@ -82848,21 +83110,21 @@ function decodeSuspiciousBase64(text) {
82848
83110
  }
82849
83111
  return out;
82850
83112
  }
82851
- function mk2(rule, severity, title, signals, fix, path108, line) {
83113
+ function mk2(rule, severity, title, signals, fix, path110, line) {
82852
83114
  return {
82853
83115
  check: "CI-6",
82854
83116
  rule,
82855
83117
  dimension: "instructions",
82856
83118
  severity,
82857
83119
  title,
82858
- file: path108,
83120
+ file: path110,
82859
83121
  ...line ? { line } : {},
82860
83122
  signals,
82861
83123
  fix
82862
83124
  };
82863
83125
  }
82864
83126
  var lineAt = (text, i) => i >= 0 ? lineAtIndex(text, i) : void 0;
82865
- function analyzeInstructionFile(path108, content) {
83127
+ function analyzeInstructionFile(path110, content) {
82866
83128
  const findings = [];
82867
83129
  const decoded = decodeSuspiciousBase64(content);
82868
83130
  const glyph = homoglyphWord(content);
@@ -82876,7 +83138,7 @@ function analyzeInstructionFile(path108, content) {
82876
83138
  `\`${glyph.folded}\` is written with ${glyph.count} non-Latin look-alike letter(s): it reads the same to a reviewer, but a search, a replace or a policy check on the real word misses it`
82877
83139
  ],
82878
83140
  "Spell the word with plain Latin letters, or explain on the same line why the look-alikes are there.",
82879
- path108,
83141
+ path110,
82880
83142
  glyph.line
82881
83143
  )
82882
83144
  );
@@ -82890,7 +83152,7 @@ function analyzeInstructionFile(path108, content) {
82890
83152
  "contains Unicode tag characters (U+E0000\u2013E007F): an invisible instruction-smuggling channel with no legitimate use in text"
82891
83153
  ],
82892
83154
  "Remove the tag characters. Instruction files must be plain, reviewable text.",
82893
- path108,
83155
+ path110,
82894
83156
  lineAt(content, content.search(TAG_CHARS))
82895
83157
  )
82896
83158
  );
@@ -82904,7 +83166,7 @@ function analyzeInstructionFile(path108, content) {
82904
83166
  "contains a bidi override (U+202D/U+202E): a Trojan-Source technique that visually reorders text so a human reads something different from what the agent parses"
82905
83167
  ],
82906
83168
  "Remove the bidi override characters.",
82907
- path108,
83169
+ path110,
82908
83170
  lineAt(content, content.search(BIDI_OVERRIDE))
82909
83171
  )
82910
83172
  );
@@ -82918,7 +83180,7 @@ function analyzeInstructionFile(path108, content) {
82918
83180
  "contains bidi embed/isolate characters (U+202A\u2013202C / U+2066\u20132069): legitimate in right-to-left text, but confirm they are not being used to hide or reorder instructions"
82919
83181
  ],
82920
83182
  "Confirm the bidi marks are legitimate RTL formatting; remove otherwise.",
82921
- path108,
83183
+ path110,
82922
83184
  lineAt(content, content.search(BIDI_EMBED_ISOLATE))
82923
83185
  )
82924
83186
  );
@@ -82934,7 +83196,7 @@ function analyzeInstructionFile(path108, content) {
82934
83196
  revealed ? "a zero-width character conceals a prompt-override directive that only appears once the hidden characters are stripped" : "a zero-width character splits a visible Latin word: a concealment technique (hides text from human review while the agent reads it as contiguous)"
82935
83197
  ],
82936
83198
  "Remove the zero-width characters. Instruction files must be plain, reviewable text.",
82937
- path108,
83199
+ path110,
82938
83200
  lineAt(content, zw.first)
82939
83201
  )
82940
83202
  );
@@ -82953,7 +83215,7 @@ function analyzeInstructionFile(path108, content) {
82953
83215
  `contains a prompt-override / role-impersonation directive (\`${safeText(m[0].slice(0, 60).trim(), 60)}\`)${ovEnc ? ", concealed in a base64 blob" : ""}`
82954
83216
  ],
82955
83217
  "Remove the override text. An instruction file should not tell the agent to ignore its own rules.",
82956
- path108,
83218
+ path110,
82957
83219
  ov ? lineAt(content, ov.index) : void 0
82958
83220
  // concealed in base64: no line, never a wrong one
82959
83221
  )
@@ -82970,7 +83232,7 @@ function analyzeInstructionFile(path108, content) {
82970
83232
  `\`${safeText(fo[0].slice(0, 70).trim(), 70)}\`: fetch-and-obey, outside an install/setup section`
82971
83233
  ],
82972
83234
  "Do not instruct the agent to pipe remote content into a shell; pin and vendor scripts instead.",
82973
- path108,
83235
+ path110,
82974
83236
  lineAt(content, fo.index)
82975
83237
  )
82976
83238
  );
@@ -82986,7 +83248,7 @@ function analyzeInstructionFile(path108, content) {
82986
83248
  `references \`${safeText(sp[0].slice(0, 50).trim(), 50)}\`: directs the agent toward secrets`
82987
83249
  ],
82988
83250
  "Do not reference credential files or paths in agent instructions.",
82989
- path108,
83251
+ path110,
82990
83252
  lineAt(content, sp.index)
82991
83253
  )
82992
83254
  );
@@ -83009,7 +83271,7 @@ function analyzeInstructionFile(path108, content) {
83009
83271
  "Instruction directs the agent to send data to an external endpoint",
83010
83272
  [`\`${safeText(ex[0].slice(0, 70).trim(), 70)}\`: possible exfiltration directive`],
83011
83273
  "Remove external post/upload directives from agent instructions.",
83012
- path108,
83274
+ path110,
83013
83275
  lineAt(content, ex.index)
83014
83276
  )
83015
83277
  );
@@ -83020,18 +83282,18 @@ function analyzeInstructionFile(path108, content) {
83020
83282
  // src/ci-check/route.ts
83021
83283
  var MCP_CONFIG_RE = /\.mcp\.json$|\.cursor\/mcp\.json$|(^|\/)\.vscode\/mcp\.json$|(^|\/)\.kiro\/settings\/mcp\.json$|(^|\/)\.gemini\/settings\.json$|(^|\/)opencode\.json$|(^|\/)\.opencode\/config\.json$/;
83022
83284
  var ISSUE_FORM_RE = /^\.github\/ISSUE_TEMPLATE\/[^/]+\.(ya?ml|md)$/i;
83023
- function routeOf(path108, skillDirs, appDirs = /* @__PURE__ */ new Set()) {
83024
- if (path108 === SUPPRESSIONS_FILE) return "suppressions";
83025
- if (/\.github\/workflows\/.+\.ya?ml$/.test(path108)) return "workflow";
83026
- if (ISSUE_FORM_RE.test(path108)) return "issue-form";
83027
- if (path108 === "package.json" || path108 === "pyproject.toml") return "manifest";
83028
- if (/\.claude\/settings(\.local)?\.json$/.test(path108)) return "agent-config";
83029
- if (isHookScript(path108)) return "hook-script";
83030
- if (isSkillScript(path108, skillDirs)) return "skill-script";
83031
- if (MCP_CONFIG_RE.test(path108)) return "mcp";
83032
- if (/(^|\/)\.codex\/config\.toml$/.test(path108)) return "codex";
83033
- if (isInstructionFile(path108, skillDirs, appDirs)) return "instruction";
83034
- if (isAppDoc(path108, skillDirs, appDirs)) return "app-doc";
83285
+ function routeOf(path110, skillDirs, appDirs = /* @__PURE__ */ new Set()) {
83286
+ if (path110 === SUPPRESSIONS_FILE) return "suppressions";
83287
+ if (/\.github\/workflows\/.+\.ya?ml$/.test(path110)) return "workflow";
83288
+ if (ISSUE_FORM_RE.test(path110)) return "issue-form";
83289
+ if (path110 === "package.json" || path110 === "pyproject.toml") return "manifest";
83290
+ if (/\.claude\/settings(\.local)?\.json$/.test(path110)) return "agent-config";
83291
+ if (isHookScript(path110)) return "hook-script";
83292
+ if (isSkillScript(path110, skillDirs)) return "skill-script";
83293
+ if (MCP_CONFIG_RE.test(path110)) return "mcp";
83294
+ if (/(^|\/)\.codex\/config\.toml$/.test(path110)) return "codex";
83295
+ if (isInstructionFile(path110, skillDirs, appDirs)) return "instruction";
83296
+ if (isAppDoc(path110, skillDirs, appDirs)) return "app-doc";
83035
83297
  return null;
83036
83298
  }
83037
83299
 
@@ -83160,7 +83422,7 @@ function parseRepoUrl(input) {
83160
83422
  function isLocalPath(input) {
83161
83423
  if (input.startsWith(".") || input.startsWith("/") || input.startsWith("~")) return true;
83162
83424
  try {
83163
- return import_fs91.default.existsSync(input) && import_fs91.default.statSync(input).isDirectory();
83425
+ return import_fs93.default.existsSync(input) && import_fs93.default.statSync(input).isDirectory();
83164
83426
  } catch {
83165
83427
  return false;
83166
83428
  }
@@ -83521,7 +83783,7 @@ function capNested(reads, cap, notes) {
83521
83783
  }
83522
83784
  var overLimit = (text) => Buffer.byteLength(text, "utf8") > MAX_FILE_BYTES3;
83523
83785
  var RAW_LIMIT = 2 * MAX_FILE_BYTES3;
83524
- var OPEN_READ = import_fs91.default.constants.O_RDONLY | (import_fs91.default.constants.O_NOFOLLOW ?? 0) | (import_fs91.default.constants.O_NONBLOCK ?? 0);
83786
+ var OPEN_READ = import_fs93.default.constants.O_RDONLY | (import_fs93.default.constants.O_NOFOLLOW ?? 0) | (import_fs93.default.constants.O_NONBLOCK ?? 0);
83525
83787
  var MAX_WALK_ENTRIES = 1e6;
83526
83788
  var direntKind = (e) => e.isSymbolicLink() ? "link" : e.isDirectory() ? "dir" : e.isFile() ? "file" : "other";
83527
83789
  function walkDisk(root, notes) {
@@ -83536,7 +83798,7 @@ function walkDisk(root, notes) {
83536
83798
  const relDir = stack.pop();
83537
83799
  let dirents;
83538
83800
  try {
83539
- dirents = import_fs91.default.readdirSync(import_path89.default.join(root, relDir), { withFileTypes: true });
83801
+ dirents = import_fs93.default.readdirSync(import_path91.default.join(root, relDir), { withFileTypes: true });
83540
83802
  } catch (e) {
83541
83803
  unlistable.push(`${relDir || "."} (${e?.code ?? "error"})`);
83542
83804
  continue;
@@ -83550,7 +83812,7 @@ function walkDisk(root, notes) {
83550
83812
  const k = direntKind(e);
83551
83813
  kinds2.set(rel, k);
83552
83814
  if (k !== "dir" || isUnwalked(`${rel}/`)) continue;
83553
- if (import_fs91.default.existsSync(import_path89.default.join(root, rel, ".git"))) {
83815
+ if (import_fs93.default.existsSync(import_path91.default.join(root, rel, ".git"))) {
83554
83816
  sealed.add(rel);
83555
83817
  nestedRepos.push(rel);
83556
83818
  } else stack.push(rel);
@@ -83573,7 +83835,7 @@ function walkDisk(root, notes) {
83573
83835
  }
83574
83836
  function gitmodulePaths(root) {
83575
83837
  try {
83576
- const text = readLocalFile(import_path89.default.join(root, ".gitmodules"), ".gitmodules");
83838
+ const text = readLocalFile(import_path91.default.join(root, ".gitmodules"), ".gitmodules");
83577
83839
  return [...text.matchAll(/^\s*path\s*=\s*(.+?)\s*$/gm)].map((m) => m[1].replace(/\/+$/, ""));
83578
83840
  } catch {
83579
83841
  return [];
@@ -83581,9 +83843,9 @@ function gitmodulePaths(root) {
83581
83843
  }
83582
83844
  function localLinkText(root, rel) {
83583
83845
  try {
83584
- const t = import_fs91.default.readlinkSync(import_path89.default.join(root, rel));
83846
+ const t = import_fs93.default.readlinkSync(import_path91.default.join(root, rel));
83585
83847
  if (process.platform !== "win32") return t;
83586
- return import_path89.default.win32.isAbsolute(t) ? `/${t.replace(/\\/g, "/")}` : t.replace(/\\/g, "/");
83848
+ return import_path91.default.win32.isAbsolute(t) ? `/${t.replace(/\\/g, "/")}` : t.replace(/\\/g, "/");
83587
83849
  } catch {
83588
83850
  return null;
83589
83851
  }
@@ -83591,11 +83853,11 @@ function localLinkText(root, rel) {
83591
83853
  function readLocalFile(abs, rel) {
83592
83854
  let fd;
83593
83855
  try {
83594
- fd = import_fs91.default.openSync(abs, OPEN_READ);
83595
- const st = import_fs91.default.fstatSync(fd);
83856
+ fd = import_fs93.default.openSync(abs, OPEN_READ);
83857
+ const st = import_fs93.default.fstatSync(fd);
83596
83858
  if (!st.isFile()) throw new Error(unreadNote(rel, "no longer a regular file"));
83597
83859
  if (st.size > RAW_LIMIT) throw new Error(tooLargeNote(rel));
83598
- const text = lf(import_fs91.default.readFileSync(fd, "utf8"));
83860
+ const text = lf(import_fs93.default.readFileSync(fd, "utf8"));
83599
83861
  if (overLimit(text)) throw new Error(tooLargeNote(rel));
83600
83862
  return text;
83601
83863
  } catch (e) {
@@ -83603,7 +83865,7 @@ function readLocalFile(abs, rel) {
83603
83865
  if (msg.includes(INCOMPLETE)) throw e;
83604
83866
  throw new Error(unreadNote(rel, e?.code ?? "error"));
83605
83867
  } finally {
83606
- if (fd !== void 0) import_fs91.default.closeSync(fd);
83868
+ if (fd !== void 0) import_fs93.default.closeSync(fd);
83607
83869
  }
83608
83870
  }
83609
83871
  function localGitHubRepo(root) {
@@ -83624,10 +83886,10 @@ function readLocalTree(dir2) {
83624
83886
  notes.push(...plan.notes);
83625
83887
  const files = [];
83626
83888
  for (const { rel, real, route } of plan.reads) {
83627
- const abs = import_path89.default.join(root, real);
83889
+ const abs = import_path91.default.join(root, real);
83628
83890
  let size = 0;
83629
83891
  try {
83630
- size = import_fs91.default.lstatSync(abs).size;
83892
+ size = import_fs93.default.lstatSync(abs).size;
83631
83893
  } catch {
83632
83894
  }
83633
83895
  if (size > RAW_LIMIT) {
@@ -85135,17 +85397,17 @@ function localTarget(uses, self) {
85135
85397
  if (!f) return null;
85136
85398
  return f[1].toLowerCase() === self.owner.toLowerCase() && f[2].toLowerCase() === self.repo.toLowerCase() ? `.github/workflows/${f[3]}` : null;
85137
85399
  }
85138
- function localCallsOf(path108, content, autoLabels, trustedRunSources, self) {
85400
+ function localCallsOf(path110, content, autoLabels, trustedRunSources, self) {
85139
85401
  AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
85140
85402
  TRUSTED_RUN_SOURCES = trustedRunSources ?? /* @__PURE__ */ new Set();
85141
85403
  try {
85142
- return localCallsOfInner(path108, content, self);
85404
+ return localCallsOfInner(path110, content, self);
85143
85405
  } finally {
85144
85406
  AUTO_LABELS = /* @__PURE__ */ new Set();
85145
85407
  TRUSTED_RUN_SOURCES = /* @__PURE__ */ new Set();
85146
85408
  }
85147
85409
  }
85148
- function localCallsOfInner(path108, content, self) {
85410
+ function localCallsOfInner(path110, content, self) {
85149
85411
  let raw;
85150
85412
  try {
85151
85413
  raw = loadWorkflow(content).raw;
@@ -85163,7 +85425,7 @@ function localCallsOfInner(path108, content, self) {
85163
85425
  out.push({
85164
85426
  target,
85165
85427
  caller: {
85166
- file: path108,
85428
+ file: path110,
85167
85429
  keys: reach.keys,
85168
85430
  untrusted: reach.untrusted,
85169
85431
  secretExposed: reach.secretExposed,
@@ -85399,7 +85661,7 @@ function upstreamRunTrusted(wf, raw) {
85399
85661
  const names = Array.isArray(run?.workflows) ? run.workflows.map(String) : [];
85400
85662
  return names.length > 0 && names.every((n) => TRUSTED_RUN_SOURCES.has(n));
85401
85663
  }
85402
- function runSourceOf(path108, content, autoLabels) {
85664
+ function runSourceOf(path110, content, autoLabels) {
85403
85665
  AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
85404
85666
  try {
85405
85667
  let raw;
@@ -85412,7 +85674,7 @@ function runSourceOf(path108, content, autoLabels) {
85412
85674
  const wf = raw;
85413
85675
  CALLERS.delete(wf);
85414
85676
  const reach = triggerReach(wf, raw);
85415
- const name = typeof raw["name"] === "string" && raw["name"] ? raw["name"] : path108;
85677
+ const name = typeof raw["name"] === "string" && raw["name"] ? raw["name"] : path110;
85416
85678
  return { name, trusted: !reach.untrusted && !reach.reusable };
85417
85679
  } finally {
85418
85680
  AUTO_LABELS = /* @__PURE__ */ new Set();
@@ -85882,18 +86144,18 @@ function severityFromScore(score) {
85882
86144
  if (score >= 1) return "advisory";
85883
86145
  return null;
85884
86146
  }
85885
- function analyzeWorkflow(path108, content, callers, autoLabels, trustedRunSources) {
86147
+ function analyzeWorkflow(path110, content, callers, autoLabels, trustedRunSources) {
85886
86148
  AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
85887
86149
  TRUSTED_RUN_SOURCES = trustedRunSources ?? /* @__PURE__ */ new Set();
85888
86150
  try {
85889
- return analyzeWorkflowInner(path108, content, callers);
86151
+ return analyzeWorkflowInner(path110, content, callers);
85890
86152
  } finally {
85891
86153
  AUTO_LABELS = /* @__PURE__ */ new Set();
85892
86154
  TRUSTED_RUN_SOURCES = /* @__PURE__ */ new Set();
85893
86155
  UPSTREAM_TRUSTED = false;
85894
86156
  }
85895
86157
  }
85896
- function analyzeWorkflowInner(path108, content, callers) {
86158
+ function analyzeWorkflowInner(path110, content, callers) {
85897
86159
  let raw;
85898
86160
  try {
85899
86161
  raw = loadWorkflow(content).raw;
@@ -86102,7 +86364,7 @@ function analyzeWorkflowInner(path108, content, callers) {
86102
86364
  dimension: "workflows",
86103
86365
  severity,
86104
86366
  title,
86105
- file: path108,
86367
+ file: path110,
86106
86368
  signals,
86107
86369
  mitigations: mitigations.length ? mitigations : void 0,
86108
86370
  fix: head === "root" && privileged ? "Do not check out the untrusted PR head into the workspace root under a privileged trigger (pull_request_target/workflow_run): check out the base ref, or isolate the head in a subdir (--add-dir). Add an actor gate and scope the agent tools." : head === "root" ? "This runs under `pull_request` (fork PRs get a read-only token), so the head checkout is low-risk today: keep it on `pull_request` (not `pull_request_target`) and keep the actor gate + scoped tools." : "Add/verify an actor gate, scope the agent tools to read-only, and env-deny secrets. See Anthropic\u2019s claude-code-action security doc."
@@ -86206,18 +86468,18 @@ function evalAgentJob(job, wf, raw, untrustedTrigger, reusable) {
86206
86468
  if (reusable && !loadedGun && SEVERITY_RANK2[severity] > SEVERITY_RANK2.medium) severity = "medium";
86207
86469
  return { severity, secrets, injectable, canReadEnv };
86208
86470
  }
86209
- function analyzeWorkflowSecrets(path108, content, callers, autoLabels, trustedRunSources) {
86471
+ function analyzeWorkflowSecrets(path110, content, callers, autoLabels, trustedRunSources) {
86210
86472
  AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
86211
86473
  TRUSTED_RUN_SOURCES = trustedRunSources ?? /* @__PURE__ */ new Set();
86212
86474
  try {
86213
- return analyzeWorkflowSecretsInner(path108, content, callers);
86475
+ return analyzeWorkflowSecretsInner(path110, content, callers);
86214
86476
  } finally {
86215
86477
  AUTO_LABELS = /* @__PURE__ */ new Set();
86216
86478
  TRUSTED_RUN_SOURCES = /* @__PURE__ */ new Set();
86217
86479
  UPSTREAM_TRUSTED = false;
86218
86480
  }
86219
86481
  }
86220
- function analyzeWorkflowSecretsInner(path108, content, callers) {
86482
+ function analyzeWorkflowSecretsInner(path110, content, callers) {
86221
86483
  let raw;
86222
86484
  try {
86223
86485
  raw = loadWorkflow(content).raw;
@@ -86244,7 +86506,7 @@ function analyzeWorkflowSecretsInner(path108, content, callers) {
86244
86506
  dimension: "data",
86245
86507
  severity: worst.severity,
86246
86508
  title: worst.severity === "advisory" ? "Secrets reachable by the agent: hardening" : "Exfiltratable secrets reachable by an injectable agent",
86247
- file: path108,
86509
+ file: path110,
86248
86510
  signals: [
86249
86511
  `agent can reach: ${worst.secrets.map((s) => s.name).join(", ")}`,
86250
86512
  worst.injectable ? "the agent is externally triggerable (untrusted trigger, no gate)" : "gated / not externally triggerable: latent risk only",
@@ -86266,7 +86528,7 @@ function marketplaceOwner(market) {
86266
86528
  market
86267
86529
  )?.[1] ?? /^([\w.-]{1,100})\/[\w.-]{1,100}(?:[#@].*)?$/.exec(market)?.[1];
86268
86530
  }
86269
- function analyzeWorkflowPlugins(path108, content, owner) {
86531
+ function analyzeWorkflowPlugins(path110, content, owner) {
86270
86532
  let raw;
86271
86533
  try {
86272
86534
  raw = loadWorkflow(content).raw;
@@ -86296,7 +86558,7 @@ function analyzeWorkflowPlugins(path108, content, owner) {
86296
86558
  dimension: "mcp",
86297
86559
  severity: "medium",
86298
86560
  title: "Agent installs plugins from a third-party marketplace on every run",
86299
- file: path108,
86561
+ file: path110,
86300
86562
  signals: [
86301
86563
  `\`plugin_marketplaces: ${safeText(market, 120)}\` is not pinned to a commit: whoever controls it changes the code and prompts the agent runs`
86302
86564
  ],
@@ -86312,11 +86574,11 @@ function readsItemList(text) {
86312
86574
  if (text.length > 2e5) return ITEM_LIST_RE.test(text);
86313
86575
  return text.replace(/\\\r?\n/g, " ").split("\n").some((l) => ITEM_LIST_RE.test(l) && !sanitizedListing(l));
86314
86576
  }
86315
- function analyzeTrustedReaders(path108, content, autoLabels, callers, trustedRunSources) {
86577
+ function analyzeTrustedReaders(path110, content, autoLabels, callers, trustedRunSources) {
86316
86578
  AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
86317
86579
  TRUSTED_RUN_SOURCES = trustedRunSources ?? /* @__PURE__ */ new Set();
86318
86580
  try {
86319
- return analyzeTrustedReadersInner(path108, content, callers);
86581
+ return analyzeTrustedReadersInner(path110, content, callers);
86320
86582
  } finally {
86321
86583
  AUTO_LABELS = /* @__PURE__ */ new Set();
86322
86584
  TRUSTED_RUN_SOURCES = /* @__PURE__ */ new Set();
@@ -86325,7 +86587,7 @@ function analyzeTrustedReaders(path108, content, autoLabels, callers, trustedRun
86325
86587
  function keysWithCallers(keys, callers) {
86326
86588
  return [.../* @__PURE__ */ new Set([...keys, ...(callers ?? []).flatMap((c) => c.keys)])];
86327
86589
  }
86328
- function analyzeTrustedReadersInner(path108, content, callers) {
86590
+ function analyzeTrustedReadersInner(path110, content, callers) {
86329
86591
  let raw;
86330
86592
  try {
86331
86593
  raw = loadWorkflow(content).raw;
@@ -86386,7 +86648,7 @@ function analyzeTrustedReadersInner(path108, content, callers) {
86386
86648
  dimension: "workflows",
86387
86649
  severity: "advisory",
86388
86650
  title: "Agent on a trusted trigger reads content strangers write, with a write token",
86389
- file: path108,
86651
+ file: path110,
86390
86652
  signals: [
86391
86653
  `runs on ${keys.map((k) => safeText(k, 40)).join(", ")}: no stranger starts it`,
86392
86654
  ...reads.map((r) => `the agent ${r}`),
@@ -86474,17 +86736,17 @@ function requiresTrustedAuthor(src) {
86474
86736
  };
86475
86737
  return req(x);
86476
86738
  }
86477
- function analyzeForkCodeOnTrust(path108, content, callers, autoLabels, trustedRunSources) {
86739
+ function analyzeForkCodeOnTrust(path110, content, callers, autoLabels, trustedRunSources) {
86478
86740
  AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
86479
86741
  TRUSTED_RUN_SOURCES = trustedRunSources ?? /* @__PURE__ */ new Set();
86480
86742
  try {
86481
- return analyzeForkCodeOnTrustInner(path108, content, callers);
86743
+ return analyzeForkCodeOnTrustInner(path110, content, callers);
86482
86744
  } finally {
86483
86745
  AUTO_LABELS = /* @__PURE__ */ new Set();
86484
86746
  TRUSTED_RUN_SOURCES = /* @__PURE__ */ new Set();
86485
86747
  }
86486
86748
  }
86487
- function analyzeForkCodeOnTrustInner(path108, content, callers) {
86749
+ function analyzeForkCodeOnTrustInner(path110, content, callers) {
86488
86750
  let raw;
86489
86751
  try {
86490
86752
  raw = loadWorkflow(content).raw;
@@ -86523,7 +86785,7 @@ function analyzeForkCodeOnTrustInner(path108, content, callers) {
86523
86785
  dimension: "workflows",
86524
86786
  severity: "advisory",
86525
86787
  title: "A maintainer's action runs the agent inside the fork's code",
86526
- file: path108,
86788
+ file: path110,
86527
86789
  signals: [
86528
86790
  `triggered by ${forkKeys.map((k) => safeText(k, 40)).join(", ")}, behind a gate a maintainer passes (a comment, a label, a push to the PR branch, a reopen)`,
86529
86791
  "checks out the untrusted PR head into the workspace root",
@@ -86555,18 +86817,18 @@ function laterSecrets(wf, job, from) {
86555
86817
  if (!/^GITHUB_TOKEN$/i.test(m[1])) out.add(m[1]);
86556
86818
  return [...out];
86557
86819
  }
86558
- function analyzeAgentOutputToEnv(path108, content, callers, autoLabels, trustedRunSources) {
86820
+ function analyzeAgentOutputToEnv(path110, content, callers, autoLabels, trustedRunSources) {
86559
86821
  AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
86560
86822
  TRUSTED_RUN_SOURCES = trustedRunSources ?? /* @__PURE__ */ new Set();
86561
86823
  try {
86562
- return analyzeAgentOutputToEnvInner(path108, content, callers);
86824
+ return analyzeAgentOutputToEnvInner(path110, content, callers);
86563
86825
  } finally {
86564
86826
  AUTO_LABELS = /* @__PURE__ */ new Set();
86565
86827
  TRUSTED_RUN_SOURCES = /* @__PURE__ */ new Set();
86566
86828
  UPSTREAM_TRUSTED = false;
86567
86829
  }
86568
86830
  }
86569
- function analyzeAgentOutputToEnvInner(path108, content, callers) {
86831
+ function analyzeAgentOutputToEnvInner(path110, content, callers) {
86570
86832
  let raw;
86571
86833
  try {
86572
86834
  raw = loadWorkflow(content).raw;
@@ -86662,7 +86924,7 @@ function analyzeAgentOutputToEnvInner(path108, content, callers) {
86662
86924
  dimension: "workflows",
86663
86925
  severity,
86664
86926
  title: sink.target === "GITHUB_PATH" ? "The agent's output is added to the job's PATH" : "The agent's output is written into the job's environment",
86665
- file: path108,
86927
+ file: path110,
86666
86928
  signals,
86667
86929
  fix: `Write the agent's result to a file and read it with a strict parser in the next step (a fixed set of values, or a number); never append free text from the agent to \`${target}\`. If a value must go there, strip newlines (\`tr -d '\\n'\`) and write it under a fixed name, or use a delimiter generated at run time.`,
86668
86930
  explain: explainAgentOutputEnv({
@@ -86690,7 +86952,7 @@ function analyzeAgentOutputToEnvInner(path108, content, callers) {
86690
86952
 
86691
86953
  // src/ci-check/agent-config.ts
86692
86954
  init_cjs_shims();
86693
- var import_path90 = __toESM(require("path"));
86955
+ var import_path92 = __toESM(require("path"));
86694
86956
  function asStrings(v) {
86695
86957
  return Array.isArray(v) ? v.filter((x) => typeof x === "string") : [];
86696
86958
  }
@@ -86798,7 +87060,7 @@ function hookScriptPath(cmd) {
86798
87060
  if (/^(https?:|\$|-)/.test(t)) continue;
86799
87061
  t = t.replace(/^\.\//, "");
86800
87062
  if (!SCRIPT_EXT_RE.test(t) && !/(^|\/)\.claude\/hooks\//.test(t)) continue;
86801
- const norm = import_path90.default.posix.normalize(t);
87063
+ const norm = import_path92.default.posix.normalize(t);
86802
87064
  if (norm.startsWith("..") || norm.startsWith("/") || norm.includes("/../")) return null;
86803
87065
  return norm;
86804
87066
  }
@@ -86808,7 +87070,7 @@ function cmdLine(content, cmd) {
86808
87070
  const i = jsonValueIndex(content, cmd);
86809
87071
  return i >= 0 ? lineAtIndex(content, i) : void 0;
86810
87072
  }
86811
- function analyzeAgentConfig(path108, content, tree) {
87073
+ function analyzeAgentConfig(path110, content, tree) {
86812
87074
  let cfg;
86813
87075
  try {
86814
87076
  cfg = JSON.parse(content);
@@ -86831,7 +87093,7 @@ function analyzeAgentConfig(path108, content, tree) {
86831
87093
  dimension: "toolRules",
86832
87094
  severity: high ? "high" : "medium",
86833
87095
  title: high ? "Agent hook runs UNPINNED/remote third-party code on every action" : "Agent hook runs third-party code in the agent hot path",
86834
- file: path108,
87096
+ file: path110,
86835
87097
  ...cmdLine(content, cmd) ? { line: cmdLine(content, cmd) } : {},
86836
87098
  signals: [
86837
87099
  `hook command: \`${safeText(cmd, 120)}\``,
@@ -86852,7 +87114,7 @@ function analyzeAgentConfig(path108, content, tree) {
86852
87114
  dimension: "toolRules",
86853
87115
  severity: "medium",
86854
87116
  title: "Agent hook runs a script that is not committed",
86855
- file: path108,
87117
+ file: path110,
86856
87118
  ...cmdLine(content, cmd) ? { line: cmdLine(content, cmd) } : {},
86857
87119
  signals: [
86858
87120
  `hook command: \`${safeText(cmd, 120)}\``,
@@ -86868,7 +87130,7 @@ function analyzeAgentConfig(path108, content, tree) {
86868
87130
  dimension: "toolRules",
86869
87131
  severity: "advisory",
86870
87132
  title: "Agent hook runs a committed script this scan did not read",
86871
- file: path108,
87133
+ file: path110,
86872
87134
  ...cmdLine(content, cmd) ? { line: cmdLine(content, cmd) } : {},
86873
87135
  signals: [
86874
87136
  `hook command: \`${safeText(cmd, 120)}\``,
@@ -86897,12 +87159,12 @@ function analyzeAgentConfig(path108, content, tree) {
86897
87159
  dimension: "toolRules",
86898
87160
  severity: high ? "high" : "medium",
86899
87161
  title: high ? "Committed agent config pre-authorizes broad tools with no deny backstop" : "Committed agent config pre-authorizes broad tools",
86900
- file: path108,
87162
+ file: path110,
86901
87163
  signals,
86902
87164
  fix: "Scope the allow-list to specific read-only subcommands (e.g. `Bash(gh pr view:*)`); avoid bare `Bash`/`git:`/`Write`, or add a `deny` backstop.",
86903
87165
  explain: explainGrant({
86904
87166
  high,
86905
- file: path108,
87167
+ file: path110,
86906
87168
  broad: grade.broad,
86907
87169
  bareShell: grade.bareShell,
86908
87170
  hasBackstop: grade.bareShell ? deny.some((d) => /^Bash\b/.test(d)) : deny.some((d) => /Bash|Write|Edit/.test(d))
@@ -86919,7 +87181,7 @@ function analyzeAgentConfig(path108, content, tree) {
86919
87181
  dimension: "toolRules",
86920
87182
  severity: "medium",
86921
87183
  title: "Committed agent config pre-approves a command that can run other programs",
86922
- file: path108,
87184
+ file: path110,
86923
87185
  signals: [
86924
87186
  `pre-approved: ${escapes.slice(0, 5).map((e) => `\`${safeText(e, 80)}\``).join(", ")}`,
86925
87187
  "`find -exec` and `make -n --eval` run other programs without a prompt"
@@ -86934,8 +87196,8 @@ var ROOT_SURFACE_RE = /^\.(claude|agents|github|codex|cursor|gemini)\//;
86934
87196
  var ITEM_TEXT_RE = /gh\s+(?:pr|issue)\s+(?:view|diff|list)\b|gh\s+pr\s+checkout\b|git\s+fetch\s+[^\n]{0,80}\bpull\/|gh\s+api\s+graphql\b|gh\s+api\s+[^\n]{0,120}\/(?:pulls|issues)\b|mcp__github__(?:get_issue|get_pull_request|list_issues|search_issues)|--json\s+[^\n]{0,120}\b(?:body|title)\b/;
86935
87197
  var PR_TEXT_RE = /gh\s+pr\s+(?:view|diff)\b|gh\s+api\s+[^\n]{0,120}\/pulls\b/;
86936
87198
  var WEB_TEXT_RE = /\bsearch the web\b|\bfetch (?:the )?(?:url|page)\b/i;
86937
- function skillReadsUntrusted(path108, content, allow, broad) {
86938
- if (!ROOT_SURFACE_RE.test(path108)) return null;
87199
+ function skillReadsUntrusted(path110, content, allow, broad) {
87200
+ if (!ROOT_SURFACE_RE.test(path110)) return null;
86939
87201
  const body = content.replace(/^---[\s\S]*?\n---/, "");
86940
87202
  const runsCode = broad.map((a) => a.replace(/^PowerShell(?=$|\()/, "Bash")).some((a) => /^Bash$|^Bash\(\s*\*/.test(a) || openRunner(a) && !/^Bash\(\s*gh\b/.test(a));
86941
87203
  const webGrant = allow.some((a) => /^(WebFetch|WebSearch)\b/.test(a));
@@ -86950,8 +87212,8 @@ function skillReadsUntrusted(path108, content, allow, broad) {
86950
87212
  return "it reads pull request text that strangers write, and may edit files and run git/gh on it";
86951
87213
  return null;
86952
87214
  }
86953
- function analyzeSkillGrants(path108, content) {
86954
- if (!GRANT_CARRIER_RE.test(path108)) return [];
87215
+ function analyzeSkillGrants(path110, content) {
87216
+ if (!GRANT_CARRIER_RE.test(path110)) return [];
86955
87217
  const allow = allowedToolsOf(parseFrontmatter(content));
86956
87218
  if (allow.length === 0) return [];
86957
87219
  const grade = gradeBroadGrant(allow, [], {
@@ -86959,9 +87221,9 @@ function analyzeSkillGrants(path108, content) {
86959
87221
  scope: "whenever this skill or command is active, for everyone who opens this repo with the agent"
86960
87222
  });
86961
87223
  if (!grade) return [];
86962
- const kind = /commands\//.test(path108) ? "slash command" : "skill";
87224
+ const kind = /commands\//.test(path110) ? "slash command" : "skill";
86963
87225
  const at = content.search(/^allowed-tools\s*:/m);
86964
- const untrusted = skillReadsUntrusted(path108, content, allow, grade.broad);
87226
+ const untrusted = skillReadsUntrusted(path110, content, allow, grade.broad);
86965
87227
  if (untrusted)
86966
87228
  return [
86967
87229
  {
@@ -86971,7 +87233,7 @@ function analyzeSkillGrants(path108, content) {
86971
87233
  dimension: "toolRules",
86972
87234
  severity: "advisory",
86973
87235
  title: `Committed ${kind} runs code or writes with text strangers control`,
86974
- file: path108,
87236
+ file: path110,
86975
87237
  signals: [...grade.signals, untrusted],
86976
87238
  fix: "Drop the shell or interpreter grant from a skill that reads PRs, issues or the web, or have it treat that text as data in a read-only step first."
86977
87239
  }
@@ -86988,7 +87250,7 @@ function analyzeSkillGrants(path108, content) {
86988
87250
  // shell — the cap is on reach, not on honesty.
86989
87251
  severity: "medium",
86990
87252
  title: grade.high ? `Committed ${kind} pre-authorizes an unrestricted shell while active` : `Committed ${kind} pre-authorizes broad tools while active`,
86991
- file: path108,
87253
+ file: path110,
86992
87254
  signals: grade.signals,
86993
87255
  fix: "Scope `allowed-tools` to the specific commands the skill needs (e.g. `Bash(git status:*)`); avoid a bare `Bash`, `Write` or `Edit`."
86994
87256
  }
@@ -87120,7 +87382,7 @@ function ownPackageNames(manifests) {
87120
87382
  }
87121
87383
  return out;
87122
87384
  }
87123
- function analyzeMcp(path108, content, own = /* @__PURE__ */ new Set()) {
87385
+ function analyzeMcp(path110, content, own = /* @__PURE__ */ new Set()) {
87124
87386
  let cfg;
87125
87387
  try {
87126
87388
  cfg = JSON.parse(content);
@@ -87156,9 +87418,9 @@ function analyzeMcp(path108, content, own = /* @__PURE__ */ new Set()) {
87156
87418
  const key = (count.get(name) ?? 0) > 1 ? `${section}.${name}` : name;
87157
87419
  servers[key] = { ...spec, anchor: name };
87158
87420
  }
87159
- return analyzeMcpServers(servers, path108, content, own);
87421
+ return analyzeMcpServers(servers, path110, content, own);
87160
87422
  }
87161
- function analyzeMcpServers(servers, path108, content = "", own = /* @__PURE__ */ new Set()) {
87423
+ function analyzeMcpServers(servers, path110, content = "", own = /* @__PURE__ */ new Set()) {
87162
87424
  const findings = [];
87163
87425
  for (const [name, srv] of Object.entries(servers ?? {})) {
87164
87426
  if (!srv || srv.disabled) continue;
@@ -87177,7 +87439,7 @@ function analyzeMcpServers(servers, path108, content = "", own = /* @__PURE__ */
87177
87439
  dimension: "mcp",
87178
87440
  severity: "medium",
87179
87441
  title: `MCP server "${name}" runs an unpinned executable`,
87180
- file: path108,
87442
+ file: path110,
87181
87443
  ...line ? { line } : {},
87182
87444
  signals: [
87183
87445
  why.launcher === "npx" ? `\`${safeText(argv, 120)}\`: unversioned/@latest npx` : `\`${safeText(argv, 120)}\`: unversioned/latest ${why.launcher}`
@@ -87202,7 +87464,7 @@ function analyzeMcpServers(servers, path108, content = "", own = /* @__PURE__ */
87202
87464
  dimension: "mcp",
87203
87465
  severity: "high",
87204
87466
  title: `MCP server "${name}" has an inline credential`,
87205
- file: path108,
87467
+ file: path110,
87206
87468
  ...line ? { line } : {},
87207
87469
  signals: [
87208
87470
  `env.${k} matches ${hit.patternName}: agent-reachable secret committed to the repo`
@@ -87218,7 +87480,7 @@ function analyzeMcpServers(servers, path108, content = "", own = /* @__PURE__ */
87218
87480
  // src/ci-check/codex.ts
87219
87481
  init_cjs_shims();
87220
87482
  var import_smol_toml7 = require("smol-toml");
87221
- function analyzeCodexConfig(path108, content, own = /* @__PURE__ */ new Set()) {
87483
+ function analyzeCodexConfig(path110, content, own = /* @__PURE__ */ new Set()) {
87222
87484
  let cfg;
87223
87485
  try {
87224
87486
  cfg = (0, import_smol_toml7.parse)(content);
@@ -87226,7 +87488,7 @@ function analyzeCodexConfig(path108, content, own = /* @__PURE__ */ new Set()) {
87226
87488
  return [];
87227
87489
  }
87228
87490
  const findings = [];
87229
- findings.push(...analyzeMcpServers(cfg.mcp_servers ?? {}, path108, content, own));
87491
+ findings.push(...analyzeMcpServers(cfg.mcp_servers ?? {}, path110, content, own));
87230
87492
  const sandbox = typeof cfg.sandbox_mode === "string" ? cfg.sandbox_mode : "";
87231
87493
  const approval = typeof cfg.approval_policy === "string" ? cfg.approval_policy : "";
87232
87494
  const fullAccess = /danger-full-access/i.test(sandbox);
@@ -87249,7 +87511,7 @@ function analyzeCodexConfig(path108, content, own = /* @__PURE__ */ new Set()) {
87249
87511
  dimension: "toolRules",
87250
87512
  severity: fullAccess ? "high" : "medium",
87251
87513
  title: fullAccess ? "Codex config grants a full-access sandbox" : "Codex config never requires approval",
87252
- file: path108,
87514
+ file: path110,
87253
87515
  signals,
87254
87516
  fix: 'Commit a least-privilege Codex config: prefer `sandbox_mode = "read-only"` (or `"workspace-write"`) and `approval_policy = "on-request"`/`"on-failure"`. A repo-committed config applies to every contributor who runs Codex here.'
87255
87517
  });
@@ -87303,7 +87565,7 @@ function reviewQuestion(rule) {
87303
87565
  return "Is this an instruction the agent follows, or text for a person?";
87304
87566
  }
87305
87567
  var RANK2 = { critical: 4, high: 3, medium: 2, advisory: 1 };
87306
- var worstRank = (fs109) => Math.max(...fs109.map((f) => RANK2[f.severity] ?? 0));
87568
+ var worstRank = (fs111) => Math.max(...fs111.map((f) => RANK2[f.severity] ?? 0));
87307
87569
  var fileOrder = (a, b) => worstRank(b[1]) - worstRank(a[1]) || b[1].length - a[1].length;
87308
87570
  function groupReview(findings) {
87309
87571
  const byFile = /* @__PURE__ */ new Map();
@@ -87368,7 +87630,7 @@ function logicalLines2(content) {
87368
87630
  }
87369
87631
  return out;
87370
87632
  }
87371
- function analyzeScript(path108, content, rulePrefix) {
87633
+ function analyzeScript(path110, content, rulePrefix) {
87372
87634
  const check = rulePrefix.startsWith("CI-1") ? "CI-1" : "CI-6";
87373
87635
  const dimension = check === "CI-1" ? "toolRules" : "instructions";
87374
87636
  const mk3 = (suffix, severity, title, signal, fix, line) => ({
@@ -87377,7 +87639,7 @@ function analyzeScript(path108, content, rulePrefix) {
87377
87639
  dimension,
87378
87640
  severity,
87379
87641
  title,
87380
- file: path108,
87642
+ file: path110,
87381
87643
  ...line ? { line } : {},
87382
87644
  signals: [signal],
87383
87645
  fix
@@ -87803,7 +88065,7 @@ async function scanRepo(input, onProgress) {
87803
88065
  // src/ci-check/render.ts
87804
88066
  init_cjs_shims();
87805
88067
  var import_chalk36 = __toESM(require("chalk"));
87806
- var listed = (fs109) => fs109.filter((f) => f.tier !== "review");
88068
+ var listed = (fs111) => fs111.filter((f) => f.tier !== "review");
87807
88069
  function excerpt(f) {
87808
88070
  const m = /`([^`]+)`/.exec(f.signals[0] ?? "");
87809
88071
  return safeText(m ? m[1] : f.title, 120).replace(/`/g, "'");
@@ -87819,14 +88081,14 @@ function reviewMd(findings) {
87819
88081
  L.push("");
87820
88082
  const files = [...byFile.keys()];
87821
88083
  for (const file2 of files.slice(0, REVIEW_FILES)) {
87822
- const fs109 = byFile.get(file2);
88084
+ const fs111 = byFile.get(file2);
87823
88085
  L.push(`- \`${safeText(file2, 300)}\``);
87824
- for (const f of fs109.slice(0, REVIEW_LINES_PER_FILE))
88086
+ for (const f of fs111.slice(0, REVIEW_LINES_PER_FILE))
87825
88087
  L.push(
87826
88088
  ` - ${f.line ? `line ${Number(f.line)}: ` : ""}\`${excerpt(f)}\`. Check: ${reviewQuestion(f.rule)}`
87827
88089
  );
87828
- if (fs109.length > REVIEW_LINES_PER_FILE)
87829
- L.push(` - and ${fs109.length - REVIEW_LINES_PER_FILE} similar lines in this file`);
88090
+ if (fs111.length > REVIEW_LINES_PER_FILE)
88091
+ L.push(` - and ${fs111.length - REVIEW_LINES_PER_FILE} similar lines in this file`);
87830
88092
  }
87831
88093
  const more = files.length - REVIEW_FILES;
87832
88094
  if (more > 0) L.push(`- and ${more} more file${more === 1 ? "" : "s"}`);
@@ -87842,7 +88104,7 @@ function reviewMd(findings) {
87842
88104
  }
87843
88105
  function reviewTerminal(findings) {
87844
88106
  const { byFile, grants } = groupReview(findings);
87845
- const items = [...byFile.values()].reduce((a, fs109) => a + fs109.length, 0);
88107
+ const items = [...byFile.values()].reduce((a, fs111) => a + fs111.length, 0);
87846
88108
  if (!items && !grants) return [];
87847
88109
  const L = [];
87848
88110
  if (items) {
@@ -87851,12 +88113,12 @@ function reviewTerminal(findings) {
87851
88113
  );
87852
88114
  const files = [...byFile.keys()];
87853
88115
  for (const file2 of files.slice(0, REVIEW_FILES)) {
87854
- const fs109 = byFile.get(file2);
88116
+ const fs111 = byFile.get(file2);
87855
88117
  L.push(import_chalk36.default.gray(` ${file2}`));
87856
- for (const f of fs109.slice(0, REVIEW_LINES_PER_FILE))
88118
+ for (const f of fs111.slice(0, REVIEW_LINES_PER_FILE))
87857
88119
  L.push(` \u2022 ${f.line ? `line ${f.line}: ` : ""}${excerpt(f)}`);
87858
- if (fs109.length > REVIEW_LINES_PER_FILE)
87859
- L.push(import_chalk36.default.gray(` and ${fs109.length - REVIEW_LINES_PER_FILE} similar lines`));
88120
+ if (fs111.length > REVIEW_LINES_PER_FILE)
88121
+ L.push(import_chalk36.default.gray(` and ${fs111.length - REVIEW_LINES_PER_FILE} similar lines`));
87860
88122
  }
87861
88123
  const more = files.length - REVIEW_FILES;
87862
88124
  if (more > 0) L.push(import_chalk36.default.gray(` and ${more} more file${more === 1 ? "" : "s"}`));
@@ -87870,7 +88132,7 @@ function reviewTerminal(findings) {
87870
88132
  L.push("");
87871
88133
  return L;
87872
88134
  }
87873
- var ICON2 = {
88135
+ var ICON3 = {
87874
88136
  critical: "\u{1F534}",
87875
88137
  high: "\u{1F534}",
87876
88138
  medium: "\u{1F7E1}",
@@ -87930,7 +88192,7 @@ function mdLine(v) {
87930
88192
  function findingMd(f, L) {
87931
88193
  const ex = f.explain;
87932
88194
  L.push(
87933
- `**${ICON2[f.severity]} ${f.severity.toUpperCase()}: ${mdLine(ex ? ex.headline : f.title)}**` + (f.suppressed ? ` _(suppressed: \`${safeText(f.suppressed.reason, 200)}\`)_` : "")
88195
+ `**${ICON3[f.severity]} ${f.severity.toUpperCase()}: ${mdLine(ex ? ex.headline : f.title)}**` + (f.suppressed ? ` _(suppressed: \`${safeText(f.suppressed.reason, 200)}\`)_` : "")
87934
88196
  );
87935
88197
  L.push(`\`${safeText(f.file, 300)}${f.line ? ":" + Number(f.line) : ""}\` \xB7 ${f.rule}`);
87936
88198
  L.push("");
@@ -87986,7 +88248,7 @@ function renderScan(res, diff) {
87986
88248
  for (const f of shown) {
87987
88249
  const ex = f.explain;
87988
88250
  L.push(
87989
- `${ICON2[f.severity]} ${COLOR[f.severity](f.severity.toUpperCase())} ${import_chalk36.default.bold(ex ? ex.headline : f.title)}`
88251
+ `${ICON3[f.severity]} ${COLOR[f.severity](f.severity.toUpperCase())} ${import_chalk36.default.bold(ex ? ex.headline : f.title)}`
87990
88252
  );
87991
88253
  L.push(import_chalk36.default.gray(` ${f.file}${f.line ? ":" + f.line : ""} \xB7 ${f.check}`));
87992
88254
  if (ex) {
@@ -88508,16 +88770,16 @@ var import_chalk40 = __toESM(require("chalk"));
88508
88770
 
88509
88771
  // src/canary/plant.ts
88510
88772
  init_cjs_shims();
88511
- var import_fs93 = __toESM(require("fs"));
88512
- var import_os76 = __toESM(require("os"));
88513
- var import_path92 = __toESM(require("path"));
88773
+ var import_fs95 = __toESM(require("fs"));
88774
+ var import_os77 = __toESM(require("os"));
88775
+ var import_path94 = __toESM(require("path"));
88514
88776
  init_jail();
88515
88777
  init_registry2();
88516
88778
 
88517
88779
  // src/canary/sites.ts
88518
88780
  init_cjs_shims();
88519
- var import_fs92 = __toESM(require("fs"));
88520
- var import_path91 = __toESM(require("path"));
88781
+ var import_fs94 = __toESM(require("fs"));
88782
+ var import_path93 = __toESM(require("path"));
88521
88783
 
88522
88784
  // src/canary/generate.ts
88523
88785
  init_cjs_shims();
@@ -88612,26 +88874,26 @@ function generateSshKey() {
88612
88874
  var SITES = {
88613
88875
  "aws-profile": {
88614
88876
  kind: "aws-profile",
88615
- primary: (h) => import_path91.default.join(h, ".aws", "credentials"),
88616
- fallback: (h) => import_path91.default.join(h, ".aws", "credentials.bak"),
88877
+ primary: (h) => import_path93.default.join(h, ".aws", "credentials"),
88878
+ fallback: (h) => import_path93.default.join(h, ".aws", "credentials.bak"),
88617
88879
  // SSO / profile-only / credential_process setups have ~/.aws/config and no
88618
88880
  // credentials file; the SDK and CLI then parse ~/.aws/credentials on every
88619
88881
  // profile lookup. A planted primary would be a file real tools read.
88620
- preferFallback: (h) => import_fs92.default.existsSync(import_path91.default.join(h, ".aws", "config")),
88882
+ preferFallback: (h) => import_fs94.default.existsSync(import_path93.default.join(h, ".aws", "config")),
88621
88883
  dirMode: 448,
88622
88884
  generate: generateAwsProfile
88623
88885
  },
88624
88886
  "env-file": {
88625
88887
  kind: "env-file",
88626
- primary: (h) => import_path91.default.join(h, ".env.bak"),
88627
- fallback: (h) => import_path91.default.join(h, ".env.local.bak"),
88888
+ primary: (h) => import_path93.default.join(h, ".env.bak"),
88889
+ fallback: (h) => import_path93.default.join(h, ".env.local.bak"),
88628
88890
  dirMode: 493,
88629
88891
  generate: generateEnvFile
88630
88892
  },
88631
88893
  "ssh-key": {
88632
88894
  kind: "ssh-key",
88633
- primary: (h) => import_path91.default.join(h, ".ssh", "id_rsa_backup"),
88634
- fallback: (h) => import_path91.default.join(h, ".ssh", "id_rsa.old"),
88895
+ primary: (h) => import_path93.default.join(h, ".ssh", "id_rsa_backup"),
88896
+ fallback: (h) => import_path93.default.join(h, ".ssh", "id_rsa.old"),
88635
88897
  // ssh refuses a group-writable ~/.ssh for config / known_hosts reads.
88636
88898
  dirMode: 448,
88637
88899
  generate: generateSshKey
@@ -88644,12 +88906,12 @@ var isKind = (s) => ALL_KINDS.includes(s);
88644
88906
  var liveRecords = (kind) => loadCanaries().filter((r) => r.kind === kind && !r.retiredAt);
88645
88907
  var fileHashOf = (p) => {
88646
88908
  try {
88647
- return sha256Hex(import_fs93.default.readFileSync(p));
88909
+ return sha256Hex(import_fs95.default.readFileSync(p));
88648
88910
  } catch {
88649
88911
  return null;
88650
88912
  }
88651
88913
  };
88652
- function plantKind(kind, home = import_os76.default.homedir()) {
88914
+ function plantKind(kind, home = import_os77.default.homedir()) {
88653
88915
  const site = SITES[kind];
88654
88916
  const live = liveRecords(kind);
88655
88917
  if (live.length > 0) {
@@ -88668,8 +88930,8 @@ function plantKind(kind, home = import_os76.default.homedir()) {
88668
88930
  const primary = site.primary(home);
88669
88931
  const fallback = site.fallback(home);
88670
88932
  let target;
88671
- if (!import_fs93.default.existsSync(primary) && !site.preferFallback?.(home)) target = primary;
88672
- else if (!import_fs93.default.existsSync(fallback)) target = fallback;
88933
+ if (!import_fs95.default.existsSync(primary) && !site.preferFallback?.(home)) target = primary;
88934
+ else if (!import_fs95.default.existsSync(fallback)) target = fallback;
88673
88935
  else {
88674
88936
  return {
88675
88937
  kind,
@@ -88680,11 +88942,11 @@ function plantKind(kind, home = import_os76.default.homedir()) {
88680
88942
  recordIds: []
88681
88943
  };
88682
88944
  }
88683
- const dir2 = import_path92.default.dirname(target);
88945
+ const dir2 = import_path94.default.dirname(target);
88684
88946
  const gen = site.generate();
88685
- const createdDir = import_fs93.default.mkdirSync(dir2, { recursive: true, mode: site.dirMode }) !== void 0;
88686
- import_fs93.default.writeFileSync(target, gen.text, { mode: 384, flag: "wx" });
88687
- import_fs93.default.chmodSync(target, 384);
88947
+ const createdDir = import_fs95.default.mkdirSync(dir2, { recursive: true, mode: site.dirMode }) !== void 0;
88948
+ import_fs95.default.writeFileSync(target, gen.text, { mode: 384, flag: "wx" });
88949
+ import_fs95.default.chmodSync(target, 384);
88688
88950
  const fileHash = sha256Hex(gen.text);
88689
88951
  regenerateUserJail(addJailPath(target, "block"));
88690
88952
  const recordIds = gen.values.map(
@@ -88702,14 +88964,14 @@ function plantKind(kind, home = import_os76.default.homedir()) {
88702
88964
  }
88703
88965
  function allowedPathsFor(kind, home) {
88704
88966
  const site = SITES[kind];
88705
- return [site.primary(home), site.fallback(home)].map((x) => import_path92.default.resolve(x));
88967
+ return [site.primary(home), site.fallback(home)].map((x) => import_path94.default.resolve(x));
88706
88968
  }
88707
- function removeKind(kind, home = import_os76.default.homedir()) {
88969
+ function removeKind(kind, home = import_os77.default.homedir()) {
88708
88970
  const live = liveRecords(kind);
88709
88971
  if (live.length === 0) return { kind, action: "absent" };
88710
88972
  const p = live[0].path;
88711
88973
  const { fileHash, createdDir } = live[0];
88712
- if (!allowedPathsFor(kind, home).includes(import_path92.default.resolve(p))) {
88974
+ if (!allowedPathsFor(kind, home).includes(import_path94.default.resolve(p))) {
88713
88975
  return {
88714
88976
  kind,
88715
88977
  action: "refused",
@@ -88717,7 +88979,7 @@ function removeKind(kind, home = import_os76.default.homedir()) {
88717
88979
  reason: `${p} is not a path node9 plants a ${kind} decoy at; refusing to delete it. If you believe this is a decoy, remove it by hand.`
88718
88980
  };
88719
88981
  }
88720
- if (!import_fs93.default.existsSync(p)) {
88982
+ if (!import_fs95.default.existsSync(p)) {
88721
88983
  for (const r of live) retireCanary(r.id);
88722
88984
  unjail(p);
88723
88985
  return { kind, action: "already-gone", path: p };
@@ -88730,13 +88992,13 @@ function removeKind(kind, home = import_os76.default.homedir()) {
88730
88992
  reason: `${p} changed since node9 wrote it; inspect and remove it by hand`
88731
88993
  };
88732
88994
  }
88733
- import_fs93.default.unlinkSync(p);
88995
+ import_fs95.default.unlinkSync(p);
88734
88996
  let dirRemoved = false;
88735
88997
  if (createdDir) {
88736
- const dir2 = import_path92.default.dirname(p);
88998
+ const dir2 = import_path94.default.dirname(p);
88737
88999
  try {
88738
- if (import_fs93.default.readdirSync(dir2).length === 0) {
88739
- import_fs93.default.rmdirSync(dir2);
89000
+ if (import_fs95.default.readdirSync(dir2).length === 0) {
89001
+ import_fs95.default.rmdirSync(dir2);
88740
89002
  dirRemoved = true;
88741
89003
  }
88742
89004
  } catch {
@@ -88760,14 +89022,14 @@ function statusAll() {
88760
89022
  const p = live[0].path;
88761
89023
  return {
88762
89024
  kind,
88763
- state: import_fs93.default.existsSync(p) ? "planted" : "missing",
89025
+ state: import_fs95.default.existsSync(p) ? "planted" : "missing",
88764
89026
  path: p,
88765
89027
  records: live.length,
88766
89028
  plantedAt: live[0].plantedAt
88767
89029
  };
88768
89030
  });
88769
89031
  }
88770
- function rotateKind(kind, home = import_os76.default.homedir()) {
89032
+ function rotateKind(kind, home = import_os77.default.homedir()) {
88771
89033
  const removed = removeKind(kind);
88772
89034
  if (removed.action === "refused") return { removed };
88773
89035
  return { removed, planted: plantKind(kind, home) };
@@ -88856,15 +89118,15 @@ init_daemon3();
88856
89118
  // src/cli/commands/sandbox.ts
88857
89119
  init_cjs_shims();
88858
89120
  var import_chalk41 = __toESM(require("chalk"));
88859
- var import_fs96 = __toESM(require("fs"));
88860
- var import_path95 = __toESM(require("path"));
89121
+ var import_fs98 = __toESM(require("fs"));
89122
+ var import_path97 = __toESM(require("path"));
88861
89123
  var import_child_process16 = require("child_process");
88862
89124
  init_config();
88863
89125
 
88864
89126
  // src/sandbox/config.ts
88865
89127
  init_cjs_shims();
88866
- var import_fs94 = __toESM(require("fs"));
88867
- var import_path93 = __toESM(require("path"));
89128
+ var import_fs96 = __toESM(require("fs"));
89129
+ var import_path95 = __toESM(require("path"));
88868
89130
  var import_yaml2 = require("yaml");
88869
89131
  var SANDBOX_CONFIG_FILE = "node9.sandbox.yaml";
88870
89132
  var FORBIDDEN_ENV = /* @__PURE__ */ new Set(["NODE9_API_KEY", "NODE9_API_URL"]);
@@ -88937,16 +89199,16 @@ function scaffoldSandboxYaml(agent) {
88937
89199
  return header + (0, import_yaml2.stringify)(defaultSandboxConfig(agent));
88938
89200
  }
88939
89201
  function sandboxConfigPath(cwd = process.cwd()) {
88940
- return import_path93.default.join(cwd, SANDBOX_CONFIG_FILE);
89202
+ return import_path95.default.join(cwd, SANDBOX_CONFIG_FILE);
88941
89203
  }
88942
89204
  function loadSandboxConfig(cwd = process.cwd(), fallbackAgent = "claude") {
88943
89205
  const p = sandboxConfigPath(cwd);
88944
- if (!import_fs94.default.existsSync(p)) {
89206
+ if (!import_fs96.default.existsSync(p)) {
88945
89207
  throw new Error(`sandbox: ${SANDBOX_CONFIG_FILE} not found \u2014 run \`node9 sandbox new\` first.`);
88946
89208
  }
88947
89209
  let raw;
88948
89210
  try {
88949
- raw = (0, import_yaml2.parse)(import_fs94.default.readFileSync(p, "utf-8"));
89211
+ raw = (0, import_yaml2.parse)(import_fs96.default.readFileSync(p, "utf-8"));
88950
89212
  } catch (err2) {
88951
89213
  throw new Error(
88952
89214
  `sandbox: ${SANDBOX_CONFIG_FILE} is not valid YAML \u2014 ${err2.message}`
@@ -89007,14 +89269,14 @@ init_atomic_write();
89007
89269
 
89008
89270
  // src/sandbox/runtime.ts
89009
89271
  init_cjs_shims();
89010
- var import_fs95 = __toESM(require("fs"));
89011
- var import_os77 = __toESM(require("os"));
89012
- var import_path94 = __toESM(require("path"));
89272
+ var import_fs97 = __toESM(require("fs"));
89273
+ var import_os78 = __toESM(require("os"));
89274
+ var import_path96 = __toESM(require("path"));
89013
89275
  var import_crypto26 = __toESM(require("crypto"));
89014
89276
  var import_child_process15 = require("child_process");
89015
89277
  init_templates();
89016
89278
  function sandboxDataDir(cwd = process.cwd()) {
89017
- return import_path94.default.join(cwd, ".node9", "sandbox", "data");
89279
+ return import_path96.default.join(cwd, ".node9", "sandbox", "data");
89018
89280
  }
89019
89281
  function detectEngine(engine) {
89020
89282
  const r = (0, import_child_process15.spawnSync)(engine, ["--version"], { encoding: "utf-8" });
@@ -89025,7 +89287,7 @@ function detectEngine(engine) {
89025
89287
  }
89026
89288
  function agentCredentialsMount(agent) {
89027
89289
  const rel = agent === "codex" ? ".codex/auth.json" : ".claude/.credentials.json";
89028
- return { hostPath: import_path94.default.join(import_os77.default.homedir(), rel), target: `/home/${RUN_AS_USER}/${rel}` };
89290
+ return { hostPath: import_path96.default.join(import_os78.default.homedir(), rel), target: `/home/${RUN_AS_USER}/${rel}` };
89029
89291
  }
89030
89292
  function buildRunArgs(opts) {
89031
89293
  const { config, workspaceHostPath, dataHostPath, allowlistHostPath, agentArgs } = opts;
@@ -89035,7 +89297,7 @@ function buildRunArgs(opts) {
89035
89297
  args.push("-v", `${allowlistHostPath}:${ALLOWED_DOMAINS_PATH}:ro`);
89036
89298
  if (config.node9.mountAgentCredentials) {
89037
89299
  const creds = agentCredentialsMount(config.agent);
89038
- if (import_fs95.default.existsSync(creds.hostPath)) {
89300
+ if (import_fs97.default.existsSync(creds.hostPath)) {
89039
89301
  args.push("-v", `${creds.hostPath}:${creds.target}`);
89040
89302
  }
89041
89303
  }
@@ -89053,30 +89315,30 @@ function imageContentHash(dockerfile, entrypoint) {
89053
89315
  return import_crypto26.default.createHash("sha256").update(dockerfile).update("\0").update(entrypoint).digest("hex").slice(0, 16);
89054
89316
  }
89055
89317
  function sandboxBuildDir(cwd = process.cwd()) {
89056
- return import_path94.default.join(cwd, ".node9", "sandbox", "build");
89318
+ return import_path96.default.join(cwd, ".node9", "sandbox", "build");
89057
89319
  }
89058
89320
  function writeBuildContext(cwd, dockerfile, entrypoint) {
89059
89321
  const dir2 = sandboxBuildDir(cwd);
89060
- import_fs95.default.mkdirSync(dir2, { recursive: true });
89061
- import_fs95.default.writeFileSync(import_path94.default.join(dir2, "Dockerfile"), dockerfile);
89062
- import_fs95.default.writeFileSync(import_path94.default.join(dir2, "entrypoint.sh"), entrypoint);
89322
+ import_fs97.default.mkdirSync(dir2, { recursive: true });
89323
+ import_fs97.default.writeFileSync(import_path96.default.join(dir2, "Dockerfile"), dockerfile);
89324
+ import_fs97.default.writeFileSync(import_path96.default.join(dir2, "entrypoint.sh"), entrypoint);
89063
89325
  return dir2;
89064
89326
  }
89065
89327
  function writeAllowlist(cwd, hosts) {
89066
- const dir2 = import_path94.default.join(cwd, ".node9", "sandbox");
89067
- import_fs95.default.mkdirSync(dir2, { recursive: true });
89068
- const p = import_path94.default.join(dir2, "allowed-domains.txt");
89069
- import_fs95.default.writeFileSync(p, hosts.join("\n") + "\n");
89328
+ const dir2 = import_path96.default.join(cwd, ".node9", "sandbox");
89329
+ import_fs97.default.mkdirSync(dir2, { recursive: true });
89330
+ const p = import_path96.default.join(dir2, "allowed-domains.txt");
89331
+ import_fs97.default.writeFileSync(p, hosts.join("\n") + "\n");
89070
89332
  return p;
89071
89333
  }
89072
89334
  function resolveHomePath(p) {
89073
- return p.startsWith("~") ? import_path94.default.join(import_os77.default.homedir(), p.slice(1)) : import_path94.default.resolve(p);
89335
+ return p.startsWith("~") ? import_path96.default.join(import_os78.default.homedir(), p.slice(1)) : import_path96.default.resolve(p);
89074
89336
  }
89075
89337
 
89076
89338
  // src/cli/commands/sandbox.ts
89077
89339
  function seedDataDirConfig(dataDir, sandbox) {
89078
- import_fs96.default.mkdirSync(dataDir, { recursive: true });
89079
- const configPath2 = import_path95.default.join(dataDir, "config.json");
89340
+ import_fs98.default.mkdirSync(dataDir, { recursive: true });
89341
+ const configPath2 = import_path97.default.join(dataDir, "config.json");
89080
89342
  const seed = {
89081
89343
  settings: {
89082
89344
  approvers: {
@@ -89087,7 +89349,7 @@ function seedDataDirConfig(dataDir, sandbox) {
89087
89349
  }
89088
89350
  }
89089
89351
  };
89090
- import_fs96.default.writeFileSync(configPath2, JSON.stringify(seed, null, 2), { mode: 384 });
89352
+ import_fs98.default.writeFileSync(configPath2, JSON.stringify(seed, null, 2), { mode: 384 });
89091
89353
  }
89092
89354
  function registerSandboxCommand(program2, version2) {
89093
89355
  const node9Version2 = pinnedNode9Version(version2);
@@ -89096,7 +89358,7 @@ function registerSandboxCommand(program2, version2) {
89096
89358
  const agent = opts.agent === "codex" ? "codex" : "claude";
89097
89359
  const p = sandboxConfigPath();
89098
89360
  try {
89099
- import_fs96.default.writeFileSync(p, scaffoldSandboxYaml(agent), { flag: "wx" });
89361
+ import_fs98.default.writeFileSync(p, scaffoldSandboxYaml(agent), { flag: "wx" });
89100
89362
  } catch (e) {
89101
89363
  if (e.code !== "EEXIST") throw e;
89102
89364
  console.log(
@@ -89143,8 +89405,8 @@ function registerSandboxCommand(program2, version2) {
89143
89405
  const buildDir = writeBuildContext(cwd, dockerfile, entrypoint);
89144
89406
  const hash2 = imageContentHash(dockerfile, entrypoint);
89145
89407
  const image = sandbox.runtime.image;
89146
- const hashFile = import_path95.default.join(sandboxBuildDir(cwd), ".image-hash");
89147
- const lastHash = import_fs96.default.existsSync(hashFile) ? import_fs96.default.readFileSync(hashFile, "utf-8").trim() : "";
89408
+ const hashFile = import_path97.default.join(sandboxBuildDir(cwd), ".image-hash");
89409
+ const lastHash = import_fs98.default.existsSync(hashFile) ? import_fs98.default.readFileSync(hashFile, "utf-8").trim() : "";
89148
89410
  const imageExists = (0, import_child_process16.spawnSync)(sandbox.runtime.engine, ["image", "inspect", image], { stdio: "ignore" }).status === 0;
89149
89411
  const needBuild = sandbox.runtime.rebuild === "always" || !imageExists || sandbox.runtime.rebuild !== "never" && lastHash !== hash2;
89150
89412
  if (needBuild) {
@@ -89170,7 +89432,7 @@ function registerSandboxCommand(program2, version2) {
89170
89432
  });
89171
89433
  if (sandbox.node9.mountAgentCredentials) {
89172
89434
  const creds = agentCredentialsMount(sandbox.agent);
89173
- if (import_fs96.default.existsSync(creds.hostPath)) {
89435
+ if (import_fs98.default.existsSync(creds.hostPath)) {
89174
89436
  console.log(import_chalk41.default.dim(` mounting ${creds.hostPath} (agent credentials, rw)`));
89175
89437
  } else {
89176
89438
  console.log(
@@ -89186,20 +89448,20 @@ function registerSandboxCommand(program2, version2) {
89186
89448
  process.exit(r.status ?? 0);
89187
89449
  });
89188
89450
  cmd.command("tail").description("Stream the sandbox's audit log (host-side)").action(() => {
89189
- const auditPath = import_path95.default.join(sandboxDataDir(), "audit.log");
89190
- if (!import_fs96.default.existsSync(auditPath)) {
89451
+ const auditPath = import_path97.default.join(sandboxDataDir(), "audit.log");
89452
+ if (!import_fs98.default.existsSync(auditPath)) {
89191
89453
  console.log(import_chalk41.default.dim(" no sandbox audit yet."));
89192
89454
  return;
89193
89455
  }
89194
89456
  (0, import_child_process16.spawnSync)("tail", ["-f", auditPath], { stdio: "inherit" });
89195
89457
  });
89196
89458
  cmd.command("logs").description("Dump the sandbox's audit log").action(() => {
89197
- const auditPath = import_path95.default.join(sandboxDataDir(), "audit.log");
89198
- if (!import_fs96.default.existsSync(auditPath)) {
89459
+ const auditPath = import_path97.default.join(sandboxDataDir(), "audit.log");
89460
+ if (!import_fs98.default.existsSync(auditPath)) {
89199
89461
  console.log(import_chalk41.default.dim(" no sandbox audit yet."));
89200
89462
  return;
89201
89463
  }
89202
- process.stdout.write(import_fs96.default.readFileSync(auditPath, "utf-8"));
89464
+ process.stdout.write(import_fs98.default.readFileSync(auditPath, "utf-8"));
89203
89465
  });
89204
89466
  cmd.command("clean").description("Remove the sandbox image, build context, and data").action(() => {
89205
89467
  const cwd = process.cwd();
@@ -89213,7 +89475,7 @@ function registerSandboxCommand(program2, version2) {
89213
89475
  stdio: "ignore"
89214
89476
  });
89215
89477
  }
89216
- import_fs96.default.rmSync(import_path95.default.join(cwd, ".node9", "sandbox"), { recursive: true, force: true });
89478
+ import_fs98.default.rmSync(import_path97.default.join(cwd, ".node9", "sandbox"), { recursive: true, force: true });
89217
89479
  console.log(import_chalk41.default.green(" \u2713 sandbox image + build + data removed."));
89218
89480
  });
89219
89481
  }
@@ -89442,12 +89704,12 @@ function registerPackageIndexCommand(program2) {
89442
89704
  // src/cli/commands/skill-pin.ts
89443
89705
  init_cjs_shims();
89444
89706
  var import_chalk45 = __toESM(require("chalk"));
89445
- var import_fs97 = __toESM(require("fs"));
89446
- var import_os78 = __toESM(require("os"));
89447
- var import_path96 = __toESM(require("path"));
89707
+ var import_fs99 = __toESM(require("fs"));
89708
+ var import_os79 = __toESM(require("os"));
89709
+ var import_path98 = __toESM(require("path"));
89448
89710
  function wipeSkillSessions() {
89449
89711
  try {
89450
- import_fs97.default.rmSync(import_path96.default.join(import_os78.default.homedir(), ".node9", "skill-sessions"), {
89712
+ import_fs99.default.rmSync(import_path98.default.join(import_os79.default.homedir(), ".node9", "skill-sessions"), {
89451
89713
  recursive: true,
89452
89714
  force: true
89453
89715
  });
@@ -89530,15 +89792,15 @@ function registerSkillPinCommand(program2) {
89530
89792
 
89531
89793
  // src/cli/commands/decisions.ts
89532
89794
  init_cjs_shims();
89533
- var import_fs98 = __toESM(require("fs"));
89534
- var import_os79 = __toESM(require("os"));
89535
- var import_path97 = __toESM(require("path"));
89795
+ var import_fs100 = __toESM(require("fs"));
89796
+ var import_os80 = __toESM(require("os"));
89797
+ var import_path99 = __toESM(require("path"));
89536
89798
  var import_chalk46 = __toESM(require("chalk"));
89537
- var DECISIONS_FILE2 = import_path97.default.join(import_os79.default.homedir(), ".node9", "decisions.json");
89799
+ var DECISIONS_FILE2 = import_path99.default.join(import_os80.default.homedir(), ".node9", "decisions.json");
89538
89800
  function readDecisions() {
89539
89801
  try {
89540
- if (!import_fs98.default.existsSync(DECISIONS_FILE2)) return {};
89541
- const raw = import_fs98.default.readFileSync(DECISIONS_FILE2, "utf-8");
89802
+ if (!import_fs100.default.existsSync(DECISIONS_FILE2)) return {};
89803
+ const raw = import_fs100.default.readFileSync(DECISIONS_FILE2, "utf-8");
89542
89804
  const parsed = JSON.parse(raw);
89543
89805
  const out = {};
89544
89806
  for (const [k, v] of Object.entries(parsed)) {
@@ -89550,11 +89812,11 @@ function readDecisions() {
89550
89812
  }
89551
89813
  }
89552
89814
  function writeDecisions(d) {
89553
- const dir2 = import_path97.default.dirname(DECISIONS_FILE2);
89554
- if (!import_fs98.default.existsSync(dir2)) import_fs98.default.mkdirSync(dir2, { recursive: true });
89815
+ const dir2 = import_path99.default.dirname(DECISIONS_FILE2);
89816
+ if (!import_fs100.default.existsSync(dir2)) import_fs100.default.mkdirSync(dir2, { recursive: true });
89555
89817
  const tmp = `${DECISIONS_FILE2}.${process.pid}.tmp`;
89556
- import_fs98.default.writeFileSync(tmp, JSON.stringify(d, null, 2));
89557
- import_fs98.default.renameSync(tmp, DECISIONS_FILE2);
89818
+ import_fs100.default.writeFileSync(tmp, JSON.stringify(d, null, 2));
89819
+ import_fs100.default.renameSync(tmp, DECISIONS_FILE2);
89558
89820
  }
89559
89821
  function registerDecisionsCommand(program2) {
89560
89822
  const cmd = program2.command("decisions").description('Manage persistent "Always Allow" / "Always Deny" tool decisions');
@@ -89612,15 +89874,15 @@ Persistent decisions (${entries.length})
89612
89874
  // src/cli/commands/dlp.ts
89613
89875
  init_cjs_shims();
89614
89876
  var import_chalk47 = __toESM(require("chalk"));
89615
- var import_fs99 = __toESM(require("fs"));
89616
- var import_path98 = __toESM(require("path"));
89617
- var import_os80 = __toESM(require("os"));
89877
+ var import_fs101 = __toESM(require("fs"));
89878
+ var import_path100 = __toESM(require("path"));
89879
+ var import_os81 = __toESM(require("os"));
89618
89880
  init_safe_text();
89619
- var AUDIT_LOG = import_path98.default.join(import_os80.default.homedir(), ".node9", "audit.log");
89620
- var RESOLVED_FILE = import_path98.default.join(import_os80.default.homedir(), ".node9", "dlp-resolved.json");
89881
+ var AUDIT_LOG = import_path100.default.join(import_os81.default.homedir(), ".node9", "audit.log");
89882
+ var RESOLVED_FILE = import_path100.default.join(import_os81.default.homedir(), ".node9", "dlp-resolved.json");
89621
89883
  function loadResolved() {
89622
89884
  try {
89623
- const raw = JSON.parse(import_fs99.default.readFileSync(RESOLVED_FILE, "utf-8"));
89885
+ const raw = JSON.parse(import_fs101.default.readFileSync(RESOLVED_FILE, "utf-8"));
89624
89886
  return new Set(raw);
89625
89887
  } catch {
89626
89888
  return /* @__PURE__ */ new Set();
@@ -89628,13 +89890,13 @@ function loadResolved() {
89628
89890
  }
89629
89891
  function saveResolved(resolved) {
89630
89892
  try {
89631
- import_fs99.default.writeFileSync(RESOLVED_FILE, JSON.stringify([...resolved], null, 2), { mode: 384 });
89893
+ import_fs101.default.writeFileSync(RESOLVED_FILE, JSON.stringify([...resolved], null, 2), { mode: 384 });
89632
89894
  } catch {
89633
89895
  }
89634
89896
  }
89635
89897
  function loadDlpFindings() {
89636
- if (!import_fs99.default.existsSync(AUDIT_LOG)) return [];
89637
- return import_fs99.default.readFileSync(AUDIT_LOG, "utf-8").split("\n").flatMap((line) => {
89898
+ if (!import_fs101.default.existsSync(AUDIT_LOG)) return [];
89899
+ return import_fs101.default.readFileSync(AUDIT_LOG, "utf-8").split("\n").flatMap((line) => {
89638
89900
  if (!line.trim()) return [];
89639
89901
  try {
89640
89902
  const e = JSON.parse(line);
@@ -89733,15 +89995,15 @@ function registerDlpCommand(program2) {
89733
89995
  // src/cli/commands/mask.ts
89734
89996
  init_cjs_shims();
89735
89997
  var import_chalk48 = __toESM(require("chalk"));
89736
- var import_fs100 = __toESM(require("fs"));
89737
- var import_path99 = __toESM(require("path"));
89738
- var import_os81 = __toESM(require("os"));
89998
+ var import_fs102 = __toESM(require("fs"));
89999
+ var import_path101 = __toESM(require("path"));
90000
+ var import_os82 = __toESM(require("os"));
89739
90001
  init_dlp();
89740
90002
  function findJsonlFiles(dir2) {
89741
90003
  const results = [];
89742
- if (!import_fs100.default.existsSync(dir2)) return results;
89743
- for (const entry of import_fs100.default.readdirSync(dir2, { withFileTypes: true })) {
89744
- const full = import_path99.default.join(dir2, entry.name);
90004
+ if (!import_fs102.default.existsSync(dir2)) return results;
90005
+ for (const entry of import_fs102.default.readdirSync(dir2, { withFileTypes: true })) {
90006
+ const full = import_path101.default.join(dir2, entry.name);
89745
90007
  if (entry.isDirectory()) results.push(...findJsonlFiles(full));
89746
90008
  else if (entry.isFile() && entry.name.endsWith(".jsonl")) results.push(full);
89747
90009
  }
@@ -89784,7 +90046,7 @@ function redactJson(obj) {
89784
90046
  function processFile(filePath, dryRun) {
89785
90047
  let raw;
89786
90048
  try {
89787
- raw = import_fs100.default.readFileSync(filePath, "utf-8");
90049
+ raw = import_fs102.default.readFileSync(filePath, "utf-8");
89788
90050
  } catch {
89789
90051
  return { redactedLines: 0, patterns: [] };
89790
90052
  }
@@ -89816,14 +90078,14 @@ function processFile(filePath, dryRun) {
89816
90078
  }
89817
90079
  }
89818
90080
  if (!dryRun && redactedLines > 0) {
89819
- import_fs100.default.writeFileSync(filePath, newLines.join("\n"), "utf-8");
90081
+ import_fs102.default.writeFileSync(filePath, newLines.join("\n"), "utf-8");
89820
90082
  }
89821
90083
  return { redactedLines, patterns };
89822
90084
  }
89823
90085
  function processJsonFile(filePath, dryRun) {
89824
90086
  let raw;
89825
90087
  try {
89826
- raw = import_fs100.default.readFileSync(filePath, "utf-8");
90088
+ raw = import_fs102.default.readFileSync(filePath, "utf-8");
89827
90089
  } catch {
89828
90090
  return { redactedLines: 0, patterns: [] };
89829
90091
  }
@@ -89836,15 +90098,15 @@ function processJsonFile(filePath, dryRun) {
89836
90098
  const { value, modified, found } = redactJson(parsed);
89837
90099
  if (!modified) return { redactedLines: 0, patterns: [] };
89838
90100
  if (!dryRun) {
89839
- import_fs100.default.writeFileSync(filePath, JSON.stringify(value, null, 2), "utf-8");
90101
+ import_fs102.default.writeFileSync(filePath, JSON.stringify(value, null, 2), "utf-8");
89840
90102
  }
89841
90103
  return { redactedLines: 1, patterns: found };
89842
90104
  }
89843
90105
  function findJsonFiles(dir2) {
89844
90106
  const results = [];
89845
- if (!import_fs100.default.existsSync(dir2)) return results;
89846
- for (const entry of import_fs100.default.readdirSync(dir2, { withFileTypes: true })) {
89847
- const full = import_path99.default.join(dir2, entry.name);
90107
+ if (!import_fs102.default.existsSync(dir2)) return results;
90108
+ for (const entry of import_fs102.default.readdirSync(dir2, { withFileTypes: true })) {
90109
+ const full = import_path101.default.join(dir2, entry.name);
89848
90110
  if (entry.isDirectory()) results.push(...findJsonFiles(full));
89849
90111
  else if (entry.isFile() && entry.name.endsWith(".json")) results.push(full);
89850
90112
  }
@@ -89853,9 +90115,9 @@ function findJsonFiles(dir2) {
89853
90115
  function registerMaskCommand(program2) {
89854
90116
  program2.command("mask").description("Redact plaintext secrets from local AI session history files").option("--dry-run", "show what would be redacted without making changes").option("--all", "scan all history (default: last 30 days)").action(async (options) => {
89855
90117
  const dryRun = !!options.dryRun;
89856
- const home = import_os81.default.homedir();
89857
- const claudeDir = import_path99.default.join(home, ".claude", "projects");
89858
- const geminiDir = import_path99.default.join(home, ".gemini", "tmp");
90118
+ const home = import_os82.default.homedir();
90119
+ const claudeDir = import_path101.default.join(home, ".claude", "projects");
90120
+ const geminiDir = import_path101.default.join(home, ".gemini", "tmp");
89859
90121
  const allFiles = [
89860
90122
  ...findJsonlFiles(claudeDir).map((p) => ({ path: p, type: "jsonl" })),
89861
90123
  ...findJsonFiles(geminiDir).map((p) => ({ path: p, type: "json" }))
@@ -89863,7 +90125,7 @@ function registerMaskCommand(program2) {
89863
90125
  const cutoff = options.all ? null : new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3);
89864
90126
  const filtered = cutoff ? allFiles.filter((f) => {
89865
90127
  try {
89866
- return import_fs100.default.statSync(f.path).mtime >= cutoff;
90128
+ return import_fs102.default.statSync(f.path).mtime >= cutoff;
89867
90129
  } catch {
89868
90130
  return false;
89869
90131
  }
@@ -89920,7 +90182,7 @@ function registerMaskCommand(program2) {
89920
90182
  init_blast();
89921
90183
  init_safe_text();
89922
90184
  var { version } = JSON.parse(
89923
- import_fs104.default.readFileSync(import_path103.default.join(__dirname, "../package.json"), "utf-8")
90185
+ import_fs106.default.readFileSync(import_path105.default.join(__dirname, "../package.json"), "utf-8")
89924
90186
  );
89925
90187
  var program = new import_commander.Command();
89926
90188
  program.name("node9").description("The Sudo Command for AI Agents").version(version);
@@ -90078,8 +90340,8 @@ function undoLeftoverNote() {
90078
90340
  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) => {
90079
90341
  console.log(import_chalk50.default.cyan("\n\u{1F6E1}\uFE0F Node9 Uninstall\n"));
90080
90342
  try {
90081
- const credRaw = import_fs104.default.readFileSync(
90082
- import_path103.default.join(import_os85.default.homedir(), ".node9", "credentials.json"),
90343
+ const credRaw = import_fs106.default.readFileSync(
90344
+ import_path105.default.join(import_os86.default.homedir(), ".node9", "credentials.json"),
90083
90345
  "utf-8"
90084
90346
  );
90085
90347
  const prof = JSON.parse(credRaw)[process.env.NODE9_PROFILE || "default"];
@@ -90154,7 +90416,7 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
90154
90416
  if (removed.length > 0 || refused.length > 0) {
90155
90417
  console.log(import_chalk50.default.bold("\nRemoving decoy credentials..."));
90156
90418
  for (const r of removed) {
90157
- if (r.path) console.log(import_chalk50.default.green(` \u2705 ${r.path.replace(import_os85.default.homedir(), "~")}`));
90419
+ if (r.path) console.log(import_chalk50.default.green(` \u2705 ${r.path.replace(import_os86.default.homedir(), "~")}`));
90158
90420
  }
90159
90421
  for (const r of refused) {
90160
90422
  decoysLeft.push(r.path ?? "(unknown path)");
@@ -90171,8 +90433,8 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
90171
90433
  decoysLeft = ["(the decoy registry could not be read)"];
90172
90434
  }
90173
90435
  if (options.purge) {
90174
- const node9Dir = import_path103.default.join(import_os85.default.homedir(), ".node9");
90175
- if (import_fs104.default.existsSync(node9Dir)) {
90436
+ const node9Dir = import_path105.default.join(import_os86.default.homedir(), ".node9");
90437
+ if (import_fs106.default.existsSync(node9Dir)) {
90176
90438
  const alsoSnapshots = undoLeftoverPaths().length > 0 ? ", old undo snapshots" : "";
90177
90439
  if (decoysLeft.length > 0) {
90178
90440
  console.error(import_chalk50.default.red("\n \u26A0\uFE0F Decoy credential files are still on disk:"));
@@ -90188,8 +90450,8 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
90188
90450
  default: false
90189
90451
  });
90190
90452
  if (confirmed) {
90191
- import_fs104.default.rmSync(node9Dir, { recursive: true });
90192
- if (import_fs104.default.existsSync(node9Dir)) {
90453
+ import_fs106.default.rmSync(node9Dir, { recursive: true });
90454
+ if (import_fs106.default.existsSync(node9Dir)) {
90193
90455
  console.error(
90194
90456
  import_chalk50.default.red("\n \u26A0\uFE0F ~/.node9/ could not be fully deleted \u2014 remove it manually.")
90195
90457
  );
@@ -90345,7 +90607,7 @@ program.command("tail").description("Stream live agent activity to the terminal"
90345
90607
  });
90346
90608
  program.command("monitor").description("Live interactive dashboard \u2014 activity feed, approvals, security signals").action(async () => {
90347
90609
  try {
90348
- const dashboardPath = import_path103.default.join(__dirname, "dashboard.mjs");
90610
+ const dashboardPath = import_path105.default.join(__dirname, "dashboard.mjs");
90349
90611
  const dynamicImport = new Function("id", "return import(id)");
90350
90612
  const mod = await dynamicImport(`file://${dashboardPath}`);
90351
90613
  await mod.startMonitor();
@@ -90383,14 +90645,14 @@ Claude Code spawns this command every ~300ms and writes a JSON payload to stdin.
90383
90645
  Run "node9 addto claude" to register it as the statusLine.`
90384
90646
  ).argument("[subcommand]", 'Optional: "debug on" / "debug off" to toggle stdin logging').argument("[state]", 'on|off \u2014 used with "debug" subcommand').action(async (subcommand, state) => {
90385
90647
  if (subcommand === "debug") {
90386
- const flagFile = import_path103.default.join(import_os85.default.homedir(), ".node9", "hud-debug");
90648
+ const flagFile = import_path105.default.join(import_os86.default.homedir(), ".node9", "hud-debug");
90387
90649
  if (state === "on") {
90388
- import_fs104.default.mkdirSync(import_path103.default.dirname(flagFile), { recursive: true });
90389
- import_fs104.default.writeFileSync(flagFile, "");
90650
+ import_fs106.default.mkdirSync(import_path105.default.dirname(flagFile), { recursive: true });
90651
+ import_fs106.default.writeFileSync(flagFile, "");
90390
90652
  console.log("HUD debug logging enabled \u2192 ~/.node9/hud-debug.log");
90391
90653
  console.log("Tail it with: tail -f ~/.node9/hud-debug.log");
90392
90654
  } else if (state === "off") {
90393
- if (import_fs104.default.existsSync(flagFile)) import_fs104.default.unlinkSync(flagFile);
90655
+ if (import_fs106.default.existsSync(flagFile)) import_fs106.default.unlinkSync(flagFile);
90394
90656
  console.log("HUD debug logging disabled.");
90395
90657
  } else {
90396
90658
  console.error("Usage: node9 hud debug on|off");
@@ -90524,9 +90786,9 @@ if (process.argv[2] !== "daemon") {
90524
90786
  const isCheckHook = process.argv[2] === "check";
90525
90787
  if (isCheckHook) {
90526
90788
  if (process.env.NODE9_DEBUG === "1" || getConfig().settings.enableHookLogDebug) {
90527
- const logPath = import_path103.default.join(import_os85.default.homedir(), ".node9", "hook-debug.log");
90789
+ const logPath = import_path105.default.join(import_os86.default.homedir(), ".node9", "hook-debug.log");
90528
90790
  const msg = reason instanceof Error ? reason.message : String(reason);
90529
- import_fs104.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] UNHANDLED: ${msg}
90791
+ import_fs106.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] UNHANDLED: ${msg}
90530
90792
  `);
90531
90793
  }
90532
90794
  process.exit(0);