@node9/proxy 2.47.2 → 2.48.1

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)) {
@@ -26723,6 +26723,70 @@ var init_loop_detector = __esm({
26723
26723
  });
26724
26724
 
26725
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
+ }
26726
26790
  function buildNegotiationMessage(blockedByLabel, isHumanDecision2, humanReason, recoveryCommand, context) {
26727
26791
  if (isHumanDecision2 && context?.redirect && humanReason) {
26728
26792
  return `NODE9: The user stopped this action and gave you an instruction.
@@ -26732,88 +26796,138 @@ INSTRUCTIONS:
26732
26796
  - Retry the original action only if the instruction says you may.`;
26733
26797
  }
26734
26798
  if (isHumanDecision2) {
26735
- 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.
26736
26802
  REASON: ${humanReason || "No specific reason provided."}
26737
26803
  INSTRUCTIONS:
26738
26804
  - Do NOT retry this exact command.
26739
26805
  - Acknowledge the block to the user and ask if there is an alternative approach.
26740
- - 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
+ );
26741
26808
  }
26742
26809
  if (context?.kind === "protected-path") {
26743
26810
  const subject = context.path ? `${context.path} is a protected file` : "This file is protected";
26744
- 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.
26745
26816
  INSTRUCTIONS:
26746
26817
  - Do NOT retry, and do NOT reach the file another way (cat, grep, a copy, a script, a redirect).
26747
26818
  - If this step needs that file, ask the user to provide what you need or to do the step themselves.
26748
- - 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
+ );
26749
26821
  }
26750
26822
  const label3 = blockedByLabel.toLowerCase();
26751
26823
  if (label3.includes("dlp") || label3.includes("secret detected") || label3.includes("credential review")) {
26752
- 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.
26753
26827
  CRITICAL INSTRUCTION: Do NOT retry this action.
26754
26828
  REQUIRED ACTIONS:
26755
26829
  1. Remove the hardcoded credential from your command or code.
26756
26830
  2. Use an environment variable or a dedicated secrets manager instead.
26757
26831
  3. Treat the leaked credential as compromised and rotate it immediately.
26758
26832
  Do NOT attempt to bypass this check or pass the credential through another tool.
26759
- - 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
+ );
26760
26835
  }
26761
26836
  if (label3.includes("package check")) {
26762
- 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."}
26763
26841
  INSTRUCTIONS:
26764
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).
26765
26843
  - If a dependency is needed, suggest a well-known alternative and let the user choose.
26766
- - 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
+ );
26767
26846
  }
26768
26847
  if (label3.includes("sql safety") && label3.includes("delete without where")) {
26769
- 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.
26770
26851
  INSTRUCTION: Add a WHERE clause to scope the deletion (e.g. WHERE id = <value>).
26771
26852
  Do NOT retry without a WHERE clause.
26772
- - 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
+ );
26773
26855
  }
26774
26856
  if (label3.includes("sql safety") && label3.includes("update without where")) {
26775
- 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.
26776
26860
  INSTRUCTION: Add a WHERE clause to scope the update (e.g. WHERE id = <value>).
26777
26861
  Do NOT retry without a WHERE clause.
26778
- - 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
+ );
26779
26864
  }
26780
26865
  if (label3.includes("dangerous word")) {
26781
26866
  const match = blockedByLabel.match(/dangerous word: "([^"]+)"/i);
26782
26867
  const word = match?.[1] ?? "a dangerous keyword";
26783
- 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}".
26784
26871
  INSTRUCTION: Do NOT use "${word}". Use a non-destructive alternative.
26785
26872
  Do NOT attempt to bypass this with shell tricks or aliases \u2014 it will be blocked again.
26786
- - 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
+ );
26787
26875
  }
26788
26876
  if (label3.includes("path blocked") || label3.includes("sandbox")) {
26789
- 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.
26790
26880
  INSTRUCTION: Move your output to an allowed directory such as /tmp/ or the project directory.
26791
26881
  Do NOT retry on the same path.
26792
- - 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
+ );
26793
26884
  }
26794
26885
  if (label3.includes("inline execution")) {
26795
- 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.
26796
26889
  INSTRUCTION: Use individual tool calls instead of embedding code in a shell string.
26797
- - 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
+ );
26798
26892
  }
26799
26893
  if (label3.includes("strict mode")) {
26800
- return `NODE9: Blocked \u2014 the Block all level is on. All tool calls require explicit human approval.
26801
- 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
+ );
26802
26899
  }
26803
26900
  if (label3.includes("rule") && label3.includes("default block")) {
26804
26901
  const match = blockedByLabel.match(/rule "([^"]+)"/i);
26805
- const rule = match?.[1] ?? "a policy rule";
26806
- return `NODE9: Blocked \u2014 action "${rule}" is forbidden by security policy.
26807
- 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.
26808
26907
  Do NOT attempt to bypass this rule.
26809
- - 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))})`;
26810
26921
  }
26811
26922
  const recovery = recoveryCommand ? `
26812
26923
  REQUIRED ACTION: Run \`${recoveryCommand}\` first, then retry your original command.` : "\n- Pivot to a non-destructive or read-only alternative.";
26813
- return `NODE9: Action blocked by security policy [${agentFacingLabel(blockedByLabel)}].
26924
+ return withUserLine(
26925
+ line,
26926
+ `NODE9: Action blocked by security policy [${agentFacingLabel(blockedByLabel)}].
26814
26927
  INSTRUCTIONS:
26815
26928
  - Do NOT retry this exact command or attempt to bypass the rule.${recovery}
26816
- - 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
+ );
26817
26931
  }
26818
26932
  function buildReviewMessage(blockedByLabel, ruleDescription, reason) {
26819
26933
  const why = ruleDescription || (reason && reason !== blockedByLabel ? reason : void 0) || blockedByLabel || "this action needs your review";
@@ -26828,7 +26942,7 @@ function isHumanDecision(label3, blockedBy, decidedBy) {
26828
26942
  return l.includes("user") || l.includes("daemon") || l.includes("decision");
26829
26943
  }
26830
26944
  function agentFacingLabel(label3) {
26831
- 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();
26832
26946
  return plain || "Security Policy";
26833
26947
  }
26834
26948
  function asApprovalRequest(description) {
@@ -26844,11 +26958,20 @@ function asApprovalRequest(description) {
26844
26958
  }
26845
26959
  return description;
26846
26960
  }
26847
- 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;
26848
26962
  var init_negotiation = __esm({
26849
26963
  "src/policy/negotiation.ts"() {
26850
26964
  "use strict";
26851
26965
  init_cjs_shims();
26966
+ init_dist();
26967
+ USER_LINE_ICON = "\u{1F6E1}\uFE0F";
26968
+ QUOTE_INSTRUCTION = "Start your reply about this blocked action with the line above, exactly as written, on its own line. Leave it out of later replies.";
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;
26852
26975
  BLOCKED_BY = " is blocked by ";
26853
26976
  DASH_BLOCKED_BY = " \u2014 blocked by ";
26854
26977
  SHIELD = " shield";
@@ -45916,21 +46039,21 @@ function patchConfig(configPath2, patch) {
45916
46039
  throw err2;
45917
46040
  }
45918
46041
  }
45919
- var import_path84, import_os71, GLOBAL_CONFIG_PATH;
46042
+ var import_path86, import_os72, GLOBAL_CONFIG_PATH;
45920
46043
  var init_patch = __esm({
45921
46044
  "src/config/patch.ts"() {
45922
46045
  "use strict";
45923
46046
  init_cjs_shims();
45924
- import_path84 = __toESM(require("path"));
45925
- import_os71 = __toESM(require("os"));
46047
+ import_path86 = __toESM(require("path"));
46048
+ import_os72 = __toESM(require("os"));
45926
46049
  init_write();
45927
- 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");
45928
46051
  }
45929
46052
  });
45930
46053
 
45931
46054
  // src/auth/egress-config.ts
45932
46055
  function egressConfigPath() {
45933
- 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");
45934
46057
  }
45935
46058
  function readEgressRawConfig() {
45936
46059
  return readConfigFileLegacy(egressConfigPath());
@@ -45990,14 +46113,14 @@ function normalizeEgressHost(host2) {
45990
46113
  function isValidEgressHost(host2) {
45991
46114
  return EGRESS_HOST_RE.test(host2);
45992
46115
  }
45993
- var import_os72, import_path85, DEFAULT_EGRESS, EGRESS_HOST_RE;
46116
+ var import_os73, import_path87, DEFAULT_EGRESS, EGRESS_HOST_RE;
45994
46117
  var init_egress_config = __esm({
45995
46118
  "src/auth/egress-config.ts"() {
45996
46119
  "use strict";
45997
46120
  init_cjs_shims();
45998
46121
  init_write();
45999
- import_os72 = __toESM(require("os"));
46000
- import_path85 = __toESM(require("path"));
46122
+ import_os73 = __toESM(require("os"));
46123
+ import_path87 = __toESM(require("path"));
46001
46124
  init_dist();
46002
46125
  DEFAULT_EGRESS = {
46003
46126
  enabled: false,
@@ -46025,27 +46148,27 @@ __export(local_setup_exports, {
46025
46148
  runLocalSetup: () => runLocalSetup
46026
46149
  });
46027
46150
  function configPath() {
46028
- 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");
46029
46152
  }
46030
46153
  function combined(values) {
46031
46154
  return values.every(Boolean) ? "on" : values.some(Boolean) ? "partial" : "off";
46032
46155
  }
46033
46156
  function readLocalState(opts = {}) {
46034
46157
  const file2 = configPath();
46035
- if (import_fs86.default.existsSync(file2) && !opts.replaceConfig) {
46158
+ if (import_fs88.default.existsSync(file2) && !opts.replaceConfig) {
46036
46159
  let raw;
46037
46160
  try {
46038
- raw = JSON.parse(import_fs86.default.readFileSync(file2, "utf8"));
46161
+ raw = JSON.parse(import_fs88.default.readFileSync(file2, "utf8"));
46039
46162
  } catch {
46040
46163
  raw = void 0;
46041
46164
  }
46042
46165
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) throw invalidConfig();
46043
46166
  }
46044
- 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"));
46045
46168
  const active = readActiveShields();
46046
46169
  const installed = isDaemonServiceInstalled();
46047
46170
  return {
46048
- fresh: !import_fs86.default.existsSync(file2),
46171
+ fresh: !import_fs88.default.existsSync(file2),
46049
46172
  managed: config.policySource === "workspace",
46050
46173
  shields: combined(DEFAULT_SHIELDS.map((s) => active.includes(s))),
46051
46174
  dlp: combined([config.policy.dlp.enabled, config.policy.dlp.pii !== "off"]),
@@ -46093,7 +46216,7 @@ function diffChoices(state, selected, partial = {}) {
46093
46216
  }
46094
46217
  function setAutostart(enabled) {
46095
46218
  const file2 = configPath();
46096
- const raw = JSON.parse(import_fs86.default.readFileSync(file2, "utf8"));
46219
+ const raw = JSON.parse(import_fs88.default.readFileSync(file2, "utf8"));
46097
46220
  if (raw.settings?.autoStartDaemon === enabled) return;
46098
46221
  raw.settings = { ...raw.settings, autoStartDaemon: enabled };
46099
46222
  atomicWriteSync(file2, JSON.stringify(raw, null, 2) + "\n", { mode: 384 });
@@ -46260,14 +46383,14 @@ async function runLocalSetup(opts) {
46260
46383
  if (interactive && !state.managed && !opts.skipSetup) await askTelemetry(agents, firstInstall);
46261
46384
  return collectSummary(applied);
46262
46385
  }
46263
- var import_fs86, import_os73, import_path86, DEFAULT_SHIELDS;
46386
+ var import_fs88, import_os74, import_path88, DEFAULT_SHIELDS;
46264
46387
  var init_local_setup = __esm({
46265
46388
  "src/cli/local-setup.ts"() {
46266
46389
  "use strict";
46267
46390
  init_cjs_shims();
46268
- import_fs86 = __toESM(require("fs"));
46269
- import_os73 = __toESM(require("os"));
46270
- import_path86 = __toESM(require("path"));
46391
+ import_fs88 = __toESM(require("fs"));
46392
+ import_os74 = __toESM(require("os"));
46393
+ import_path88 = __toESM(require("path"));
46271
46394
  init_config();
46272
46395
  init_patch();
46273
46396
  init_keyed_guard();
@@ -46330,8 +46453,8 @@ async function askTelemetry(agents, firstInstall) {
46330
46453
  }
46331
46454
  }
46332
46455
  function ensureConfig(mode, force = false) {
46333
- const file2 = import_path87.default.join(import_os74.default.homedir(), ".node9", "config.json");
46334
- 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);
46335
46458
  if (firstInstall || force) {
46336
46459
  const body = legacyToV2(
46337
46460
  mode !== void 0 && mode !== DEFAULT_CONFIG.settings.mode ? { settings: { mode } } : {}
@@ -46383,16 +46506,16 @@ function registerInitCommand(program2) {
46383
46506
  }
46384
46507
  );
46385
46508
  }
46386
- var import_fs87, import_path87, import_os74, import_https6, TELEMETRY_PROMPT;
46509
+ var import_fs89, import_path89, import_os75, import_https6, TELEMETRY_PROMPT;
46387
46510
  var init_init = __esm({
46388
46511
  "src/cli/commands/init.ts"() {
46389
46512
  "use strict";
46390
46513
  init_cjs_shims();
46391
46514
  init_v2();
46392
46515
  init_write();
46393
- import_fs87 = __toESM(require("fs"));
46394
- import_path87 = __toESM(require("path"));
46395
- import_os74 = __toESM(require("os"));
46516
+ import_fs89 = __toESM(require("fs"));
46517
+ import_path89 = __toESM(require("path"));
46518
+ import_os75 = __toESM(require("os"));
46396
46519
  import_https6 = __toESM(require("https"));
46397
46520
  init_config();
46398
46521
  init_setup();
@@ -47519,14 +47642,14 @@ var require_util = __commonJS({
47519
47642
  }
47520
47643
  const port = url.port != null ? url.port : url.protocol === "https:" ? 443 : 80;
47521
47644
  let origin = url.origin != null ? url.origin : `${url.protocol || ""}//${url.hostname || ""}:${port}`;
47522
- let path108 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`;
47645
+ let path110 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`;
47523
47646
  if (origin[origin.length - 1] === "/") {
47524
47647
  origin = origin.slice(0, origin.length - 1);
47525
47648
  }
47526
- if (path108 && path108[0] !== "/") {
47527
- path108 = `/${path108}`;
47649
+ if (path110 && path110[0] !== "/") {
47650
+ path110 = `/${path110}`;
47528
47651
  }
47529
- return new URL(`${origin}${path108}`);
47652
+ return new URL(`${origin}${path110}`);
47530
47653
  }
47531
47654
  if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) {
47532
47655
  throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`.");
@@ -48349,9 +48472,9 @@ var require_diagnostics = __commonJS({
48349
48472
  "undici:client:sendHeaders",
48350
48473
  (evt) => {
48351
48474
  const {
48352
- request: { method, path: path108, origin }
48475
+ request: { method, path: path110, origin }
48353
48476
  } = evt;
48354
- debugLog2("sending request to %s %s%s", method, origin, path108);
48477
+ debugLog2("sending request to %s %s%s", method, origin, path110);
48355
48478
  }
48356
48479
  );
48357
48480
  }
@@ -48369,14 +48492,14 @@ var require_diagnostics = __commonJS({
48369
48492
  "undici:request:headers",
48370
48493
  (evt) => {
48371
48494
  const {
48372
- request: { method, path: path108, origin },
48495
+ request: { method, path: path110, origin },
48373
48496
  response: { statusCode }
48374
48497
  } = evt;
48375
48498
  debugLog2(
48376
48499
  "received response to %s %s%s - HTTP %d",
48377
48500
  method,
48378
48501
  origin,
48379
- path108,
48502
+ path110,
48380
48503
  statusCode
48381
48504
  );
48382
48505
  }
@@ -48385,23 +48508,23 @@ var require_diagnostics = __commonJS({
48385
48508
  "undici:request:trailers",
48386
48509
  (evt) => {
48387
48510
  const {
48388
- request: { method, path: path108, origin }
48511
+ request: { method, path: path110, origin }
48389
48512
  } = evt;
48390
- debugLog2("trailers received from %s %s%s", method, origin, path108);
48513
+ debugLog2("trailers received from %s %s%s", method, origin, path110);
48391
48514
  }
48392
48515
  );
48393
48516
  diagnosticsChannel.subscribe(
48394
48517
  "undici:request:error",
48395
48518
  (evt) => {
48396
48519
  const {
48397
- request: { method, path: path108, origin },
48520
+ request: { method, path: path110, origin },
48398
48521
  error
48399
48522
  } = evt;
48400
48523
  debugLog2(
48401
48524
  "request to %s %s%s errored - %s",
48402
48525
  method,
48403
48526
  origin,
48404
- path108,
48527
+ path110,
48405
48528
  error.message
48406
48529
  );
48407
48530
  }
@@ -48517,7 +48640,7 @@ var require_request = __commonJS({
48517
48640
  var kHandler = /* @__PURE__ */ Symbol("handler");
48518
48641
  var Request = class {
48519
48642
  constructor(origin, {
48520
- path: path108,
48643
+ path: path110,
48521
48644
  method,
48522
48645
  body,
48523
48646
  headers,
@@ -48534,11 +48657,11 @@ var require_request = __commonJS({
48534
48657
  maxRedirections,
48535
48658
  typeOfService
48536
48659
  }, handler) {
48537
- if (typeof path108 !== "string") {
48660
+ if (typeof path110 !== "string") {
48538
48661
  throw new InvalidArgumentError("path must be a string");
48539
- } 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") {
48540
48663
  throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
48541
- } else if (invalidPathRegex.test(path108)) {
48664
+ } else if (invalidPathRegex.test(path110)) {
48542
48665
  throw new InvalidArgumentError("invalid request path");
48543
48666
  }
48544
48667
  if (typeof method !== "string") {
@@ -48613,7 +48736,7 @@ var require_request = __commonJS({
48613
48736
  this.completed = false;
48614
48737
  this.aborted = false;
48615
48738
  this.upgrade = upgrade || null;
48616
- this.path = query ? serializePathWithQuery(path108, query) : path108;
48739
+ this.path = query ? serializePathWithQuery(path110, query) : path110;
48617
48740
  this.origin = origin;
48618
48741
  this.protocol = getProtocolFromUrlString(origin);
48619
48742
  this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent;
@@ -53860,7 +53983,7 @@ var require_client_h1 = __commonJS({
53860
53983
  return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT";
53861
53984
  }
53862
53985
  function writeH1(client, request2) {
53863
- const { method, path: path108, host: host2, upgrade, blocking, reset } = request2;
53986
+ const { method, path: path110, host: host2, upgrade, blocking, reset } = request2;
53864
53987
  let { body, headers, contentLength } = request2;
53865
53988
  const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH" || method === "QUERY" || method === "PROPFIND" || method === "PROPPATCH";
53866
53989
  if (util.isFormDataLike(body)) {
@@ -53938,7 +54061,7 @@ var require_client_h1 = __commonJS({
53938
54061
  if (socket.setTypeOfService) {
53939
54062
  socket.setTypeOfService(request2.typeOfService);
53940
54063
  }
53941
- let header = `${method} ${path108} HTTP/1.1\r
54064
+ let header = `${method} ${path110} HTTP/1.1\r
53942
54065
  `;
53943
54066
  if (typeof host2 === "string") {
53944
54067
  header += `host: ${host2}\r
@@ -54616,7 +54739,7 @@ var require_client_h2 = __commonJS({
54616
54739
  const headersTimeout = request2.headersTimeout ?? client[kHeadersTimeout];
54617
54740
  const bodyTimeout = request2.bodyTimeout ?? client[kBodyTimeout];
54618
54741
  const session = client[kHTTP2Session];
54619
- 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;
54620
54743
  let { body } = request2;
54621
54744
  if (upgrade != null && upgrade !== "websocket") {
54622
54745
  util.errorRequest(client, request2, new InvalidArgumentError(`Custom upgrade "${upgrade}" not supported over HTTP/2`));
@@ -54685,7 +54808,7 @@ var require_client_h2 = __commonJS({
54685
54808
  }
54686
54809
  headers[HTTP2_HEADER_METHOD] = "CONNECT";
54687
54810
  headers[HTTP2_HEADER_PROTOCOL] = "websocket";
54688
- headers[HTTP2_HEADER_PATH] = path108;
54811
+ headers[HTTP2_HEADER_PATH] = path110;
54689
54812
  if (protocol === "ws:" || protocol === "wss:") {
54690
54813
  headers[HTTP2_HEADER_SCHEME] = protocol === "ws:" ? "http" : "https";
54691
54814
  } else {
@@ -54737,7 +54860,7 @@ var require_client_h2 = __commonJS({
54737
54860
  stream.setTimeout(headersTimeout);
54738
54861
  return true;
54739
54862
  }
54740
- headers[HTTP2_HEADER_PATH] = path108;
54863
+ headers[HTTP2_HEADER_PATH] = path110;
54741
54864
  headers[HTTP2_HEADER_SCHEME] = protocol === "http:" ? "http" : "https";
54742
54865
  const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
54743
54866
  if (body && typeof body.read === "function") {
@@ -57104,10 +57227,10 @@ var require_proxy_agent = __commonJS({
57104
57227
  };
57105
57228
  const {
57106
57229
  origin,
57107
- path: path108 = "/",
57230
+ path: path110 = "/",
57108
57231
  headers = {}
57109
57232
  } = opts;
57110
- opts.path = origin + path108;
57233
+ opts.path = origin + path110;
57111
57234
  if (!("host" in headers) && !("Host" in headers)) {
57112
57235
  const { host: host2 } = new URL(origin);
57113
57236
  headers.host = host2;
@@ -59282,20 +59405,20 @@ var require_mock_utils = __commonJS({
59282
59405
  }
59283
59406
  return normalizedQp;
59284
59407
  }
59285
- function safeUrl(path108) {
59286
- if (typeof path108 !== "string") {
59287
- return path108;
59408
+ function safeUrl(path110) {
59409
+ if (typeof path110 !== "string") {
59410
+ return path110;
59288
59411
  }
59289
- const pathSegments = path108.split("?", 3);
59412
+ const pathSegments = path110.split("?", 3);
59290
59413
  if (pathSegments.length !== 2) {
59291
- return path108;
59414
+ return path110;
59292
59415
  }
59293
59416
  const qp = new URLSearchParams(pathSegments.pop());
59294
59417
  qp.sort();
59295
59418
  return [...pathSegments, qp.toString()].join("?");
59296
59419
  }
59297
- function matchKey(mockDispatch2, { path: path108, method, body, headers }) {
59298
- const pathMatch = matchValue(mockDispatch2.path, path108);
59420
+ function matchKey(mockDispatch2, { path: path110, method, body, headers }) {
59421
+ const pathMatch = matchValue(mockDispatch2.path, path110);
59299
59422
  const methodMatch = matchValue(mockDispatch2.method, method);
59300
59423
  const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true;
59301
59424
  const headersMatch = matchHeaders(mockDispatch2, headers);
@@ -59320,8 +59443,8 @@ var require_mock_utils = __commonJS({
59320
59443
  const basePath = key.query ? serializePathWithQuery(key.path, key.query) : key.path;
59321
59444
  const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
59322
59445
  const resolvedPathWithoutTrailingSlash = removeTrailingSlash(resolvedPath);
59323
- let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path108, ignoreTrailingSlash }) => {
59324
- 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);
59325
59448
  });
59326
59449
  if (matchedMockDispatches.length === 0) {
59327
59450
  throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
@@ -59360,19 +59483,19 @@ var require_mock_utils = __commonJS({
59360
59483
  mockDispatches.splice(index, 1);
59361
59484
  }
59362
59485
  }
59363
- function removeTrailingSlash(path108) {
59364
- while (path108.endsWith("/")) {
59365
- path108 = path108.slice(0, -1);
59486
+ function removeTrailingSlash(path110) {
59487
+ while (path110.endsWith("/")) {
59488
+ path110 = path110.slice(0, -1);
59366
59489
  }
59367
- if (path108.length === 0) {
59368
- path108 = "/";
59490
+ if (path110.length === 0) {
59491
+ path110 = "/";
59369
59492
  }
59370
- return path108;
59493
+ return path110;
59371
59494
  }
59372
59495
  function buildKey(opts) {
59373
- const { path: path108, method, body, headers, query } = opts;
59496
+ const { path: path110, method, body, headers, query } = opts;
59374
59497
  return {
59375
- path: path108,
59498
+ path: path110,
59376
59499
  method,
59377
59500
  body,
59378
59501
  headers,
@@ -60067,10 +60190,10 @@ var require_pending_interceptors_formatter = __commonJS({
60067
60190
  }
60068
60191
  format(pendingInterceptors) {
60069
60192
  const withPrettyHeaders = pendingInterceptors.map(
60070
- ({ method, path: path108, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
60193
+ ({ method, path: path110, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
60071
60194
  Method: method,
60072
60195
  Origin: origin,
60073
- Path: path108,
60196
+ Path: path110,
60074
60197
  "Status code": statusCode,
60075
60198
  Persistent: persist ? PERSISTENT : NOT_PERSISTENT,
60076
60199
  Invocations: timesInvoked,
@@ -60153,9 +60276,9 @@ var require_mock_agent = __commonJS({
60153
60276
  const acceptNonStandardSearchParameters = this[kMockAgentAcceptsNonStandardSearchParameters];
60154
60277
  const dispatchOpts = { ...opts };
60155
60278
  if (acceptNonStandardSearchParameters && dispatchOpts.path) {
60156
- const [path108, searchParams] = dispatchOpts.path.split("?");
60279
+ const [path110, searchParams] = dispatchOpts.path.split("?");
60157
60280
  const normalizedSearchParams = normalizeSearchParams(searchParams, acceptNonStandardSearchParameters);
60158
- dispatchOpts.path = `${path108}?${normalizedSearchParams}`;
60281
+ dispatchOpts.path = `${path110}?${normalizedSearchParams}`;
60159
60282
  }
60160
60283
  return this[kAgent].dispatch(dispatchOpts, handler);
60161
60284
  }
@@ -60558,12 +60681,12 @@ var require_snapshot_recorder = __commonJS({
60558
60681
  * @return {Promise<void>} - Resolves when snapshots are loaded
60559
60682
  */
60560
60683
  async loadSnapshots(filePath) {
60561
- const path108 = filePath || this.#snapshotPath;
60562
- if (!path108) {
60684
+ const path110 = filePath || this.#snapshotPath;
60685
+ if (!path110) {
60563
60686
  throw new InvalidArgumentError("Snapshot path is required");
60564
60687
  }
60565
60688
  try {
60566
- const data = await readFile(resolve2(path108), "utf8");
60689
+ const data = await readFile(resolve2(path110), "utf8");
60567
60690
  const parsed = JSON.parse(data);
60568
60691
  if (Array.isArray(parsed)) {
60569
60692
  this.#snapshots.clear();
@@ -60577,7 +60700,7 @@ var require_snapshot_recorder = __commonJS({
60577
60700
  if (error.code === "ENOENT") {
60578
60701
  this.#snapshots.clear();
60579
60702
  } else {
60580
- throw new UndiciError(`Failed to load snapshots from ${path108}`, { cause: error });
60703
+ throw new UndiciError(`Failed to load snapshots from ${path110}`, { cause: error });
60581
60704
  }
60582
60705
  }
60583
60706
  }
@@ -60588,11 +60711,11 @@ var require_snapshot_recorder = __commonJS({
60588
60711
  * @returns {Promise<void>} - Resolves when snapshots are saved
60589
60712
  */
60590
60713
  async saveSnapshots(filePath) {
60591
- const path108 = filePath || this.#snapshotPath;
60592
- if (!path108) {
60714
+ const path110 = filePath || this.#snapshotPath;
60715
+ if (!path110) {
60593
60716
  throw new InvalidArgumentError("Snapshot path is required");
60594
60717
  }
60595
- const resolvedPath = resolve2(path108);
60718
+ const resolvedPath = resolve2(path110);
60596
60719
  await mkdir(dirname3(resolvedPath), { recursive: true });
60597
60720
  const data = Array.from(this.#snapshots.entries()).map(([hash2, snapshot]) => ({
60598
60721
  hash: hash2,
@@ -61233,15 +61356,15 @@ var require_redirect_handler = __commonJS({
61233
61356
  }
61234
61357
  this.history[kRedirectCacheControl].push(headers["cache-control"]);
61235
61358
  const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)));
61236
- const path108 = search ? `${pathname}${search}` : pathname;
61237
- const redirectUrlString = `${origin}${path108}`;
61359
+ const path110 = search ? `${pathname}${search}` : pathname;
61360
+ const redirectUrlString = `${origin}${path110}`;
61238
61361
  for (const historyUrl of this.history) {
61239
61362
  if (historyUrl.toString() === redirectUrlString) {
61240
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.`);
61241
61364
  }
61242
61365
  }
61243
61366
  this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin);
61244
- this.opts.path = path108;
61367
+ this.opts.path = path110;
61245
61368
  this.opts.origin = origin;
61246
61369
  this.opts.query = null;
61247
61370
  }
@@ -63017,10 +63140,10 @@ var require_cache_handler = __commonJS({
63017
63140
  }
63018
63141
  return locationUrl.pathname + locationUrl.search;
63019
63142
  }
63020
- function deleteCachedUri(store, cacheKey, path108) {
63143
+ function deleteCachedUri(store, cacheKey, path110) {
63021
63144
  deleteCachedValue(store, {
63022
63145
  ...cacheKey,
63023
- path: path108
63146
+ path: path110
63024
63147
  });
63025
63148
  for (let i = 0; i < util.safeHTTPMethods.length; i++) {
63026
63149
  const method = util.safeHTTPMethods[i];
@@ -63028,7 +63151,7 @@ var require_cache_handler = __commonJS({
63028
63151
  deleteCachedValue(store, {
63029
63152
  ...cacheKey,
63030
63153
  method,
63031
- path: path108
63154
+ path: path110
63032
63155
  });
63033
63156
  }
63034
63157
  }
@@ -63039,9 +63162,9 @@ var require_cache_handler = __commonJS({
63039
63162
  }
63040
63163
  const values = Array.isArray(headerValue) ? headerValue : [headerValue];
63041
63164
  for (let i = 0; i < values.length; i++) {
63042
- const path108 = getSameOriginPath(cacheKey, values[i]);
63043
- if (path108 !== void 0) {
63044
- deleteCachedUri(store, cacheKey, path108);
63165
+ const path110 = getSameOriginPath(cacheKey, values[i]);
63166
+ if (path110 !== void 0) {
63167
+ deleteCachedUri(store, cacheKey, path110);
63045
63168
  }
63046
63169
  }
63047
63170
  }
@@ -68264,11 +68387,11 @@ var require_fetch = __commonJS({
68264
68387
  function dispatch({ body }) {
68265
68388
  const url = requestCurrentURL(request2);
68266
68389
  const agent = fetchParams.controller.dispatcher;
68267
- const path108 = url.pathname + url.search;
68390
+ const path110 = url.pathname + url.search;
68268
68391
  const hasTrailingQuestionMark = url.search.length === 0 && url.href[url.href.length - url.hash.length - 1] === "?";
68269
68392
  return new Promise((resolve2, reject) => agent.dispatch(
68270
68393
  {
68271
- path: hasTrailingQuestionMark ? `${path108}?` : path108,
68394
+ path: hasTrailingQuestionMark ? `${path110}?` : path110,
68272
68395
  origin: url.origin,
68273
68396
  method: request2.method,
68274
68397
  body: agent.isMockActive ? request2.body && (request2.body.source || request2.body.stream) : body,
@@ -69220,9 +69343,9 @@ var require_util4 = __commonJS({
69220
69343
  }
69221
69344
  }
69222
69345
  }
69223
- function validateCookiePath(path108) {
69224
- for (let i = 0; i < path108.length; ++i) {
69225
- const code2 = path108.charCodeAt(i);
69346
+ function validateCookiePath(path110) {
69347
+ for (let i = 0; i < path110.length; ++i) {
69348
+ const code2 = path110.charCodeAt(i);
69226
69349
  if (code2 < 32 || // exclude CTLs (0-31)
69227
69350
  code2 > 126 || // exclude DEL and non-ascii
69228
69351
  code2 === 59) {
@@ -72675,11 +72798,11 @@ var require_undici = __commonJS({
72675
72798
  if (typeof opts.path !== "string") {
72676
72799
  throw new InvalidArgumentError("invalid opts.path");
72677
72800
  }
72678
- let path108 = opts.path;
72801
+ let path110 = opts.path;
72679
72802
  if (!opts.path.startsWith("/")) {
72680
- path108 = `/${path108}`;
72803
+ path110 = `/${path110}`;
72681
72804
  }
72682
- url = new URL(util.parseOrigin(url).origin + path108);
72805
+ url = new URL(util.parseOrigin(url).origin + path110);
72683
72806
  } else {
72684
72807
  if (!opts) {
72685
72808
  opts = typeof url === "object" ? url : {};
@@ -72801,10 +72924,10 @@ function readFirstRunEnv() {
72801
72924
  stdinTTY: !!process.stdin.isTTY,
72802
72925
  stdoutTTY: !!process.stdout.isTTY,
72803
72926
  ci: isCI() || process.env.NODE9_NONINTERACTIVE === "1",
72804
- 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")),
72805
72928
  // Any stored profile means this is not a never-configured machine. Treat
72806
72929
  // malformed credential files conservatively and leave repair to explicit setup.
72807
- 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"))
72808
72931
  };
72809
72932
  }
72810
72933
  function shouldOfferFirstRun(env) {
@@ -72909,14 +73032,14 @@ async function runSetupWizard(opts) {
72909
73032
  process.exitCode = 130;
72910
73033
  }
72911
73034
  }
72912
- var import_fs101, import_os82, import_path100;
73035
+ var import_fs103, import_os83, import_path102;
72913
73036
  var init_first_run = __esm({
72914
73037
  "src/cli/first-run.ts"() {
72915
73038
  "use strict";
72916
73039
  init_cjs_shims();
72917
- import_fs101 = __toESM(require("fs"));
72918
- import_os82 = __toESM(require("os"));
72919
- import_path100 = __toESM(require("path"));
73040
+ import_fs103 = __toESM(require("fs"));
73041
+ import_os83 = __toESM(require("os"));
73042
+ import_path102 = __toESM(require("path"));
72920
73043
  init_config();
72921
73044
  init_agent_wiring();
72922
73045
  init_browser_login();
@@ -72962,20 +73085,20 @@ function getModelContextLimit(model) {
72962
73085
  return 2e5;
72963
73086
  }
72964
73087
  function readSessionUsage() {
72965
- const projectsDir = import_path101.default.join(import_os83.default.homedir(), ".claude", "projects");
72966
- 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;
72967
73090
  let latestFile = null;
72968
73091
  let latestMtime = 0;
72969
73092
  try {
72970
- for (const dir2 of import_fs102.default.readdirSync(projectsDir)) {
72971
- 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);
72972
73095
  try {
72973
- if (!import_fs102.default.statSync(dirPath).isDirectory()) continue;
72974
- 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)) {
72975
73098
  if (!file2.endsWith(".jsonl") || file2.startsWith("agent-")) continue;
72976
- const filePath = import_path101.default.join(dirPath, file2);
73099
+ const filePath = import_path103.default.join(dirPath, file2);
72977
73100
  try {
72978
- const mtime = import_fs102.default.statSync(filePath).mtimeMs;
73101
+ const mtime = import_fs104.default.statSync(filePath).mtimeMs;
72979
73102
  if (mtime > latestMtime) {
72980
73103
  latestMtime = mtime;
72981
73104
  latestFile = filePath;
@@ -72990,7 +73113,7 @@ function readSessionUsage() {
72990
73113
  }
72991
73114
  if (!latestFile) return null;
72992
73115
  try {
72993
- const lines = import_fs102.default.readFileSync(latestFile, "utf-8").split("\n");
73116
+ const lines = import_fs104.default.readFileSync(latestFile, "utf-8").split("\n");
72994
73117
  let lastModel = "";
72995
73118
  let lastInput = 0;
72996
73119
  let lastOutput = 0;
@@ -73051,7 +73174,7 @@ function formatBase(activity) {
73051
73174
  const time = new Date(activity.ts).toLocaleTimeString([], { hour12: false });
73052
73175
  const icon = getIcon(activity.tool);
73053
73176
  const toolName = activity.tool.slice(0, 16).padEnd(16);
73054
- 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(), "~");
73055
73178
  const argsPreview = argsStr.length > 70 ? argsStr.slice(0, 70) + "\u2026" : argsStr;
73056
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)}`;
73057
73180
  }
@@ -73090,9 +73213,9 @@ function renderPending(activity) {
73090
73213
  }
73091
73214
  async function ensureDaemon() {
73092
73215
  let pidPort = null;
73093
- if (import_fs102.default.existsSync(PID_FILE)) {
73216
+ if (import_fs104.default.existsSync(PID_FILE)) {
73094
73217
  try {
73095
- 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"));
73096
73219
  pidPort = port;
73097
73220
  } catch {
73098
73221
  console.error(import_chalk49.default.dim("\u26A0\uFE0F Could not read PID file; falling back to default port."));
@@ -73118,7 +73241,7 @@ async function ensureDaemon() {
73118
73241
  child.unref();
73119
73242
  if (startupFd !== void 0) {
73120
73243
  try {
73121
- import_fs102.default.closeSync(startupFd);
73244
+ import_fs104.default.closeSync(startupFd);
73122
73245
  } catch {
73123
73246
  }
73124
73247
  }
@@ -73488,8 +73611,8 @@ async function startTail(options = {}) {
73488
73611
  );
73489
73612
  }).catch((err2) => {
73490
73613
  try {
73491
- import_fs102.default.appendFileSync(
73492
- 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"),
73493
73616
  `[tail] POST /decision failed: ${String(err2)}
73494
73617
  `
73495
73618
  );
@@ -73555,9 +73678,9 @@ async function startTail(options = {}) {
73555
73678
  };
73556
73679
  process.stdin.on("keypress", onKeypress);
73557
73680
  }
73558
- 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");
73559
73682
  try {
73560
- 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;
73561
73684
  if (unackedDlp > 0) {
73562
73685
  console.log("");
73563
73686
  console.log(
@@ -73597,7 +73720,7 @@ async function startTail(options = {}) {
73597
73720
  if (stallWarned) return;
73598
73721
  if (Date.now() - lastActivityFromDaemon < STALL_THRESHOLD_MS) return;
73599
73722
  try {
73600
- const auditMtime = import_fs102.default.statSync(auditLog).mtimeMs;
73723
+ const auditMtime = import_fs104.default.statSync(auditLog).mtimeMs;
73601
73724
  if (Date.now() - auditMtime >= STALL_THRESHOLD_MS) return;
73602
73725
  console.log("");
73603
73726
  console.log(
@@ -73769,7 +73892,7 @@ async function startTail(options = {}) {
73769
73892
  process.exit(1);
73770
73893
  });
73771
73894
  }
73772
- 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;
73773
73896
  var init_tail = __esm({
73774
73897
  "src/tui/tail.ts"() {
73775
73898
  "use strict";
@@ -73777,16 +73900,16 @@ var init_tail = __esm({
73777
73900
  import_http6 = __toESM(require("http"));
73778
73901
  init_write();
73779
73902
  import_chalk49 = __toESM(require("chalk"));
73780
- import_fs102 = __toESM(require("fs"));
73781
- import_os83 = __toESM(require("os"));
73782
- import_path101 = __toESM(require("path"));
73903
+ import_fs104 = __toESM(require("fs"));
73904
+ import_os84 = __toESM(require("os"));
73905
+ import_path103 = __toESM(require("path"));
73783
73906
  import_readline5 = __toESM(require("readline"));
73784
73907
  import_child_process17 = require("child_process");
73785
73908
  init_startup_log();
73786
73909
  init_daemon3();
73787
73910
  init_daemon();
73788
73911
  init_safe_text();
73789
- 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");
73790
73913
  ICONS = {
73791
73914
  bash: "\u{1F4BB}",
73792
73915
  shell: "\u{1F4BB}",
@@ -73908,9 +74031,9 @@ function formatTimeLeft(resetsAt) {
73908
74031
  return ` (${m}m left)`;
73909
74032
  }
73910
74033
  function safeReadJson(filePath) {
73911
- if (!import_fs103.default.existsSync(filePath)) return null;
74034
+ if (!import_fs105.default.existsSync(filePath)) return null;
73912
74035
  try {
73913
- return JSON.parse(import_fs103.default.readFileSync(filePath, "utf-8"));
74036
+ return JSON.parse(import_fs105.default.readFileSync(filePath, "utf-8"));
73914
74037
  } catch {
73915
74038
  return null;
73916
74039
  }
@@ -73931,12 +74054,12 @@ function countHooksInFile(filePath) {
73931
74054
  return Object.keys(cfg.hooks).length;
73932
74055
  }
73933
74056
  function countRulesInDir(rulesDir) {
73934
- if (!import_fs103.default.existsSync(rulesDir)) return 0;
74057
+ if (!import_fs105.default.existsSync(rulesDir)) return 0;
73935
74058
  let count = 0;
73936
74059
  try {
73937
- for (const entry of import_fs103.default.readdirSync(rulesDir, { withFileTypes: true })) {
74060
+ for (const entry of import_fs105.default.readdirSync(rulesDir, { withFileTypes: true })) {
73938
74061
  if (entry.isDirectory()) {
73939
- count += countRulesInDir(import_path102.default.join(rulesDir, entry.name));
74062
+ count += countRulesInDir(import_path104.default.join(rulesDir, entry.name));
73940
74063
  } else if (entry.isFile() && entry.name.endsWith(".md")) {
73941
74064
  count++;
73942
74065
  }
@@ -73947,46 +74070,46 @@ function countRulesInDir(rulesDir) {
73947
74070
  }
73948
74071
  function isSamePath(a, b) {
73949
74072
  try {
73950
- return import_path102.default.resolve(a) === import_path102.default.resolve(b);
74073
+ return import_path104.default.resolve(a) === import_path104.default.resolve(b);
73951
74074
  } catch {
73952
74075
  return false;
73953
74076
  }
73954
74077
  }
73955
74078
  function countConfigs(cwd) {
73956
- const homeDir2 = import_os84.default.homedir();
73957
- const claudeDir = import_path102.default.join(homeDir2, ".claude");
74079
+ const homeDir2 = import_os85.default.homedir();
74080
+ const claudeDir = import_path104.default.join(homeDir2, ".claude");
73958
74081
  let claudeMdCount = 0;
73959
74082
  let rulesCount = 0;
73960
74083
  let hooksCount = 0;
73961
74084
  const userMcpServers = /* @__PURE__ */ new Set();
73962
74085
  const projectMcpServers = /* @__PURE__ */ new Set();
73963
- if (import_fs103.default.existsSync(import_path102.default.join(claudeDir, "CLAUDE.md"))) claudeMdCount++;
73964
- rulesCount += countRulesInDir(import_path102.default.join(claudeDir, "rules"));
73965
- 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");
73966
74089
  for (const name of getMcpServerNames(userSettings)) userMcpServers.add(name);
73967
74090
  hooksCount += countHooksInFile(userSettings);
73968
- const userClaudeJson = import_path102.default.join(homeDir2, ".claude.json");
74091
+ const userClaudeJson = import_path104.default.join(homeDir2, ".claude.json");
73969
74092
  for (const name of getMcpServerNames(userClaudeJson)) userMcpServers.add(name);
73970
74093
  for (const name of getDisabledMcpServers(userClaudeJson, "disabledMcpServers")) {
73971
74094
  userMcpServers.delete(name);
73972
74095
  }
73973
74096
  if (cwd) {
73974
- if (import_fs103.default.existsSync(import_path102.default.join(cwd, "CLAUDE.md"))) claudeMdCount++;
73975
- if (import_fs103.default.existsSync(import_path102.default.join(cwd, "CLAUDE.local.md"))) claudeMdCount++;
73976
- 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");
73977
74100
  const overlapsUserScope = isSamePath(projectClaudeDir, claudeDir);
73978
74101
  if (!overlapsUserScope) {
73979
- if (import_fs103.default.existsSync(import_path102.default.join(projectClaudeDir, "CLAUDE.md"))) claudeMdCount++;
73980
- rulesCount += countRulesInDir(import_path102.default.join(projectClaudeDir, "rules"));
73981
- 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");
73982
74105
  for (const name of getMcpServerNames(projSettings)) projectMcpServers.add(name);
73983
74106
  hooksCount += countHooksInFile(projSettings);
73984
74107
  }
73985
- if (import_fs103.default.existsSync(import_path102.default.join(projectClaudeDir, "CLAUDE.local.md"))) claudeMdCount++;
73986
- 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");
73987
74110
  for (const name of getMcpServerNames(localSettings)) projectMcpServers.add(name);
73988
74111
  hooksCount += countHooksInFile(localSettings);
73989
- const mcpJsonServers = getMcpServerNames(import_path102.default.join(cwd, ".mcp.json"));
74112
+ const mcpJsonServers = getMcpServerNames(import_path104.default.join(cwd, ".mcp.json"));
73990
74113
  const disabledMcpJson = getDisabledMcpServers(localSettings, "disabledMcpjsonServers");
73991
74114
  for (const name of disabledMcpJson) mcpJsonServers.delete(name);
73992
74115
  for (const name of mcpJsonServers) projectMcpServers.add(name);
@@ -74019,12 +74142,12 @@ function readActiveShieldsHud() {
74019
74142
  return shieldsCache.value;
74020
74143
  }
74021
74144
  try {
74022
- const shieldsPath = import_path102.default.join(import_os84.default.homedir(), ".node9", "shields.json");
74023
- 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)) {
74024
74147
  shieldsCache = { value: [], ts: now };
74025
74148
  return [];
74026
74149
  }
74027
- const parsed = JSON.parse(import_fs103.default.readFileSync(shieldsPath, "utf-8"));
74150
+ const parsed = JSON.parse(import_fs105.default.readFileSync(shieldsPath, "utf-8"));
74028
74151
  if (!Array.isArray(parsed.active)) {
74029
74152
  shieldsCache = { value: [], ts: now };
74030
74153
  return [];
@@ -74126,17 +74249,17 @@ function renderContextLine(stdin) {
74126
74249
  async function main() {
74127
74250
  try {
74128
74251
  const [stdin, daemonStatus2] = await Promise.all([readStdin(), queryDaemon()]);
74129
- 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"))) {
74130
74253
  try {
74131
- 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");
74132
74255
  const MAX_LOG_SIZE = 10 * 1024 * 1024;
74133
74256
  let size = 0;
74134
74257
  try {
74135
- size = import_fs103.default.statSync(logPath).size;
74258
+ size = import_fs105.default.statSync(logPath).size;
74136
74259
  } catch {
74137
74260
  }
74138
74261
  if (size < MAX_LOG_SIZE) {
74139
- import_fs103.default.appendFileSync(
74262
+ import_fs105.default.appendFileSync(
74140
74263
  logPath,
74141
74264
  JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), stdin }) + "\n"
74142
74265
  );
@@ -74157,11 +74280,11 @@ async function main() {
74157
74280
  try {
74158
74281
  const cwd = stdin.cwd ?? process.cwd();
74159
74282
  for (const configPath2 of [
74160
- import_path102.default.join(cwd, "node9.config.json"),
74161
- 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")
74162
74285
  ]) {
74163
- if (!import_fs103.default.existsSync(configPath2)) continue;
74164
- 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"));
74165
74288
  const hud = cfg.settings?.hud;
74166
74289
  if (hud && "showEnvironmentCounts" in hud) return hud.showEnvironmentCounts !== false;
74167
74290
  }
@@ -74179,14 +74302,14 @@ async function main() {
74179
74302
  renderOffline();
74180
74303
  }
74181
74304
  }
74182
- 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;
74183
74306
  var init_hud = __esm({
74184
74307
  "src/cli/hud.ts"() {
74185
74308
  "use strict";
74186
74309
  init_cjs_shims();
74187
- import_fs103 = __toESM(require("fs"));
74188
- import_path102 = __toESM(require("path"));
74189
- import_os84 = __toESM(require("os"));
74310
+ import_fs105 = __toESM(require("fs"));
74311
+ import_path104 = __toESM(require("path"));
74312
+ import_os85 = __toESM(require("os"));
74190
74313
  import_http7 = __toESM(require("http"));
74191
74314
  init_daemon();
74192
74315
  init_dist();
@@ -74251,9 +74374,9 @@ init_agent_wiring();
74251
74374
  init_credentials();
74252
74375
  init_daemon3();
74253
74376
  var import_chalk50 = __toESM(require("chalk"));
74254
- var import_fs104 = __toESM(require("fs"));
74255
- var import_path103 = __toESM(require("path"));
74256
- 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"));
74257
74380
  var import_prompts4 = require("@inquirer/prompts");
74258
74381
 
74259
74382
  // src/utils/duration.ts
@@ -74341,7 +74464,8 @@ async function runProxy(targetCommand) {
74341
74464
  {
74342
74465
  kind: result.blockKind,
74343
74466
  path: result.blockedPath,
74344
- redirect: !!result.redirect
74467
+ redirect: !!result.redirect,
74468
+ ruleDescription: result.ruleDescription
74345
74469
  }
74346
74470
  );
74347
74471
  const errorResponse = {
@@ -74461,10 +74585,10 @@ function buildExplainJsonError(message) {
74461
74585
  // src/cli/commands/check.ts
74462
74586
  init_cjs_shims();
74463
74587
  var import_chalk14 = __toESM(require("chalk"));
74464
- var import_fs73 = __toESM(require("fs"));
74588
+ var import_fs75 = __toESM(require("fs"));
74465
74589
  var import_child_process9 = require("child_process");
74466
- var import_path73 = __toESM(require("path"));
74467
- var import_os61 = __toESM(require("os"));
74590
+ var import_path75 = __toESM(require("path"));
74591
+ var import_os62 = __toESM(require("os"));
74468
74592
  init_orchestrator();
74469
74593
  init_state();
74470
74594
  init_daemon();
@@ -74750,6 +74874,159 @@ function discardPendingReview(key, now = Date.now()) {
74750
74874
  // src/cli/commands/check.ts
74751
74875
  init_hook_payload();
74752
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
+ init_atomic_write();
74928
+ var ICON2 = "\u{1F6E1}\uFE0F";
74929
+ var LEVEL_NAMES = {
74930
+ audit: "Audit",
74931
+ soft: "Soft",
74932
+ standard: "Standard",
74933
+ strict: "Strict",
74934
+ "block-all": "Block all"
74935
+ };
74936
+ var SESSION_NOTICE_NOTE = "node9 shows the user this line itself. Do not mention it unless the user asks about node9.";
74937
+ var FLAG_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
74938
+ var SAFE_SESSION_ID = /^[A-Za-z0-9_-]{1,128}$/;
74939
+ function sessionNoticeLine(mode, kind = "first") {
74940
+ const level = levelOf(mode);
74941
+ const name = LEVEL_NAMES[level];
74942
+ if (kind === "changed") {
74943
+ return level === "audit" ? `${ICON2} Node9 level changed to Audit: actions are logged, nothing is blocked.` : `${ICON2} Node9 level changed to ${name}. Every action in this session is checked.`;
74944
+ }
74945
+ if (level === "audit") {
74946
+ return `${ICON2} Node9 is in Audit mode: actions are logged, nothing is blocked.`;
74947
+ }
74948
+ return `${ICON2} Node9 is on (${name}). Every action in this session is checked.`;
74949
+ }
74950
+ function sessionNoticeOutput(mode, kind = "first") {
74951
+ const line = sessionNoticeLine(mode, kind);
74952
+ return JSON.stringify({
74953
+ hookSpecificOutput: {
74954
+ hookEventName: "PreToolUse",
74955
+ additionalContext: `${line}
74956
+ ${SESSION_NOTICE_NOTE}`
74957
+ },
74958
+ systemMessage: line
74959
+ });
74960
+ }
74961
+ function sessionNoticeEnabled(env = process.env) {
74962
+ if (env.NODE9_SESSION_NOTICE === "1") return true;
74963
+ return env.NODE9_TESTING !== "1";
74964
+ }
74965
+ var FLAG_MAX_BYTES = 32;
74966
+ function claimSessionNotice(sessionId, home = import_os61.default.homedir(), level = "standard") {
74967
+ if (!sessionId || !SAFE_SESSION_ID.test(sessionId)) return null;
74968
+ const dir2 = import_path74.default.join(home, ".node9", "notice-sessions");
74969
+ const seen = ensureOwnDir(dir2);
74970
+ if (!seen) return null;
74971
+ const flag = import_path74.default.join(dir2, sessionId + SESSION_FLAG_SUFFIX);
74972
+ let created = false;
74973
+ try {
74974
+ if (!isSameOwnDir(dir2, seen)) return null;
74975
+ const fd = import_fs74.default.openSync(flag, "wx", 384);
74976
+ created = true;
74977
+ try {
74978
+ import_fs74.default.writeSync(fd, level);
74979
+ } finally {
74980
+ import_fs74.default.closeSync(fd);
74981
+ }
74982
+ } catch (err2) {
74983
+ if (created) {
74984
+ try {
74985
+ import_fs74.default.unlinkSync(flag);
74986
+ } catch {
74987
+ }
74988
+ return null;
74989
+ }
74990
+ if (err2.code !== "EEXIST") return null;
74991
+ return levelChange(dir2, seen, flag, level);
74992
+ }
74993
+ removeOldFlags(dir2, seen);
74994
+ return "first";
74995
+ }
74996
+ function levelChange(dir2, seen, flag, level) {
74997
+ try {
74998
+ const told = readFlag(flag);
74999
+ if (told === null) return null;
75000
+ if (told === level) return null;
75001
+ if (!isSameOwnDir(dir2, seen)) return null;
75002
+ atomicWriteSync(flag, level, { mode: 384 });
75003
+ return told === "" ? null : "changed";
75004
+ } catch {
75005
+ return null;
75006
+ }
75007
+ }
75008
+ function readFlag(flag) {
75009
+ const c = import_fs74.default.constants;
75010
+ const fd = import_fs74.default.openSync(flag, c.O_RDONLY | (c.O_NOFOLLOW ?? 0) | (c.O_NONBLOCK ?? 0));
75011
+ try {
75012
+ const st = import_fs74.default.fstatSync(fd);
75013
+ if (!st.isFile() || st.nlink !== 1 || st.size > FLAG_MAX_BYTES) return null;
75014
+ const buf = Buffer.alloc(FLAG_MAX_BYTES);
75015
+ const n = import_fs74.default.readSync(fd, buf, 0, FLAG_MAX_BYTES, 0);
75016
+ return buf.toString("utf8", 0, n).trim();
75017
+ } finally {
75018
+ import_fs74.default.closeSync(fd);
75019
+ }
75020
+ }
75021
+ function removeOldFlags(dir2, seen) {
75022
+ const cutoff = Date.now() - FLAG_TTL_MS;
75023
+ try {
75024
+ for (const name of import_fs74.default.readdirSync(dir2)) removeOldFlag(dir2, seen, name, cutoff);
75025
+ } catch {
75026
+ }
75027
+ }
75028
+
75029
+ // src/cli/commands/check.ts
74753
75030
  function detectAiAgent(payload) {
74754
75031
  const meta = payload.meta;
74755
75032
  if (meta && typeof meta === "object") {
@@ -74827,9 +75104,9 @@ function registerCheckCommand(program2) {
74827
75104
  } catch (err2) {
74828
75105
  const tempConfig = getConfig();
74829
75106
  if (process.env.NODE9_DEBUG === "1" || tempConfig.settings.enableHookLogDebug) {
74830
- const logPath = import_path73.default.join(import_os61.default.homedir(), ".node9", "hook-debug.log");
75107
+ const logPath = import_path75.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
74831
75108
  const errMsg = err2 instanceof Error ? err2.message : String(err2);
74832
- import_fs73.default.appendFileSync(
75109
+ import_fs75.default.appendFileSync(
74833
75110
  logPath,
74834
75111
  `[${(/* @__PURE__ */ new Date()).toISOString()}] JSON_PARSE_ERROR: ${errMsg}
74835
75112
  RAW: ${raw}
@@ -74842,14 +75119,14 @@ RAW: ${raw}
74842
75119
  const prompt = typeof payload.prompt === "string" ? payload.prompt : "";
74843
75120
  if (process.env.NODE9_DEBUG === "1") {
74844
75121
  try {
74845
- const logPath = import_path73.default.join(import_os61.default.homedir(), ".node9", "hook-debug.log");
74846
- if (!import_fs73.default.existsSync(import_path73.default.dirname(logPath)))
74847
- import_fs73.default.mkdirSync(import_path73.default.dirname(logPath), { recursive: true });
75122
+ const logPath = import_path75.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
75123
+ if (!import_fs75.default.existsSync(import_path75.default.dirname(logPath)))
75124
+ import_fs75.default.mkdirSync(import_path75.default.dirname(logPath), { recursive: true });
74848
75125
  const sanitized = JSON.stringify({
74849
75126
  ...payload,
74850
75127
  prompt: `<redacted, ${prompt.length} bytes>`
74851
75128
  });
74852
- import_fs73.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] STDIN: ${sanitized}
75129
+ import_fs75.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] STDIN: ${sanitized}
74853
75130
  `);
74854
75131
  } catch {
74855
75132
  }
@@ -74867,7 +75144,7 @@ RAW: ${raw}
74867
75144
  if (!dlpMatch && !canaryHit) {
74868
75145
  try {
74869
75146
  const sid = typeof payload.session_id === "string" ? payload.session_id : typeof payload.conversationId === "string" ? payload.conversationId : "";
74870
- const promptCwd = typeof payload.cwd === "string" && import_path73.default.isAbsolute(payload.cwd) ? payload.cwd : void 0;
75147
+ const promptCwd = typeof payload.cwd === "string" && import_path75.default.isAbsolute(payload.cwd) ? payload.cwd : void 0;
74871
75148
  if (sid && getConfig(promptCwd).policy.untrustedContent?.enabled) {
74872
75149
  await notifyUserMentions(sid, extractContentDestinations(prompt));
74873
75150
  }
@@ -74908,8 +75185,8 @@ RAW: ${raw}
74908
75185
  );
74909
75186
  const reason = `\u{1F6A8} Node9 DLP: ${shownPattern} detected in prompt (${shownSample}). Prompt was not submitted \u2014 remove the credential and try again.`;
74910
75187
  try {
74911
- const ttyFd = import_fs73.default.openSync("/dev/tty", "w");
74912
- import_fs73.default.writeSync(
75188
+ const ttyFd = import_fs75.default.openSync("/dev/tty", "w");
75189
+ import_fs75.default.writeSync(
74913
75190
  ttyFd,
74914
75191
  import_chalk14.default.bgRed.white.bold(`
74915
75192
  \u{1F6A8} NODE9 DLP \u2014 PROMPT BLOCKED
@@ -74919,7 +75196,7 @@ RAW: ${raw}
74919
75196
 
74920
75197
  `)
74921
75198
  );
74922
- import_fs73.default.closeSync(ttyFd);
75199
+ import_fs75.default.closeSync(ttyFd);
74923
75200
  } catch {
74924
75201
  }
74925
75202
  const isCodex = agent2 === "Codex";
@@ -74938,17 +75215,17 @@ RAW: ${raw}
74938
75215
  process.exit(2);
74939
75216
  }
74940
75217
  const payloadCwd = typeof payload.cwd === "string" ? payload.cwd : Array.isArray(payload.workspacePaths) && typeof payload.workspacePaths[0] === "string" ? payload.workspacePaths[0] : void 0;
74941
- const safeCwdForConfig = typeof payloadCwd === "string" && import_path73.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
75218
+ const safeCwdForConfig = typeof payloadCwd === "string" && import_path75.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
74942
75219
  const config = getConfig(safeCwdForConfig);
74943
75220
  const daemonDown = !isDaemonRunning();
74944
75221
  if (config.settings.autoStartDaemon && daemonDown && !process.env.NODE9_NO_AUTO_DAEMON) {
74945
75222
  try {
74946
75223
  const scriptPath = process.argv[1];
74947
- if (typeof scriptPath !== "string" || !import_path73.default.isAbsolute(scriptPath))
75224
+ if (typeof scriptPath !== "string" || !import_path75.default.isAbsolute(scriptPath))
74948
75225
  throw new Error("node9: argv[1] is not an absolute path");
74949
- const resolvedScript = import_fs73.default.realpathSync(scriptPath);
74950
- const packageDist = import_fs73.default.realpathSync(import_path73.default.resolve(__dirname, "../.."));
74951
- if (!resolvedScript.startsWith(packageDist + import_path73.default.sep) && resolvedScript !== packageDist)
75226
+ const resolvedScript = import_fs75.default.realpathSync(scriptPath);
75227
+ const packageDist = import_fs75.default.realpathSync(import_path75.default.resolve(__dirname, "../.."));
75228
+ if (!resolvedScript.startsWith(packageDist + import_path75.default.sep) && resolvedScript !== packageDist)
74952
75229
  throw new Error(
74953
75230
  `node9: daemon spawn aborted \u2014 argv[1] (${resolvedScript}) is outside package dist (${packageDist})`
74954
75231
  );
@@ -74978,17 +75255,17 @@ RAW: ${raw}
74978
75255
  } finally {
74979
75256
  if (startupFd !== void 0) {
74980
75257
  try {
74981
- import_fs73.default.closeSync(startupFd);
75258
+ import_fs75.default.closeSync(startupFd);
74982
75259
  } catch {
74983
75260
  }
74984
75261
  }
74985
75262
  }
74986
75263
  } catch (spawnErr) {
74987
- const logPath = import_path73.default.join(import_os61.default.homedir(), ".node9", "hook-debug.log");
75264
+ const logPath = import_path75.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
74988
75265
  const msg = spawnErr instanceof Error ? spawnErr.message : String(spawnErr);
74989
75266
  recordStartupState("failed", "spawn-aborted", msg);
74990
75267
  try {
74991
- import_fs73.default.appendFileSync(
75268
+ import_fs75.default.appendFileSync(
74992
75269
  logPath,
74993
75270
  `[${(/* @__PURE__ */ new Date()).toISOString()}] daemon-autostart-failed: ${msg}
74994
75271
  `
@@ -75002,10 +75279,10 @@ RAW: ${raw}
75002
75279
  );
75003
75280
  }
75004
75281
  if (process.env.NODE9_DEBUG === "1" || config.settings.enableHookLogDebug) {
75005
- const logPath = import_path73.default.join(import_os61.default.homedir(), ".node9", "hook-debug.log");
75006
- if (!import_fs73.default.existsSync(import_path73.default.dirname(logPath)))
75007
- import_fs73.default.mkdirSync(import_path73.default.dirname(logPath), { recursive: true });
75008
- import_fs73.default.appendFileSync(
75282
+ const logPath = import_path75.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
75283
+ if (!import_fs75.default.existsSync(import_path75.default.dirname(logPath)))
75284
+ import_fs75.default.mkdirSync(import_path75.default.dirname(logPath), { recursive: true });
75285
+ import_fs75.default.appendFileSync(
75009
75286
  logPath,
75010
75287
  `[${(/* @__PURE__ */ new Date()).toISOString()}] STDIN: ${JSON.stringify(raw)}
75011
75288
  `
@@ -75026,8 +75303,8 @@ RAW: ${raw}
75026
75303
  );
75027
75304
  let ttyFd = null;
75028
75305
  try {
75029
- ttyFd = import_fs73.default.openSync("/dev/tty", "w");
75030
- const writeTty = (line) => import_fs73.default.writeSync(ttyFd, line + "\n");
75306
+ ttyFd = import_fs75.default.openSync("/dev/tty", "w");
75307
+ const writeTty = (line) => import_fs75.default.writeSync(ttyFd, line + "\n");
75031
75308
  if (result2?.blockKind === "protected-path") {
75032
75309
  writeTty(
75033
75310
  import_chalk14.default.red.bold(
@@ -75054,7 +75331,7 @@ RAW: ${raw}
75054
75331
  } finally {
75055
75332
  if (ttyFd !== null)
75056
75333
  try {
75057
- import_fs73.default.closeSync(ttyFd);
75334
+ import_fs75.default.closeSync(ttyFd);
75058
75335
  } catch {
75059
75336
  }
75060
75337
  }
@@ -75063,7 +75340,12 @@ RAW: ${raw}
75063
75340
  humanDecision,
75064
75341
  msg,
75065
75342
  result2?.recoveryCommand,
75066
- { kind: result2?.blockKind, path: result2?.blockedPath, redirect: !!result2?.redirect }
75343
+ {
75344
+ kind: result2?.blockKind,
75345
+ path: result2?.blockedPath,
75346
+ redirect: !!result2?.redirect,
75347
+ ruleDescription: result2?.ruleDescription
75348
+ }
75067
75349
  );
75068
75350
  if (agent === "Antigravity") {
75069
75351
  process.stdout.write(
@@ -75080,11 +75362,13 @@ RAW: ${raw}
75080
75362
  );
75081
75363
  process.exit(0);
75082
75364
  }
75365
+ const userLine = userLineOf(aiFeedbackMessage);
75083
75366
  process.stdout.write(
75084
75367
  JSON.stringify({
75085
75368
  decision: "block",
75086
75369
  reason: aiFeedbackMessage,
75087
75370
  // This is the core instruction
75371
+ ...agent === "Claude Code" && userLine ? { systemMessage: userLine } : {},
75088
75372
  hookSpecificOutput: {
75089
75373
  hookEventName: "PreToolUse",
75090
75374
  permissionDecision: "deny",
@@ -75118,8 +75402,8 @@ RAW: ${raw}
75118
75402
  } catch {
75119
75403
  }
75120
75404
  try {
75121
- const ttyFd = import_fs73.default.openSync("/dev/tty", "w");
75122
- import_fs73.default.writeSync(
75405
+ const ttyFd = import_fs75.default.openSync("/dev/tty", "w");
75406
+ import_fs75.default.writeSync(
75123
75407
  ttyFd,
75124
75408
  import_chalk14.default.yellow(
75125
75409
  `
@@ -75127,7 +75411,7 @@ RAW: ${raw}
75127
75411
  `
75128
75412
  )
75129
75413
  );
75130
- import_fs73.default.closeSync(ttyFd);
75414
+ import_fs75.default.closeSync(ttyFd);
75131
75415
  } catch {
75132
75416
  }
75133
75417
  if (agent === "GitHub Copilot") {
@@ -75159,17 +75443,20 @@ RAW: ${raw}
75159
75443
  const safeSessionId = /^[A-Za-z0-9_\-]{1,128}$/.test(rawSessionId) ? rawSessionId : "";
75160
75444
  if (skillPinCfg.enabled && safeSessionId) {
75161
75445
  try {
75162
- const sessionsDir = import_path73.default.join(import_os61.default.homedir(), ".node9", "skill-sessions");
75163
- const flagPath = import_path73.default.join(sessionsDir, `${safeSessionId}.json`);
75446
+ const sessionsDir = import_path75.default.join(import_os62.default.homedir(), ".node9", "skill-sessions");
75447
+ const flagPath = import_path75.default.join(sessionsDir, `${safeSessionId}${SESSION_FLAG_SUFFIX}`);
75448
+ const memo = ensureOwnDir(sessionsDir);
75164
75449
  let flag = null;
75165
75450
  try {
75166
- flag = JSON.parse(import_fs73.default.readFileSync(flagPath, "utf-8"));
75451
+ const st = memo ? import_fs75.default.lstatSync(flagPath) : null;
75452
+ if (st && st.isFile() && st.nlink === 1)
75453
+ flag = JSON.parse(import_fs75.default.readFileSync(flagPath, "utf-8"));
75167
75454
  } catch {
75168
75455
  }
75169
75456
  const writeFlag = (data2) => {
75457
+ if (!memo || !isSameOwnDir(sessionsDir, memo)) return;
75170
75458
  try {
75171
- import_fs73.default.mkdirSync(sessionsDir, { recursive: true });
75172
- import_fs73.default.writeFileSync(
75459
+ atomicWriteSync(
75173
75460
  flagPath,
75174
75461
  JSON.stringify({ ...data2, timestamp: (/* @__PURE__ */ new Date()).toISOString() }, null, 2),
75175
75462
  { mode: 384 }
@@ -75180,8 +75467,8 @@ RAW: ${raw}
75180
75467
  const sendSkillWarn = (detail, recoveryCmd) => {
75181
75468
  let ttyFd = null;
75182
75469
  try {
75183
- ttyFd = import_fs73.default.openSync("/dev/tty", "w");
75184
- const w = (line) => import_fs73.default.writeSync(ttyFd, line + "\n");
75470
+ ttyFd = import_fs75.default.openSync("/dev/tty", "w");
75471
+ const w = (line) => import_fs75.default.writeSync(ttyFd, line + "\n");
75185
75472
  w(import_chalk14.default.yellow(`
75186
75473
  \u26A0\uFE0F Node9: installed skill drift detected`));
75187
75474
  w(import_chalk14.default.gray(` ${detail}`));
@@ -75196,7 +75483,7 @@ RAW: ${raw}
75196
75483
  } finally {
75197
75484
  if (ttyFd !== null)
75198
75485
  try {
75199
- import_fs73.default.closeSync(ttyFd);
75486
+ import_fs75.default.closeSync(ttyFd);
75200
75487
  } catch {
75201
75488
  }
75202
75489
  }
@@ -75212,7 +75499,7 @@ RAW: ${raw}
75212
75499
  return;
75213
75500
  }
75214
75501
  if (!flag || flag.state !== "verified" && flag.state !== "warned") {
75215
- const absoluteCwd = typeof payloadCwd === "string" && import_path73.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
75502
+ const absoluteCwd = typeof payloadCwd === "string" && import_path75.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
75216
75503
  const extraRoots = skillPinCfg.roots;
75217
75504
  const resolvedExtra = extraRoots.map((r) => resolveUserSkillRoot(r, absoluteCwd)).filter((r) => typeof r === "string");
75218
75505
  const roots = [...defaultSkillRoots(absoluteCwd), ...resolvedExtra];
@@ -75251,31 +75538,27 @@ RAW: ${raw}
75251
75538
  } else {
75252
75539
  writeFlag({ state: "verified" });
75253
75540
  }
75254
- try {
75255
- const cutoff = Date.now() - 7 * 24 * 60 * 60 * 1e3;
75256
- for (const name of import_fs73.default.readdirSync(sessionsDir)) {
75257
- const p = import_path73.default.join(sessionsDir, name);
75258
- try {
75259
- if (import_fs73.default.statSync(p).mtimeMs < cutoff) import_fs73.default.unlinkSync(p);
75260
- } catch {
75261
- }
75541
+ if (memo)
75542
+ try {
75543
+ const cutoff = Date.now() - 7 * 24 * 60 * 60 * 1e3;
75544
+ for (const name of import_fs75.default.readdirSync(sessionsDir))
75545
+ removeOldFlag(sessionsDir, memo, name, cutoff);
75546
+ } catch {
75262
75547
  }
75263
- } catch {
75264
- }
75265
75548
  }
75266
75549
  } catch (err2) {
75267
75550
  if (process.env.NODE9_DEBUG === "1") {
75268
75551
  try {
75269
- const dbg = import_path73.default.join(import_os61.default.homedir(), ".node9", "hook-debug.log");
75552
+ const dbg = import_path75.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
75270
75553
  const msg = err2 instanceof Error ? err2.message : String(err2);
75271
- import_fs73.default.appendFileSync(dbg, `[${(/* @__PURE__ */ new Date()).toISOString()}] SKILL_PIN_ERROR: ${msg}
75554
+ import_fs75.default.appendFileSync(dbg, `[${(/* @__PURE__ */ new Date()).toISOString()}] SKILL_PIN_ERROR: ${msg}
75272
75555
  `);
75273
75556
  } catch {
75274
75557
  }
75275
75558
  }
75276
75559
  }
75277
75560
  }
75278
- const safeCwdForAuth = typeof payloadCwd === "string" && import_path73.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
75561
+ const safeCwdForAuth = typeof payloadCwd === "string" && import_path75.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
75279
75562
  const askMode = resolveAskMode(agent, opts, config);
75280
75563
  const result = await authorizeHeadless(toolName, toolInput, meta, {
75281
75564
  cwd: safeCwdForAuth,
@@ -75288,11 +75571,22 @@ RAW: ${raw}
75288
75571
  } catch {
75289
75572
  }
75290
75573
  }
75574
+ const isSubagentCall = typeof payload.agent_id === "string" && payload.agent_id !== "";
75575
+ const allowExit = (checkedBy) => {
75576
+ const notice = checkedBy !== "paused" && agent === "Claude Code" && !isSubagentCall && sessionNoticeEnabled() ? claimSessionNotice(safeSessionId, import_os62.default.homedir(), levelOf(config.settings.mode)) : null;
75577
+ if (notice) {
75578
+ try {
75579
+ import_fs75.default.writeSync(1, sessionNoticeOutput(config.settings.mode, notice) + "\n");
75580
+ } catch {
75581
+ }
75582
+ }
75583
+ process.exit(0);
75584
+ };
75291
75585
  if (result.approved) {
75292
75586
  if (result.checkedBy && process.env.NODE9_DEBUG === "1")
75293
75587
  process.stderr.write(`\u2713 node9 [${result.checkedBy}]: "${toolName}" allowed
75294
75588
  `);
75295
- process.exit(0);
75589
+ allowExit(result.checkedBy);
75296
75590
  }
75297
75591
  if (result.review) {
75298
75592
  sendAsk(result);
@@ -75300,12 +75594,12 @@ RAW: ${raw}
75300
75594
  }
75301
75595
  if (result.noApprovalMechanism && !isDaemonRunning() && !process.env.NODE9_NO_AUTO_DAEMON && !process.stdout.isTTY && config.settings.autoStartDaemon) {
75302
75596
  try {
75303
- const tty = import_fs73.default.openSync("/dev/tty", "w");
75304
- import_fs73.default.writeSync(
75597
+ const tty = import_fs75.default.openSync("/dev/tty", "w");
75598
+ import_fs75.default.writeSync(
75305
75599
  tty,
75306
75600
  import_chalk14.default.cyan("\n\u{1F6E1}\uFE0F Node9: Starting approval daemon automatically...\n")
75307
75601
  );
75308
- import_fs73.default.closeSync(tty);
75602
+ import_fs75.default.closeSync(tty);
75309
75603
  } catch {
75310
75604
  }
75311
75605
  const daemonReady = await autoStartDaemonAndWait();
@@ -75317,7 +75611,7 @@ RAW: ${raw}
75317
75611
  if (retry.checkedBy && process.env.NODE9_DEBUG === "1")
75318
75612
  process.stderr.write(`\u2713 node9 [${retry.checkedBy}]: "${toolName}" allowed
75319
75613
  `);
75320
- process.exit(0);
75614
+ allowExit(retry.checkedBy);
75321
75615
  }
75322
75616
  sendBlock(retry.reason ?? `Node9 blocked "${toolName}".`, {
75323
75617
  ...retry,
@@ -75332,9 +75626,9 @@ RAW: ${raw}
75332
75626
  });
75333
75627
  } catch (err2) {
75334
75628
  if (process.env.NODE9_DEBUG === "1") {
75335
- const logPath = import_path73.default.join(import_os61.default.homedir(), ".node9", "hook-debug.log");
75629
+ const logPath = import_path75.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
75336
75630
  const errMsg = err2 instanceof Error ? err2.message : String(err2);
75337
- import_fs73.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] ERROR: ${errMsg}
75631
+ import_fs75.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] ERROR: ${errMsg}
75338
75632
  `);
75339
75633
  }
75340
75634
  process.exit(0);
@@ -75369,9 +75663,9 @@ RAW: ${raw}
75369
75663
 
75370
75664
  // src/cli/commands/log.ts
75371
75665
  init_cjs_shims();
75372
- var import_fs74 = __toESM(require("fs"));
75373
- var import_path74 = __toESM(require("path"));
75374
- var import_os62 = __toESM(require("os"));
75666
+ var import_fs76 = __toESM(require("fs"));
75667
+ var import_path76 = __toESM(require("path"));
75668
+ var import_os63 = __toESM(require("os"));
75375
75669
  init_audit();
75376
75670
  init_config();
75377
75671
  init_daemon();
@@ -75651,12 +75945,12 @@ function registerLogCommand(program2) {
75651
75945
  if (rawToolName !== tool) entry.agentToolName = rawToolName;
75652
75946
  const payloadSessionId = payload.session_id ?? payload.conversationId;
75653
75947
  if (payloadSessionId) entry.sessionId = payloadSessionId;
75654
- const logPath = import_path74.default.join(import_os62.default.homedir(), ".node9", "audit.log");
75655
- if (!import_fs74.default.existsSync(import_path74.default.dirname(logPath)))
75656
- import_fs74.default.mkdirSync(import_path74.default.dirname(logPath), { recursive: true });
75657
- import_fs74.default.appendFileSync(logPath, JSON.stringify(entry) + "\n");
75948
+ const logPath = import_path76.default.join(import_os63.default.homedir(), ".node9", "audit.log");
75949
+ if (!import_fs76.default.existsSync(import_path76.default.dirname(logPath)))
75950
+ import_fs76.default.mkdirSync(import_path76.default.dirname(logPath), { recursive: true });
75951
+ import_fs76.default.appendFileSync(logPath, JSON.stringify(entry) + "\n");
75658
75952
  const payloadCwd = typeof payload.cwd === "string" ? payload.cwd : Array.isArray(payload.workspacePaths) && typeof payload.workspacePaths[0] === "string" ? payload.workspacePaths[0] : void 0;
75659
- const safeCwd = typeof payloadCwd === "string" && import_path74.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
75953
+ const safeCwd = typeof payloadCwd === "string" && import_path76.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
75660
75954
  if ((tool === "Bash" || tool === "bash") && isDaemonRunning()) {
75661
75955
  const command = typeof rawInput === "object" && rawInput !== null && "command" in rawInput && typeof rawInput.command === "string" ? rawInput.command : null;
75662
75956
  if (command) {
@@ -75877,9 +76171,9 @@ function registerLogCommand(program2) {
75877
76171
  const msg = err2 instanceof Error ? err2.message : String(err2);
75878
76172
  process.stderr.write(`[Node9] audit log error: ${msg}
75879
76173
  `);
75880
- const debugPath = import_path74.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
76174
+ const debugPath = import_path76.default.join(import_os63.default.homedir(), ".node9", "hook-debug.log");
75881
76175
  try {
75882
- import_fs74.default.appendFileSync(debugPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] LOG_ERROR: ${msg}
76176
+ import_fs76.default.appendFileSync(debugPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] LOG_ERROR: ${msg}
75883
76177
  `);
75884
76178
  } catch {
75885
76179
  }
@@ -75902,9 +76196,9 @@ function registerLogCommand(program2) {
75902
76196
  });
75903
76197
  }
75904
76198
  function absolutePathFor(spelled, cwd) {
75905
- const expanded = spelled === "~" || spelled.startsWith("~/") ? import_path74.default.join(import_os62.default.homedir(), spelled.slice(1)) : spelled;
75906
- if (import_path74.default.isAbsolute(expanded)) return expanded;
75907
- return cwd ? import_path74.default.resolve(cwd, expanded) : import_path74.default.resolve(expanded);
76199
+ const expanded = spelled === "~" || spelled.startsWith("~/") ? import_path76.default.join(import_os63.default.homedir(), spelled.slice(1)) : spelled;
76200
+ if (import_path76.default.isAbsolute(expanded)) return expanded;
76201
+ return cwd ? import_path76.default.resolve(cwd, expanded) : import_path76.default.resolve(expanded);
75908
76202
  }
75909
76203
  async function carryTaintAcrossWrites(command, cwd) {
75910
76204
  let pairs;
@@ -75923,23 +76217,23 @@ async function carryTaintAcrossWrites(command, cwd) {
75923
76217
  continue;
75924
76218
  }
75925
76219
  const sensitive = scanFilePath(src, cwd);
75926
- if (sensitive) await notifyTaint(dst, `copy:${sensitive.patternName}:${import_path74.default.basename(src)}`);
76220
+ if (sensitive) await notifyTaint(dst, `copy:${sensitive.patternName}:${import_path76.default.basename(src)}`);
75927
76221
  }
75928
76222
  }
75929
76223
 
75930
76224
  // src/cli/commands/shield.ts
75931
76225
  init_cjs_shims();
75932
76226
  var import_chalk16 = __toESM(require("chalk"));
75933
- var import_fs76 = __toESM(require("fs"));
75934
- var import_path76 = __toESM(require("path"));
75935
- var import_os63 = __toESM(require("os"));
76227
+ var import_fs78 = __toESM(require("fs"));
76228
+ var import_path78 = __toESM(require("path"));
76229
+ var import_os64 = __toESM(require("os"));
75936
76230
  init_shields();
75937
76231
  init_build();
75938
76232
 
75939
76233
  // src/shields/create.ts
75940
76234
  init_cjs_shims();
75941
- var import_fs75 = __toESM(require("fs"));
75942
- var import_path75 = __toESM(require("path"));
76235
+ var import_fs77 = __toESM(require("fs"));
76236
+ var import_path77 = __toESM(require("path"));
75943
76237
  init_dist();
75944
76238
  init_shields();
75945
76239
  init_audit();
@@ -75959,8 +76253,8 @@ function createShield(def, opts = {}) {
75959
76253
  error: `"${name}" is a built-in shield \u2014 choose a different name (a user shield with this name would shadow the built-in).`
75960
76254
  };
75961
76255
  }
75962
- const filePath = import_path75.default.join(USER_SHIELDS_DIR_PATH, `${name}.json`);
75963
- if (!opts.overwrite && import_fs75.default.existsSync(filePath)) {
76256
+ const filePath = import_path77.default.join(USER_SHIELDS_DIR_PATH, `${name}.json`);
76257
+ if (!opts.overwrite && import_fs77.default.existsSync(filePath)) {
75964
76258
  return {
75965
76259
  ok: false,
75966
76260
  error: `Shield "${name}" already exists at ${filePath}. Pass --overwrite to replace it.`
@@ -76058,8 +76352,8 @@ var COMMUNITY_INDEX_URL = "https://raw.githubusercontent.com/node9ai/node9-proxy
76058
76352
  function readCloudShields() {
76059
76353
  const out = /* @__PURE__ */ new Set();
76060
76354
  try {
76061
- const file2 = import_path76.default.join(import_os63.default.homedir(), ".node9", "rules-cache.json");
76062
- const raw = JSON.parse(import_fs76.default.readFileSync(file2, "utf-8"));
76355
+ const file2 = import_path78.default.join(import_os64.default.homedir(), ".node9", "rules-cache.json");
76356
+ const raw = JSON.parse(import_fs78.default.readFileSync(file2, "utf-8"));
76063
76357
  for (const r of raw.rules ?? []) {
76064
76358
  const rule = r;
76065
76359
  const fromSource = rule.source?.startsWith("SHIELD:") ? rule.source.slice("SHIELD:".length).toLowerCase() : void 0;
@@ -76396,7 +76690,7 @@ function registerShieldCommand(program2) {
76396
76690
  if (opts.fromFile) {
76397
76691
  let raw;
76398
76692
  try {
76399
- raw = JSON.parse(import_fs76.default.readFileSync(opts.fromFile, "utf-8"));
76693
+ raw = JSON.parse(import_fs78.default.readFileSync(opts.fromFile, "utf-8"));
76400
76694
  } catch (err2) {
76401
76695
  console.error(
76402
76696
  import_chalk16.default.red(`
@@ -76744,9 +77038,9 @@ init_migrate();
76744
77038
  // src/cli/commands/doctor.ts
76745
77039
  init_cjs_shims();
76746
77040
  var import_chalk19 = __toESM(require("chalk"));
76747
- var import_fs78 = __toESM(require("fs"));
76748
- var import_path78 = __toESM(require("path"));
76749
- var import_os65 = __toESM(require("os"));
77041
+ var import_fs80 = __toESM(require("fs"));
77042
+ var import_path80 = __toESM(require("path"));
77043
+ var import_os66 = __toESM(require("os"));
76750
77044
  var import_child_process10 = require("child_process");
76751
77045
  init_daemon();
76752
77046
  init_build_id();
@@ -76775,22 +77069,22 @@ init_startup_log();
76775
77069
 
76776
77070
  // src/utils/undo-leftovers.ts
76777
77071
  init_cjs_shims();
76778
- var import_fs77 = __toESM(require("fs"));
76779
- var import_os64 = __toESM(require("os"));
76780
- var import_path77 = __toESM(require("path"));
77072
+ var import_fs79 = __toESM(require("fs"));
77073
+ var import_os65 = __toESM(require("os"));
77074
+ var import_path79 = __toESM(require("path"));
76781
77075
  function candidates(homeDir2) {
76782
- const node9Dir = import_path77.default.join(homeDir2, ".node9");
77076
+ const node9Dir = import_path79.default.join(homeDir2, ".node9");
76783
77077
  return [
76784
- import_path77.default.join(node9Dir, "snapshots"),
76785
- import_path77.default.join(node9Dir, "snapshots.json"),
76786
- import_path77.default.join(node9Dir, "undo_latest.txt")
77078
+ import_path79.default.join(node9Dir, "snapshots"),
77079
+ import_path79.default.join(node9Dir, "snapshots.json"),
77080
+ import_path79.default.join(node9Dir, "undo_latest.txt")
76787
77081
  ];
76788
77082
  }
76789
- function undoLeftoverPaths(homeDir2 = import_os64.default.homedir()) {
77083
+ function undoLeftoverPaths(homeDir2 = import_os65.default.homedir()) {
76790
77084
  const found = [];
76791
77085
  for (const p of candidates(homeDir2)) {
76792
77086
  try {
76793
- import_fs77.default.lstatSync(p);
77087
+ import_fs79.default.lstatSync(p);
76794
77088
  found.push(p);
76795
77089
  } catch (err2) {
76796
77090
  if (err2.code !== "ENOENT") found.push(p);
@@ -76798,11 +77092,11 @@ function undoLeftoverPaths(homeDir2 = import_os64.default.homedir()) {
76798
77092
  }
76799
77093
  return found;
76800
77094
  }
76801
- function purgeUndoLeftovers(homeDir2 = import_os64.default.homedir()) {
77095
+ function purgeUndoLeftovers(homeDir2 = import_os65.default.homedir()) {
76802
77096
  const out = { deleted: [], skipped: [], failed: [] };
76803
77097
  for (const p of undoLeftoverPaths(homeDir2)) {
76804
77098
  try {
76805
- if (import_fs77.default.lstatSync(p).isSymbolicLink()) {
77099
+ if (import_fs79.default.lstatSync(p).isSymbolicLink()) {
76806
77100
  out.skipped.push({
76807
77101
  path: p,
76808
77102
  reason: "is a symlink \u2014 remove it yourself so nothing else is followed"
@@ -76815,11 +77109,11 @@ function purgeUndoLeftovers(homeDir2 = import_os64.default.homedir()) {
76815
77109
  }
76816
77110
  let reason = null;
76817
77111
  try {
76818
- import_fs77.default.rmSync(p, { recursive: true, force: true });
77112
+ import_fs79.default.rmSync(p, { recursive: true, force: true });
76819
77113
  } catch (err2) {
76820
77114
  reason = err2.message;
76821
77115
  }
76822
- if (import_fs77.default.existsSync(p)) {
77116
+ if (import_fs79.default.existsSync(p)) {
76823
77117
  out.failed.push({ path: p, reason: reason ?? "still present after removal" });
76824
77118
  } else {
76825
77119
  out.deleted.push(p);
@@ -76835,7 +77129,7 @@ function keyRejected(health) {
76835
77129
  }
76836
77130
  function registerDoctorCommand(program2, version2) {
76837
77131
  program2.command("doctor").description("Check that Node9 is installed and configured correctly").action(async () => {
76838
- const homeDir2 = import_os65.default.homedir();
77132
+ const homeDir2 = import_os66.default.homedir();
76839
77133
  let failures = 0;
76840
77134
  let warnings = 0;
76841
77135
  function pass(msg) {
@@ -76889,10 +77183,10 @@ function registerDoctorCommand(program2, version2) {
76889
77183
  "Policy source: workspace config (app.node9.ai) \u2014 local config files govern operational settings only"
76890
77184
  );
76891
77185
  }
76892
- const globalConfigPath2 = import_path78.default.join(homeDir2, ".node9", "config.json");
76893
- if (import_fs78.default.existsSync(globalConfigPath2)) {
77186
+ const globalConfigPath2 = import_path80.default.join(homeDir2, ".node9", "config.json");
77187
+ if (import_fs80.default.existsSync(globalConfigPath2)) {
76894
77188
  try {
76895
- JSON.parse(import_fs78.default.readFileSync(globalConfigPath2, "utf-8"));
77189
+ JSON.parse(import_fs80.default.readFileSync(globalConfigPath2, "utf-8"));
76896
77190
  pass(
76897
77191
  wsGoverned ? "~/.node9/config.json found and valid (policy fields ignored \u2014 workspace governs)" : "~/.node9/config.json found and valid"
76898
77192
  );
@@ -76911,10 +77205,10 @@ function registerDoctorCommand(program2, version2) {
76911
77205
  "Remove them when ready: node9 undo --purge"
76912
77206
  );
76913
77207
  }
76914
- const projectConfigPath = import_path78.default.join(process.cwd(), "node9.config.json");
76915
- if (import_fs78.default.existsSync(projectConfigPath)) {
77208
+ const projectConfigPath = import_path80.default.join(process.cwd(), "node9.config.json");
77209
+ if (import_fs80.default.existsSync(projectConfigPath)) {
76916
77210
  try {
76917
- JSON.parse(import_fs78.default.readFileSync(projectConfigPath, "utf-8"));
77211
+ JSON.parse(import_fs80.default.readFileSync(projectConfigPath, "utf-8"));
76918
77212
  pass("node9.config.json found and valid (project)");
76919
77213
  } catch {
76920
77214
  fail2(
@@ -76923,8 +77217,8 @@ function registerDoctorCommand(program2, version2) {
76923
77217
  );
76924
77218
  }
76925
77219
  }
76926
- const credsPath = import_path78.default.join(homeDir2, ".node9", "credentials.json");
76927
- if (import_fs78.default.existsSync(credsPath)) {
77220
+ const credsPath = import_path80.default.join(homeDir2, ".node9", "credentials.json");
77221
+ if (import_fs80.default.existsSync(credsPath)) {
76928
77222
  pass("Cloud credentials found (~/.node9/credentials.json)");
76929
77223
  } else {
76930
77224
  warn(
@@ -76978,7 +77272,7 @@ function registerDoctorCommand(program2, version2) {
76978
77272
  )
76979
77273
  );
76980
77274
  }
76981
- const cloudOn = import_fs78.default.existsSync(import_path78.default.join(homeDir2, ".node9", "credentials.json")) && !!getConfig().settings.approvers?.cloud;
77275
+ const cloudOn = import_fs80.default.existsSync(import_path80.default.join(homeDir2, ".node9", "credentials.json")) && !!getConfig().settings.approvers?.cloud;
76982
77276
  section(cloudOn ? "Daemon" : "Daemon (optional)");
76983
77277
  if (isDaemonRunning()) {
76984
77278
  pass(
@@ -77016,7 +77310,7 @@ function registerDoctorCommand(program2, version2) {
77016
77310
  cloudEnabled: !!getConfig().settings.approvers?.cloud
77017
77311
  });
77018
77312
  if (autostart) warn(autostart.message, autostart.hint);
77019
- if (import_fs78.default.existsSync(import_path78.default.join(import_os65.default.homedir(), ".node9", "credentials.json")) && getConfig().settings.approvers?.cloud) {
77313
+ if (import_fs80.default.existsSync(import_path80.default.join(import_os66.default.homedir(), ".node9", "credentials.json")) && getConfig().settings.approvers?.cloud) {
77020
77314
  section("Policy sync");
77021
77315
  const health = readSyncHealth();
77022
77316
  if (keyRejected(health)) {
@@ -77042,7 +77336,7 @@ function registerDoctorCommand(program2, version2) {
77042
77336
  try {
77043
77337
  const { shipLagBytes: shipLagBytes2, readWatermark: readWatermark2, AUDIT_SHIP_WATERMARK: AUDIT_SHIP_WATERMARK2 } = await Promise.resolve().then(() => (init_audit_shipper(), audit_shipper_exports));
77044
77338
  const cfg = getConfig();
77045
- const creds = import_fs78.default.existsSync(import_path78.default.join(import_os65.default.homedir(), ".node9", "credentials.json"));
77339
+ const creds = import_fs80.default.existsSync(import_path80.default.join(import_os66.default.homedir(), ".node9", "credentials.json"));
77046
77340
  if (!creds) {
77047
77341
  warn("Not logged in \u2014 audit rows stay local", "Run: node9 login <api-key>");
77048
77342
  } else if (!cfg.settings.approvers.cloud) {
@@ -77108,10 +77402,10 @@ function registerDoctorCommand(program2, version2) {
77108
77402
  // src/cli/commands/audit.ts
77109
77403
  init_cjs_shims();
77110
77404
  var import_chalk20 = __toESM(require("chalk"));
77111
- var import_fs79 = __toESM(require("fs"));
77112
- var import_path79 = __toESM(require("path"));
77405
+ var import_fs81 = __toESM(require("fs"));
77406
+ var import_path81 = __toESM(require("path"));
77113
77407
  init_decision();
77114
- var import_os66 = __toESM(require("os"));
77408
+ var import_os67 = __toESM(require("os"));
77115
77409
  function formatRelativeTime(timestamp2) {
77116
77410
  const diff = Date.now() - new Date(timestamp2).getTime();
77117
77411
  const sec = Math.floor(diff / 1e3);
@@ -77124,14 +77418,14 @@ function formatRelativeTime(timestamp2) {
77124
77418
  }
77125
77419
  function registerAuditCommand(program2) {
77126
77420
  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) => {
77127
- const logPath = import_path79.default.join(import_os66.default.homedir(), ".node9", "audit.log");
77128
- if (!import_fs79.default.existsSync(logPath)) {
77421
+ const logPath = import_path81.default.join(import_os67.default.homedir(), ".node9", "audit.log");
77422
+ if (!import_fs81.default.existsSync(logPath)) {
77129
77423
  console.log(
77130
77424
  import_chalk20.default.yellow("No audit logs found. Run node9 with an agent to generate entries.")
77131
77425
  );
77132
77426
  return;
77133
77427
  }
77134
- const raw = import_fs79.default.readFileSync(logPath, "utf-8");
77428
+ const raw = import_fs81.default.readFileSync(logPath, "utf-8");
77135
77429
  const lines = raw.split("\n").filter((l) => l.trim() !== "");
77136
77430
  let entries = lines.flatMap((line) => {
77137
77431
  try {
@@ -77194,7 +77488,7 @@ init_cjs_shims();
77194
77488
 
77195
77489
  // src/apps/report.ts
77196
77490
  init_cjs_shims();
77197
- var import_fs80 = __toESM(require("fs"));
77491
+ var import_fs82 = __toESM(require("fs"));
77198
77492
  init_catalog();
77199
77493
  init_dist();
77200
77494
  function appsReportLines(file2, activeShields, opts = {}) {
@@ -77224,17 +77518,17 @@ var AUDIT_TAIL_BYTES2 = 5 * 1024 * 1024;
77224
77518
  function readTail2(file2) {
77225
77519
  let fd;
77226
77520
  try {
77227
- fd = import_fs80.default.openSync(file2, "r");
77228
- const size = import_fs80.default.fstatSync(fd).size;
77521
+ fd = import_fs82.default.openSync(file2, "r");
77522
+ const size = import_fs82.default.fstatSync(fd).size;
77229
77523
  const start = Math.max(0, size - AUDIT_TAIL_BYTES2);
77230
77524
  const buf = Buffer.alloc(size - start);
77231
- import_fs80.default.readSync(fd, buf, 0, buf.length, start);
77525
+ import_fs82.default.readSync(fd, buf, 0, buf.length, start);
77232
77526
  const text = buf.toString("utf8");
77233
77527
  return start > 0 ? text.slice(text.indexOf("\n") + 1) : text;
77234
77528
  } catch {
77235
77529
  return "";
77236
77530
  } finally {
77237
- if (fd !== void 0) import_fs80.default.closeSync(fd);
77531
+ if (fd !== void 0) import_fs82.default.closeSync(fd);
77238
77532
  }
77239
77533
  }
77240
77534
  function approvalsFromAudit(auditFile, sinceMs) {
@@ -77289,21 +77583,21 @@ init_detect();
77289
77583
 
77290
77584
  // src/apps/nudges.ts
77291
77585
  init_cjs_shims();
77292
- var import_fs81 = __toESM(require("fs"));
77293
- var import_os67 = __toESM(require("os"));
77294
- var import_path80 = __toESM(require("path"));
77586
+ var import_fs83 = __toESM(require("fs"));
77587
+ var import_os68 = __toESM(require("os"));
77588
+ var import_path82 = __toESM(require("path"));
77295
77589
  var import_child_process11 = require("child_process");
77296
77590
  var UNANSWERED_AT = 3;
77297
77591
  var QUESTIONS_AT = 10;
77298
77592
  var TEAM_AUTHORS_AT = 2;
77299
77593
  var TEAM_PROJECTS = 5;
77300
77594
  var GIT_TIMEOUT_MS = 2e3;
77301
- function nudgesFilePath(home = import_os67.default.homedir()) {
77302
- return import_path80.default.join(home, ".node9", "nudges.json");
77595
+ function nudgesFilePath(home = import_os68.default.homedir()) {
77596
+ return import_path82.default.join(home, ".node9", "nudges.json");
77303
77597
  }
77304
77598
  function readShownNudges(home) {
77305
77599
  try {
77306
- const raw = JSON.parse(import_fs81.default.readFileSync(nudgesFilePath(home), "utf8"));
77600
+ const raw = JSON.parse(import_fs83.default.readFileSync(nudgesFilePath(home), "utf8"));
77307
77601
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) return /* @__PURE__ */ new Set();
77308
77602
  return new Set(
77309
77603
  Object.keys(raw).filter(
@@ -77318,14 +77612,14 @@ function markNudgeShown(key, home, now = /* @__PURE__ */ new Date()) {
77318
77612
  const file2 = nudgesFilePath(home);
77319
77613
  let data = {};
77320
77614
  try {
77321
- const raw = JSON.parse(import_fs81.default.readFileSync(file2, "utf8"));
77615
+ const raw = JSON.parse(import_fs83.default.readFileSync(file2, "utf8"));
77322
77616
  if (raw && typeof raw === "object" && !Array.isArray(raw)) data = raw;
77323
77617
  } catch {
77324
77618
  }
77325
77619
  data[key] = now.toISOString();
77326
77620
  try {
77327
- import_fs81.default.mkdirSync(import_path80.default.dirname(file2), { recursive: true });
77328
- import_fs81.default.writeFileSync(file2, JSON.stringify(data, null, 2) + "\n", { mode: 384 });
77621
+ import_fs83.default.mkdirSync(import_path82.default.dirname(file2), { recursive: true });
77622
+ import_fs83.default.writeFileSync(file2, JSON.stringify(data, null, 2) + "\n", { mode: 384 });
77329
77623
  } catch {
77330
77624
  }
77331
77625
  }
@@ -77346,7 +77640,7 @@ function recentAuthorCount(dir2) {
77346
77640
  }
77347
77641
  function teamProject(dirs, countAuthors = recentAuthorCount) {
77348
77642
  for (const dir2 of dirs.slice(0, TEAM_PROJECTS)) {
77349
- if (countAuthors(dir2) >= TEAM_AUTHORS_AT) return import_path80.default.basename(dir2);
77643
+ if (countAuthors(dir2) >= TEAM_AUTHORS_AT) return import_path82.default.basename(dir2);
77350
77644
  }
77351
77645
  return void 0;
77352
77646
  }
@@ -77381,9 +77675,9 @@ var import_chalk22 = __toESM(require("chalk"));
77381
77675
 
77382
77676
  // src/cli/aggregate/report-audit.ts
77383
77677
  init_cjs_shims();
77384
- var import_fs82 = __toESM(require("fs"));
77385
- var import_os68 = __toESM(require("os"));
77386
- var import_path81 = __toESM(require("path"));
77678
+ var import_fs84 = __toESM(require("fs"));
77679
+ var import_os69 = __toESM(require("os"));
77680
+ var import_path83 = __toESM(require("path"));
77387
77681
  init_costSync();
77388
77682
  init_litellm();
77389
77683
  init_cost_codex();
@@ -77468,8 +77762,8 @@ function getDateRange(period, now) {
77468
77762
  }
77469
77763
  }
77470
77764
  function parseAuditLog(logPath) {
77471
- if (!import_fs82.default.existsSync(logPath)) return [];
77472
- const raw = import_fs82.default.readFileSync(logPath, "utf-8");
77765
+ if (!import_fs84.default.existsSync(logPath)) return [];
77766
+ const raw = import_fs84.default.readFileSync(logPath, "utf-8");
77473
77767
  return raw.split("\n").flatMap((line) => {
77474
77768
  if (!line.trim()) return [];
77475
77769
  try {
@@ -77523,10 +77817,10 @@ function freezeClaudeCost(acc) {
77523
77817
  };
77524
77818
  }
77525
77819
  function processClaudeCostProject(proj, projectsDir, start, end, acc) {
77526
- const projPath = import_path81.default.join(projectsDir, proj);
77820
+ const projPath = import_path83.default.join(projectsDir, proj);
77527
77821
  let files;
77528
77822
  try {
77529
- const stat = import_fs82.default.statSync(projPath);
77823
+ const stat = import_fs84.default.statSync(projPath);
77530
77824
  if (!stat.isDirectory()) return;
77531
77825
  files = listSessionFiles(projPath);
77532
77826
  } catch {
@@ -77534,14 +77828,14 @@ function processClaudeCostProject(proj, projectsDir, start, end, acc) {
77534
77828
  }
77535
77829
  const startMs = start.getTime();
77536
77830
  for (const file2 of files) {
77537
- const filePath = import_path81.default.join(projPath, file2);
77831
+ const filePath = import_path83.default.join(projPath, file2);
77538
77832
  try {
77539
- if (import_fs82.default.statSync(filePath).mtimeMs < startMs) continue;
77833
+ if (import_fs84.default.statSync(filePath).mtimeMs < startMs) continue;
77540
77834
  } catch {
77541
77835
  continue;
77542
77836
  }
77543
77837
  try {
77544
- const raw = import_fs82.default.readFileSync(filePath, "utf-8");
77838
+ const raw = import_fs84.default.readFileSync(filePath, "utf-8");
77545
77839
  for (const line of raw.split("\n")) {
77546
77840
  if (!line.trim()) continue;
77547
77841
  let entry;
@@ -77591,10 +77885,10 @@ function processClaudeCostProject(proj, projectsDir, start, end, acc) {
77591
77885
  }
77592
77886
  function loadClaudeCost(start, end, projectsDir) {
77593
77887
  const acc = emptyClaudeCostAccumulator();
77594
- if (!import_fs82.default.existsSync(projectsDir)) return freezeClaudeCost(acc);
77888
+ if (!import_fs84.default.existsSync(projectsDir)) return freezeClaudeCost(acc);
77595
77889
  let dirs;
77596
77890
  try {
77597
- dirs = import_fs82.default.readdirSync(projectsDir);
77891
+ dirs = import_fs84.default.readdirSync(projectsDir);
77598
77892
  } catch {
77599
77893
  return freezeClaudeCost(acc);
77600
77894
  }
@@ -77606,7 +77900,7 @@ function loadClaudeCost(start, end, projectsDir) {
77606
77900
  function processCodexCostFile(filePath, start, end, acc) {
77607
77901
  let lines;
77608
77902
  try {
77609
- lines = import_fs82.default.readFileSync(filePath, "utf-8").split("\n");
77903
+ lines = import_fs84.default.readFileSync(filePath, "utf-8").split("\n");
77610
77904
  } catch {
77611
77905
  return;
77612
77906
  }
@@ -77681,13 +77975,13 @@ function freezeGeminiCost(acc) {
77681
77975
  function processGeminiCostFile(filePath, projectKey, start, end, acc) {
77682
77976
  const startMs = start.getTime();
77683
77977
  try {
77684
- if (import_fs82.default.statSync(filePath).mtimeMs < startMs) return;
77978
+ if (import_fs84.default.statSync(filePath).mtimeMs < startMs) return;
77685
77979
  } catch {
77686
77980
  return;
77687
77981
  }
77688
77982
  let raw;
77689
77983
  try {
77690
- raw = import_fs82.default.readFileSync(filePath, "utf-8");
77984
+ raw = import_fs84.default.readFileSync(filePath, "utf-8");
77691
77985
  } catch {
77692
77986
  return;
77693
77987
  }
@@ -77736,30 +78030,30 @@ function listGeminiSessionFiles2(geminiTmpDir2) {
77736
78030
  const out = [];
77737
78031
  let dirs;
77738
78032
  try {
77739
- if (!import_fs82.default.statSync(geminiTmpDir2).isDirectory()) return out;
77740
- dirs = import_fs82.default.readdirSync(geminiTmpDir2);
78033
+ if (!import_fs84.default.statSync(geminiTmpDir2).isDirectory()) return out;
78034
+ dirs = import_fs84.default.readdirSync(geminiTmpDir2);
77741
78035
  } catch {
77742
78036
  return out;
77743
78037
  }
77744
78038
  for (const proj of dirs) {
77745
- const chatsDir = import_path81.default.join(geminiTmpDir2, proj, "chats");
78039
+ const chatsDir = import_path83.default.join(geminiTmpDir2, proj, "chats");
77746
78040
  let files;
77747
78041
  try {
77748
- if (!import_fs82.default.statSync(chatsDir).isDirectory()) continue;
77749
- files = import_fs82.default.readdirSync(chatsDir);
78042
+ if (!import_fs84.default.statSync(chatsDir).isDirectory()) continue;
78043
+ files = import_fs84.default.readdirSync(chatsDir);
77750
78044
  } catch {
77751
78045
  continue;
77752
78046
  }
77753
78047
  for (const f of files) {
77754
78048
  if (!f.endsWith(".jsonl")) continue;
77755
- out.push({ projectKey: proj, file: import_path81.default.join(chatsDir, f) });
78049
+ out.push({ projectKey: proj, file: import_path83.default.join(chatsDir, f) });
77756
78050
  }
77757
78051
  }
77758
78052
  return out;
77759
78053
  }
77760
78054
  function loadGeminiCost(start, end, geminiTmpDir2) {
77761
78055
  const acc = emptyGeminiAccumulator();
77762
- if (!import_fs82.default.existsSync(geminiTmpDir2)) return freezeGeminiCost(acc);
78056
+ if (!import_fs84.default.existsSync(geminiTmpDir2)) return freezeGeminiCost(acc);
77763
78057
  for (const { projectKey, file: file2 } of listGeminiSessionFiles2(geminiTmpDir2)) {
77764
78058
  processGeminiCostFile(file2, projectKey, start, end, acc);
77765
78059
  }
@@ -77780,11 +78074,11 @@ function dimensionOfBlock(checkedBy, ruleName) {
77780
78074
  }
77781
78075
  function aggregateReportFromAudit(period, opts = {}) {
77782
78076
  const now = opts.now ?? /* @__PURE__ */ new Date();
77783
- const auditLogPath = opts.auditLogPath ?? import_path81.default.join(import_os68.default.homedir(), ".node9", "audit.log");
77784
- const claudeProjectsDir = opts.claudeProjectsDir ?? import_path81.default.join(import_os68.default.homedir(), ".claude", "projects");
78077
+ const auditLogPath = opts.auditLogPath ?? import_path83.default.join(import_os69.default.homedir(), ".node9", "audit.log");
78078
+ const claudeProjectsDir = opts.claudeProjectsDir ?? import_path83.default.join(import_os69.default.homedir(), ".claude", "projects");
77785
78079
  const codexSessionsDir2 = opts.codexSessionsDir ?? codexSessionsDir();
77786
- const geminiTmpDir2 = opts.geminiTmpDir ?? import_path81.default.join(import_os68.default.homedir(), ".gemini", "tmp");
77787
- const hasAuditFile = import_fs82.default.existsSync(auditLogPath);
78080
+ const geminiTmpDir2 = opts.geminiTmpDir ?? import_path83.default.join(import_os69.default.homedir(), ".gemini", "tmp");
78081
+ const hasAuditFile = import_fs84.default.existsSync(auditLogPath);
77788
78082
  const allEntries = opts.preloadedAuditEntries ?? parseAuditLog(auditLogPath);
77789
78083
  const unackedDlp = allEntries.filter((e) => e.source === "response-dlp");
77790
78084
  const { start, end } = getDateRange(period, now);
@@ -78070,10 +78364,10 @@ function buildReportJson(input) {
78070
78364
  // src/cli/commands/sessions.ts
78071
78365
  init_cjs_shims();
78072
78366
  var import_chalk21 = __toESM(require("chalk"));
78073
- var import_fs83 = __toESM(require("fs"));
78074
- var import_path82 = __toESM(require("path"));
78367
+ var import_fs85 = __toESM(require("fs"));
78368
+ var import_path84 = __toESM(require("path"));
78075
78369
  init_decision();
78076
- var import_os69 = __toESM(require("os"));
78370
+ var import_os70 = __toESM(require("os"));
78077
78371
  init_scan_summary();
78078
78372
  init_litellm();
78079
78373
  init_cost_gemini();
@@ -78094,10 +78388,10 @@ function encodeProjectPath(projectPath) {
78094
78388
  }
78095
78389
  function sessionJsonlPath(projectPath, sessionId) {
78096
78390
  const encoded = encodeProjectPath(projectPath);
78097
- return import_path82.default.join(import_os69.default.homedir(), ".claude", "projects", encoded, `${sessionId}.jsonl`);
78391
+ return import_path84.default.join(import_os70.default.homedir(), ".claude", "projects", encoded, `${sessionId}.jsonl`);
78098
78392
  }
78099
78393
  function projectLabel(projectPath) {
78100
- return projectPath.replace(import_os69.default.homedir(), "~");
78394
+ return projectPath.replace(import_os70.default.homedir(), "~");
78101
78395
  }
78102
78396
  function parseHistoryLines(lines) {
78103
78397
  const entries = [];
@@ -78166,10 +78460,10 @@ function parseSessionLines(lines) {
78166
78460
  return { toolCalls, costUSD, hasSnapshot, modifiedFiles };
78167
78461
  }
78168
78462
  function loadAuditEntries(auditPath) {
78169
- const aPath = auditPath ?? import_path82.default.join(import_os69.default.homedir(), ".node9", "audit.log");
78463
+ const aPath = auditPath ?? import_path84.default.join(import_os70.default.homedir(), ".node9", "audit.log");
78170
78464
  let raw;
78171
78465
  try {
78172
- raw = import_fs83.default.readFileSync(aPath, "utf-8");
78466
+ raw = import_fs85.default.readFileSync(aPath, "utf-8");
78173
78467
  } catch {
78174
78468
  return [];
78175
78469
  }
@@ -78205,8 +78499,8 @@ function auditEntriesInWindow(entries, windowStart, windowEnd) {
78205
78499
  return result;
78206
78500
  }
78207
78501
  function buildGeminiSessions(days, allAuditEntries) {
78208
- const tmpDir = import_path82.default.join(import_os69.default.homedir(), ".gemini", "tmp");
78209
- if (!import_fs83.default.existsSync(tmpDir)) return [];
78502
+ const tmpDir = import_path84.default.join(import_os70.default.homedir(), ".gemini", "tmp");
78503
+ if (!import_fs85.default.existsSync(tmpDir)) return [];
78210
78504
  const cutoff = days !== null ? (() => {
78211
78505
  const d = /* @__PURE__ */ new Date();
78212
78506
  d.setDate(d.getDate() - days);
@@ -78215,35 +78509,35 @@ function buildGeminiSessions(days, allAuditEntries) {
78215
78509
  })() : null;
78216
78510
  let slugDirs;
78217
78511
  try {
78218
- slugDirs = import_fs83.default.readdirSync(tmpDir);
78512
+ slugDirs = import_fs85.default.readdirSync(tmpDir);
78219
78513
  } catch {
78220
78514
  return [];
78221
78515
  }
78222
78516
  const summaries = [];
78223
78517
  for (const slug2 of slugDirs) {
78224
- const slugPath = import_path82.default.join(tmpDir, slug2);
78518
+ const slugPath = import_path84.default.join(tmpDir, slug2);
78225
78519
  try {
78226
- if (!import_fs83.default.statSync(slugPath).isDirectory()) continue;
78520
+ if (!import_fs85.default.statSync(slugPath).isDirectory()) continue;
78227
78521
  } catch {
78228
78522
  continue;
78229
78523
  }
78230
- let projectRoot = import_path82.default.join(import_os69.default.homedir(), slug2);
78524
+ let projectRoot = import_path84.default.join(import_os70.default.homedir(), slug2);
78231
78525
  try {
78232
- projectRoot = import_fs83.default.readFileSync(import_path82.default.join(slugPath, ".project_root"), "utf-8").trim();
78526
+ projectRoot = import_fs85.default.readFileSync(import_path84.default.join(slugPath, ".project_root"), "utf-8").trim();
78233
78527
  } catch {
78234
78528
  }
78235
- const chatsDir = import_path82.default.join(slugPath, "chats");
78236
- if (!import_fs83.default.existsSync(chatsDir)) continue;
78529
+ const chatsDir = import_path84.default.join(slugPath, "chats");
78530
+ if (!import_fs85.default.existsSync(chatsDir)) continue;
78237
78531
  let chatFiles;
78238
78532
  try {
78239
- chatFiles = import_fs83.default.readdirSync(chatsDir).filter((f) => f.endsWith(".json"));
78533
+ chatFiles = import_fs85.default.readdirSync(chatsDir).filter((f) => f.endsWith(".json"));
78240
78534
  } catch {
78241
78535
  continue;
78242
78536
  }
78243
78537
  for (const chatFile of chatFiles) {
78244
78538
  let raw;
78245
78539
  try {
78246
- raw = import_fs83.default.readFileSync(import_path82.default.join(chatsDir, chatFile), "utf-8");
78540
+ raw = import_fs85.default.readFileSync(import_path84.default.join(chatsDir, chatFile), "utf-8");
78247
78541
  } catch {
78248
78542
  continue;
78249
78543
  }
@@ -78334,7 +78628,7 @@ function buildCodexSessions(days, allAuditEntries) {
78334
78628
  for (const filePath of jsonlFiles) {
78335
78629
  let lines;
78336
78630
  try {
78337
- lines = import_fs83.default.readFileSync(filePath, "utf-8").split("\n");
78631
+ lines = import_fs85.default.readFileSync(filePath, "utf-8").split("\n");
78338
78632
  } catch {
78339
78633
  continue;
78340
78634
  }
@@ -78405,10 +78699,10 @@ function buildCodexSessions(days, allAuditEntries) {
78405
78699
  return summaries;
78406
78700
  }
78407
78701
  function buildSessions(days, historyPath) {
78408
- const hPath = historyPath ?? import_path82.default.join(import_os69.default.homedir(), ".claude", "history.jsonl");
78702
+ const hPath = historyPath ?? import_path84.default.join(import_os70.default.homedir(), ".claude", "history.jsonl");
78409
78703
  let historyRaw = "";
78410
78704
  try {
78411
- historyRaw = import_fs83.default.readFileSync(hPath, "utf-8");
78705
+ historyRaw = import_fs85.default.readFileSync(hPath, "utf-8");
78412
78706
  } catch {
78413
78707
  }
78414
78708
  const cutoff = days !== null ? (() => {
@@ -78432,7 +78726,7 @@ function buildSessions(days, historyPath) {
78432
78726
  const jsonlFile = sessionJsonlPath(entry.project, entry.sessionId);
78433
78727
  let sessionLines = [];
78434
78728
  try {
78435
- sessionLines = import_fs83.default.readFileSync(jsonlFile, "utf-8").split("\n");
78729
+ sessionLines = import_fs85.default.readFileSync(jsonlFile, "utf-8").split("\n");
78436
78730
  } catch {
78437
78731
  }
78438
78732
  const { toolCalls, costUSD, hasSnapshot, modifiedFiles } = parseSessionLines(sessionLines);
@@ -79223,7 +79517,7 @@ init_cjs_shims();
79223
79517
  var import_chalk23 = __toESM(require("chalk"));
79224
79518
  var import_child_process12 = require("child_process");
79225
79519
  init_daemon();
79226
- var import_fs84 = __toESM(require("fs"));
79520
+ var import_fs86 = __toESM(require("fs"));
79227
79521
  init_startup_log();
79228
79522
  init_daemon3();
79229
79523
  init_service();
@@ -79300,7 +79594,7 @@ function registerDaemonCommand(program2) {
79300
79594
  child.unref();
79301
79595
  if (restartFd !== void 0) {
79302
79596
  try {
79303
- import_fs84.default.closeSync(restartFd);
79597
+ import_fs86.default.closeSync(restartFd);
79304
79598
  } catch {
79305
79599
  }
79306
79600
  }
@@ -79351,7 +79645,7 @@ function registerDaemonCommand(program2) {
79351
79645
  } finally {
79352
79646
  if (startupFd !== void 0) {
79353
79647
  try {
79354
- import_fs84.default.closeSync(startupFd);
79648
+ import_fs86.default.closeSync(startupFd);
79355
79649
  } catch {
79356
79650
  }
79357
79651
  }
@@ -79366,9 +79660,9 @@ function registerDaemonCommand(program2) {
79366
79660
  // src/cli/commands/status.ts
79367
79661
  init_cjs_shims();
79368
79662
  var import_chalk24 = __toESM(require("chalk"));
79369
- var import_fs85 = __toESM(require("fs"));
79370
- var import_path83 = __toESM(require("path"));
79371
- var import_os70 = __toESM(require("os"));
79663
+ var import_fs87 = __toESM(require("fs"));
79664
+ var import_path85 = __toESM(require("path"));
79665
+ var import_os71 = __toESM(require("os"));
79372
79666
  init_core();
79373
79667
  init_daemon();
79374
79668
  init_build_id();
@@ -79469,20 +79763,20 @@ function registerStatusCommand(program2) {
79469
79763
  console.log(` Policy: ${import_chalk24.default.cyan("Workspace config (app.node9.ai)")}`);
79470
79764
  }
79471
79765
  const ignoredLabel = import_chalk24.default.gray("Present \u2014 ignored (workspace config governs)");
79472
- const projectConfig = import_path83.default.join(process.cwd(), "node9.config.json");
79473
- const globalConfig = import_path83.default.join(import_os70.default.homedir(), ".node9", "config.json");
79766
+ const projectConfig = import_path85.default.join(process.cwd(), "node9.config.json");
79767
+ const globalConfig = import_path85.default.join(import_os71.default.homedir(), ".node9", "config.json");
79474
79768
  console.log(
79475
- ` Local: ${import_fs85.default.existsSync(projectConfig) ? wsGoverned ? ignoredLabel : import_chalk24.default.green("Active (node9.config.json)") : import_chalk24.default.gray("Not present")}`
79769
+ ` Local: ${import_fs87.default.existsSync(projectConfig) ? wsGoverned ? ignoredLabel : import_chalk24.default.green("Active (node9.config.json)") : import_chalk24.default.gray("Not present")}`
79476
79770
  );
79477
79771
  console.log(
79478
- ` Global: ${import_fs85.default.existsSync(globalConfig) ? wsGoverned ? ignoredLabel : import_chalk24.default.green("Active (~/.node9/config.json)") : import_chalk24.default.gray("Not present")}`
79772
+ ` Global: ${import_fs87.default.existsSync(globalConfig) ? wsGoverned ? ignoredLabel : import_chalk24.default.green("Active (~/.node9/config.json)") : import_chalk24.default.gray("Not present")}`
79479
79773
  );
79480
79774
  if (mergedConfig.policy.sandboxPaths.length > 0) {
79481
79775
  console.log(
79482
79776
  ` Sandbox: ${import_chalk24.default.green(`${mergedConfig.policy.sandboxPaths.length} safe zones active`)}`
79483
79777
  );
79484
79778
  }
79485
- const wiring = getAgentWiring(import_os70.default.homedir()).filter((a) => a.present);
79779
+ const wiring = getAgentWiring(import_os71.default.homedir()).filter((a) => a.present);
79486
79780
  if (wiring.length > 0) {
79487
79781
  console.log("");
79488
79782
  console.log(import_chalk24.default.bold(" Agent Wiring:"));
@@ -79501,7 +79795,7 @@ function registerStatusCommand(program2) {
79501
79795
  a.mcpServers
79502
79796
  );
79503
79797
  if (a.id === "codex" && a.hooks.some((h) => h.wired)) {
79504
- const t = assessCodexTrust(import_os70.default.homedir());
79798
+ const t = assessCodexTrust(import_os71.default.homedir());
79505
79799
  if (t.state === "observed") {
79506
79800
  console.log(
79507
79801
  import_chalk24.default.green(
@@ -79545,7 +79839,7 @@ init_init();
79545
79839
  // src/cli/commands/heal.ts
79546
79840
  init_cjs_shims();
79547
79841
  var import_chalk25 = __toESM(require("chalk"));
79548
- var import_fs88 = __toESM(require("fs"));
79842
+ var import_fs90 = __toESM(require("fs"));
79549
79843
  init_agent_wiring();
79550
79844
  init_mcp_wrap();
79551
79845
  init_setup();
@@ -79553,7 +79847,7 @@ init_hook_baseline();
79553
79847
  var hasHookSurface = (a) => a.hooks.length > 0;
79554
79848
  function backupForHeal(file2) {
79555
79849
  try {
79556
- if (file2 && import_fs88.default.existsSync(file2)) import_fs88.default.copyFileSync(file2, `${file2}.node9-heal-bak`);
79850
+ if (file2 && import_fs90.default.existsSync(file2)) import_fs90.default.copyFileSync(file2, `${file2}.node9-heal-bak`);
79557
79851
  } catch {
79558
79852
  }
79559
79853
  }
@@ -80174,7 +80468,12 @@ async function runMcpGateway(upstreamCommand, configName) {
80174
80468
  humanDecision,
80175
80469
  result.reason,
80176
80470
  void 0,
80177
- { kind: result.blockKind, path: result.blockedPath, redirect: !!result.redirect }
80471
+ {
80472
+ kind: result.blockKind,
80473
+ path: result.blockedPath,
80474
+ redirect: !!result.redirect,
80475
+ ruleDescription: result.ruleDescription
80476
+ }
80178
80477
  );
80179
80478
  const errorResponse = {
80180
80479
  jsonrpc: "2.0",
@@ -80518,9 +80817,9 @@ init_cjs_shims();
80518
80817
  init_cjs_shims();
80519
80818
  var import_readline4 = __toESM(require("readline"));
80520
80819
  init_write();
80521
- var import_fs89 = __toESM(require("fs"));
80522
- var import_os75 = __toESM(require("os"));
80523
- var import_path88 = __toESM(require("path"));
80820
+ var import_fs91 = __toESM(require("fs"));
80821
+ var import_os76 = __toESM(require("os"));
80822
+ var import_path90 = __toESM(require("path"));
80524
80823
  var import_child_process14 = require("child_process");
80525
80824
  init_decision();
80526
80825
  init_core();
@@ -81071,14 +81370,14 @@ function handleStatus() {
81071
81370
  const state = !a.installed ? "not installed" : hooked ? "wired" : a.isProtected ? "protected through MCP" : "not wired";
81072
81371
  lines.push(` ${a.label}: ${state}`);
81073
81372
  }
81074
- const projectConfig = import_path88.default.join(process.cwd(), "node9.config.json");
81075
- const globalConfig = import_path88.default.join(import_os75.default.homedir(), ".node9", "config.json");
81373
+ const projectConfig = import_path90.default.join(process.cwd(), "node9.config.json");
81374
+ const globalConfig = import_path90.default.join(import_os76.default.homedir(), ".node9", "config.json");
81076
81375
  const presentLabel = wsGoverned ? "present \u2014 ignored (workspace config governs)" : "present";
81077
81376
  lines.push(
81078
- `Project config (node9.config.json): ${import_fs89.default.existsSync(projectConfig) ? presentLabel : "not found"}`
81377
+ `Project config (node9.config.json): ${import_fs91.default.existsSync(projectConfig) ? presentLabel : "not found"}`
81079
81378
  );
81080
81379
  lines.push(
81081
- `Global config (~/.node9/config.json): ${import_fs89.default.existsSync(globalConfig) ? presentLabel : "not found"}`
81380
+ `Global config (~/.node9/config.json): ${import_fs91.default.existsSync(globalConfig) ? presentLabel : "not found"}`
81082
81381
  );
81083
81382
  return lines.join("\n");
81084
81383
  }
@@ -81215,7 +81514,7 @@ function handleEgressDeny(args) {
81215
81514
  addEgressHost("deny", host2);
81216
81515
  return `Denied egress to ${host2} (deny always wins over allow).`;
81217
81516
  }
81218
- var GLOBAL_CONFIG_PATH2 = import_path88.default.join(import_os75.default.homedir(), ".node9", "config.json");
81517
+ var GLOBAL_CONFIG_PATH2 = import_path90.default.join(import_os76.default.homedir(), ".node9", "config.json");
81219
81518
  var APPROVER_CHANNELS2 = ["native", "browser", "cloud", "terminal"];
81220
81519
  function handleApproverList() {
81221
81520
  const config = getConfig();
@@ -81256,9 +81555,9 @@ function handleApproverSet(args) {
81256
81555
  function handleAuditGet(args) {
81257
81556
  const limit = Math.min(typeof args.limit === "number" ? args.limit : 20, 100);
81258
81557
  const filter = typeof args.filter === "string" && args.filter !== "all" ? args.filter : null;
81259
- const auditPath = import_path88.default.join(import_os75.default.homedir(), ".node9", "audit.log");
81260
- if (!import_fs89.default.existsSync(auditPath)) return "No audit log found.";
81261
- const rawLines = import_fs89.default.readFileSync(auditPath, "utf-8").trim().split("\n").filter(Boolean);
81558
+ const auditPath = import_path90.default.join(import_os76.default.homedir(), ".node9", "audit.log");
81559
+ if (!import_fs91.default.existsSync(auditPath)) return "No audit log found.";
81560
+ const rawLines = import_fs91.default.readFileSync(auditPath, "utf-8").trim().split("\n").filter(Boolean);
81262
81561
  const wanted = filter === "block" ? "deny" : filter;
81263
81562
  const parsed = [];
81264
81563
  for (const line of rawLines) {
@@ -81618,7 +81917,7 @@ function registerTrustCommand(program2) {
81618
81917
  init_cjs_shims();
81619
81918
  var import_chalk32 = __toESM(require("chalk"));
81620
81919
  init_mcp_pin();
81621
- var import_fs90 = __toESM(require("fs"));
81920
+ var import_fs92 = __toESM(require("fs"));
81622
81921
 
81623
81922
  // src/cli/commands/mcp-gateway-cmd.ts
81624
81923
  init_cjs_shims();
@@ -81827,7 +82126,7 @@ function registerMcpPinCommand(program2) {
81827
82126
  let repoCorrupt = false;
81828
82127
  if (found.source === "repo") {
81829
82128
  try {
81830
- const raw = import_fs90.default.readFileSync(found.path, "utf-8");
82129
+ const raw = import_fs92.default.readFileSync(found.path, "utf-8");
81831
82130
  const parsed = JSON.parse(raw);
81832
82131
  repoEntries = parsed.servers ?? {};
81833
82132
  } catch {
@@ -82279,8 +82578,8 @@ init_cjs_shims();
82279
82578
 
82280
82579
  // src/ci-check/fetch.ts
82281
82580
  init_cjs_shims();
82282
- var import_fs91 = __toESM(require("fs"));
82283
- var import_path89 = __toESM(require("path"));
82581
+ var import_fs93 = __toESM(require("fs"));
82582
+ var import_path91 = __toESM(require("path"));
82284
82583
  var import_node_child_process = require("child_process");
82285
82584
  var import_undici = __toESM(require_undici());
82286
82585
 
@@ -82480,8 +82779,8 @@ function isOfficialInstaller(u) {
82480
82779
  if (u.username || u.password) return false;
82481
82780
  const host2 = u.hostname.toLowerCase().replace(/^www\./, "");
82482
82781
  if (OFFICIAL_HOSTS.has(host2)) return true;
82483
- const path108 = OFFICIAL_PATHS[host2];
82484
- return !!path108 && path108.test(u.pathname);
82782
+ const path110 = OFFICIAL_PATHS[host2];
82783
+ return !!path110 && path110.test(u.pathname);
82485
82784
  }
82486
82785
  function onlyOfficialInstaller(s) {
82487
82786
  const urls = s.match(URL_RE3);
@@ -82672,21 +82971,21 @@ function appSkillDirsOf(paths, skillDirs) {
82672
82971
  }
82673
82972
  return apps;
82674
82973
  }
82675
- function isSkillSupportFile(path108, skillDirs, appDirs) {
82676
- if (!path108.endsWith(".md") || /(^|\/)[Ss][Kk][Ii][Ll][Ll]\.md$/.test(path108)) return false;
82677
- for (let d = path108.lastIndexOf("/"); d > 0; d = path108.lastIndexOf("/", d - 1)) {
82678
- const dir2 = path108.slice(0, d);
82974
+ function isSkillSupportFile(path110, skillDirs, appDirs) {
82975
+ if (!path110.endsWith(".md") || /(^|\/)[Ss][Kk][Ii][Ll][Ll]\.md$/.test(path110)) return false;
82976
+ for (let d = path110.lastIndexOf("/"); d > 0; d = path110.lastIndexOf("/", d - 1)) {
82977
+ const dir2 = path110.slice(0, d);
82679
82978
  if (!skillDirs.has(dir2)) continue;
82680
- return !appDirs?.has(dir2) || SKILL_LAYOUT_RE.test(path108.slice(d + 1));
82979
+ return !appDirs?.has(dir2) || SKILL_LAYOUT_RE.test(path110.slice(d + 1));
82681
82980
  }
82682
82981
  return false;
82683
82982
  }
82684
- function isAppDoc(path108, skillDirs, appDirs) {
82685
- if (!path108.endsWith(".md") || INSTRUCTION_FILE_RE.test(path108)) return false;
82686
- for (let d = path108.lastIndexOf("/"); d > 0; d = path108.lastIndexOf("/", d - 1)) {
82687
- const dir2 = path108.slice(0, d);
82983
+ function isAppDoc(path110, skillDirs, appDirs) {
82984
+ if (!path110.endsWith(".md") || INSTRUCTION_FILE_RE.test(path110)) return false;
82985
+ for (let d = path110.lastIndexOf("/"); d > 0; d = path110.lastIndexOf("/", d - 1)) {
82986
+ const dir2 = path110.slice(0, d);
82688
82987
  if (!skillDirs.has(dir2)) continue;
82689
- return appDirs.has(dir2) && !SKILL_LAYOUT_RE.test(path108.slice(d + 1));
82988
+ return appDirs.has(dir2) && !SKILL_LAYOUT_RE.test(path110.slice(d + 1));
82690
82989
  }
82691
82990
  return false;
82692
82991
  }
@@ -82709,20 +83008,20 @@ function namedDocs(dir2, skillMd) {
82709
83008
  return out;
82710
83009
  }
82711
83010
  var SCRIPT_EXT_RE = /\.(sh|bash|zsh|py|js|mjs|cjs|ts|rb|pl|ps1)$/i;
82712
- function isHookScript(path108) {
82713
- return /(^|\/)\.claude\/hooks\/.+/.test(path108) && SCRIPT_EXT_RE.test(path108);
82714
- }
82715
- function isSkillScript(path108, skillDirs) {
82716
- if (!SCRIPT_EXT_RE.test(path108)) return false;
82717
- for (let d = path108.lastIndexOf("/"); d > 0; d = path108.lastIndexOf("/", d - 1)) {
82718
- if (!skillDirs.has(path108.slice(0, d))) continue;
82719
- const rel = path108.slice(d + 1);
83011
+ function isHookScript(path110) {
83012
+ return /(^|\/)\.claude\/hooks\/.+/.test(path110) && SCRIPT_EXT_RE.test(path110);
83013
+ }
83014
+ function isSkillScript(path110, skillDirs) {
83015
+ if (!SCRIPT_EXT_RE.test(path110)) return false;
83016
+ for (let d = path110.lastIndexOf("/"); d > 0; d = path110.lastIndexOf("/", d - 1)) {
83017
+ if (!skillDirs.has(path110.slice(0, d))) continue;
83018
+ const rel = path110.slice(d + 1);
82720
83019
  return !rel.includes("/") || /^(scripts|bin)\//.test(rel);
82721
83020
  }
82722
83021
  return false;
82723
83022
  }
82724
- function isInstructionFile(path108, skillDirs, appDirs) {
82725
- return INSTRUCTION_FILE_RE.test(path108) || isSkillSupportFile(path108, skillDirs, appDirs);
83023
+ function isInstructionFile(path110, skillDirs, appDirs) {
83024
+ return INSTRUCTION_FILE_RE.test(path110) || isSkillSupportFile(path110, skillDirs, appDirs);
82726
83025
  }
82727
83026
  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;
82728
83027
  var FETCH_WORD_RE = /\b(curl|wget|iwr|invoke-webrequest)\b/gi;
@@ -82859,21 +83158,21 @@ function decodeSuspiciousBase64(text) {
82859
83158
  }
82860
83159
  return out;
82861
83160
  }
82862
- function mk2(rule, severity, title, signals, fix, path108, line) {
83161
+ function mk2(rule, severity, title, signals, fix, path110, line) {
82863
83162
  return {
82864
83163
  check: "CI-6",
82865
83164
  rule,
82866
83165
  dimension: "instructions",
82867
83166
  severity,
82868
83167
  title,
82869
- file: path108,
83168
+ file: path110,
82870
83169
  ...line ? { line } : {},
82871
83170
  signals,
82872
83171
  fix
82873
83172
  };
82874
83173
  }
82875
83174
  var lineAt = (text, i) => i >= 0 ? lineAtIndex(text, i) : void 0;
82876
- function analyzeInstructionFile(path108, content) {
83175
+ function analyzeInstructionFile(path110, content) {
82877
83176
  const findings = [];
82878
83177
  const decoded = decodeSuspiciousBase64(content);
82879
83178
  const glyph = homoglyphWord(content);
@@ -82887,7 +83186,7 @@ function analyzeInstructionFile(path108, content) {
82887
83186
  `\`${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`
82888
83187
  ],
82889
83188
  "Spell the word with plain Latin letters, or explain on the same line why the look-alikes are there.",
82890
- path108,
83189
+ path110,
82891
83190
  glyph.line
82892
83191
  )
82893
83192
  );
@@ -82901,7 +83200,7 @@ function analyzeInstructionFile(path108, content) {
82901
83200
  "contains Unicode tag characters (U+E0000\u2013E007F): an invisible instruction-smuggling channel with no legitimate use in text"
82902
83201
  ],
82903
83202
  "Remove the tag characters. Instruction files must be plain, reviewable text.",
82904
- path108,
83203
+ path110,
82905
83204
  lineAt(content, content.search(TAG_CHARS))
82906
83205
  )
82907
83206
  );
@@ -82915,7 +83214,7 @@ function analyzeInstructionFile(path108, content) {
82915
83214
  "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"
82916
83215
  ],
82917
83216
  "Remove the bidi override characters.",
82918
- path108,
83217
+ path110,
82919
83218
  lineAt(content, content.search(BIDI_OVERRIDE))
82920
83219
  )
82921
83220
  );
@@ -82929,7 +83228,7 @@ function analyzeInstructionFile(path108, content) {
82929
83228
  "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"
82930
83229
  ],
82931
83230
  "Confirm the bidi marks are legitimate RTL formatting; remove otherwise.",
82932
- path108,
83231
+ path110,
82933
83232
  lineAt(content, content.search(BIDI_EMBED_ISOLATE))
82934
83233
  )
82935
83234
  );
@@ -82945,7 +83244,7 @@ function analyzeInstructionFile(path108, content) {
82945
83244
  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)"
82946
83245
  ],
82947
83246
  "Remove the zero-width characters. Instruction files must be plain, reviewable text.",
82948
- path108,
83247
+ path110,
82949
83248
  lineAt(content, zw.first)
82950
83249
  )
82951
83250
  );
@@ -82964,7 +83263,7 @@ function analyzeInstructionFile(path108, content) {
82964
83263
  `contains a prompt-override / role-impersonation directive (\`${safeText(m[0].slice(0, 60).trim(), 60)}\`)${ovEnc ? ", concealed in a base64 blob" : ""}`
82965
83264
  ],
82966
83265
  "Remove the override text. An instruction file should not tell the agent to ignore its own rules.",
82967
- path108,
83266
+ path110,
82968
83267
  ov ? lineAt(content, ov.index) : void 0
82969
83268
  // concealed in base64: no line, never a wrong one
82970
83269
  )
@@ -82981,7 +83280,7 @@ function analyzeInstructionFile(path108, content) {
82981
83280
  `\`${safeText(fo[0].slice(0, 70).trim(), 70)}\`: fetch-and-obey, outside an install/setup section`
82982
83281
  ],
82983
83282
  "Do not instruct the agent to pipe remote content into a shell; pin and vendor scripts instead.",
82984
- path108,
83283
+ path110,
82985
83284
  lineAt(content, fo.index)
82986
83285
  )
82987
83286
  );
@@ -82997,7 +83296,7 @@ function analyzeInstructionFile(path108, content) {
82997
83296
  `references \`${safeText(sp[0].slice(0, 50).trim(), 50)}\`: directs the agent toward secrets`
82998
83297
  ],
82999
83298
  "Do not reference credential files or paths in agent instructions.",
83000
- path108,
83299
+ path110,
83001
83300
  lineAt(content, sp.index)
83002
83301
  )
83003
83302
  );
@@ -83020,7 +83319,7 @@ function analyzeInstructionFile(path108, content) {
83020
83319
  "Instruction directs the agent to send data to an external endpoint",
83021
83320
  [`\`${safeText(ex[0].slice(0, 70).trim(), 70)}\`: possible exfiltration directive`],
83022
83321
  "Remove external post/upload directives from agent instructions.",
83023
- path108,
83322
+ path110,
83024
83323
  lineAt(content, ex.index)
83025
83324
  )
83026
83325
  );
@@ -83031,18 +83330,18 @@ function analyzeInstructionFile(path108, content) {
83031
83330
  // src/ci-check/route.ts
83032
83331
  var MCP_CONFIG_RE = /\.mcp\.json$|\.cursor\/mcp\.json$|(^|\/)\.vscode\/mcp\.json$|(^|\/)\.kiro\/settings\/mcp\.json$|(^|\/)\.gemini\/settings\.json$|(^|\/)opencode\.json$|(^|\/)\.opencode\/config\.json$/;
83033
83332
  var ISSUE_FORM_RE = /^\.github\/ISSUE_TEMPLATE\/[^/]+\.(ya?ml|md)$/i;
83034
- function routeOf(path108, skillDirs, appDirs = /* @__PURE__ */ new Set()) {
83035
- if (path108 === SUPPRESSIONS_FILE) return "suppressions";
83036
- if (/\.github\/workflows\/.+\.ya?ml$/.test(path108)) return "workflow";
83037
- if (ISSUE_FORM_RE.test(path108)) return "issue-form";
83038
- if (path108 === "package.json" || path108 === "pyproject.toml") return "manifest";
83039
- if (/\.claude\/settings(\.local)?\.json$/.test(path108)) return "agent-config";
83040
- if (isHookScript(path108)) return "hook-script";
83041
- if (isSkillScript(path108, skillDirs)) return "skill-script";
83042
- if (MCP_CONFIG_RE.test(path108)) return "mcp";
83043
- if (/(^|\/)\.codex\/config\.toml$/.test(path108)) return "codex";
83044
- if (isInstructionFile(path108, skillDirs, appDirs)) return "instruction";
83045
- if (isAppDoc(path108, skillDirs, appDirs)) return "app-doc";
83333
+ function routeOf(path110, skillDirs, appDirs = /* @__PURE__ */ new Set()) {
83334
+ if (path110 === SUPPRESSIONS_FILE) return "suppressions";
83335
+ if (/\.github\/workflows\/.+\.ya?ml$/.test(path110)) return "workflow";
83336
+ if (ISSUE_FORM_RE.test(path110)) return "issue-form";
83337
+ if (path110 === "package.json" || path110 === "pyproject.toml") return "manifest";
83338
+ if (/\.claude\/settings(\.local)?\.json$/.test(path110)) return "agent-config";
83339
+ if (isHookScript(path110)) return "hook-script";
83340
+ if (isSkillScript(path110, skillDirs)) return "skill-script";
83341
+ if (MCP_CONFIG_RE.test(path110)) return "mcp";
83342
+ if (/(^|\/)\.codex\/config\.toml$/.test(path110)) return "codex";
83343
+ if (isInstructionFile(path110, skillDirs, appDirs)) return "instruction";
83344
+ if (isAppDoc(path110, skillDirs, appDirs)) return "app-doc";
83046
83345
  return null;
83047
83346
  }
83048
83347
 
@@ -83171,7 +83470,7 @@ function parseRepoUrl(input) {
83171
83470
  function isLocalPath(input) {
83172
83471
  if (input.startsWith(".") || input.startsWith("/") || input.startsWith("~")) return true;
83173
83472
  try {
83174
- return import_fs91.default.existsSync(input) && import_fs91.default.statSync(input).isDirectory();
83473
+ return import_fs93.default.existsSync(input) && import_fs93.default.statSync(input).isDirectory();
83175
83474
  } catch {
83176
83475
  return false;
83177
83476
  }
@@ -83532,7 +83831,7 @@ function capNested(reads, cap, notes) {
83532
83831
  }
83533
83832
  var overLimit = (text) => Buffer.byteLength(text, "utf8") > MAX_FILE_BYTES3;
83534
83833
  var RAW_LIMIT = 2 * MAX_FILE_BYTES3;
83535
- var OPEN_READ = import_fs91.default.constants.O_RDONLY | (import_fs91.default.constants.O_NOFOLLOW ?? 0) | (import_fs91.default.constants.O_NONBLOCK ?? 0);
83834
+ var OPEN_READ = import_fs93.default.constants.O_RDONLY | (import_fs93.default.constants.O_NOFOLLOW ?? 0) | (import_fs93.default.constants.O_NONBLOCK ?? 0);
83536
83835
  var MAX_WALK_ENTRIES = 1e6;
83537
83836
  var direntKind = (e) => e.isSymbolicLink() ? "link" : e.isDirectory() ? "dir" : e.isFile() ? "file" : "other";
83538
83837
  function walkDisk(root, notes) {
@@ -83547,7 +83846,7 @@ function walkDisk(root, notes) {
83547
83846
  const relDir = stack.pop();
83548
83847
  let dirents;
83549
83848
  try {
83550
- dirents = import_fs91.default.readdirSync(import_path89.default.join(root, relDir), { withFileTypes: true });
83849
+ dirents = import_fs93.default.readdirSync(import_path91.default.join(root, relDir), { withFileTypes: true });
83551
83850
  } catch (e) {
83552
83851
  unlistable.push(`${relDir || "."} (${e?.code ?? "error"})`);
83553
83852
  continue;
@@ -83561,7 +83860,7 @@ function walkDisk(root, notes) {
83561
83860
  const k = direntKind(e);
83562
83861
  kinds2.set(rel, k);
83563
83862
  if (k !== "dir" || isUnwalked(`${rel}/`)) continue;
83564
- if (import_fs91.default.existsSync(import_path89.default.join(root, rel, ".git"))) {
83863
+ if (import_fs93.default.existsSync(import_path91.default.join(root, rel, ".git"))) {
83565
83864
  sealed.add(rel);
83566
83865
  nestedRepos.push(rel);
83567
83866
  } else stack.push(rel);
@@ -83584,7 +83883,7 @@ function walkDisk(root, notes) {
83584
83883
  }
83585
83884
  function gitmodulePaths(root) {
83586
83885
  try {
83587
- const text = readLocalFile(import_path89.default.join(root, ".gitmodules"), ".gitmodules");
83886
+ const text = readLocalFile(import_path91.default.join(root, ".gitmodules"), ".gitmodules");
83588
83887
  return [...text.matchAll(/^\s*path\s*=\s*(.+?)\s*$/gm)].map((m) => m[1].replace(/\/+$/, ""));
83589
83888
  } catch {
83590
83889
  return [];
@@ -83592,9 +83891,9 @@ function gitmodulePaths(root) {
83592
83891
  }
83593
83892
  function localLinkText(root, rel) {
83594
83893
  try {
83595
- const t = import_fs91.default.readlinkSync(import_path89.default.join(root, rel));
83894
+ const t = import_fs93.default.readlinkSync(import_path91.default.join(root, rel));
83596
83895
  if (process.platform !== "win32") return t;
83597
- return import_path89.default.win32.isAbsolute(t) ? `/${t.replace(/\\/g, "/")}` : t.replace(/\\/g, "/");
83896
+ return import_path91.default.win32.isAbsolute(t) ? `/${t.replace(/\\/g, "/")}` : t.replace(/\\/g, "/");
83598
83897
  } catch {
83599
83898
  return null;
83600
83899
  }
@@ -83602,11 +83901,11 @@ function localLinkText(root, rel) {
83602
83901
  function readLocalFile(abs, rel) {
83603
83902
  let fd;
83604
83903
  try {
83605
- fd = import_fs91.default.openSync(abs, OPEN_READ);
83606
- const st = import_fs91.default.fstatSync(fd);
83904
+ fd = import_fs93.default.openSync(abs, OPEN_READ);
83905
+ const st = import_fs93.default.fstatSync(fd);
83607
83906
  if (!st.isFile()) throw new Error(unreadNote(rel, "no longer a regular file"));
83608
83907
  if (st.size > RAW_LIMIT) throw new Error(tooLargeNote(rel));
83609
- const text = lf(import_fs91.default.readFileSync(fd, "utf8"));
83908
+ const text = lf(import_fs93.default.readFileSync(fd, "utf8"));
83610
83909
  if (overLimit(text)) throw new Error(tooLargeNote(rel));
83611
83910
  return text;
83612
83911
  } catch (e) {
@@ -83614,7 +83913,7 @@ function readLocalFile(abs, rel) {
83614
83913
  if (msg.includes(INCOMPLETE)) throw e;
83615
83914
  throw new Error(unreadNote(rel, e?.code ?? "error"));
83616
83915
  } finally {
83617
- if (fd !== void 0) import_fs91.default.closeSync(fd);
83916
+ if (fd !== void 0) import_fs93.default.closeSync(fd);
83618
83917
  }
83619
83918
  }
83620
83919
  function localGitHubRepo(root) {
@@ -83635,10 +83934,10 @@ function readLocalTree(dir2) {
83635
83934
  notes.push(...plan.notes);
83636
83935
  const files = [];
83637
83936
  for (const { rel, real, route } of plan.reads) {
83638
- const abs = import_path89.default.join(root, real);
83937
+ const abs = import_path91.default.join(root, real);
83639
83938
  let size = 0;
83640
83939
  try {
83641
- size = import_fs91.default.lstatSync(abs).size;
83940
+ size = import_fs93.default.lstatSync(abs).size;
83642
83941
  } catch {
83643
83942
  }
83644
83943
  if (size > RAW_LIMIT) {
@@ -85146,17 +85445,17 @@ function localTarget(uses, self) {
85146
85445
  if (!f) return null;
85147
85446
  return f[1].toLowerCase() === self.owner.toLowerCase() && f[2].toLowerCase() === self.repo.toLowerCase() ? `.github/workflows/${f[3]}` : null;
85148
85447
  }
85149
- function localCallsOf(path108, content, autoLabels, trustedRunSources, self) {
85448
+ function localCallsOf(path110, content, autoLabels, trustedRunSources, self) {
85150
85449
  AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
85151
85450
  TRUSTED_RUN_SOURCES = trustedRunSources ?? /* @__PURE__ */ new Set();
85152
85451
  try {
85153
- return localCallsOfInner(path108, content, self);
85452
+ return localCallsOfInner(path110, content, self);
85154
85453
  } finally {
85155
85454
  AUTO_LABELS = /* @__PURE__ */ new Set();
85156
85455
  TRUSTED_RUN_SOURCES = /* @__PURE__ */ new Set();
85157
85456
  }
85158
85457
  }
85159
- function localCallsOfInner(path108, content, self) {
85458
+ function localCallsOfInner(path110, content, self) {
85160
85459
  let raw;
85161
85460
  try {
85162
85461
  raw = loadWorkflow(content).raw;
@@ -85174,7 +85473,7 @@ function localCallsOfInner(path108, content, self) {
85174
85473
  out.push({
85175
85474
  target,
85176
85475
  caller: {
85177
- file: path108,
85476
+ file: path110,
85178
85477
  keys: reach.keys,
85179
85478
  untrusted: reach.untrusted,
85180
85479
  secretExposed: reach.secretExposed,
@@ -85410,7 +85709,7 @@ function upstreamRunTrusted(wf, raw) {
85410
85709
  const names = Array.isArray(run?.workflows) ? run.workflows.map(String) : [];
85411
85710
  return names.length > 0 && names.every((n) => TRUSTED_RUN_SOURCES.has(n));
85412
85711
  }
85413
- function runSourceOf(path108, content, autoLabels) {
85712
+ function runSourceOf(path110, content, autoLabels) {
85414
85713
  AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
85415
85714
  try {
85416
85715
  let raw;
@@ -85423,7 +85722,7 @@ function runSourceOf(path108, content, autoLabels) {
85423
85722
  const wf = raw;
85424
85723
  CALLERS.delete(wf);
85425
85724
  const reach = triggerReach(wf, raw);
85426
- const name = typeof raw["name"] === "string" && raw["name"] ? raw["name"] : path108;
85725
+ const name = typeof raw["name"] === "string" && raw["name"] ? raw["name"] : path110;
85427
85726
  return { name, trusted: !reach.untrusted && !reach.reusable };
85428
85727
  } finally {
85429
85728
  AUTO_LABELS = /* @__PURE__ */ new Set();
@@ -85893,18 +86192,18 @@ function severityFromScore(score) {
85893
86192
  if (score >= 1) return "advisory";
85894
86193
  return null;
85895
86194
  }
85896
- function analyzeWorkflow(path108, content, callers, autoLabels, trustedRunSources) {
86195
+ function analyzeWorkflow(path110, content, callers, autoLabels, trustedRunSources) {
85897
86196
  AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
85898
86197
  TRUSTED_RUN_SOURCES = trustedRunSources ?? /* @__PURE__ */ new Set();
85899
86198
  try {
85900
- return analyzeWorkflowInner(path108, content, callers);
86199
+ return analyzeWorkflowInner(path110, content, callers);
85901
86200
  } finally {
85902
86201
  AUTO_LABELS = /* @__PURE__ */ new Set();
85903
86202
  TRUSTED_RUN_SOURCES = /* @__PURE__ */ new Set();
85904
86203
  UPSTREAM_TRUSTED = false;
85905
86204
  }
85906
86205
  }
85907
- function analyzeWorkflowInner(path108, content, callers) {
86206
+ function analyzeWorkflowInner(path110, content, callers) {
85908
86207
  let raw;
85909
86208
  try {
85910
86209
  raw = loadWorkflow(content).raw;
@@ -86113,7 +86412,7 @@ function analyzeWorkflowInner(path108, content, callers) {
86113
86412
  dimension: "workflows",
86114
86413
  severity,
86115
86414
  title,
86116
- file: path108,
86415
+ file: path110,
86117
86416
  signals,
86118
86417
  mitigations: mitigations.length ? mitigations : void 0,
86119
86418
  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."
@@ -86217,18 +86516,18 @@ function evalAgentJob(job, wf, raw, untrustedTrigger, reusable) {
86217
86516
  if (reusable && !loadedGun && SEVERITY_RANK2[severity] > SEVERITY_RANK2.medium) severity = "medium";
86218
86517
  return { severity, secrets, injectable, canReadEnv };
86219
86518
  }
86220
- function analyzeWorkflowSecrets(path108, content, callers, autoLabels, trustedRunSources) {
86519
+ function analyzeWorkflowSecrets(path110, content, callers, autoLabels, trustedRunSources) {
86221
86520
  AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
86222
86521
  TRUSTED_RUN_SOURCES = trustedRunSources ?? /* @__PURE__ */ new Set();
86223
86522
  try {
86224
- return analyzeWorkflowSecretsInner(path108, content, callers);
86523
+ return analyzeWorkflowSecretsInner(path110, content, callers);
86225
86524
  } finally {
86226
86525
  AUTO_LABELS = /* @__PURE__ */ new Set();
86227
86526
  TRUSTED_RUN_SOURCES = /* @__PURE__ */ new Set();
86228
86527
  UPSTREAM_TRUSTED = false;
86229
86528
  }
86230
86529
  }
86231
- function analyzeWorkflowSecretsInner(path108, content, callers) {
86530
+ function analyzeWorkflowSecretsInner(path110, content, callers) {
86232
86531
  let raw;
86233
86532
  try {
86234
86533
  raw = loadWorkflow(content).raw;
@@ -86255,7 +86554,7 @@ function analyzeWorkflowSecretsInner(path108, content, callers) {
86255
86554
  dimension: "data",
86256
86555
  severity: worst.severity,
86257
86556
  title: worst.severity === "advisory" ? "Secrets reachable by the agent: hardening" : "Exfiltratable secrets reachable by an injectable agent",
86258
- file: path108,
86557
+ file: path110,
86259
86558
  signals: [
86260
86559
  `agent can reach: ${worst.secrets.map((s) => s.name).join(", ")}`,
86261
86560
  worst.injectable ? "the agent is externally triggerable (untrusted trigger, no gate)" : "gated / not externally triggerable: latent risk only",
@@ -86277,7 +86576,7 @@ function marketplaceOwner(market) {
86277
86576
  market
86278
86577
  )?.[1] ?? /^([\w.-]{1,100})\/[\w.-]{1,100}(?:[#@].*)?$/.exec(market)?.[1];
86279
86578
  }
86280
- function analyzeWorkflowPlugins(path108, content, owner) {
86579
+ function analyzeWorkflowPlugins(path110, content, owner) {
86281
86580
  let raw;
86282
86581
  try {
86283
86582
  raw = loadWorkflow(content).raw;
@@ -86307,7 +86606,7 @@ function analyzeWorkflowPlugins(path108, content, owner) {
86307
86606
  dimension: "mcp",
86308
86607
  severity: "medium",
86309
86608
  title: "Agent installs plugins from a third-party marketplace on every run",
86310
- file: path108,
86609
+ file: path110,
86311
86610
  signals: [
86312
86611
  `\`plugin_marketplaces: ${safeText(market, 120)}\` is not pinned to a commit: whoever controls it changes the code and prompts the agent runs`
86313
86612
  ],
@@ -86323,11 +86622,11 @@ function readsItemList(text) {
86323
86622
  if (text.length > 2e5) return ITEM_LIST_RE.test(text);
86324
86623
  return text.replace(/\\\r?\n/g, " ").split("\n").some((l) => ITEM_LIST_RE.test(l) && !sanitizedListing(l));
86325
86624
  }
86326
- function analyzeTrustedReaders(path108, content, autoLabels, callers, trustedRunSources) {
86625
+ function analyzeTrustedReaders(path110, content, autoLabels, callers, trustedRunSources) {
86327
86626
  AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
86328
86627
  TRUSTED_RUN_SOURCES = trustedRunSources ?? /* @__PURE__ */ new Set();
86329
86628
  try {
86330
- return analyzeTrustedReadersInner(path108, content, callers);
86629
+ return analyzeTrustedReadersInner(path110, content, callers);
86331
86630
  } finally {
86332
86631
  AUTO_LABELS = /* @__PURE__ */ new Set();
86333
86632
  TRUSTED_RUN_SOURCES = /* @__PURE__ */ new Set();
@@ -86336,7 +86635,7 @@ function analyzeTrustedReaders(path108, content, autoLabels, callers, trustedRun
86336
86635
  function keysWithCallers(keys, callers) {
86337
86636
  return [.../* @__PURE__ */ new Set([...keys, ...(callers ?? []).flatMap((c) => c.keys)])];
86338
86637
  }
86339
- function analyzeTrustedReadersInner(path108, content, callers) {
86638
+ function analyzeTrustedReadersInner(path110, content, callers) {
86340
86639
  let raw;
86341
86640
  try {
86342
86641
  raw = loadWorkflow(content).raw;
@@ -86397,7 +86696,7 @@ function analyzeTrustedReadersInner(path108, content, callers) {
86397
86696
  dimension: "workflows",
86398
86697
  severity: "advisory",
86399
86698
  title: "Agent on a trusted trigger reads content strangers write, with a write token",
86400
- file: path108,
86699
+ file: path110,
86401
86700
  signals: [
86402
86701
  `runs on ${keys.map((k) => safeText(k, 40)).join(", ")}: no stranger starts it`,
86403
86702
  ...reads.map((r) => `the agent ${r}`),
@@ -86485,17 +86784,17 @@ function requiresTrustedAuthor(src) {
86485
86784
  };
86486
86785
  return req(x);
86487
86786
  }
86488
- function analyzeForkCodeOnTrust(path108, content, callers, autoLabels, trustedRunSources) {
86787
+ function analyzeForkCodeOnTrust(path110, content, callers, autoLabels, trustedRunSources) {
86489
86788
  AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
86490
86789
  TRUSTED_RUN_SOURCES = trustedRunSources ?? /* @__PURE__ */ new Set();
86491
86790
  try {
86492
- return analyzeForkCodeOnTrustInner(path108, content, callers);
86791
+ return analyzeForkCodeOnTrustInner(path110, content, callers);
86493
86792
  } finally {
86494
86793
  AUTO_LABELS = /* @__PURE__ */ new Set();
86495
86794
  TRUSTED_RUN_SOURCES = /* @__PURE__ */ new Set();
86496
86795
  }
86497
86796
  }
86498
- function analyzeForkCodeOnTrustInner(path108, content, callers) {
86797
+ function analyzeForkCodeOnTrustInner(path110, content, callers) {
86499
86798
  let raw;
86500
86799
  try {
86501
86800
  raw = loadWorkflow(content).raw;
@@ -86534,7 +86833,7 @@ function analyzeForkCodeOnTrustInner(path108, content, callers) {
86534
86833
  dimension: "workflows",
86535
86834
  severity: "advisory",
86536
86835
  title: "A maintainer's action runs the agent inside the fork's code",
86537
- file: path108,
86836
+ file: path110,
86538
86837
  signals: [
86539
86838
  `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)`,
86540
86839
  "checks out the untrusted PR head into the workspace root",
@@ -86566,18 +86865,18 @@ function laterSecrets(wf, job, from) {
86566
86865
  if (!/^GITHUB_TOKEN$/i.test(m[1])) out.add(m[1]);
86567
86866
  return [...out];
86568
86867
  }
86569
- function analyzeAgentOutputToEnv(path108, content, callers, autoLabels, trustedRunSources) {
86868
+ function analyzeAgentOutputToEnv(path110, content, callers, autoLabels, trustedRunSources) {
86570
86869
  AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
86571
86870
  TRUSTED_RUN_SOURCES = trustedRunSources ?? /* @__PURE__ */ new Set();
86572
86871
  try {
86573
- return analyzeAgentOutputToEnvInner(path108, content, callers);
86872
+ return analyzeAgentOutputToEnvInner(path110, content, callers);
86574
86873
  } finally {
86575
86874
  AUTO_LABELS = /* @__PURE__ */ new Set();
86576
86875
  TRUSTED_RUN_SOURCES = /* @__PURE__ */ new Set();
86577
86876
  UPSTREAM_TRUSTED = false;
86578
86877
  }
86579
86878
  }
86580
- function analyzeAgentOutputToEnvInner(path108, content, callers) {
86879
+ function analyzeAgentOutputToEnvInner(path110, content, callers) {
86581
86880
  let raw;
86582
86881
  try {
86583
86882
  raw = loadWorkflow(content).raw;
@@ -86673,7 +86972,7 @@ function analyzeAgentOutputToEnvInner(path108, content, callers) {
86673
86972
  dimension: "workflows",
86674
86973
  severity,
86675
86974
  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",
86676
- file: path108,
86975
+ file: path110,
86677
86976
  signals,
86678
86977
  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.`,
86679
86978
  explain: explainAgentOutputEnv({
@@ -86701,7 +87000,7 @@ function analyzeAgentOutputToEnvInner(path108, content, callers) {
86701
87000
 
86702
87001
  // src/ci-check/agent-config.ts
86703
87002
  init_cjs_shims();
86704
- var import_path90 = __toESM(require("path"));
87003
+ var import_path92 = __toESM(require("path"));
86705
87004
  function asStrings(v) {
86706
87005
  return Array.isArray(v) ? v.filter((x) => typeof x === "string") : [];
86707
87006
  }
@@ -86809,7 +87108,7 @@ function hookScriptPath(cmd) {
86809
87108
  if (/^(https?:|\$|-)/.test(t)) continue;
86810
87109
  t = t.replace(/^\.\//, "");
86811
87110
  if (!SCRIPT_EXT_RE.test(t) && !/(^|\/)\.claude\/hooks\//.test(t)) continue;
86812
- const norm = import_path90.default.posix.normalize(t);
87111
+ const norm = import_path92.default.posix.normalize(t);
86813
87112
  if (norm.startsWith("..") || norm.startsWith("/") || norm.includes("/../")) return null;
86814
87113
  return norm;
86815
87114
  }
@@ -86819,7 +87118,7 @@ function cmdLine(content, cmd) {
86819
87118
  const i = jsonValueIndex(content, cmd);
86820
87119
  return i >= 0 ? lineAtIndex(content, i) : void 0;
86821
87120
  }
86822
- function analyzeAgentConfig(path108, content, tree) {
87121
+ function analyzeAgentConfig(path110, content, tree) {
86823
87122
  let cfg;
86824
87123
  try {
86825
87124
  cfg = JSON.parse(content);
@@ -86842,7 +87141,7 @@ function analyzeAgentConfig(path108, content, tree) {
86842
87141
  dimension: "toolRules",
86843
87142
  severity: high ? "high" : "medium",
86844
87143
  title: high ? "Agent hook runs UNPINNED/remote third-party code on every action" : "Agent hook runs third-party code in the agent hot path",
86845
- file: path108,
87144
+ file: path110,
86846
87145
  ...cmdLine(content, cmd) ? { line: cmdLine(content, cmd) } : {},
86847
87146
  signals: [
86848
87147
  `hook command: \`${safeText(cmd, 120)}\``,
@@ -86863,7 +87162,7 @@ function analyzeAgentConfig(path108, content, tree) {
86863
87162
  dimension: "toolRules",
86864
87163
  severity: "medium",
86865
87164
  title: "Agent hook runs a script that is not committed",
86866
- file: path108,
87165
+ file: path110,
86867
87166
  ...cmdLine(content, cmd) ? { line: cmdLine(content, cmd) } : {},
86868
87167
  signals: [
86869
87168
  `hook command: \`${safeText(cmd, 120)}\``,
@@ -86879,7 +87178,7 @@ function analyzeAgentConfig(path108, content, tree) {
86879
87178
  dimension: "toolRules",
86880
87179
  severity: "advisory",
86881
87180
  title: "Agent hook runs a committed script this scan did not read",
86882
- file: path108,
87181
+ file: path110,
86883
87182
  ...cmdLine(content, cmd) ? { line: cmdLine(content, cmd) } : {},
86884
87183
  signals: [
86885
87184
  `hook command: \`${safeText(cmd, 120)}\``,
@@ -86908,12 +87207,12 @@ function analyzeAgentConfig(path108, content, tree) {
86908
87207
  dimension: "toolRules",
86909
87208
  severity: high ? "high" : "medium",
86910
87209
  title: high ? "Committed agent config pre-authorizes broad tools with no deny backstop" : "Committed agent config pre-authorizes broad tools",
86911
- file: path108,
87210
+ file: path110,
86912
87211
  signals,
86913
87212
  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.",
86914
87213
  explain: explainGrant({
86915
87214
  high,
86916
- file: path108,
87215
+ file: path110,
86917
87216
  broad: grade.broad,
86918
87217
  bareShell: grade.bareShell,
86919
87218
  hasBackstop: grade.bareShell ? deny.some((d) => /^Bash\b/.test(d)) : deny.some((d) => /Bash|Write|Edit/.test(d))
@@ -86930,7 +87229,7 @@ function analyzeAgentConfig(path108, content, tree) {
86930
87229
  dimension: "toolRules",
86931
87230
  severity: "medium",
86932
87231
  title: "Committed agent config pre-approves a command that can run other programs",
86933
- file: path108,
87232
+ file: path110,
86934
87233
  signals: [
86935
87234
  `pre-approved: ${escapes.slice(0, 5).map((e) => `\`${safeText(e, 80)}\``).join(", ")}`,
86936
87235
  "`find -exec` and `make -n --eval` run other programs without a prompt"
@@ -86945,8 +87244,8 @@ var ROOT_SURFACE_RE = /^\.(claude|agents|github|codex|cursor|gemini)\//;
86945
87244
  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/;
86946
87245
  var PR_TEXT_RE = /gh\s+pr\s+(?:view|diff)\b|gh\s+api\s+[^\n]{0,120}\/pulls\b/;
86947
87246
  var WEB_TEXT_RE = /\bsearch the web\b|\bfetch (?:the )?(?:url|page)\b/i;
86948
- function skillReadsUntrusted(path108, content, allow, broad) {
86949
- if (!ROOT_SURFACE_RE.test(path108)) return null;
87247
+ function skillReadsUntrusted(path110, content, allow, broad) {
87248
+ if (!ROOT_SURFACE_RE.test(path110)) return null;
86950
87249
  const body = content.replace(/^---[\s\S]*?\n---/, "");
86951
87250
  const runsCode = broad.map((a) => a.replace(/^PowerShell(?=$|\()/, "Bash")).some((a) => /^Bash$|^Bash\(\s*\*/.test(a) || openRunner(a) && !/^Bash\(\s*gh\b/.test(a));
86952
87251
  const webGrant = allow.some((a) => /^(WebFetch|WebSearch)\b/.test(a));
@@ -86961,8 +87260,8 @@ function skillReadsUntrusted(path108, content, allow, broad) {
86961
87260
  return "it reads pull request text that strangers write, and may edit files and run git/gh on it";
86962
87261
  return null;
86963
87262
  }
86964
- function analyzeSkillGrants(path108, content) {
86965
- if (!GRANT_CARRIER_RE.test(path108)) return [];
87263
+ function analyzeSkillGrants(path110, content) {
87264
+ if (!GRANT_CARRIER_RE.test(path110)) return [];
86966
87265
  const allow = allowedToolsOf(parseFrontmatter(content));
86967
87266
  if (allow.length === 0) return [];
86968
87267
  const grade = gradeBroadGrant(allow, [], {
@@ -86970,9 +87269,9 @@ function analyzeSkillGrants(path108, content) {
86970
87269
  scope: "whenever this skill or command is active, for everyone who opens this repo with the agent"
86971
87270
  });
86972
87271
  if (!grade) return [];
86973
- const kind = /commands\//.test(path108) ? "slash command" : "skill";
87272
+ const kind = /commands\//.test(path110) ? "slash command" : "skill";
86974
87273
  const at = content.search(/^allowed-tools\s*:/m);
86975
- const untrusted = skillReadsUntrusted(path108, content, allow, grade.broad);
87274
+ const untrusted = skillReadsUntrusted(path110, content, allow, grade.broad);
86976
87275
  if (untrusted)
86977
87276
  return [
86978
87277
  {
@@ -86982,7 +87281,7 @@ function analyzeSkillGrants(path108, content) {
86982
87281
  dimension: "toolRules",
86983
87282
  severity: "advisory",
86984
87283
  title: `Committed ${kind} runs code or writes with text strangers control`,
86985
- file: path108,
87284
+ file: path110,
86986
87285
  signals: [...grade.signals, untrusted],
86987
87286
  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."
86988
87287
  }
@@ -86999,7 +87298,7 @@ function analyzeSkillGrants(path108, content) {
86999
87298
  // shell — the cap is on reach, not on honesty.
87000
87299
  severity: "medium",
87001
87300
  title: grade.high ? `Committed ${kind} pre-authorizes an unrestricted shell while active` : `Committed ${kind} pre-authorizes broad tools while active`,
87002
- file: path108,
87301
+ file: path110,
87003
87302
  signals: grade.signals,
87004
87303
  fix: "Scope `allowed-tools` to the specific commands the skill needs (e.g. `Bash(git status:*)`); avoid a bare `Bash`, `Write` or `Edit`."
87005
87304
  }
@@ -87131,7 +87430,7 @@ function ownPackageNames(manifests) {
87131
87430
  }
87132
87431
  return out;
87133
87432
  }
87134
- function analyzeMcp(path108, content, own = /* @__PURE__ */ new Set()) {
87433
+ function analyzeMcp(path110, content, own = /* @__PURE__ */ new Set()) {
87135
87434
  let cfg;
87136
87435
  try {
87137
87436
  cfg = JSON.parse(content);
@@ -87167,9 +87466,9 @@ function analyzeMcp(path108, content, own = /* @__PURE__ */ new Set()) {
87167
87466
  const key = (count.get(name) ?? 0) > 1 ? `${section}.${name}` : name;
87168
87467
  servers[key] = { ...spec, anchor: name };
87169
87468
  }
87170
- return analyzeMcpServers(servers, path108, content, own);
87469
+ return analyzeMcpServers(servers, path110, content, own);
87171
87470
  }
87172
- function analyzeMcpServers(servers, path108, content = "", own = /* @__PURE__ */ new Set()) {
87471
+ function analyzeMcpServers(servers, path110, content = "", own = /* @__PURE__ */ new Set()) {
87173
87472
  const findings = [];
87174
87473
  for (const [name, srv] of Object.entries(servers ?? {})) {
87175
87474
  if (!srv || srv.disabled) continue;
@@ -87188,7 +87487,7 @@ function analyzeMcpServers(servers, path108, content = "", own = /* @__PURE__ */
87188
87487
  dimension: "mcp",
87189
87488
  severity: "medium",
87190
87489
  title: `MCP server "${name}" runs an unpinned executable`,
87191
- file: path108,
87490
+ file: path110,
87192
87491
  ...line ? { line } : {},
87193
87492
  signals: [
87194
87493
  why.launcher === "npx" ? `\`${safeText(argv, 120)}\`: unversioned/@latest npx` : `\`${safeText(argv, 120)}\`: unversioned/latest ${why.launcher}`
@@ -87213,7 +87512,7 @@ function analyzeMcpServers(servers, path108, content = "", own = /* @__PURE__ */
87213
87512
  dimension: "mcp",
87214
87513
  severity: "high",
87215
87514
  title: `MCP server "${name}" has an inline credential`,
87216
- file: path108,
87515
+ file: path110,
87217
87516
  ...line ? { line } : {},
87218
87517
  signals: [
87219
87518
  `env.${k} matches ${hit.patternName}: agent-reachable secret committed to the repo`
@@ -87229,7 +87528,7 @@ function analyzeMcpServers(servers, path108, content = "", own = /* @__PURE__ */
87229
87528
  // src/ci-check/codex.ts
87230
87529
  init_cjs_shims();
87231
87530
  var import_smol_toml7 = require("smol-toml");
87232
- function analyzeCodexConfig(path108, content, own = /* @__PURE__ */ new Set()) {
87531
+ function analyzeCodexConfig(path110, content, own = /* @__PURE__ */ new Set()) {
87233
87532
  let cfg;
87234
87533
  try {
87235
87534
  cfg = (0, import_smol_toml7.parse)(content);
@@ -87237,7 +87536,7 @@ function analyzeCodexConfig(path108, content, own = /* @__PURE__ */ new Set()) {
87237
87536
  return [];
87238
87537
  }
87239
87538
  const findings = [];
87240
- findings.push(...analyzeMcpServers(cfg.mcp_servers ?? {}, path108, content, own));
87539
+ findings.push(...analyzeMcpServers(cfg.mcp_servers ?? {}, path110, content, own));
87241
87540
  const sandbox = typeof cfg.sandbox_mode === "string" ? cfg.sandbox_mode : "";
87242
87541
  const approval = typeof cfg.approval_policy === "string" ? cfg.approval_policy : "";
87243
87542
  const fullAccess = /danger-full-access/i.test(sandbox);
@@ -87260,7 +87559,7 @@ function analyzeCodexConfig(path108, content, own = /* @__PURE__ */ new Set()) {
87260
87559
  dimension: "toolRules",
87261
87560
  severity: fullAccess ? "high" : "medium",
87262
87561
  title: fullAccess ? "Codex config grants a full-access sandbox" : "Codex config never requires approval",
87263
- file: path108,
87562
+ file: path110,
87264
87563
  signals,
87265
87564
  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.'
87266
87565
  });
@@ -87314,7 +87613,7 @@ function reviewQuestion(rule) {
87314
87613
  return "Is this an instruction the agent follows, or text for a person?";
87315
87614
  }
87316
87615
  var RANK2 = { critical: 4, high: 3, medium: 2, advisory: 1 };
87317
- var worstRank = (fs109) => Math.max(...fs109.map((f) => RANK2[f.severity] ?? 0));
87616
+ var worstRank = (fs111) => Math.max(...fs111.map((f) => RANK2[f.severity] ?? 0));
87318
87617
  var fileOrder = (a, b) => worstRank(b[1]) - worstRank(a[1]) || b[1].length - a[1].length;
87319
87618
  function groupReview(findings) {
87320
87619
  const byFile = /* @__PURE__ */ new Map();
@@ -87379,7 +87678,7 @@ function logicalLines2(content) {
87379
87678
  }
87380
87679
  return out;
87381
87680
  }
87382
- function analyzeScript(path108, content, rulePrefix) {
87681
+ function analyzeScript(path110, content, rulePrefix) {
87383
87682
  const check = rulePrefix.startsWith("CI-1") ? "CI-1" : "CI-6";
87384
87683
  const dimension = check === "CI-1" ? "toolRules" : "instructions";
87385
87684
  const mk3 = (suffix, severity, title, signal, fix, line) => ({
@@ -87388,7 +87687,7 @@ function analyzeScript(path108, content, rulePrefix) {
87388
87687
  dimension,
87389
87688
  severity,
87390
87689
  title,
87391
- file: path108,
87690
+ file: path110,
87392
87691
  ...line ? { line } : {},
87393
87692
  signals: [signal],
87394
87693
  fix
@@ -87814,7 +88113,7 @@ async function scanRepo(input, onProgress) {
87814
88113
  // src/ci-check/render.ts
87815
88114
  init_cjs_shims();
87816
88115
  var import_chalk36 = __toESM(require("chalk"));
87817
- var listed = (fs109) => fs109.filter((f) => f.tier !== "review");
88116
+ var listed = (fs111) => fs111.filter((f) => f.tier !== "review");
87818
88117
  function excerpt(f) {
87819
88118
  const m = /`([^`]+)`/.exec(f.signals[0] ?? "");
87820
88119
  return safeText(m ? m[1] : f.title, 120).replace(/`/g, "'");
@@ -87830,14 +88129,14 @@ function reviewMd(findings) {
87830
88129
  L.push("");
87831
88130
  const files = [...byFile.keys()];
87832
88131
  for (const file2 of files.slice(0, REVIEW_FILES)) {
87833
- const fs109 = byFile.get(file2);
88132
+ const fs111 = byFile.get(file2);
87834
88133
  L.push(`- \`${safeText(file2, 300)}\``);
87835
- for (const f of fs109.slice(0, REVIEW_LINES_PER_FILE))
88134
+ for (const f of fs111.slice(0, REVIEW_LINES_PER_FILE))
87836
88135
  L.push(
87837
88136
  ` - ${f.line ? `line ${Number(f.line)}: ` : ""}\`${excerpt(f)}\`. Check: ${reviewQuestion(f.rule)}`
87838
88137
  );
87839
- if (fs109.length > REVIEW_LINES_PER_FILE)
87840
- L.push(` - and ${fs109.length - REVIEW_LINES_PER_FILE} similar lines in this file`);
88138
+ if (fs111.length > REVIEW_LINES_PER_FILE)
88139
+ L.push(` - and ${fs111.length - REVIEW_LINES_PER_FILE} similar lines in this file`);
87841
88140
  }
87842
88141
  const more = files.length - REVIEW_FILES;
87843
88142
  if (more > 0) L.push(`- and ${more} more file${more === 1 ? "" : "s"}`);
@@ -87853,7 +88152,7 @@ function reviewMd(findings) {
87853
88152
  }
87854
88153
  function reviewTerminal(findings) {
87855
88154
  const { byFile, grants } = groupReview(findings);
87856
- const items = [...byFile.values()].reduce((a, fs109) => a + fs109.length, 0);
88155
+ const items = [...byFile.values()].reduce((a, fs111) => a + fs111.length, 0);
87857
88156
  if (!items && !grants) return [];
87858
88157
  const L = [];
87859
88158
  if (items) {
@@ -87862,12 +88161,12 @@ function reviewTerminal(findings) {
87862
88161
  );
87863
88162
  const files = [...byFile.keys()];
87864
88163
  for (const file2 of files.slice(0, REVIEW_FILES)) {
87865
- const fs109 = byFile.get(file2);
88164
+ const fs111 = byFile.get(file2);
87866
88165
  L.push(import_chalk36.default.gray(` ${file2}`));
87867
- for (const f of fs109.slice(0, REVIEW_LINES_PER_FILE))
88166
+ for (const f of fs111.slice(0, REVIEW_LINES_PER_FILE))
87868
88167
  L.push(` \u2022 ${f.line ? `line ${f.line}: ` : ""}${excerpt(f)}`);
87869
- if (fs109.length > REVIEW_LINES_PER_FILE)
87870
- L.push(import_chalk36.default.gray(` and ${fs109.length - REVIEW_LINES_PER_FILE} similar lines`));
88168
+ if (fs111.length > REVIEW_LINES_PER_FILE)
88169
+ L.push(import_chalk36.default.gray(` and ${fs111.length - REVIEW_LINES_PER_FILE} similar lines`));
87871
88170
  }
87872
88171
  const more = files.length - REVIEW_FILES;
87873
88172
  if (more > 0) L.push(import_chalk36.default.gray(` and ${more} more file${more === 1 ? "" : "s"}`));
@@ -87881,7 +88180,7 @@ function reviewTerminal(findings) {
87881
88180
  L.push("");
87882
88181
  return L;
87883
88182
  }
87884
- var ICON2 = {
88183
+ var ICON3 = {
87885
88184
  critical: "\u{1F534}",
87886
88185
  high: "\u{1F534}",
87887
88186
  medium: "\u{1F7E1}",
@@ -87941,7 +88240,7 @@ function mdLine(v) {
87941
88240
  function findingMd(f, L) {
87942
88241
  const ex = f.explain;
87943
88242
  L.push(
87944
- `**${ICON2[f.severity]} ${f.severity.toUpperCase()}: ${mdLine(ex ? ex.headline : f.title)}**` + (f.suppressed ? ` _(suppressed: \`${safeText(f.suppressed.reason, 200)}\`)_` : "")
88243
+ `**${ICON3[f.severity]} ${f.severity.toUpperCase()}: ${mdLine(ex ? ex.headline : f.title)}**` + (f.suppressed ? ` _(suppressed: \`${safeText(f.suppressed.reason, 200)}\`)_` : "")
87945
88244
  );
87946
88245
  L.push(`\`${safeText(f.file, 300)}${f.line ? ":" + Number(f.line) : ""}\` \xB7 ${f.rule}`);
87947
88246
  L.push("");
@@ -87997,7 +88296,7 @@ function renderScan(res, diff) {
87997
88296
  for (const f of shown) {
87998
88297
  const ex = f.explain;
87999
88298
  L.push(
88000
- `${ICON2[f.severity]} ${COLOR[f.severity](f.severity.toUpperCase())} ${import_chalk36.default.bold(ex ? ex.headline : f.title)}`
88299
+ `${ICON3[f.severity]} ${COLOR[f.severity](f.severity.toUpperCase())} ${import_chalk36.default.bold(ex ? ex.headline : f.title)}`
88001
88300
  );
88002
88301
  L.push(import_chalk36.default.gray(` ${f.file}${f.line ? ":" + f.line : ""} \xB7 ${f.check}`));
88003
88302
  if (ex) {
@@ -88519,16 +88818,16 @@ var import_chalk40 = __toESM(require("chalk"));
88519
88818
 
88520
88819
  // src/canary/plant.ts
88521
88820
  init_cjs_shims();
88522
- var import_fs93 = __toESM(require("fs"));
88523
- var import_os76 = __toESM(require("os"));
88524
- var import_path92 = __toESM(require("path"));
88821
+ var import_fs95 = __toESM(require("fs"));
88822
+ var import_os77 = __toESM(require("os"));
88823
+ var import_path94 = __toESM(require("path"));
88525
88824
  init_jail();
88526
88825
  init_registry2();
88527
88826
 
88528
88827
  // src/canary/sites.ts
88529
88828
  init_cjs_shims();
88530
- var import_fs92 = __toESM(require("fs"));
88531
- var import_path91 = __toESM(require("path"));
88829
+ var import_fs94 = __toESM(require("fs"));
88830
+ var import_path93 = __toESM(require("path"));
88532
88831
 
88533
88832
  // src/canary/generate.ts
88534
88833
  init_cjs_shims();
@@ -88623,26 +88922,26 @@ function generateSshKey() {
88623
88922
  var SITES = {
88624
88923
  "aws-profile": {
88625
88924
  kind: "aws-profile",
88626
- primary: (h) => import_path91.default.join(h, ".aws", "credentials"),
88627
- fallback: (h) => import_path91.default.join(h, ".aws", "credentials.bak"),
88925
+ primary: (h) => import_path93.default.join(h, ".aws", "credentials"),
88926
+ fallback: (h) => import_path93.default.join(h, ".aws", "credentials.bak"),
88628
88927
  // SSO / profile-only / credential_process setups have ~/.aws/config and no
88629
88928
  // credentials file; the SDK and CLI then parse ~/.aws/credentials on every
88630
88929
  // profile lookup. A planted primary would be a file real tools read.
88631
- preferFallback: (h) => import_fs92.default.existsSync(import_path91.default.join(h, ".aws", "config")),
88930
+ preferFallback: (h) => import_fs94.default.existsSync(import_path93.default.join(h, ".aws", "config")),
88632
88931
  dirMode: 448,
88633
88932
  generate: generateAwsProfile
88634
88933
  },
88635
88934
  "env-file": {
88636
88935
  kind: "env-file",
88637
- primary: (h) => import_path91.default.join(h, ".env.bak"),
88638
- fallback: (h) => import_path91.default.join(h, ".env.local.bak"),
88936
+ primary: (h) => import_path93.default.join(h, ".env.bak"),
88937
+ fallback: (h) => import_path93.default.join(h, ".env.local.bak"),
88639
88938
  dirMode: 493,
88640
88939
  generate: generateEnvFile
88641
88940
  },
88642
88941
  "ssh-key": {
88643
88942
  kind: "ssh-key",
88644
- primary: (h) => import_path91.default.join(h, ".ssh", "id_rsa_backup"),
88645
- fallback: (h) => import_path91.default.join(h, ".ssh", "id_rsa.old"),
88943
+ primary: (h) => import_path93.default.join(h, ".ssh", "id_rsa_backup"),
88944
+ fallback: (h) => import_path93.default.join(h, ".ssh", "id_rsa.old"),
88646
88945
  // ssh refuses a group-writable ~/.ssh for config / known_hosts reads.
88647
88946
  dirMode: 448,
88648
88947
  generate: generateSshKey
@@ -88655,12 +88954,12 @@ var isKind = (s) => ALL_KINDS.includes(s);
88655
88954
  var liveRecords = (kind) => loadCanaries().filter((r) => r.kind === kind && !r.retiredAt);
88656
88955
  var fileHashOf = (p) => {
88657
88956
  try {
88658
- return sha256Hex(import_fs93.default.readFileSync(p));
88957
+ return sha256Hex(import_fs95.default.readFileSync(p));
88659
88958
  } catch {
88660
88959
  return null;
88661
88960
  }
88662
88961
  };
88663
- function plantKind(kind, home = import_os76.default.homedir()) {
88962
+ function plantKind(kind, home = import_os77.default.homedir()) {
88664
88963
  const site = SITES[kind];
88665
88964
  const live = liveRecords(kind);
88666
88965
  if (live.length > 0) {
@@ -88679,8 +88978,8 @@ function plantKind(kind, home = import_os76.default.homedir()) {
88679
88978
  const primary = site.primary(home);
88680
88979
  const fallback = site.fallback(home);
88681
88980
  let target;
88682
- if (!import_fs93.default.existsSync(primary) && !site.preferFallback?.(home)) target = primary;
88683
- else if (!import_fs93.default.existsSync(fallback)) target = fallback;
88981
+ if (!import_fs95.default.existsSync(primary) && !site.preferFallback?.(home)) target = primary;
88982
+ else if (!import_fs95.default.existsSync(fallback)) target = fallback;
88684
88983
  else {
88685
88984
  return {
88686
88985
  kind,
@@ -88691,11 +88990,11 @@ function plantKind(kind, home = import_os76.default.homedir()) {
88691
88990
  recordIds: []
88692
88991
  };
88693
88992
  }
88694
- const dir2 = import_path92.default.dirname(target);
88993
+ const dir2 = import_path94.default.dirname(target);
88695
88994
  const gen = site.generate();
88696
- const createdDir = import_fs93.default.mkdirSync(dir2, { recursive: true, mode: site.dirMode }) !== void 0;
88697
- import_fs93.default.writeFileSync(target, gen.text, { mode: 384, flag: "wx" });
88698
- import_fs93.default.chmodSync(target, 384);
88995
+ const createdDir = import_fs95.default.mkdirSync(dir2, { recursive: true, mode: site.dirMode }) !== void 0;
88996
+ import_fs95.default.writeFileSync(target, gen.text, { mode: 384, flag: "wx" });
88997
+ import_fs95.default.chmodSync(target, 384);
88699
88998
  const fileHash = sha256Hex(gen.text);
88700
88999
  regenerateUserJail(addJailPath(target, "block"));
88701
89000
  const recordIds = gen.values.map(
@@ -88713,14 +89012,14 @@ function plantKind(kind, home = import_os76.default.homedir()) {
88713
89012
  }
88714
89013
  function allowedPathsFor(kind, home) {
88715
89014
  const site = SITES[kind];
88716
- return [site.primary(home), site.fallback(home)].map((x) => import_path92.default.resolve(x));
89015
+ return [site.primary(home), site.fallback(home)].map((x) => import_path94.default.resolve(x));
88717
89016
  }
88718
- function removeKind(kind, home = import_os76.default.homedir()) {
89017
+ function removeKind(kind, home = import_os77.default.homedir()) {
88719
89018
  const live = liveRecords(kind);
88720
89019
  if (live.length === 0) return { kind, action: "absent" };
88721
89020
  const p = live[0].path;
88722
89021
  const { fileHash, createdDir } = live[0];
88723
- if (!allowedPathsFor(kind, home).includes(import_path92.default.resolve(p))) {
89022
+ if (!allowedPathsFor(kind, home).includes(import_path94.default.resolve(p))) {
88724
89023
  return {
88725
89024
  kind,
88726
89025
  action: "refused",
@@ -88728,7 +89027,7 @@ function removeKind(kind, home = import_os76.default.homedir()) {
88728
89027
  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.`
88729
89028
  };
88730
89029
  }
88731
- if (!import_fs93.default.existsSync(p)) {
89030
+ if (!import_fs95.default.existsSync(p)) {
88732
89031
  for (const r of live) retireCanary(r.id);
88733
89032
  unjail(p);
88734
89033
  return { kind, action: "already-gone", path: p };
@@ -88741,13 +89040,13 @@ function removeKind(kind, home = import_os76.default.homedir()) {
88741
89040
  reason: `${p} changed since node9 wrote it; inspect and remove it by hand`
88742
89041
  };
88743
89042
  }
88744
- import_fs93.default.unlinkSync(p);
89043
+ import_fs95.default.unlinkSync(p);
88745
89044
  let dirRemoved = false;
88746
89045
  if (createdDir) {
88747
- const dir2 = import_path92.default.dirname(p);
89046
+ const dir2 = import_path94.default.dirname(p);
88748
89047
  try {
88749
- if (import_fs93.default.readdirSync(dir2).length === 0) {
88750
- import_fs93.default.rmdirSync(dir2);
89048
+ if (import_fs95.default.readdirSync(dir2).length === 0) {
89049
+ import_fs95.default.rmdirSync(dir2);
88751
89050
  dirRemoved = true;
88752
89051
  }
88753
89052
  } catch {
@@ -88771,14 +89070,14 @@ function statusAll() {
88771
89070
  const p = live[0].path;
88772
89071
  return {
88773
89072
  kind,
88774
- state: import_fs93.default.existsSync(p) ? "planted" : "missing",
89073
+ state: import_fs95.default.existsSync(p) ? "planted" : "missing",
88775
89074
  path: p,
88776
89075
  records: live.length,
88777
89076
  plantedAt: live[0].plantedAt
88778
89077
  };
88779
89078
  });
88780
89079
  }
88781
- function rotateKind(kind, home = import_os76.default.homedir()) {
89080
+ function rotateKind(kind, home = import_os77.default.homedir()) {
88782
89081
  const removed = removeKind(kind);
88783
89082
  if (removed.action === "refused") return { removed };
88784
89083
  return { removed, planted: plantKind(kind, home) };
@@ -88867,15 +89166,15 @@ init_daemon3();
88867
89166
  // src/cli/commands/sandbox.ts
88868
89167
  init_cjs_shims();
88869
89168
  var import_chalk41 = __toESM(require("chalk"));
88870
- var import_fs96 = __toESM(require("fs"));
88871
- var import_path95 = __toESM(require("path"));
89169
+ var import_fs98 = __toESM(require("fs"));
89170
+ var import_path97 = __toESM(require("path"));
88872
89171
  var import_child_process16 = require("child_process");
88873
89172
  init_config();
88874
89173
 
88875
89174
  // src/sandbox/config.ts
88876
89175
  init_cjs_shims();
88877
- var import_fs94 = __toESM(require("fs"));
88878
- var import_path93 = __toESM(require("path"));
89176
+ var import_fs96 = __toESM(require("fs"));
89177
+ var import_path95 = __toESM(require("path"));
88879
89178
  var import_yaml2 = require("yaml");
88880
89179
  var SANDBOX_CONFIG_FILE = "node9.sandbox.yaml";
88881
89180
  var FORBIDDEN_ENV = /* @__PURE__ */ new Set(["NODE9_API_KEY", "NODE9_API_URL"]);
@@ -88948,16 +89247,16 @@ function scaffoldSandboxYaml(agent) {
88948
89247
  return header + (0, import_yaml2.stringify)(defaultSandboxConfig(agent));
88949
89248
  }
88950
89249
  function sandboxConfigPath(cwd = process.cwd()) {
88951
- return import_path93.default.join(cwd, SANDBOX_CONFIG_FILE);
89250
+ return import_path95.default.join(cwd, SANDBOX_CONFIG_FILE);
88952
89251
  }
88953
89252
  function loadSandboxConfig(cwd = process.cwd(), fallbackAgent = "claude") {
88954
89253
  const p = sandboxConfigPath(cwd);
88955
- if (!import_fs94.default.existsSync(p)) {
89254
+ if (!import_fs96.default.existsSync(p)) {
88956
89255
  throw new Error(`sandbox: ${SANDBOX_CONFIG_FILE} not found \u2014 run \`node9 sandbox new\` first.`);
88957
89256
  }
88958
89257
  let raw;
88959
89258
  try {
88960
- raw = (0, import_yaml2.parse)(import_fs94.default.readFileSync(p, "utf-8"));
89259
+ raw = (0, import_yaml2.parse)(import_fs96.default.readFileSync(p, "utf-8"));
88961
89260
  } catch (err2) {
88962
89261
  throw new Error(
88963
89262
  `sandbox: ${SANDBOX_CONFIG_FILE} is not valid YAML \u2014 ${err2.message}`
@@ -89018,14 +89317,14 @@ init_atomic_write();
89018
89317
 
89019
89318
  // src/sandbox/runtime.ts
89020
89319
  init_cjs_shims();
89021
- var import_fs95 = __toESM(require("fs"));
89022
- var import_os77 = __toESM(require("os"));
89023
- var import_path94 = __toESM(require("path"));
89320
+ var import_fs97 = __toESM(require("fs"));
89321
+ var import_os78 = __toESM(require("os"));
89322
+ var import_path96 = __toESM(require("path"));
89024
89323
  var import_crypto26 = __toESM(require("crypto"));
89025
89324
  var import_child_process15 = require("child_process");
89026
89325
  init_templates();
89027
89326
  function sandboxDataDir(cwd = process.cwd()) {
89028
- return import_path94.default.join(cwd, ".node9", "sandbox", "data");
89327
+ return import_path96.default.join(cwd, ".node9", "sandbox", "data");
89029
89328
  }
89030
89329
  function detectEngine(engine) {
89031
89330
  const r = (0, import_child_process15.spawnSync)(engine, ["--version"], { encoding: "utf-8" });
@@ -89036,7 +89335,7 @@ function detectEngine(engine) {
89036
89335
  }
89037
89336
  function agentCredentialsMount(agent) {
89038
89337
  const rel = agent === "codex" ? ".codex/auth.json" : ".claude/.credentials.json";
89039
- return { hostPath: import_path94.default.join(import_os77.default.homedir(), rel), target: `/home/${RUN_AS_USER}/${rel}` };
89338
+ return { hostPath: import_path96.default.join(import_os78.default.homedir(), rel), target: `/home/${RUN_AS_USER}/${rel}` };
89040
89339
  }
89041
89340
  function buildRunArgs(opts) {
89042
89341
  const { config, workspaceHostPath, dataHostPath, allowlistHostPath, agentArgs } = opts;
@@ -89046,7 +89345,7 @@ function buildRunArgs(opts) {
89046
89345
  args.push("-v", `${allowlistHostPath}:${ALLOWED_DOMAINS_PATH}:ro`);
89047
89346
  if (config.node9.mountAgentCredentials) {
89048
89347
  const creds = agentCredentialsMount(config.agent);
89049
- if (import_fs95.default.existsSync(creds.hostPath)) {
89348
+ if (import_fs97.default.existsSync(creds.hostPath)) {
89050
89349
  args.push("-v", `${creds.hostPath}:${creds.target}`);
89051
89350
  }
89052
89351
  }
@@ -89064,30 +89363,30 @@ function imageContentHash(dockerfile, entrypoint) {
89064
89363
  return import_crypto26.default.createHash("sha256").update(dockerfile).update("\0").update(entrypoint).digest("hex").slice(0, 16);
89065
89364
  }
89066
89365
  function sandboxBuildDir(cwd = process.cwd()) {
89067
- return import_path94.default.join(cwd, ".node9", "sandbox", "build");
89366
+ return import_path96.default.join(cwd, ".node9", "sandbox", "build");
89068
89367
  }
89069
89368
  function writeBuildContext(cwd, dockerfile, entrypoint) {
89070
89369
  const dir2 = sandboxBuildDir(cwd);
89071
- import_fs95.default.mkdirSync(dir2, { recursive: true });
89072
- import_fs95.default.writeFileSync(import_path94.default.join(dir2, "Dockerfile"), dockerfile);
89073
- import_fs95.default.writeFileSync(import_path94.default.join(dir2, "entrypoint.sh"), entrypoint);
89370
+ import_fs97.default.mkdirSync(dir2, { recursive: true });
89371
+ import_fs97.default.writeFileSync(import_path96.default.join(dir2, "Dockerfile"), dockerfile);
89372
+ import_fs97.default.writeFileSync(import_path96.default.join(dir2, "entrypoint.sh"), entrypoint);
89074
89373
  return dir2;
89075
89374
  }
89076
89375
  function writeAllowlist(cwd, hosts) {
89077
- const dir2 = import_path94.default.join(cwd, ".node9", "sandbox");
89078
- import_fs95.default.mkdirSync(dir2, { recursive: true });
89079
- const p = import_path94.default.join(dir2, "allowed-domains.txt");
89080
- import_fs95.default.writeFileSync(p, hosts.join("\n") + "\n");
89376
+ const dir2 = import_path96.default.join(cwd, ".node9", "sandbox");
89377
+ import_fs97.default.mkdirSync(dir2, { recursive: true });
89378
+ const p = import_path96.default.join(dir2, "allowed-domains.txt");
89379
+ import_fs97.default.writeFileSync(p, hosts.join("\n") + "\n");
89081
89380
  return p;
89082
89381
  }
89083
89382
  function resolveHomePath(p) {
89084
- return p.startsWith("~") ? import_path94.default.join(import_os77.default.homedir(), p.slice(1)) : import_path94.default.resolve(p);
89383
+ return p.startsWith("~") ? import_path96.default.join(import_os78.default.homedir(), p.slice(1)) : import_path96.default.resolve(p);
89085
89384
  }
89086
89385
 
89087
89386
  // src/cli/commands/sandbox.ts
89088
89387
  function seedDataDirConfig(dataDir, sandbox) {
89089
- import_fs96.default.mkdirSync(dataDir, { recursive: true });
89090
- const configPath2 = import_path95.default.join(dataDir, "config.json");
89388
+ import_fs98.default.mkdirSync(dataDir, { recursive: true });
89389
+ const configPath2 = import_path97.default.join(dataDir, "config.json");
89091
89390
  const seed = {
89092
89391
  settings: {
89093
89392
  approvers: {
@@ -89098,7 +89397,7 @@ function seedDataDirConfig(dataDir, sandbox) {
89098
89397
  }
89099
89398
  }
89100
89399
  };
89101
- import_fs96.default.writeFileSync(configPath2, JSON.stringify(seed, null, 2), { mode: 384 });
89400
+ import_fs98.default.writeFileSync(configPath2, JSON.stringify(seed, null, 2), { mode: 384 });
89102
89401
  }
89103
89402
  function registerSandboxCommand(program2, version2) {
89104
89403
  const node9Version2 = pinnedNode9Version(version2);
@@ -89107,7 +89406,7 @@ function registerSandboxCommand(program2, version2) {
89107
89406
  const agent = opts.agent === "codex" ? "codex" : "claude";
89108
89407
  const p = sandboxConfigPath();
89109
89408
  try {
89110
- import_fs96.default.writeFileSync(p, scaffoldSandboxYaml(agent), { flag: "wx" });
89409
+ import_fs98.default.writeFileSync(p, scaffoldSandboxYaml(agent), { flag: "wx" });
89111
89410
  } catch (e) {
89112
89411
  if (e.code !== "EEXIST") throw e;
89113
89412
  console.log(
@@ -89154,8 +89453,8 @@ function registerSandboxCommand(program2, version2) {
89154
89453
  const buildDir = writeBuildContext(cwd, dockerfile, entrypoint);
89155
89454
  const hash2 = imageContentHash(dockerfile, entrypoint);
89156
89455
  const image = sandbox.runtime.image;
89157
- const hashFile = import_path95.default.join(sandboxBuildDir(cwd), ".image-hash");
89158
- const lastHash = import_fs96.default.existsSync(hashFile) ? import_fs96.default.readFileSync(hashFile, "utf-8").trim() : "";
89456
+ const hashFile = import_path97.default.join(sandboxBuildDir(cwd), ".image-hash");
89457
+ const lastHash = import_fs98.default.existsSync(hashFile) ? import_fs98.default.readFileSync(hashFile, "utf-8").trim() : "";
89159
89458
  const imageExists = (0, import_child_process16.spawnSync)(sandbox.runtime.engine, ["image", "inspect", image], { stdio: "ignore" }).status === 0;
89160
89459
  const needBuild = sandbox.runtime.rebuild === "always" || !imageExists || sandbox.runtime.rebuild !== "never" && lastHash !== hash2;
89161
89460
  if (needBuild) {
@@ -89181,7 +89480,7 @@ function registerSandboxCommand(program2, version2) {
89181
89480
  });
89182
89481
  if (sandbox.node9.mountAgentCredentials) {
89183
89482
  const creds = agentCredentialsMount(sandbox.agent);
89184
- if (import_fs96.default.existsSync(creds.hostPath)) {
89483
+ if (import_fs98.default.existsSync(creds.hostPath)) {
89185
89484
  console.log(import_chalk41.default.dim(` mounting ${creds.hostPath} (agent credentials, rw)`));
89186
89485
  } else {
89187
89486
  console.log(
@@ -89197,20 +89496,20 @@ function registerSandboxCommand(program2, version2) {
89197
89496
  process.exit(r.status ?? 0);
89198
89497
  });
89199
89498
  cmd.command("tail").description("Stream the sandbox's audit log (host-side)").action(() => {
89200
- const auditPath = import_path95.default.join(sandboxDataDir(), "audit.log");
89201
- if (!import_fs96.default.existsSync(auditPath)) {
89499
+ const auditPath = import_path97.default.join(sandboxDataDir(), "audit.log");
89500
+ if (!import_fs98.default.existsSync(auditPath)) {
89202
89501
  console.log(import_chalk41.default.dim(" no sandbox audit yet."));
89203
89502
  return;
89204
89503
  }
89205
89504
  (0, import_child_process16.spawnSync)("tail", ["-f", auditPath], { stdio: "inherit" });
89206
89505
  });
89207
89506
  cmd.command("logs").description("Dump the sandbox's audit log").action(() => {
89208
- const auditPath = import_path95.default.join(sandboxDataDir(), "audit.log");
89209
- if (!import_fs96.default.existsSync(auditPath)) {
89507
+ const auditPath = import_path97.default.join(sandboxDataDir(), "audit.log");
89508
+ if (!import_fs98.default.existsSync(auditPath)) {
89210
89509
  console.log(import_chalk41.default.dim(" no sandbox audit yet."));
89211
89510
  return;
89212
89511
  }
89213
- process.stdout.write(import_fs96.default.readFileSync(auditPath, "utf-8"));
89512
+ process.stdout.write(import_fs98.default.readFileSync(auditPath, "utf-8"));
89214
89513
  });
89215
89514
  cmd.command("clean").description("Remove the sandbox image, build context, and data").action(() => {
89216
89515
  const cwd = process.cwd();
@@ -89224,7 +89523,7 @@ function registerSandboxCommand(program2, version2) {
89224
89523
  stdio: "ignore"
89225
89524
  });
89226
89525
  }
89227
- import_fs96.default.rmSync(import_path95.default.join(cwd, ".node9", "sandbox"), { recursive: true, force: true });
89526
+ import_fs98.default.rmSync(import_path97.default.join(cwd, ".node9", "sandbox"), { recursive: true, force: true });
89228
89527
  console.log(import_chalk41.default.green(" \u2713 sandbox image + build + data removed."));
89229
89528
  });
89230
89529
  }
@@ -89453,12 +89752,12 @@ function registerPackageIndexCommand(program2) {
89453
89752
  // src/cli/commands/skill-pin.ts
89454
89753
  init_cjs_shims();
89455
89754
  var import_chalk45 = __toESM(require("chalk"));
89456
- var import_fs97 = __toESM(require("fs"));
89457
- var import_os78 = __toESM(require("os"));
89458
- var import_path96 = __toESM(require("path"));
89755
+ var import_fs99 = __toESM(require("fs"));
89756
+ var import_os79 = __toESM(require("os"));
89757
+ var import_path98 = __toESM(require("path"));
89459
89758
  function wipeSkillSessions() {
89460
89759
  try {
89461
- import_fs97.default.rmSync(import_path96.default.join(import_os78.default.homedir(), ".node9", "skill-sessions"), {
89760
+ import_fs99.default.rmSync(import_path98.default.join(import_os79.default.homedir(), ".node9", "skill-sessions"), {
89462
89761
  recursive: true,
89463
89762
  force: true
89464
89763
  });
@@ -89541,15 +89840,15 @@ function registerSkillPinCommand(program2) {
89541
89840
 
89542
89841
  // src/cli/commands/decisions.ts
89543
89842
  init_cjs_shims();
89544
- var import_fs98 = __toESM(require("fs"));
89545
- var import_os79 = __toESM(require("os"));
89546
- var import_path97 = __toESM(require("path"));
89843
+ var import_fs100 = __toESM(require("fs"));
89844
+ var import_os80 = __toESM(require("os"));
89845
+ var import_path99 = __toESM(require("path"));
89547
89846
  var import_chalk46 = __toESM(require("chalk"));
89548
- var DECISIONS_FILE2 = import_path97.default.join(import_os79.default.homedir(), ".node9", "decisions.json");
89847
+ var DECISIONS_FILE2 = import_path99.default.join(import_os80.default.homedir(), ".node9", "decisions.json");
89549
89848
  function readDecisions() {
89550
89849
  try {
89551
- if (!import_fs98.default.existsSync(DECISIONS_FILE2)) return {};
89552
- const raw = import_fs98.default.readFileSync(DECISIONS_FILE2, "utf-8");
89850
+ if (!import_fs100.default.existsSync(DECISIONS_FILE2)) return {};
89851
+ const raw = import_fs100.default.readFileSync(DECISIONS_FILE2, "utf-8");
89553
89852
  const parsed = JSON.parse(raw);
89554
89853
  const out = {};
89555
89854
  for (const [k, v] of Object.entries(parsed)) {
@@ -89561,11 +89860,11 @@ function readDecisions() {
89561
89860
  }
89562
89861
  }
89563
89862
  function writeDecisions(d) {
89564
- const dir2 = import_path97.default.dirname(DECISIONS_FILE2);
89565
- if (!import_fs98.default.existsSync(dir2)) import_fs98.default.mkdirSync(dir2, { recursive: true });
89863
+ const dir2 = import_path99.default.dirname(DECISIONS_FILE2);
89864
+ if (!import_fs100.default.existsSync(dir2)) import_fs100.default.mkdirSync(dir2, { recursive: true });
89566
89865
  const tmp = `${DECISIONS_FILE2}.${process.pid}.tmp`;
89567
- import_fs98.default.writeFileSync(tmp, JSON.stringify(d, null, 2));
89568
- import_fs98.default.renameSync(tmp, DECISIONS_FILE2);
89866
+ import_fs100.default.writeFileSync(tmp, JSON.stringify(d, null, 2));
89867
+ import_fs100.default.renameSync(tmp, DECISIONS_FILE2);
89569
89868
  }
89570
89869
  function registerDecisionsCommand(program2) {
89571
89870
  const cmd = program2.command("decisions").description('Manage persistent "Always Allow" / "Always Deny" tool decisions');
@@ -89623,15 +89922,15 @@ Persistent decisions (${entries.length})
89623
89922
  // src/cli/commands/dlp.ts
89624
89923
  init_cjs_shims();
89625
89924
  var import_chalk47 = __toESM(require("chalk"));
89626
- var import_fs99 = __toESM(require("fs"));
89627
- var import_path98 = __toESM(require("path"));
89628
- var import_os80 = __toESM(require("os"));
89925
+ var import_fs101 = __toESM(require("fs"));
89926
+ var import_path100 = __toESM(require("path"));
89927
+ var import_os81 = __toESM(require("os"));
89629
89928
  init_safe_text();
89630
- var AUDIT_LOG = import_path98.default.join(import_os80.default.homedir(), ".node9", "audit.log");
89631
- var RESOLVED_FILE = import_path98.default.join(import_os80.default.homedir(), ".node9", "dlp-resolved.json");
89929
+ var AUDIT_LOG = import_path100.default.join(import_os81.default.homedir(), ".node9", "audit.log");
89930
+ var RESOLVED_FILE = import_path100.default.join(import_os81.default.homedir(), ".node9", "dlp-resolved.json");
89632
89931
  function loadResolved() {
89633
89932
  try {
89634
- const raw = JSON.parse(import_fs99.default.readFileSync(RESOLVED_FILE, "utf-8"));
89933
+ const raw = JSON.parse(import_fs101.default.readFileSync(RESOLVED_FILE, "utf-8"));
89635
89934
  return new Set(raw);
89636
89935
  } catch {
89637
89936
  return /* @__PURE__ */ new Set();
@@ -89639,13 +89938,13 @@ function loadResolved() {
89639
89938
  }
89640
89939
  function saveResolved(resolved) {
89641
89940
  try {
89642
- import_fs99.default.writeFileSync(RESOLVED_FILE, JSON.stringify([...resolved], null, 2), { mode: 384 });
89941
+ import_fs101.default.writeFileSync(RESOLVED_FILE, JSON.stringify([...resolved], null, 2), { mode: 384 });
89643
89942
  } catch {
89644
89943
  }
89645
89944
  }
89646
89945
  function loadDlpFindings() {
89647
- if (!import_fs99.default.existsSync(AUDIT_LOG)) return [];
89648
- return import_fs99.default.readFileSync(AUDIT_LOG, "utf-8").split("\n").flatMap((line) => {
89946
+ if (!import_fs101.default.existsSync(AUDIT_LOG)) return [];
89947
+ return import_fs101.default.readFileSync(AUDIT_LOG, "utf-8").split("\n").flatMap((line) => {
89649
89948
  if (!line.trim()) return [];
89650
89949
  try {
89651
89950
  const e = JSON.parse(line);
@@ -89744,15 +90043,15 @@ function registerDlpCommand(program2) {
89744
90043
  // src/cli/commands/mask.ts
89745
90044
  init_cjs_shims();
89746
90045
  var import_chalk48 = __toESM(require("chalk"));
89747
- var import_fs100 = __toESM(require("fs"));
89748
- var import_path99 = __toESM(require("path"));
89749
- var import_os81 = __toESM(require("os"));
90046
+ var import_fs102 = __toESM(require("fs"));
90047
+ var import_path101 = __toESM(require("path"));
90048
+ var import_os82 = __toESM(require("os"));
89750
90049
  init_dlp();
89751
90050
  function findJsonlFiles(dir2) {
89752
90051
  const results = [];
89753
- if (!import_fs100.default.existsSync(dir2)) return results;
89754
- for (const entry of import_fs100.default.readdirSync(dir2, { withFileTypes: true })) {
89755
- const full = import_path99.default.join(dir2, entry.name);
90052
+ if (!import_fs102.default.existsSync(dir2)) return results;
90053
+ for (const entry of import_fs102.default.readdirSync(dir2, { withFileTypes: true })) {
90054
+ const full = import_path101.default.join(dir2, entry.name);
89756
90055
  if (entry.isDirectory()) results.push(...findJsonlFiles(full));
89757
90056
  else if (entry.isFile() && entry.name.endsWith(".jsonl")) results.push(full);
89758
90057
  }
@@ -89795,7 +90094,7 @@ function redactJson(obj) {
89795
90094
  function processFile(filePath, dryRun) {
89796
90095
  let raw;
89797
90096
  try {
89798
- raw = import_fs100.default.readFileSync(filePath, "utf-8");
90097
+ raw = import_fs102.default.readFileSync(filePath, "utf-8");
89799
90098
  } catch {
89800
90099
  return { redactedLines: 0, patterns: [] };
89801
90100
  }
@@ -89827,14 +90126,14 @@ function processFile(filePath, dryRun) {
89827
90126
  }
89828
90127
  }
89829
90128
  if (!dryRun && redactedLines > 0) {
89830
- import_fs100.default.writeFileSync(filePath, newLines.join("\n"), "utf-8");
90129
+ import_fs102.default.writeFileSync(filePath, newLines.join("\n"), "utf-8");
89831
90130
  }
89832
90131
  return { redactedLines, patterns };
89833
90132
  }
89834
90133
  function processJsonFile(filePath, dryRun) {
89835
90134
  let raw;
89836
90135
  try {
89837
- raw = import_fs100.default.readFileSync(filePath, "utf-8");
90136
+ raw = import_fs102.default.readFileSync(filePath, "utf-8");
89838
90137
  } catch {
89839
90138
  return { redactedLines: 0, patterns: [] };
89840
90139
  }
@@ -89847,15 +90146,15 @@ function processJsonFile(filePath, dryRun) {
89847
90146
  const { value, modified, found } = redactJson(parsed);
89848
90147
  if (!modified) return { redactedLines: 0, patterns: [] };
89849
90148
  if (!dryRun) {
89850
- import_fs100.default.writeFileSync(filePath, JSON.stringify(value, null, 2), "utf-8");
90149
+ import_fs102.default.writeFileSync(filePath, JSON.stringify(value, null, 2), "utf-8");
89851
90150
  }
89852
90151
  return { redactedLines: 1, patterns: found };
89853
90152
  }
89854
90153
  function findJsonFiles(dir2) {
89855
90154
  const results = [];
89856
- if (!import_fs100.default.existsSync(dir2)) return results;
89857
- for (const entry of import_fs100.default.readdirSync(dir2, { withFileTypes: true })) {
89858
- const full = import_path99.default.join(dir2, entry.name);
90155
+ if (!import_fs102.default.existsSync(dir2)) return results;
90156
+ for (const entry of import_fs102.default.readdirSync(dir2, { withFileTypes: true })) {
90157
+ const full = import_path101.default.join(dir2, entry.name);
89859
90158
  if (entry.isDirectory()) results.push(...findJsonFiles(full));
89860
90159
  else if (entry.isFile() && entry.name.endsWith(".json")) results.push(full);
89861
90160
  }
@@ -89864,9 +90163,9 @@ function findJsonFiles(dir2) {
89864
90163
  function registerMaskCommand(program2) {
89865
90164
  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) => {
89866
90165
  const dryRun = !!options.dryRun;
89867
- const home = import_os81.default.homedir();
89868
- const claudeDir = import_path99.default.join(home, ".claude", "projects");
89869
- const geminiDir = import_path99.default.join(home, ".gemini", "tmp");
90166
+ const home = import_os82.default.homedir();
90167
+ const claudeDir = import_path101.default.join(home, ".claude", "projects");
90168
+ const geminiDir = import_path101.default.join(home, ".gemini", "tmp");
89870
90169
  const allFiles = [
89871
90170
  ...findJsonlFiles(claudeDir).map((p) => ({ path: p, type: "jsonl" })),
89872
90171
  ...findJsonFiles(geminiDir).map((p) => ({ path: p, type: "json" }))
@@ -89874,7 +90173,7 @@ function registerMaskCommand(program2) {
89874
90173
  const cutoff = options.all ? null : new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3);
89875
90174
  const filtered = cutoff ? allFiles.filter((f) => {
89876
90175
  try {
89877
- return import_fs100.default.statSync(f.path).mtime >= cutoff;
90176
+ return import_fs102.default.statSync(f.path).mtime >= cutoff;
89878
90177
  } catch {
89879
90178
  return false;
89880
90179
  }
@@ -89931,7 +90230,7 @@ function registerMaskCommand(program2) {
89931
90230
  init_blast();
89932
90231
  init_safe_text();
89933
90232
  var { version } = JSON.parse(
89934
- import_fs104.default.readFileSync(import_path103.default.join(__dirname, "../package.json"), "utf-8")
90233
+ import_fs106.default.readFileSync(import_path105.default.join(__dirname, "../package.json"), "utf-8")
89935
90234
  );
89936
90235
  var program = new import_commander.Command();
89937
90236
  program.name("node9").description("The Sudo Command for AI Agents").version(version);
@@ -90089,8 +90388,8 @@ function undoLeftoverNote() {
90089
90388
  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) => {
90090
90389
  console.log(import_chalk50.default.cyan("\n\u{1F6E1}\uFE0F Node9 Uninstall\n"));
90091
90390
  try {
90092
- const credRaw = import_fs104.default.readFileSync(
90093
- import_path103.default.join(import_os85.default.homedir(), ".node9", "credentials.json"),
90391
+ const credRaw = import_fs106.default.readFileSync(
90392
+ import_path105.default.join(import_os86.default.homedir(), ".node9", "credentials.json"),
90094
90393
  "utf-8"
90095
90394
  );
90096
90395
  const prof = JSON.parse(credRaw)[process.env.NODE9_PROFILE || "default"];
@@ -90165,7 +90464,7 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
90165
90464
  if (removed.length > 0 || refused.length > 0) {
90166
90465
  console.log(import_chalk50.default.bold("\nRemoving decoy credentials..."));
90167
90466
  for (const r of removed) {
90168
- if (r.path) console.log(import_chalk50.default.green(` \u2705 ${r.path.replace(import_os85.default.homedir(), "~")}`));
90467
+ if (r.path) console.log(import_chalk50.default.green(` \u2705 ${r.path.replace(import_os86.default.homedir(), "~")}`));
90169
90468
  }
90170
90469
  for (const r of refused) {
90171
90470
  decoysLeft.push(r.path ?? "(unknown path)");
@@ -90182,8 +90481,8 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
90182
90481
  decoysLeft = ["(the decoy registry could not be read)"];
90183
90482
  }
90184
90483
  if (options.purge) {
90185
- const node9Dir = import_path103.default.join(import_os85.default.homedir(), ".node9");
90186
- if (import_fs104.default.existsSync(node9Dir)) {
90484
+ const node9Dir = import_path105.default.join(import_os86.default.homedir(), ".node9");
90485
+ if (import_fs106.default.existsSync(node9Dir)) {
90187
90486
  const alsoSnapshots = undoLeftoverPaths().length > 0 ? ", old undo snapshots" : "";
90188
90487
  if (decoysLeft.length > 0) {
90189
90488
  console.error(import_chalk50.default.red("\n \u26A0\uFE0F Decoy credential files are still on disk:"));
@@ -90199,8 +90498,8 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
90199
90498
  default: false
90200
90499
  });
90201
90500
  if (confirmed) {
90202
- import_fs104.default.rmSync(node9Dir, { recursive: true });
90203
- if (import_fs104.default.existsSync(node9Dir)) {
90501
+ import_fs106.default.rmSync(node9Dir, { recursive: true });
90502
+ if (import_fs106.default.existsSync(node9Dir)) {
90204
90503
  console.error(
90205
90504
  import_chalk50.default.red("\n \u26A0\uFE0F ~/.node9/ could not be fully deleted \u2014 remove it manually.")
90206
90505
  );
@@ -90356,7 +90655,7 @@ program.command("tail").description("Stream live agent activity to the terminal"
90356
90655
  });
90357
90656
  program.command("monitor").description("Live interactive dashboard \u2014 activity feed, approvals, security signals").action(async () => {
90358
90657
  try {
90359
- const dashboardPath = import_path103.default.join(__dirname, "dashboard.mjs");
90658
+ const dashboardPath = import_path105.default.join(__dirname, "dashboard.mjs");
90360
90659
  const dynamicImport = new Function("id", "return import(id)");
90361
90660
  const mod = await dynamicImport(`file://${dashboardPath}`);
90362
90661
  await mod.startMonitor();
@@ -90394,14 +90693,14 @@ Claude Code spawns this command every ~300ms and writes a JSON payload to stdin.
90394
90693
  Run "node9 addto claude" to register it as the statusLine.`
90395
90694
  ).argument("[subcommand]", 'Optional: "debug on" / "debug off" to toggle stdin logging').argument("[state]", 'on|off \u2014 used with "debug" subcommand').action(async (subcommand, state) => {
90396
90695
  if (subcommand === "debug") {
90397
- const flagFile = import_path103.default.join(import_os85.default.homedir(), ".node9", "hud-debug");
90696
+ const flagFile = import_path105.default.join(import_os86.default.homedir(), ".node9", "hud-debug");
90398
90697
  if (state === "on") {
90399
- import_fs104.default.mkdirSync(import_path103.default.dirname(flagFile), { recursive: true });
90400
- import_fs104.default.writeFileSync(flagFile, "");
90698
+ import_fs106.default.mkdirSync(import_path105.default.dirname(flagFile), { recursive: true });
90699
+ import_fs106.default.writeFileSync(flagFile, "");
90401
90700
  console.log("HUD debug logging enabled \u2192 ~/.node9/hud-debug.log");
90402
90701
  console.log("Tail it with: tail -f ~/.node9/hud-debug.log");
90403
90702
  } else if (state === "off") {
90404
- if (import_fs104.default.existsSync(flagFile)) import_fs104.default.unlinkSync(flagFile);
90703
+ if (import_fs106.default.existsSync(flagFile)) import_fs106.default.unlinkSync(flagFile);
90405
90704
  console.log("HUD debug logging disabled.");
90406
90705
  } else {
90407
90706
  console.error("Usage: node9 hud debug on|off");
@@ -90535,9 +90834,9 @@ if (process.argv[2] !== "daemon") {
90535
90834
  const isCheckHook = process.argv[2] === "check";
90536
90835
  if (isCheckHook) {
90537
90836
  if (process.env.NODE9_DEBUG === "1" || getConfig().settings.enableHookLogDebug) {
90538
- const logPath = import_path103.default.join(import_os85.default.homedir(), ".node9", "hook-debug.log");
90837
+ const logPath = import_path105.default.join(import_os86.default.homedir(), ".node9", "hook-debug.log");
90539
90838
  const msg = reason instanceof Error ? reason.message : String(reason);
90540
- import_fs104.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] UNHANDLED: ${msg}
90839
+ import_fs106.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] UNHANDLED: ${msg}
90541
90840
  `);
90542
90841
  }
90543
90842
  process.exit(0);