@node9/proxy 1.64.0 → 1.65.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -243,8 +243,8 @@ function sanitizeConfig(raw) {
243
243
  }
244
244
  }
245
245
  const lines = result.error.issues.map((issue) => {
246
- const path71 = issue.path.length > 0 ? issue.path.join(".") : "root";
247
- return ` \u2022 ${path71}: ${issue.message}`;
246
+ const path72 = issue.path.length > 0 ? issue.path.join(".") : "root";
247
+ return ` \u2022 ${path72}: ${issue.message}`;
248
248
  });
249
249
  return {
250
250
  sanitized,
@@ -1455,9 +1455,9 @@ function matchesPattern(text, patterns) {
1455
1455
  const withoutDotSlash = text.replace(/^\.\//, "");
1456
1456
  return isMatch(withoutDotSlash) || isMatch(`./${withoutDotSlash}`);
1457
1457
  }
1458
- function getNestedValue(obj, path71) {
1458
+ function getNestedValue(obj, path72) {
1459
1459
  if (!obj || typeof obj !== "object") return null;
1460
- const segments = path71.split(".");
1460
+ const segments = path72.split(".");
1461
1461
  for (const seg of segments) {
1462
1462
  if (FORBIDDEN_PATH_SEGMENTS.has(seg)) return null;
1463
1463
  }
@@ -4612,6 +4612,7 @@ function getActiveEnvironment(config) {
4612
4612
  }
4613
4613
  function readRulesCacheResilient(cacheFile) {
4614
4614
  let existed = false;
4615
+ let sawReadError = false;
4615
4616
  for (let attempt = 0; attempt < 3; attempt++) {
4616
4617
  let content;
4617
4618
  try {
@@ -4619,30 +4620,39 @@ function readRulesCacheResilient(cacheFile) {
4619
4620
  existed = true;
4620
4621
  } catch (err2) {
4621
4622
  if (err2.code === "ENOENT") return {};
4623
+ sawReadError = true;
4622
4624
  continue;
4623
4625
  }
4624
4626
  try {
4625
- return JSON.parse(content);
4627
+ const parsed = JSON.parse(content);
4628
+ lastParsedRulesCache = parsed;
4629
+ return parsed;
4626
4630
  } catch {
4627
4631
  }
4628
4632
  }
4629
- if (existed) {
4633
+ if (existed || sawReadError) {
4630
4634
  const backup = import_path4.default.join(import_path4.default.dirname(cacheFile), "rules-cache.last-good.json");
4631
4635
  if (backup !== cacheFile) {
4632
4636
  try {
4633
4637
  const raw = JSON.parse(import_fs4.default.readFileSync(backup, "utf-8"));
4634
4638
  logCacheReadIssue(cacheFile, "RULES_CACHE_CORRUPT_USED_BACKUP");
4639
+ lastParsedRulesCache = raw;
4635
4640
  return raw;
4636
4641
  } catch {
4637
4642
  }
4638
4643
  }
4644
+ if (lastParsedRulesCache) {
4645
+ logCacheReadIssue(cacheFile, "RULES_CACHE_USED_MEMORY");
4646
+ return lastParsedRulesCache;
4647
+ }
4639
4648
  logCacheReadIssue(cacheFile, "RULES_CACHE_UNREADABLE");
4640
4649
  }
4641
4650
  return {};
4642
4651
  }
4643
4652
  function logCacheReadIssue(cacheFile, kind) {
4644
- if (cacheReadFailureLogged) return;
4645
- cacheReadFailureLogged = true;
4653
+ const now = Date.now();
4654
+ if (now - cacheReadLastLoggedAt < CACHE_LOG_REARM_MS) return;
4655
+ cacheReadLastLoggedAt = now;
4646
4656
  try {
4647
4657
  import_fs4.default.appendFileSync(
4648
4658
  import_path4.default.join(import_os4.default.homedir(), ".node9", "hook-debug.log"),
@@ -4893,10 +4903,10 @@ function getConfig(cwd) {
4893
4903
  }
4894
4904
  if (Array.isArray(mc.jailPaths)) {
4895
4905
  for (const jp of mc.jailPaths) {
4896
- const path71 = typeof jp?.path === "string" ? jp.path.trim() : "";
4897
- if (!path71) continue;
4906
+ const path72 = typeof jp?.path === "string" ? jp.path.trim() : "";
4907
+ if (!path72) continue;
4898
4908
  const verdict = jp?.verdict === "review" ? "review" : "block";
4899
- for (const r of pathRules(path71, verdict, "org-managed jail")) {
4909
+ for (const r of pathRules(path72, verdict, "org-managed jail")) {
4900
4910
  mergedPolicy.smartRules.push({ ...r, name: `org:${r.name}` });
4901
4911
  }
4902
4912
  }
@@ -5049,7 +5059,7 @@ ${error.replace("Invalid config:\n", "")}
5049
5059
  }
5050
5060
  return sanitized;
5051
5061
  }
5052
- var import_fs4, import_path4, import_os4, DANGEROUS_WORDS, DEFAULT_CONFIG, ADVISORY_SMART_RULES, cachedConfig, cacheReadFailureLogged;
5062
+ var import_fs4, import_path4, import_os4, DANGEROUS_WORDS, DEFAULT_CONFIG, ADVISORY_SMART_RULES, cachedConfig, lastParsedRulesCache, CACHE_LOG_REARM_MS, cacheReadLastLoggedAt;
5053
5063
  var init_config = __esm({
5054
5064
  "src/config/index.ts"() {
5055
5065
  "use strict";
@@ -5339,7 +5349,9 @@ var init_config = __esm({
5339
5349
  }
5340
5350
  ];
5341
5351
  cachedConfig = null;
5342
- cacheReadFailureLogged = false;
5352
+ lastParsedRulesCache = null;
5353
+ CACHE_LOG_REARM_MS = 5 * 60 * 1e3;
5354
+ cacheReadLastLoggedAt = 0;
5343
5355
  }
5344
5356
  });
5345
5357
 
@@ -6057,6 +6069,18 @@ async function isDaemonReachable(timeoutMs = 500) {
6057
6069
  return false;
6058
6070
  }
6059
6071
  }
6072
+ async function probeDaemonHealth(timeoutMs = 800) {
6073
+ try {
6074
+ const res = await fetch(`http://${DAEMON_HOST}:${DAEMON_PORT}/health`, {
6075
+ signal: AbortSignal.timeout(timeoutMs)
6076
+ });
6077
+ if (!res.ok) return { kind: "no-health" };
6078
+ const j = await res.json().catch(() => null);
6079
+ return j && typeof j === "object" ? { kind: "health", health: j } : { kind: "no-health" };
6080
+ } catch {
6081
+ return { kind: "unreachable" };
6082
+ }
6083
+ }
6060
6084
  async function daemonHasInteractiveApprover(timeoutMs = 400) {
6061
6085
  try {
6062
6086
  const res = await fetch(`http://${DAEMON_HOST}:${DAEMON_PORT}/approver`, {
@@ -7032,6 +7056,7 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
7032
7056
  let riskMetadata;
7033
7057
  let statefulRecoveryCommand;
7034
7058
  let localSmartRuleMatched = false;
7059
+ let hardBlockDowngraded = false;
7035
7060
  let taintWarning = null;
7036
7061
  if (isNetworkTool(toolName, args)) {
7037
7062
  const filePaths = extractFilePaths(toolName, args);
@@ -7273,6 +7298,7 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
7273
7298
  return { approved: true, checkedBy: "local-policy" };
7274
7299
  }
7275
7300
  if (policyResult.decision === "block") {
7301
+ hardBlockDowngraded = true;
7276
7302
  const daemonUp = isDaemonRunning();
7277
7303
  let humanApproverReachable = false;
7278
7304
  if (!policyResult.dependsOnStatePredicates?.length && daemonUp && !isTestEnv2) {
@@ -7346,7 +7372,8 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
7346
7372
  explainableLabel = policyResult.blockedByLabel || "Local Config";
7347
7373
  policyMatchedField = policyResult.matchedField;
7348
7374
  policyMatchedWord = policyResult.matchedWord;
7349
- if (policyResult.ruleName || policyResult.tier === 7) localSmartRuleMatched = true;
7375
+ if (policyResult.ruleName || policyResult.tier === 7 || hardBlockDowngraded)
7376
+ localSmartRuleMatched = true;
7350
7377
  if (policyResult.ruleDescription) policyRuleDescription = policyResult.ruleDescription;
7351
7378
  else if (policyResult.reason) policyRuleDescription = policyResult.reason;
7352
7379
  riskMetadata = computeRiskMetadata(
@@ -7358,7 +7385,7 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
7358
7385
  policyResult.ruleName
7359
7386
  );
7360
7387
  if (policyRuleDescription) riskMetadata.ruleDescription = policyRuleDescription.slice(0, 200);
7361
- const persistent = policyResult.ruleName || policyResult.tier === 7 ? null : getPersistentDecision(toolName);
7388
+ const persistent = policyResult.ruleName || policyResult.tier === 7 || hardBlockDowngraded ? null : getPersistentDecision(toolName);
7362
7389
  if (persistent === "allow" && !appPermReview) {
7363
7390
  if (!isManual) appendLocalAudit(toolName, args, "allow", "persistent", meta, hashAuditArgs);
7364
7391
  return { approved: true, checkedBy: "persistent" };
@@ -7391,7 +7418,7 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
7391
7418
  return { approved: true };
7392
7419
  }
7393
7420
  }
7394
- if (!taintWarning && !appPermReview && getActiveTrustSession(toolName, args)) {
7421
+ if (!taintWarning && !appPermReview && !hardBlockDowngraded && getActiveTrustSession(toolName, args)) {
7395
7422
  if (!isManual) appendLocalAudit(toolName, args, "allow", "trust", meta, hashAuditArgs);
7396
7423
  return { approved: true, checkedBy: "trust" };
7397
7424
  }
@@ -7455,7 +7482,7 @@ ${appPermReview}`
7455
7482
  forceReview
7456
7483
  );
7457
7484
  if (!initResult.pending) {
7458
- if (initResult.shadowMode && !appPermReview) {
7485
+ if (initResult.shadowMode && !localSmartRuleMatched && !options?.localSmartRuleMatched && !appPermReview) {
7459
7486
  return { approved: true, checkedBy: "cloud" };
7460
7487
  }
7461
7488
  if (!localSmartRuleMatched && !options?.localSmartRuleMatched && !appPermReview) {
@@ -15482,6 +15509,73 @@ var init_scan = __esm({
15482
15509
  }
15483
15510
  });
15484
15511
 
15512
+ // src/daemon/build-id.ts
15513
+ function readOwnVersion() {
15514
+ for (const rel of ["../package.json", "../../package.json"]) {
15515
+ try {
15516
+ const raw = import_fs26.default.readFileSync(import_path28.default.join(__dirname, rel), "utf-8");
15517
+ const v = JSON.parse(raw).version;
15518
+ if (typeof v === "string" && v.length > 0) return v;
15519
+ } catch {
15520
+ }
15521
+ }
15522
+ return "0.0.0";
15523
+ }
15524
+ function computeBuildId(entry = process.argv[1] ?? "") {
15525
+ let mtimeMs = 0;
15526
+ try {
15527
+ if (entry) mtimeMs = import_fs26.default.statSync(entry).mtimeMs;
15528
+ } catch {
15529
+ }
15530
+ return { version: readOwnVersion(), mtimeMs };
15531
+ }
15532
+ function buildIdString(b) {
15533
+ return `${b.version}+${Math.round(b.mtimeMs)}`;
15534
+ }
15535
+ function parseBuildId(s) {
15536
+ if (typeof s !== "string") return null;
15537
+ const at = s.lastIndexOf("+");
15538
+ if (at <= 0) return null;
15539
+ const version2 = s.slice(0, at);
15540
+ const mtimeMs = Number(s.slice(at + 1));
15541
+ if (!/^\d+(\.\d+){2}/.test(version2) || !Number.isFinite(mtimeMs) || mtimeMs < 0) return null;
15542
+ return { version: version2, mtimeMs };
15543
+ }
15544
+ function compareVersion(a, b) {
15545
+ const pa = a.split(".").map((n) => parseInt(n, 10) || 0);
15546
+ const pb = b.split(".").map((n) => parseInt(n, 10) || 0);
15547
+ for (let i = 0; i < 3; i++) {
15548
+ const d = (pa[i] ?? 0) - (pb[i] ?? 0);
15549
+ if (d !== 0) return d;
15550
+ }
15551
+ return 0;
15552
+ }
15553
+ function compareBuild(a, b) {
15554
+ const v = compareVersion(a.version, b.version);
15555
+ if (v !== 0) return v;
15556
+ return a.mtimeMs - b.mtimeMs;
15557
+ }
15558
+ function describeBuildDrift(running, installed) {
15559
+ const mine = buildIdString(installed);
15560
+ if (running === null) return null;
15561
+ if (running === "no-health") {
15562
+ return `running daemon predates the installed build (no /health \u2014 older than v${installed.version}) \u2014 it is enforcing OLD code`;
15563
+ }
15564
+ const theirs = typeof running.buildId === "string" ? running.buildId : null;
15565
+ if (!theirs || theirs === mine) return null;
15566
+ const theirVersion = typeof running.version === "string" ? running.version : "unknown";
15567
+ return `running daemon is v${theirVersion} (build ${theirs}) but installed is v${installed.version} (build ${mine}) \u2014 it is enforcing a different build`;
15568
+ }
15569
+ var import_fs26, import_path28, CURRENT_BUILD;
15570
+ var init_build_id = __esm({
15571
+ "src/daemon/build-id.ts"() {
15572
+ "use strict";
15573
+ import_fs26 = __toESM(require("fs"));
15574
+ import_path28 = __toESM(require("path"));
15575
+ CURRENT_BUILD = parseBuildId(process.env.NODE9_BUILD_ID_OVERRIDE) ?? computeBuildId();
15576
+ }
15577
+ });
15578
+
15485
15579
  // src/daemon/suggestion-tracker.ts
15486
15580
  function extractPath(args) {
15487
15581
  if (!args || typeof args !== "object") return null;
@@ -15573,12 +15667,12 @@ var init_suggestion_tracker = __esm({
15573
15667
  });
15574
15668
 
15575
15669
  // src/daemon/taint-store.ts
15576
- var import_fs26, import_path28, DEFAULT_TTL_MS, TaintStore, SESSION_TAINT_TTL_MS, SessionTaintStore;
15670
+ var import_fs27, import_path29, DEFAULT_TTL_MS, TaintStore, SESSION_TAINT_TTL_MS, SessionTaintStore;
15577
15671
  var init_taint_store = __esm({
15578
15672
  "src/daemon/taint-store.ts"() {
15579
15673
  "use strict";
15580
- import_fs26 = __toESM(require("fs"));
15581
- import_path28 = __toESM(require("path"));
15674
+ import_fs27 = __toESM(require("fs"));
15675
+ import_path29 = __toESM(require("path"));
15582
15676
  DEFAULT_TTL_MS = 60 * 60 * 1e3;
15583
15677
  TaintStore = class {
15584
15678
  records = /* @__PURE__ */ new Map();
@@ -15644,9 +15738,9 @@ var init_taint_store = __esm({
15644
15738
  /** Resolve to absolute path, falling back to path.resolve if file doesn't exist yet. */
15645
15739
  _resolve(filePath) {
15646
15740
  try {
15647
- return import_fs26.default.realpathSync.native(import_path28.default.resolve(filePath));
15741
+ return import_fs27.default.realpathSync.native(import_path29.default.resolve(filePath));
15648
15742
  } catch {
15649
- return import_path28.default.resolve(filePath);
15743
+ return import_path29.default.resolve(filePath);
15650
15744
  }
15651
15745
  }
15652
15746
  };
@@ -15812,8 +15906,8 @@ var init_session_history = __esm({
15812
15906
  // src/daemon/state.ts
15813
15907
  function loadInsightCounts() {
15814
15908
  try {
15815
- if (!import_fs27.default.existsSync(INSIGHT_COUNTS_FILE)) return;
15816
- const data = JSON.parse(import_fs27.default.readFileSync(INSIGHT_COUNTS_FILE, "utf-8"));
15909
+ if (!import_fs28.default.existsSync(INSIGHT_COUNTS_FILE)) return;
15910
+ const data = JSON.parse(import_fs28.default.readFileSync(INSIGHT_COUNTS_FILE, "utf-8"));
15817
15911
  for (const [tool, count] of Object.entries(data)) {
15818
15912
  if (typeof count === "number" && count > 0) insightCounts.set(tool, count);
15819
15913
  }
@@ -15852,23 +15946,23 @@ function markRejectionHandlerRegistered() {
15852
15946
  daemonRejectionHandlerRegistered = true;
15853
15947
  }
15854
15948
  function atomicWriteSync2(filePath, data, options) {
15855
- const dir = import_path29.default.dirname(filePath);
15856
- if (!import_fs27.default.existsSync(dir)) import_fs27.default.mkdirSync(dir, { recursive: true });
15949
+ const dir = import_path30.default.dirname(filePath);
15950
+ if (!import_fs28.default.existsSync(dir)) import_fs28.default.mkdirSync(dir, { recursive: true });
15857
15951
  const tmpPath = `${filePath}.${(0, import_crypto8.randomUUID)()}.tmp`;
15858
15952
  try {
15859
- import_fs27.default.writeFileSync(tmpPath, data, options);
15953
+ import_fs28.default.writeFileSync(tmpPath, data, options);
15860
15954
  } catch (err2) {
15861
15955
  try {
15862
- import_fs27.default.unlinkSync(tmpPath);
15956
+ import_fs28.default.unlinkSync(tmpPath);
15863
15957
  } catch {
15864
15958
  }
15865
15959
  throw err2;
15866
15960
  }
15867
15961
  try {
15868
- import_fs27.default.renameSync(tmpPath, filePath);
15962
+ import_fs28.default.renameSync(tmpPath, filePath);
15869
15963
  } catch (err2) {
15870
15964
  try {
15871
- import_fs27.default.unlinkSync(tmpPath);
15965
+ import_fs28.default.unlinkSync(tmpPath);
15872
15966
  } catch {
15873
15967
  }
15874
15968
  throw err2;
@@ -15892,16 +15986,16 @@ function appendAuditLog(data) {
15892
15986
  decision: data.decision,
15893
15987
  source: "daemon"
15894
15988
  };
15895
- const dir = import_path29.default.dirname(AUDIT_LOG_FILE);
15896
- if (!import_fs27.default.existsSync(dir)) import_fs27.default.mkdirSync(dir, { recursive: true });
15897
- import_fs27.default.appendFileSync(AUDIT_LOG_FILE, JSON.stringify(entry) + "\n");
15989
+ const dir = import_path30.default.dirname(AUDIT_LOG_FILE);
15990
+ if (!import_fs28.default.existsSync(dir)) import_fs28.default.mkdirSync(dir, { recursive: true });
15991
+ import_fs28.default.appendFileSync(AUDIT_LOG_FILE, JSON.stringify(entry) + "\n");
15898
15992
  } catch {
15899
15993
  }
15900
15994
  }
15901
15995
  function getAuditHistory(limit = 20) {
15902
15996
  try {
15903
- if (!import_fs27.default.existsSync(AUDIT_LOG_FILE)) return [];
15904
- const lines = import_fs27.default.readFileSync(AUDIT_LOG_FILE, "utf-8").trim().split("\n");
15997
+ if (!import_fs28.default.existsSync(AUDIT_LOG_FILE)) return [];
15998
+ const lines = import_fs28.default.readFileSync(AUDIT_LOG_FILE, "utf-8").trim().split("\n");
15905
15999
  if (lines.length === 1 && lines[0] === "") return [];
15906
16000
  return lines.slice(-limit).map((l) => JSON.parse(l)).reverse();
15907
16001
  } catch {
@@ -15910,7 +16004,7 @@ function getAuditHistory(limit = 20) {
15910
16004
  }
15911
16005
  function getOrgName() {
15912
16006
  try {
15913
- if (import_fs27.default.existsSync(CREDENTIALS_FILE)) return "Node9 Cloud";
16007
+ if (import_fs28.default.existsSync(CREDENTIALS_FILE)) return "Node9 Cloud";
15914
16008
  } catch {
15915
16009
  }
15916
16010
  return null;
@@ -15918,8 +16012,8 @@ function getOrgName() {
15918
16012
  function writeGlobalSetting(key, value) {
15919
16013
  let config = {};
15920
16014
  try {
15921
- if (import_fs27.default.existsSync(GLOBAL_CONFIG_FILE)) {
15922
- config = JSON.parse(import_fs27.default.readFileSync(GLOBAL_CONFIG_FILE, "utf-8"));
16015
+ if (import_fs28.default.existsSync(GLOBAL_CONFIG_FILE)) {
16016
+ config = JSON.parse(import_fs28.default.readFileSync(GLOBAL_CONFIG_FILE, "utf-8"));
15923
16017
  }
15924
16018
  } catch {
15925
16019
  }
@@ -15931,8 +16025,8 @@ function writeTrustEntry(toolName, durationMs, commandPattern) {
15931
16025
  try {
15932
16026
  let trust = { entries: [] };
15933
16027
  try {
15934
- if (import_fs27.default.existsSync(TRUST_FILE2))
15935
- trust = JSON.parse(import_fs27.default.readFileSync(TRUST_FILE2, "utf-8"));
16028
+ if (import_fs28.default.existsSync(TRUST_FILE2))
16029
+ trust = JSON.parse(import_fs28.default.readFileSync(TRUST_FILE2, "utf-8"));
15936
16030
  } catch {
15937
16031
  }
15938
16032
  trust.entries = trust.entries.filter(
@@ -15949,8 +16043,8 @@ function writeTrustEntry(toolName, durationMs, commandPattern) {
15949
16043
  }
15950
16044
  function readPersistentDecisions() {
15951
16045
  try {
15952
- if (import_fs27.default.existsSync(DECISIONS_FILE)) {
15953
- return JSON.parse(import_fs27.default.readFileSync(DECISIONS_FILE, "utf-8"));
16046
+ if (import_fs28.default.existsSync(DECISIONS_FILE)) {
16047
+ return JSON.parse(import_fs28.default.readFileSync(DECISIONS_FILE, "utf-8"));
15954
16048
  }
15955
16049
  } catch {
15956
16050
  }
@@ -15978,7 +16072,7 @@ function estimateToolCost(tool, args) {
15978
16072
  const filePath = a.file_path ?? a.path;
15979
16073
  if (filePath) {
15980
16074
  try {
15981
- const bytes = import_fs27.default.statSync(filePath).size;
16075
+ const bytes = import_fs28.default.statSync(filePath).size;
15982
16076
  return bytes / BYTES_PER_TOKEN / 1e6 * INPUT_PRICE_PER_1M;
15983
16077
  } catch {
15984
16078
  }
@@ -16052,7 +16146,7 @@ function abandonPending() {
16052
16146
  });
16053
16147
  if (autoStarted) {
16054
16148
  try {
16055
- import_fs27.default.unlinkSync(DAEMON_PID_FILE);
16149
+ import_fs28.default.unlinkSync(DAEMON_PID_FILE);
16056
16150
  } catch {
16057
16151
  }
16058
16152
  setTimeout(() => {
@@ -16063,8 +16157,8 @@ function abandonPending() {
16063
16157
  }
16064
16158
  function logActivitySocket(msg) {
16065
16159
  try {
16066
- import_fs27.default.appendFileSync(
16067
- import_path29.default.join(homeDir, ".node9", "hook-debug.log"),
16160
+ import_fs28.default.appendFileSync(
16161
+ import_path30.default.join(homeDir, ".node9", "hook-debug.log"),
16068
16162
  `[${(/* @__PURE__ */ new Date()).toISOString()}] [activity-socket] ${msg}
16069
16163
  `
16070
16164
  );
@@ -16086,13 +16180,13 @@ function shouldRebind(now = Date.now()) {
16086
16180
  function startActivitySocket() {
16087
16181
  bindActivitySocket();
16088
16182
  activityHealthInterval = setInterval(() => {
16089
- if (!import_fs27.default.existsSync(ACTIVITY_SOCKET_PATH2)) attemptRebind("health-probe");
16183
+ if (!import_fs28.default.existsSync(ACTIVITY_SOCKET_PATH2)) attemptRebind("health-probe");
16090
16184
  }, ACTIVITY_HEALTH_PROBE_MS);
16091
16185
  activityHealthInterval.unref();
16092
16186
  process.on("exit", () => {
16093
16187
  if (activityHealthInterval) clearInterval(activityHealthInterval);
16094
16188
  try {
16095
- import_fs27.default.unlinkSync(ACTIVITY_SOCKET_PATH2);
16189
+ import_fs28.default.unlinkSync(ACTIVITY_SOCKET_PATH2);
16096
16190
  } catch {
16097
16191
  }
16098
16192
  });
@@ -16120,7 +16214,7 @@ function attemptRebind(reason) {
16120
16214
  }
16121
16215
  function bindActivitySocket() {
16122
16216
  try {
16123
- import_fs27.default.unlinkSync(ACTIVITY_SOCKET_PATH2);
16217
+ import_fs28.default.unlinkSync(ACTIVITY_SOCKET_PATH2);
16124
16218
  } catch {
16125
16219
  }
16126
16220
  const ACTIVITY_MAX_BYTES = 1024 * 1024;
@@ -16224,13 +16318,13 @@ function bindActivitySocket() {
16224
16318
  });
16225
16319
  activitySocketServer = unixServer;
16226
16320
  }
16227
- var import_net2, import_fs27, import_path29, import_os25, import_crypto8, homeDir, DAEMON_PID_FILE, DECISIONS_FILE, AUDIT_LOG_FILE, TRUST_FILE2, GLOBAL_CONFIG_FILE, CREDENTIALS_FILE, INSIGHT_COUNTS_FILE, pending, sseClients, suggestionTracker, taintStore, sessionTaintStore, insightCounts, _abandonTimer, _hadBrowserClient, _daemonServer, daemonRejectionHandlerRegistered, AUTO_DENY_MS, TRUST_DURATIONS, autoStarted, ACTIVITY_SOCKET_PATH2, ACTIVITY_RING_SIZE, activityRing, LARGE_RESPONSE_RING_SIZE, largeResponseRing, cachedScanResult, cachedScanTs, SCAN_CACHE_TTL_MS, SECRET_KEY_RE, INPUT_PRICE_PER_1M, OUTPUT_PRICE_PER_1M, BYTES_PER_TOKEN, CRITICAL_FORENSIC_CATEGORIES, WRITE_TOOL_NAMES, ACTIVITY_REBIND_MAX_ATTEMPTS, ACTIVITY_REBIND_WINDOW_MS, ACTIVITY_HEALTH_PROBE_MS, activitySocketServer, activityHealthInterval, activityRebindAttempts, activityCircuitTripped;
16321
+ var import_net2, import_fs28, import_path30, import_os25, import_crypto8, homeDir, DAEMON_PID_FILE, DECISIONS_FILE, AUDIT_LOG_FILE, TRUST_FILE2, GLOBAL_CONFIG_FILE, CREDENTIALS_FILE, INSIGHT_COUNTS_FILE, pending, sseClients, suggestionTracker, taintStore, sessionTaintStore, insightCounts, _abandonTimer, _hadBrowserClient, _daemonServer, daemonRejectionHandlerRegistered, AUTO_DENY_MS, TRUST_DURATIONS, autoStarted, ACTIVITY_SOCKET_PATH2, ACTIVITY_RING_SIZE, activityRing, LARGE_RESPONSE_RING_SIZE, largeResponseRing, cachedScanResult, cachedScanTs, SCAN_CACHE_TTL_MS, SECRET_KEY_RE, INPUT_PRICE_PER_1M, OUTPUT_PRICE_PER_1M, BYTES_PER_TOKEN, CRITICAL_FORENSIC_CATEGORIES, WRITE_TOOL_NAMES, ACTIVITY_REBIND_MAX_ATTEMPTS, ACTIVITY_REBIND_WINDOW_MS, ACTIVITY_HEALTH_PROBE_MS, activitySocketServer, activityHealthInterval, activityRebindAttempts, activityCircuitTripped;
16228
16322
  var init_state2 = __esm({
16229
16323
  "src/daemon/state.ts"() {
16230
16324
  "use strict";
16231
16325
  import_net2 = __toESM(require("net"));
16232
- import_fs27 = __toESM(require("fs"));
16233
- import_path29 = __toESM(require("path"));
16326
+ import_fs28 = __toESM(require("fs"));
16327
+ import_path30 = __toESM(require("path"));
16234
16328
  import_os25 = __toESM(require("os"));
16235
16329
  import_crypto8 = require("crypto");
16236
16330
  init_daemon();
@@ -16239,13 +16333,13 @@ var init_state2 = __esm({
16239
16333
  init_session_counters();
16240
16334
  init_session_history();
16241
16335
  homeDir = import_os25.default.homedir();
16242
- DAEMON_PID_FILE = import_path29.default.join(homeDir, ".node9", "daemon.pid");
16243
- DECISIONS_FILE = import_path29.default.join(homeDir, ".node9", "decisions.json");
16244
- AUDIT_LOG_FILE = import_path29.default.join(homeDir, ".node9", "audit.log");
16245
- TRUST_FILE2 = import_path29.default.join(homeDir, ".node9", "trust.json");
16246
- GLOBAL_CONFIG_FILE = import_path29.default.join(homeDir, ".node9", "config.json");
16247
- CREDENTIALS_FILE = import_path29.default.join(homeDir, ".node9", "credentials.json");
16248
- INSIGHT_COUNTS_FILE = import_path29.default.join(homeDir, ".node9", "insight-counts.json");
16336
+ DAEMON_PID_FILE = import_path30.default.join(homeDir, ".node9", "daemon.pid");
16337
+ DECISIONS_FILE = import_path30.default.join(homeDir, ".node9", "decisions.json");
16338
+ AUDIT_LOG_FILE = import_path30.default.join(homeDir, ".node9", "audit.log");
16339
+ TRUST_FILE2 = import_path30.default.join(homeDir, ".node9", "trust.json");
16340
+ GLOBAL_CONFIG_FILE = import_path30.default.join(homeDir, ".node9", "config.json");
16341
+ CREDENTIALS_FILE = import_path30.default.join(homeDir, ".node9", "credentials.json");
16342
+ INSIGHT_COUNTS_FILE = import_path30.default.join(homeDir, ".node9", "insight-counts.json");
16249
16343
  pending = /* @__PURE__ */ new Map();
16250
16344
  sseClients = /* @__PURE__ */ new Set();
16251
16345
  suggestionTracker = new SuggestionTracker(3);
@@ -16263,7 +16357,7 @@ var init_state2 = __esm({
16263
16357
  "2h": 2 * 60 * 6e4
16264
16358
  };
16265
16359
  autoStarted = process.env.NODE9_AUTO_STARTED === "1";
16266
- ACTIVITY_SOCKET_PATH2 = process.platform === "win32" ? "\\\\.\\pipe\\node9-activity" : import_path29.default.join(import_os25.default.tmpdir(), "node9-activity.sock");
16360
+ ACTIVITY_SOCKET_PATH2 = process.platform === "win32" ? "\\\\.\\pipe\\node9-activity" : import_path30.default.join(import_os25.default.tmpdir(), "node9-activity.sock");
16267
16361
  ACTIVITY_RING_SIZE = 100;
16268
16362
  activityRing = [];
16269
16363
  LARGE_RESPONSE_RING_SIZE = 20;
@@ -16304,15 +16398,15 @@ var init_state2 = __esm({
16304
16398
  // src/posture/secrets.ts
16305
16399
  function displayPath(p, home) {
16306
16400
  if (p === home) return "~";
16307
- const prefix = home.endsWith(import_path30.default.sep) ? home : home + import_path30.default.sep;
16308
- if (p.startsWith(prefix)) return "~" + import_path30.default.sep + p.slice(prefix.length);
16401
+ const prefix = home.endsWith(import_path31.default.sep) ? home : home + import_path31.default.sep;
16402
+ if (p.startsWith(prefix)) return "~" + import_path31.default.sep + p.slice(prefix.length);
16309
16403
  return p;
16310
16404
  }
16311
16405
  function safeRead(file) {
16312
16406
  try {
16313
- const stat = import_fs28.default.statSync(file);
16407
+ const stat = import_fs29.default.statSync(file);
16314
16408
  if (!stat.isFile() || stat.size === 0 || stat.size > MAX_FILE_BYTES) return null;
16315
- return import_fs28.default.readFileSync(file, "utf8");
16409
+ return import_fs29.default.readFileSync(file, "utf8");
16316
16410
  } catch {
16317
16411
  return null;
16318
16412
  }
@@ -16320,8 +16414,8 @@ function safeRead(file) {
16320
16414
  function candidateFiles(home, cwd) {
16321
16415
  const files = /* @__PURE__ */ new Set();
16322
16416
  try {
16323
- for (const name of import_fs28.default.readdirSync(cwd)) {
16324
- if (name === ".env" || name.startsWith(".env.")) files.add(import_path30.default.join(cwd, name));
16417
+ for (const name of import_fs29.default.readdirSync(cwd)) {
16418
+ if (name === ".env" || name.startsWith(".env.")) files.add(import_path31.default.join(cwd, name));
16325
16419
  }
16326
16420
  } catch {
16327
16421
  }
@@ -16329,17 +16423,17 @@ function candidateFiles(home, cwd) {
16329
16423
  if (spec.hookFile) files.add(spec.hookFile(home));
16330
16424
  if (spec.mcpFile) files.add(spec.mcpFile(home));
16331
16425
  }
16332
- files.add(import_path30.default.join(home, ".env"));
16426
+ files.add(import_path31.default.join(home, ".env"));
16333
16427
  return [...files];
16334
16428
  }
16335
16429
  function credentialMaterial(home) {
16336
16430
  return [
16337
- import_path30.default.join(home, ".ssh", "id_rsa"),
16338
- import_path30.default.join(home, ".ssh", "id_dsa"),
16339
- import_path30.default.join(home, ".ssh", "id_ecdsa"),
16340
- import_path30.default.join(home, ".ssh", "id_ed25519"),
16341
- import_path30.default.join(home, ".aws", "credentials"),
16342
- import_path30.default.join(home, ".config", "gcloud", "application_default_credentials.json")
16431
+ import_path31.default.join(home, ".ssh", "id_rsa"),
16432
+ import_path31.default.join(home, ".ssh", "id_dsa"),
16433
+ import_path31.default.join(home, ".ssh", "id_ecdsa"),
16434
+ import_path31.default.join(home, ".ssh", "id_ed25519"),
16435
+ import_path31.default.join(home, ".aws", "credentials"),
16436
+ import_path31.default.join(home, ".config", "gcloud", "application_default_credentials.json")
16343
16437
  ];
16344
16438
  }
16345
16439
  function checkSecrets(ctx) {
@@ -16376,7 +16470,7 @@ function checkSecrets(ctx) {
16376
16470
  const credPaths = [];
16377
16471
  for (const file of credentialMaterial(home)) {
16378
16472
  try {
16379
- if (import_fs28.default.statSync(file).isFile()) {
16473
+ if (import_fs29.default.statSync(file).isFile()) {
16380
16474
  creds.push(displayPath(file, home));
16381
16475
  credPaths.push(file);
16382
16476
  }
@@ -16399,12 +16493,12 @@ function checkSecrets(ctx) {
16399
16493
  }
16400
16494
  return findings;
16401
16495
  }
16402
- var import_fs28, import_path30, import_os26, MAX_FILE_BYTES;
16496
+ var import_fs29, import_path31, import_os26, MAX_FILE_BYTES;
16403
16497
  var init_secrets = __esm({
16404
16498
  "src/posture/secrets.ts"() {
16405
16499
  "use strict";
16406
- import_fs28 = __toESM(require("fs"));
16407
- import_path30 = __toESM(require("path"));
16500
+ import_fs29 = __toESM(require("fs"));
16501
+ import_path31 = __toESM(require("path"));
16408
16502
  import_os26 = __toESM(require("os"));
16409
16503
  init_dist();
16410
16504
  init_agent_wiring();
@@ -16537,7 +16631,7 @@ var init_templates = __esm({
16537
16631
  // src/posture/egress.ts
16538
16632
  function sandboxEgressWallActive() {
16539
16633
  try {
16540
- return import_fs29.default.existsSync(ALLOWED_DOMAINS_PATH);
16634
+ return import_fs30.default.existsSync(ALLOWED_DOMAINS_PATH);
16541
16635
  } catch {
16542
16636
  return false;
16543
16637
  }
@@ -16610,11 +16704,11 @@ function checkEgress(ctx) {
16610
16704
  const egress = config.policy.egress;
16611
16705
  return [evaluateEgressConfig({ enabled: egress.enabled, mode: egress.mode })];
16612
16706
  }
16613
- var import_fs29;
16707
+ var import_fs30;
16614
16708
  var init_egress = __esm({
16615
16709
  "src/posture/egress.ts"() {
16616
16710
  "use strict";
16617
- import_fs29 = __toESM(require("fs"));
16711
+ import_fs30 = __toESM(require("fs"));
16618
16712
  init_config();
16619
16713
  init_templates();
16620
16714
  }
@@ -16663,17 +16757,17 @@ var init_gate = __esm({
16663
16757
  // src/posture/supply-chain.ts
16664
16758
  function isNode9Managed(command, args = []) {
16665
16759
  if (!command) return false;
16666
- if (import_path31.default.basename(command).toLowerCase() === "node9") return true;
16667
- if (PACKAGE_RUNNERS.has(import_path31.default.basename(command).toLowerCase())) {
16668
- return args.some((a) => a === "node9" || import_path31.default.basename(a).toLowerCase() === "node9");
16760
+ if (import_path32.default.basename(command).toLowerCase() === "node9") return true;
16761
+ if (PACKAGE_RUNNERS.has(import_path32.default.basename(command).toLowerCase())) {
16762
+ return args.some((a) => a === "node9" || import_path32.default.basename(a).toLowerCase() === "node9");
16669
16763
  }
16670
16764
  return false;
16671
16765
  }
16672
16766
  function readServers(file, format, agent) {
16673
16767
  try {
16674
- const stat = import_fs30.default.statSync(file);
16768
+ const stat = import_fs31.default.statSync(file);
16675
16769
  if (!stat.isFile() || stat.size > MAX_CONFIG_BYTES) return [];
16676
- const text = import_fs30.default.readFileSync(file, "utf8");
16770
+ const text = import_fs31.default.readFileSync(file, "utf8");
16677
16771
  const map = format === "toml" ? (0, import_smol_toml3.parse)(text)?.mcp_servers : JSON.parse(text)?.mcpServers;
16678
16772
  if (!map || typeof map !== "object") return [];
16679
16773
  return Object.entries(map).map(([name, v]) => ({
@@ -16727,13 +16821,13 @@ function checkSupplyChain(ctx) {
16727
16821
  }
16728
16822
  return findings;
16729
16823
  }
16730
- var import_fs30, import_os27, import_path31, import_smol_toml3, PACKAGE_RUNNERS, MAX_CONFIG_BYTES;
16824
+ var import_fs31, import_os27, import_path32, import_smol_toml3, PACKAGE_RUNNERS, MAX_CONFIG_BYTES;
16731
16825
  var init_supply_chain = __esm({
16732
16826
  "src/posture/supply-chain.ts"() {
16733
16827
  "use strict";
16734
- import_fs30 = __toESM(require("fs"));
16828
+ import_fs31 = __toESM(require("fs"));
16735
16829
  import_os27 = __toESM(require("os"));
16736
- import_path31 = __toESM(require("path"));
16830
+ import_path32 = __toESM(require("path"));
16737
16831
  import_smol_toml3 = require("smol-toml");
16738
16832
  init_provenance();
16739
16833
  init_agent_wiring();
@@ -16790,9 +16884,9 @@ var init_privilege = __esm({
16790
16884
 
16791
16885
  // src/posture/containment.ts
16792
16886
  function inContainer() {
16793
- if (import_fs31.default.existsSync("/.dockerenv") || import_fs31.default.existsSync("/run/.containerenv")) return true;
16887
+ if (import_fs32.default.existsSync("/.dockerenv") || import_fs32.default.existsSync("/run/.containerenv")) return true;
16794
16888
  try {
16795
- const cgroup = import_fs31.default.readFileSync("/proc/1/cgroup", "utf8");
16889
+ const cgroup = import_fs32.default.readFileSync("/proc/1/cgroup", "utf8");
16796
16890
  if (/docker|kubepods|containerd|lxc|libpod/.test(cgroup)) return true;
16797
16891
  } catch {
16798
16892
  }
@@ -16829,11 +16923,11 @@ Lighter \u2014 harden in place, keep full host access (about +${Math.round(
16829
16923
  }
16830
16924
  ];
16831
16925
  }
16832
- var import_fs31, ISOLATION_WEIGHT;
16926
+ var import_fs32, ISOLATION_WEIGHT;
16833
16927
  var init_containment = __esm({
16834
16928
  "src/posture/containment.ts"() {
16835
16929
  "use strict";
16836
- import_fs31 = __toESM(require("fs"));
16930
+ import_fs32 = __toESM(require("fs"));
16837
16931
  ISOLATION_WEIGHT = 12;
16838
16932
  }
16839
16933
  });
@@ -16896,7 +16990,7 @@ function collectListeners() {
16896
16990
  const byPort = /* @__PURE__ */ new Map();
16897
16991
  for (const file of ["/proc/net/tcp", "/proc/net/tcp6"]) {
16898
16992
  try {
16899
- for (const l of parseListeners(import_fs32.default.readFileSync(file, "utf8"))) {
16993
+ for (const l of parseListeners(import_fs33.default.readFileSync(file, "utf8"))) {
16900
16994
  if (!byPort.has(l.port)) byPort.set(l.port, l);
16901
16995
  }
16902
16996
  } catch {
@@ -16908,11 +17002,11 @@ function readProc(pid) {
16908
17002
  let comm = "unknown";
16909
17003
  let cmdline = "";
16910
17004
  try {
16911
- comm = import_fs32.default.readFileSync(`/proc/${pid}/comm`, "utf8").trim().replace(/-MainThread$/, "") || "unknown";
17005
+ comm = import_fs33.default.readFileSync(`/proc/${pid}/comm`, "utf8").trim().replace(/-MainThread$/, "") || "unknown";
16912
17006
  } catch {
16913
17007
  }
16914
17008
  try {
16915
- cmdline = import_fs32.default.readFileSync(`/proc/${pid}/cmdline`).toString().replace(/\0/g, " ").trim();
17009
+ cmdline = import_fs33.default.readFileSync(`/proc/${pid}/cmdline`).toString().replace(/\0/g, " ").trim();
16916
17010
  } catch {
16917
17011
  }
16918
17012
  return { comm, cmdline };
@@ -16922,21 +17016,21 @@ function resolveProcesses(inodes) {
16922
17016
  if (inodes.size === 0) return map;
16923
17017
  let pids;
16924
17018
  try {
16925
- pids = import_fs32.default.readdirSync("/proc").filter((d) => /^\d+$/.test(d));
17019
+ pids = import_fs33.default.readdirSync("/proc").filter((d) => /^\d+$/.test(d));
16926
17020
  } catch {
16927
17021
  return map;
16928
17022
  }
16929
17023
  for (const pid of pids) {
16930
17024
  let fds;
16931
17025
  try {
16932
- fds = import_fs32.default.readdirSync(`/proc/${pid}/fd`);
17026
+ fds = import_fs33.default.readdirSync(`/proc/${pid}/fd`);
16933
17027
  } catch {
16934
17028
  continue;
16935
17029
  }
16936
17030
  for (const fd of fds) {
16937
17031
  let link;
16938
17032
  try {
16939
- link = import_fs32.default.readlinkSync(`/proc/${pid}/fd/${fd}`);
17033
+ link = import_fs33.default.readlinkSync(`/proc/${pid}/fd/${fd}`);
16940
17034
  } catch {
16941
17035
  continue;
16942
17036
  }
@@ -17004,11 +17098,11 @@ function checkInbound(ctx) {
17004
17098
  }
17005
17099
  return findings;
17006
17100
  }
17007
- var import_fs32, DB_EXPOSURE_WEIGHT, KNOWN_SERVICE_PORTS, KNOWN_SERVICE_COMMS, DB_LABEL, SHIELD_FOR_SERVICE;
17101
+ var import_fs33, DB_EXPOSURE_WEIGHT, KNOWN_SERVICE_PORTS, KNOWN_SERVICE_COMMS, DB_LABEL, SHIELD_FOR_SERVICE;
17008
17102
  var init_inbound = __esm({
17009
17103
  "src/posture/inbound.ts"() {
17010
17104
  "use strict";
17011
- import_fs32 = __toESM(require("fs"));
17105
+ import_fs33 = __toESM(require("fs"));
17012
17106
  DB_EXPOSURE_WEIGHT = 4;
17013
17107
  KNOWN_SERVICE_PORTS = {
17014
17108
  5432: "PostgreSQL",
@@ -17226,13 +17320,13 @@ function checkCost(_ctx) {
17226
17320
  }
17227
17321
  ];
17228
17322
  }
17229
- var import_path32, jailProbePath;
17323
+ var import_path33, jailProbePath;
17230
17324
  var init_governance = __esm({
17231
17325
  "src/posture/governance.ts"() {
17232
17326
  "use strict";
17233
- import_path32 = __toESM(require("path"));
17327
+ import_path33 = __toESM(require("path"));
17234
17328
  init_config();
17235
- jailProbePath = (home) => import_path32.default.join(home, ".aws", "credentials");
17329
+ jailProbePath = (home) => import_path33.default.join(home, ".aws", "credentials");
17236
17330
  }
17237
17331
  });
17238
17332
 
@@ -17725,13 +17819,13 @@ function deriveServerName(cmd) {
17725
17819
  return strip(base) || "MCP Server";
17726
17820
  }
17727
17821
  function getMcpToolsFile() {
17728
- return import_path33.default.join(import_os30.default.homedir(), ".node9", "mcp-tools.json");
17822
+ return import_path34.default.join(import_os30.default.homedir(), ".node9", "mcp-tools.json");
17729
17823
  }
17730
17824
  function readMcpToolsConfig() {
17731
17825
  try {
17732
17826
  const file = getMcpToolsFile();
17733
- if (!import_fs33.default.existsSync(file)) return {};
17734
- const raw = import_fs33.default.readFileSync(file, "utf-8");
17827
+ if (!import_fs34.default.existsSync(file)) return {};
17828
+ const raw = import_fs34.default.readFileSync(file, "utf-8");
17735
17829
  return JSON.parse(raw);
17736
17830
  } catch {
17737
17831
  return {};
@@ -17740,11 +17834,11 @@ function readMcpToolsConfig() {
17740
17834
  function writeMcpToolsConfig(config) {
17741
17835
  try {
17742
17836
  const file = getMcpToolsFile();
17743
- const dir = import_path33.default.dirname(file);
17744
- if (!import_fs33.default.existsSync(dir)) import_fs33.default.mkdirSync(dir, { recursive: true });
17837
+ const dir = import_path34.default.dirname(file);
17838
+ if (!import_fs34.default.existsSync(dir)) import_fs34.default.mkdirSync(dir, { recursive: true });
17745
17839
  const tmpPath = `${file}.${import_os30.default.hostname()}.${process.pid}.tmp`;
17746
- import_fs33.default.writeFileSync(tmpPath, JSON.stringify(config, null, 2));
17747
- import_fs33.default.renameSync(tmpPath, file);
17840
+ import_fs34.default.writeFileSync(tmpPath, JSON.stringify(config, null, 2));
17841
+ import_fs34.default.renameSync(tmpPath, file);
17748
17842
  } catch (e) {
17749
17843
  console.error("Failed to write mcp-tools.json", e);
17750
17844
  }
@@ -17791,12 +17885,12 @@ function approveServer(serverKey, disabledTools) {
17791
17885
  writeMcpToolsConfig(config);
17792
17886
  }
17793
17887
  }
17794
- var import_fs33, import_path33, import_os30;
17888
+ var import_fs34, import_path34, import_os30;
17795
17889
  var init_mcp_tools = __esm({
17796
17890
  "src/daemon/mcp-tools.ts"() {
17797
17891
  "use strict";
17798
- import_fs33 = __toESM(require("fs"));
17799
- import_path33 = __toESM(require("path"));
17892
+ import_fs34 = __toESM(require("fs"));
17893
+ import_path34 = __toESM(require("path"));
17800
17894
  import_os30 = __toESM(require("os"));
17801
17895
  init_mcp_cmd();
17802
17896
  }
@@ -17873,11 +17967,11 @@ function inventoryServerKeys(inv) {
17873
17967
  function writeMcpEntry(mcpFile, format, name, entry) {
17874
17968
  const key = format === "toml" ? "mcp_servers" : "mcpServers";
17875
17969
  let root = {};
17876
- if (import_fs34.default.existsSync(mcpFile)) {
17877
- const raw = import_fs34.default.readFileSync(mcpFile, "utf-8");
17970
+ if (import_fs35.default.existsSync(mcpFile)) {
17971
+ const raw = import_fs35.default.readFileSync(mcpFile, "utf-8");
17878
17972
  root = format === "toml" ? (0, import_smol_toml4.parse)(raw) : JSON.parse(raw);
17879
17973
  const bak = `${mcpFile}.node9-bak`;
17880
- if (!import_fs34.default.existsSync(bak)) import_fs34.default.writeFileSync(bak, raw, { mode: 384 });
17974
+ if (!import_fs35.default.existsSync(bak)) import_fs35.default.writeFileSync(bak, raw, { mode: 384 });
17881
17975
  }
17882
17976
  const existing = root[key];
17883
17977
  const servers = existing && typeof existing === "object" && !Array.isArray(existing) ? existing : {};
@@ -17885,14 +17979,14 @@ function writeMcpEntry(mcpFile, format, name, entry) {
17885
17979
  root[key] = servers;
17886
17980
  const serialized = format === "toml" ? (0, import_smol_toml4.stringify)(root) : JSON.stringify(root, null, 2);
17887
17981
  const tmp = `${mcpFile}.${process.pid}.tmp`;
17888
- import_fs34.default.writeFileSync(tmp, serialized, { mode: 384 });
17889
- import_fs34.default.renameSync(tmp, mcpFile);
17982
+ import_fs35.default.writeFileSync(tmp, serialized, { mode: 384 });
17983
+ import_fs35.default.renameSync(tmp, mcpFile);
17890
17984
  }
17891
- var import_fs34, import_os31, import_smol_toml4;
17985
+ var import_fs35, import_os31, import_smol_toml4;
17892
17986
  var init_mcp_wrap = __esm({
17893
17987
  "src/mcp-wrap.ts"() {
17894
17988
  "use strict";
17895
- import_fs34 = __toESM(require("fs"));
17989
+ import_fs35 = __toESM(require("fs"));
17896
17990
  import_os31 = __toESM(require("os"));
17897
17991
  import_smol_toml4 = require("smol-toml");
17898
17992
  init_agent_wiring();
@@ -18062,8 +18156,8 @@ function readCredentials() {
18062
18156
  };
18063
18157
  }
18064
18158
  try {
18065
- const credPath = import_path34.default.join(import_os32.default.homedir(), ".node9", "credentials.json");
18066
- const creds = JSON.parse(import_fs35.default.readFileSync(credPath, "utf-8"));
18159
+ const credPath = import_path35.default.join(import_os32.default.homedir(), ".node9", "credentials.json");
18160
+ const creds = JSON.parse(import_fs36.default.readFileSync(credPath, "utf-8"));
18067
18161
  const profileName = process.env.NODE9_PROFILE ?? "default";
18068
18162
  const profile = creds[profileName];
18069
18163
  if (typeof profile?.apiKey === "string" && profile.apiKey.length > 0) {
@@ -18089,7 +18183,7 @@ function readCredentials() {
18089
18183
  }
18090
18184
  function readCachedEtag() {
18091
18185
  try {
18092
- const raw = JSON.parse(import_fs35.default.readFileSync(rulesCacheFile(), "utf-8"));
18186
+ const raw = JSON.parse(import_fs36.default.readFileSync(rulesCacheFile(), "utf-8"));
18093
18187
  return typeof raw.etag === "string" ? raw.etag : void 0;
18094
18188
  } catch {
18095
18189
  return void 0;
@@ -18097,7 +18191,7 @@ function readCachedEtag() {
18097
18191
  }
18098
18192
  function readCachedSyncIntervalHours() {
18099
18193
  try {
18100
- const raw = JSON.parse(import_fs35.default.readFileSync(rulesCacheFile(), "utf-8"));
18194
+ const raw = JSON.parse(import_fs36.default.readFileSync(rulesCacheFile(), "utf-8"));
18101
18195
  return typeof raw.syncIntervalHours === "number" ? raw.syncIntervalHours : void 0;
18102
18196
  } catch {
18103
18197
  return void 0;
@@ -18114,7 +18208,7 @@ function effectiveSyncIntervalMs() {
18114
18208
  }
18115
18209
  function readSyncHealth() {
18116
18210
  try {
18117
- const raw = JSON.parse(import_fs35.default.readFileSync(syncHealthFile(), "utf-8"));
18211
+ const raw = JSON.parse(import_fs36.default.readFileSync(syncHealthFile(), "utf-8"));
18118
18212
  return {
18119
18213
  lastCheckedAt: typeof raw.lastCheckedAt === "string" ? raw.lastCheckedAt : void 0,
18120
18214
  lastChangedAt: typeof raw.lastChangedAt === "string" ? raw.lastChangedAt : void 0,
@@ -18129,17 +18223,17 @@ function readSyncHealth() {
18129
18223
  function writeSyncHealth(h) {
18130
18224
  try {
18131
18225
  const file = syncHealthFile();
18132
- const dir = import_path34.default.dirname(file);
18133
- if (!import_fs35.default.existsSync(dir)) import_fs35.default.mkdirSync(dir, { recursive: true });
18226
+ const dir = import_path35.default.dirname(file);
18227
+ if (!import_fs36.default.existsSync(dir)) import_fs36.default.mkdirSync(dir, { recursive: true });
18134
18228
  const tmp = `${file}.${process.pid}.tmp`;
18135
- import_fs35.default.writeFileSync(tmp, JSON.stringify(h, null, 2) + "\n", "utf-8");
18136
- import_fs35.default.renameSync(tmp, file);
18229
+ import_fs36.default.writeFileSync(tmp, JSON.stringify(h, null, 2) + "\n", "utf-8");
18230
+ import_fs36.default.renameSync(tmp, file);
18137
18231
  } catch {
18138
18232
  }
18139
18233
  }
18140
18234
  function readCacheFetchedAt() {
18141
18235
  try {
18142
- const raw = JSON.parse(import_fs35.default.readFileSync(rulesCacheFile(), "utf-8"));
18236
+ const raw = JSON.parse(import_fs36.default.readFileSync(rulesCacheFile(), "utf-8"));
18143
18237
  return typeof raw.fetchedAt === "string" ? raw.fetchedAt : void 0;
18144
18238
  } catch {
18145
18239
  return void 0;
@@ -18325,8 +18419,24 @@ function extractManagedConfig(body) {
18325
18419
  }
18326
18420
  return out.mode !== void 0 || out.egress !== void 0 || out.dlp !== void 0 || out.approvers !== void 0 || out.reviewChannel !== void 0 || out.approvalTimeoutMs !== void 0 || out.injectionScan !== void 0 || out.loopDetection !== void 0 || out.skillPinning !== void 0 || out.jailPaths !== void 0 || out.trustedHosts !== void 0 || out.appPermissions !== void 0 ? out : void 0;
18327
18421
  }
18422
+ function sweepStaleTmp(target) {
18423
+ try {
18424
+ const dir = import_path35.default.dirname(target);
18425
+ const prefix = `${import_path35.default.basename(target)}.`;
18426
+ for (const name of import_fs36.default.readdirSync(dir)) {
18427
+ if (!name.startsWith(prefix) || !name.endsWith(".tmp")) continue;
18428
+ const full = import_path35.default.join(dir, name);
18429
+ try {
18430
+ if (Date.now() - import_fs36.default.statSync(full).mtimeMs > 5 * 60 * 1e3) import_fs36.default.unlinkSync(full);
18431
+ } catch {
18432
+ }
18433
+ }
18434
+ } catch {
18435
+ }
18436
+ }
18328
18437
  function writeCache2(cache) {
18329
18438
  const data = JSON.stringify(cache, null, 2) + "\n";
18439
+ sweepStaleTmp(rulesCacheFile());
18330
18440
  atomicWriteSync2(rulesCacheFile(), data, "utf-8");
18331
18441
  try {
18332
18442
  atomicWriteSync2(rulesCacheBackupFile(), data, "utf-8");
@@ -18573,7 +18683,7 @@ async function runCloudSync() {
18573
18683
  }
18574
18684
  function getCloudSyncStatus() {
18575
18685
  try {
18576
- const raw = JSON.parse(import_fs35.default.readFileSync(rulesCacheFile(), "utf-8"));
18686
+ const raw = JSON.parse(import_fs36.default.readFileSync(rulesCacheFile(), "utf-8"));
18577
18687
  if (!Array.isArray(raw.rules) || typeof raw.fetchedAt !== "string") return { cached: false };
18578
18688
  return {
18579
18689
  cached: true,
@@ -18590,7 +18700,7 @@ function getCloudSyncStatus() {
18590
18700
  }
18591
18701
  function getCloudRules() {
18592
18702
  try {
18593
- const raw = JSON.parse(import_fs35.default.readFileSync(rulesCacheFile(), "utf-8"));
18703
+ const raw = JSON.parse(import_fs36.default.readFileSync(rulesCacheFile(), "utf-8"));
18594
18704
  return Array.isArray(raw.rules) ? raw.rules : null;
18595
18705
  } catch {
18596
18706
  return null;
@@ -18625,14 +18735,14 @@ function startForensicBroadcast() {
18625
18735
  const recurring = setInterval(() => void tick(), FORENSIC_BROADCAST_INTERVAL_MS);
18626
18736
  recurring.unref();
18627
18737
  }
18628
- var import_fs35, import_https4, import_os32, import_path34, FINDING_TO_SIGNAL3, rulesCacheFile, rulesCacheBackupFile, DEFAULT_API_URL2, DEFAULT_INTERVAL_HOURS, MIN_INTERVAL_SECONDS, MAX_INTERVAL_SECONDS, syncHealthFile, STALE_MIN_MS, STALE_MAX_MS, STALE_FACTOR, FORENSIC_BROADCAST_INTERVAL_MS, FORENSIC_INITIAL_DELAY_MS, forensicBroadcastOffsets;
18738
+ var import_fs36, import_https4, import_os32, import_path35, FINDING_TO_SIGNAL3, rulesCacheFile, rulesCacheBackupFile, DEFAULT_API_URL2, DEFAULT_INTERVAL_HOURS, MIN_INTERVAL_SECONDS, MAX_INTERVAL_SECONDS, syncHealthFile, STALE_MIN_MS, STALE_MAX_MS, STALE_FACTOR, FORENSIC_BROADCAST_INTERVAL_MS, FORENSIC_INITIAL_DELAY_MS, forensicBroadcastOffsets;
18629
18739
  var init_sync = __esm({
18630
18740
  "src/daemon/sync.ts"() {
18631
18741
  "use strict";
18632
- import_fs35 = __toESM(require("fs"));
18742
+ import_fs36 = __toESM(require("fs"));
18633
18743
  import_https4 = __toESM(require("https"));
18634
18744
  import_os32 = __toESM(require("os"));
18635
- import_path34 = __toESM(require("path"));
18745
+ import_path35 = __toESM(require("path"));
18636
18746
  init_config();
18637
18747
  init_blast();
18638
18748
  init_posture();
@@ -18659,13 +18769,13 @@ var init_sync = __esm({
18659
18769
  loop: "loops",
18660
18770
  "long-output-redacted": "longOutputRedactions"
18661
18771
  };
18662
- rulesCacheFile = () => import_path34.default.join(import_os32.default.homedir(), ".node9", "rules-cache.json");
18663
- rulesCacheBackupFile = () => import_path34.default.join(import_os32.default.homedir(), ".node9", "rules-cache.last-good.json");
18772
+ rulesCacheFile = () => import_path35.default.join(import_os32.default.homedir(), ".node9", "rules-cache.json");
18773
+ rulesCacheBackupFile = () => import_path35.default.join(import_os32.default.homedir(), ".node9", "rules-cache.last-good.json");
18664
18774
  DEFAULT_API_URL2 = "https://api.node9.ai/api/v1/intercept/policies/sync";
18665
18775
  DEFAULT_INTERVAL_HOURS = 5;
18666
18776
  MIN_INTERVAL_SECONDS = 15;
18667
18777
  MAX_INTERVAL_SECONDS = 24 * 60 * 60;
18668
- syncHealthFile = () => import_path34.default.join(import_os32.default.homedir(), ".node9", "sync-health.json");
18778
+ syncHealthFile = () => import_path35.default.join(import_os32.default.homedir(), ".node9", "sync-health.json");
18669
18779
  STALE_MIN_MS = 3 * 60 * 60 * 1e3;
18670
18780
  STALE_MAX_MS = 24 * 60 * 60 * 1e3;
18671
18781
  STALE_FACTOR = 3;
@@ -18689,21 +18799,21 @@ __export(audit_shipper_exports, {
18689
18799
  writeWatermark: () => writeWatermark
18690
18800
  });
18691
18801
  function fileSignature(filePath) {
18692
- const fd = import_fs36.default.openSync(filePath, "r");
18802
+ const fd = import_fs37.default.openSync(filePath, "r");
18693
18803
  try {
18694
18804
  const buf = Buffer.alloc(512);
18695
- const read2 = import_fs36.default.readSync(fd, buf, 0, 512, 0);
18805
+ const read2 = import_fs37.default.readSync(fd, buf, 0, 512, 0);
18696
18806
  const slice = buf.subarray(0, read2);
18697
18807
  const nl = slice.indexOf(10);
18698
18808
  const firstLine = nl === -1 ? slice : slice.subarray(0, nl);
18699
18809
  return import_crypto9.default.createHash("sha256").update(firstLine).digest("hex").slice(0, 16);
18700
18810
  } finally {
18701
- import_fs36.default.closeSync(fd);
18811
+ import_fs37.default.closeSync(fd);
18702
18812
  }
18703
18813
  }
18704
18814
  function readWatermark(watermarkPath) {
18705
18815
  try {
18706
- const raw = JSON.parse(import_fs36.default.readFileSync(watermarkPath, "utf-8"));
18816
+ const raw = JSON.parse(import_fs37.default.readFileSync(watermarkPath, "utf-8"));
18707
18817
  if (typeof raw.fileSig === "string" && typeof raw.offset === "number" && raw.offset >= 0)
18708
18818
  return raw;
18709
18819
  } catch {
@@ -18712,8 +18822,8 @@ function readWatermark(watermarkPath) {
18712
18822
  }
18713
18823
  function writeWatermark(watermarkPath, wm) {
18714
18824
  const tmp = `${watermarkPath}.tmp`;
18715
- import_fs36.default.writeFileSync(tmp, JSON.stringify(wm));
18716
- import_fs36.default.renameSync(tmp, watermarkPath);
18825
+ import_fs37.default.writeFileSync(tmp, JSON.stringify(wm));
18826
+ import_fs37.default.renameSync(tmp, watermarkPath);
18717
18827
  }
18718
18828
  function buildWireRows(chunk2) {
18719
18829
  const lastNl = chunk2.lastIndexOf(10);
@@ -18791,11 +18901,11 @@ async function shipOnce(deps = {}) {
18791
18901
  if (!creds?.apiKey) return { status: "no-creds", shipped: 0 };
18792
18902
  const endpoint = buildBatchEndpoint(creds.apiUrl);
18793
18903
  if (!endpoint) return { status: "no-creds", shipped: 0 };
18794
- if (!import_fs36.default.existsSync(auditLogPath)) return { status: "idle", shipped: 0 };
18904
+ if (!import_fs37.default.existsSync(auditLogPath)) return { status: "idle", shipped: 0 };
18795
18905
  let shipped = 0;
18796
18906
  try {
18797
18907
  for (let chunkN = 0; chunkN < MAX_CHUNKS_PER_TICK; chunkN++) {
18798
- const size = import_fs36.default.statSync(auditLogPath).size;
18908
+ const size = import_fs37.default.statSync(auditLogPath).size;
18799
18909
  if (size === 0) break;
18800
18910
  const sig = fileSignature(auditLogPath);
18801
18911
  const wm = readWatermark(watermarkPath);
@@ -18803,12 +18913,12 @@ async function shipOnce(deps = {}) {
18803
18913
  if (offset >= size) break;
18804
18914
  const toRead = Math.min(size - offset, MAX_CHUNK_BYTES);
18805
18915
  const buf = Buffer.alloc(toRead);
18806
- const fd = import_fs36.default.openSync(auditLogPath, "r");
18916
+ const fd = import_fs37.default.openSync(auditLogPath, "r");
18807
18917
  let read2;
18808
18918
  try {
18809
- read2 = import_fs36.default.readSync(fd, buf, 0, toRead, offset);
18919
+ read2 = import_fs37.default.readSync(fd, buf, 0, toRead, offset);
18810
18920
  } finally {
18811
- import_fs36.default.closeSync(fd);
18921
+ import_fs37.default.closeSync(fd);
18812
18922
  }
18813
18923
  const { rows, consumed } = buildWireRows(buf.subarray(0, read2));
18814
18924
  if (consumed === 0) break;
@@ -18855,8 +18965,8 @@ async function shipOnce(deps = {}) {
18855
18965
  }
18856
18966
  function shipLagBytes(auditLogPath = LOCAL_AUDIT_LOG, watermarkPath = AUDIT_SHIP_WATERMARK) {
18857
18967
  try {
18858
- if (!import_fs36.default.existsSync(auditLogPath)) return 0;
18859
- const size = import_fs36.default.statSync(auditLogPath).size;
18968
+ if (!import_fs37.default.existsSync(auditLogPath)) return 0;
18969
+ const size = import_fs37.default.statSync(auditLogPath).size;
18860
18970
  const wm = readWatermark(watermarkPath);
18861
18971
  if (!wm) return size;
18862
18972
  if (wm.fileSig !== fileSignature(auditLogPath)) return size;
@@ -18879,19 +18989,19 @@ function startAuditShipper() {
18879
18989
  setTimeout(() => void shipOnce(), 3e3);
18880
18990
  setInterval(() => void shipOnce(), intervalMs);
18881
18991
  }
18882
- var import_fs36, import_path35, import_os33, import_crypto9, AUDIT_SHIP_WATERMARK, DEFAULT_INTERVAL_MS, MAX_BATCH, MAX_CHUNK_BYTES, MAX_CHUNKS_PER_TICK, FETCH_TIMEOUT_MS, SKIP_CHECKED_BY, shipperStarted;
18992
+ var import_fs37, import_path36, import_os33, import_crypto9, AUDIT_SHIP_WATERMARK, DEFAULT_INTERVAL_MS, MAX_BATCH, MAX_CHUNK_BYTES, MAX_CHUNKS_PER_TICK, FETCH_TIMEOUT_MS, SKIP_CHECKED_BY, shipperStarted;
18883
18993
  var init_audit_shipper = __esm({
18884
18994
  "src/daemon/audit-shipper.ts"() {
18885
18995
  "use strict";
18886
- import_fs36 = __toESM(require("fs"));
18887
- import_path35 = __toESM(require("path"));
18996
+ import_fs37 = __toESM(require("fs"));
18997
+ import_path36 = __toESM(require("path"));
18888
18998
  import_os33 = __toESM(require("os"));
18889
18999
  import_crypto9 = __toESM(require("crypto"));
18890
19000
  init_audit();
18891
19001
  init_config();
18892
19002
  init_sync();
18893
19003
  init_cloud();
18894
- AUDIT_SHIP_WATERMARK = import_path35.default.join(import_os33.default.homedir(), ".node9", "audit-ship.json");
19004
+ AUDIT_SHIP_WATERMARK = import_path36.default.join(import_os33.default.homedir(), ".node9", "audit-ship.json");
18895
19005
  DEFAULT_INTERVAL_MS = 2e4;
18896
19006
  MAX_BATCH = 500;
18897
19007
  MAX_CHUNK_BYTES = 4 * 1024 * 1024;
@@ -18952,7 +19062,7 @@ var init_decision = __esm({
18952
19062
  // src/daemon/dlp-scanner.ts
18953
19063
  function loadIndex() {
18954
19064
  try {
18955
- const raw = JSON.parse(import_fs37.default.readFileSync(INDEX_FILE, "utf-8"));
19065
+ const raw = JSON.parse(import_fs38.default.readFileSync(INDEX_FILE, "utf-8"));
18956
19066
  if (raw && typeof raw === "object" && !Array.isArray(raw)) {
18957
19067
  const r = raw;
18958
19068
  if (r.offsets && typeof r.offsets === "object") return r.offsets;
@@ -18964,63 +19074,63 @@ function loadIndex() {
18964
19074
  }
18965
19075
  function saveIndex(index) {
18966
19076
  try {
18967
- import_fs37.default.writeFileSync(INDEX_FILE, JSON.stringify(index), { encoding: "utf-8", mode: 384 });
19077
+ import_fs38.default.writeFileSync(INDEX_FILE, JSON.stringify(index), { encoding: "utf-8", mode: 384 });
18968
19078
  } catch {
18969
19079
  }
18970
19080
  }
18971
19081
  function appendAuditEntry(entry) {
18972
19082
  try {
18973
- import_fs37.default.appendFileSync(AUDIT_LOG_FILE, JSON.stringify(entry) + "\n");
19083
+ import_fs38.default.appendFileSync(AUDIT_LOG_FILE, JSON.stringify(entry) + "\n");
18974
19084
  } catch {
18975
19085
  }
18976
19086
  }
18977
19087
  function runDlpScan() {
18978
- if (!import_fs37.default.existsSync(PROJECTS_DIR2)) return;
19088
+ if (!import_fs38.default.existsSync(PROJECTS_DIR2)) return;
18979
19089
  const index = loadIndex();
18980
19090
  const seenThisPass = /* @__PURE__ */ new Set();
18981
19091
  const newFindings = [];
18982
19092
  let updated = false;
18983
19093
  let projDirs;
18984
19094
  try {
18985
- projDirs = import_fs37.default.readdirSync(PROJECTS_DIR2);
19095
+ projDirs = import_fs38.default.readdirSync(PROJECTS_DIR2);
18986
19096
  } catch {
18987
19097
  return;
18988
19098
  }
18989
19099
  for (const proj of projDirs) {
18990
- const projPath = import_path36.default.join(PROJECTS_DIR2, proj);
19100
+ const projPath = import_path37.default.join(PROJECTS_DIR2, proj);
18991
19101
  try {
18992
- if (!import_fs37.default.lstatSync(projPath).isDirectory()) continue;
18993
- const real = import_fs37.default.realpathSync(projPath);
18994
- if (!real.startsWith(PROJECTS_DIR2 + import_path36.default.sep) && real !== PROJECTS_DIR2) continue;
19102
+ if (!import_fs38.default.lstatSync(projPath).isDirectory()) continue;
19103
+ const real = import_fs38.default.realpathSync(projPath);
19104
+ if (!real.startsWith(PROJECTS_DIR2 + import_path37.default.sep) && real !== PROJECTS_DIR2) continue;
18995
19105
  } catch {
18996
19106
  continue;
18997
19107
  }
18998
19108
  let files;
18999
19109
  try {
19000
- files = import_fs37.default.readdirSync(projPath).filter((f) => f.endsWith(".jsonl") && !f.startsWith("agent-"));
19110
+ files = import_fs38.default.readdirSync(projPath).filter((f) => f.endsWith(".jsonl") && !f.startsWith("agent-"));
19001
19111
  } catch {
19002
19112
  continue;
19003
19113
  }
19004
19114
  for (const file of files) {
19005
- const filePath = import_path36.default.join(projPath, file);
19115
+ const filePath = import_path37.default.join(projPath, file);
19006
19116
  const lastOffset = index[filePath] ?? 0;
19007
19117
  let size;
19008
19118
  try {
19009
- size = import_fs37.default.statSync(filePath).size;
19119
+ size = import_fs38.default.statSync(filePath).size;
19010
19120
  } catch {
19011
19121
  continue;
19012
19122
  }
19013
19123
  if (size <= lastOffset) continue;
19014
19124
  let fd;
19015
19125
  try {
19016
- fd = import_fs37.default.openSync(filePath, "r");
19126
+ fd = import_fs38.default.openSync(filePath, "r");
19017
19127
  } catch {
19018
19128
  continue;
19019
19129
  }
19020
19130
  try {
19021
19131
  const chunkSize = size - lastOffset;
19022
19132
  const buf = Buffer.alloc(chunkSize);
19023
- import_fs37.default.readSync(fd, buf, 0, chunkSize, lastOffset);
19133
+ import_fs38.default.readSync(fd, buf, 0, chunkSize, lastOffset);
19024
19134
  const chunk2 = buf.toString("utf-8");
19025
19135
  for (const line of chunk2.split("\n")) {
19026
19136
  if (!line.trim()) continue;
@@ -19067,7 +19177,7 @@ function runDlpScan() {
19067
19177
  updated = true;
19068
19178
  } finally {
19069
19179
  try {
19070
- import_fs37.default.closeSync(fd);
19180
+ import_fs38.default.closeSync(fd);
19071
19181
  } catch {
19072
19182
  }
19073
19183
  }
@@ -19108,18 +19218,18 @@ function startDlpScanner() {
19108
19218
  );
19109
19219
  timer.unref();
19110
19220
  }
19111
- var import_fs37, import_path36, import_os34, INDEX_FILE, PROJECTS_DIR2;
19221
+ var import_fs38, import_path37, import_os34, INDEX_FILE, PROJECTS_DIR2;
19112
19222
  var init_dlp_scanner = __esm({
19113
19223
  "src/daemon/dlp-scanner.ts"() {
19114
19224
  "use strict";
19115
- import_fs37 = __toESM(require("fs"));
19116
- import_path36 = __toESM(require("path"));
19225
+ import_fs38 = __toESM(require("fs"));
19226
+ import_path37 = __toESM(require("path"));
19117
19227
  import_os34 = __toESM(require("os"));
19118
19228
  init_dlp();
19119
19229
  init_native();
19120
19230
  init_state2();
19121
- INDEX_FILE = import_path36.default.join(import_os34.default.homedir(), ".node9", "dlp-index.json");
19122
- PROJECTS_DIR2 = import_path36.default.join(import_os34.default.homedir(), ".claude", "projects");
19231
+ INDEX_FILE = import_path37.default.join(import_os34.default.homedir(), ".node9", "dlp-index.json");
19232
+ PROJECTS_DIR2 = import_path37.default.join(import_os34.default.homedir(), ".claude", "projects");
19123
19233
  }
19124
19234
  });
19125
19235
 
@@ -19130,7 +19240,7 @@ function idKey(e) {
19130
19240
  }
19131
19241
  function loadBaseline() {
19132
19242
  try {
19133
- const raw = JSON.parse(import_fs38.default.readFileSync(BASELINE_FILE2, "utf-8"));
19243
+ const raw = JSON.parse(import_fs39.default.readFileSync(BASELINE_FILE2, "utf-8"));
19134
19244
  return new Set(Array.isArray(raw) ? raw : []);
19135
19245
  } catch {
19136
19246
  return /* @__PURE__ */ new Set();
@@ -19138,7 +19248,7 @@ function loadBaseline() {
19138
19248
  }
19139
19249
  function saveBaseline(keys) {
19140
19250
  try {
19141
- import_fs38.default.writeFileSync(BASELINE_FILE2, JSON.stringify([...keys].slice(-BASELINE_CAP)), {
19251
+ import_fs39.default.writeFileSync(BASELINE_FILE2, JSON.stringify([...keys].slice(-BASELINE_CAP)), {
19142
19252
  mode: 384
19143
19253
  });
19144
19254
  } catch {
@@ -19316,12 +19426,12 @@ function startMcpReconciler() {
19316
19426
  };
19317
19427
  schedule();
19318
19428
  }
19319
- var import_fs38, import_path37, import_os35, import_crypto10, BASELINE_FILE2, BASELINE_CAP, DEFAULT_INTERVAL_MIN, DEFAULT_STALE_DAYS;
19429
+ var import_fs39, import_path38, import_os35, import_crypto10, BASELINE_FILE2, BASELINE_CAP, DEFAULT_INTERVAL_MIN, DEFAULT_STALE_DAYS;
19320
19430
  var init_mcp_reconciler = __esm({
19321
19431
  "src/daemon/mcp-reconciler.ts"() {
19322
19432
  "use strict";
19323
- import_fs38 = __toESM(require("fs"));
19324
- import_path37 = __toESM(require("path"));
19433
+ import_fs39 = __toESM(require("fs"));
19434
+ import_path38 = __toESM(require("path"));
19325
19435
  import_os35 = __toESM(require("os"));
19326
19436
  import_crypto10 = __toESM(require("crypto"));
19327
19437
  init_mcp_wrap();
@@ -19330,7 +19440,7 @@ var init_mcp_reconciler = __esm({
19330
19440
  init_cloud();
19331
19441
  init_audit();
19332
19442
  init_mcp_pin();
19333
- BASELINE_FILE2 = import_path37.default.join(import_os35.default.homedir(), ".node9", "mcp-baseline.json");
19443
+ BASELINE_FILE2 = import_path38.default.join(import_os35.default.homedir(), ".node9", "mcp-baseline.json");
19334
19444
  BASELINE_CAP = 500;
19335
19445
  DEFAULT_INTERVAL_MIN = 60;
19336
19446
  DEFAULT_STALE_DAYS = 7;
@@ -19407,17 +19517,17 @@ var init_hook_heal = __esm({
19407
19517
  // src/daemon/startup-log.ts
19408
19518
  function capStartupLog(file) {
19409
19519
  try {
19410
- if (import_fs39.default.statSync(file).size > MAX_STARTUP_LOG_BYTES) import_fs39.default.truncateSync(file);
19520
+ if (import_fs40.default.statSync(file).size > MAX_STARTUP_LOG_BYTES) import_fs40.default.truncateSync(file);
19411
19521
  } catch {
19412
19522
  }
19413
19523
  }
19414
19524
  function openStartupLogFd() {
19415
19525
  try {
19416
19526
  const file = DAEMON_STARTUP_LOG();
19417
- const dir = import_path38.default.dirname(file);
19418
- if (!import_fs39.default.existsSync(dir)) import_fs39.default.mkdirSync(dir, { recursive: true });
19527
+ const dir = import_path39.default.dirname(file);
19528
+ if (!import_fs40.default.existsSync(dir)) import_fs40.default.mkdirSync(dir, { recursive: true });
19419
19529
  capStartupLog(file);
19420
- return import_fs39.default.openSync(file, "a");
19530
+ return import_fs40.default.openSync(file, "a");
19421
19531
  } catch {
19422
19532
  return void 0;
19423
19533
  }
@@ -19433,18 +19543,18 @@ function recordStartupState(outcome, kind, detail) {
19433
19543
  }
19434
19544
  }
19435
19545
  const file = DAEMON_STARTUP_STATE();
19436
- const dir = import_path38.default.dirname(file);
19437
- if (!import_fs39.default.existsSync(dir)) import_fs39.default.mkdirSync(dir, { recursive: true });
19546
+ const dir = import_path39.default.dirname(file);
19547
+ if (!import_fs40.default.existsSync(dir)) import_fs40.default.mkdirSync(dir, { recursive: true });
19438
19548
  const state = { outcome, at: (/* @__PURE__ */ new Date()).toISOString() };
19439
19549
  if (kind) state.kind = kind;
19440
19550
  if (detail) state.detail = detail.slice(0, MAX_DETAIL);
19441
19551
  const tmp = `${file}.${process.pid}.tmp`;
19442
19552
  try {
19443
- import_fs39.default.writeFileSync(tmp, JSON.stringify(state), "utf-8");
19444
- import_fs39.default.renameSync(tmp, file);
19553
+ import_fs40.default.writeFileSync(tmp, JSON.stringify(state), "utf-8");
19554
+ import_fs40.default.renameSync(tmp, file);
19445
19555
  } catch (err2) {
19446
19556
  try {
19447
- import_fs39.default.unlinkSync(tmp);
19557
+ import_fs40.default.unlinkSync(tmp);
19448
19558
  } catch {
19449
19559
  }
19450
19560
  throw err2;
@@ -19454,7 +19564,7 @@ function recordStartupState(outcome, kind, detail) {
19454
19564
  }
19455
19565
  function readStartupState() {
19456
19566
  try {
19457
- const raw = import_fs39.default.readFileSync(DAEMON_STARTUP_STATE(), "utf-8");
19567
+ const raw = import_fs40.default.readFileSync(DAEMON_STARTUP_STATE(), "utf-8");
19458
19568
  const s = JSON.parse(raw);
19459
19569
  if (!s || typeof s.outcome !== "string" || typeof s.at !== "string") return null;
19460
19570
  return s;
@@ -19489,24 +19599,24 @@ function readStartupCause(maxAgeMs = 24 * 60 * 60 * 1e3) {
19489
19599
  function logDaemonStartup(kind, detail) {
19490
19600
  try {
19491
19601
  const file = DAEMON_STARTUP_LOG();
19492
- const dir = import_path38.default.dirname(file);
19493
- if (!import_fs39.default.existsSync(dir)) import_fs39.default.mkdirSync(dir, { recursive: true });
19602
+ const dir = import_path39.default.dirname(file);
19603
+ if (!import_fs40.default.existsSync(dir)) import_fs40.default.mkdirSync(dir, { recursive: true });
19494
19604
  const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] daemon-startup:${kind}${detail ? ` ${detail}` : ""}
19495
19605
  `;
19496
- import_fs39.default.appendFileSync(file, line, "utf-8");
19606
+ import_fs40.default.appendFileSync(file, line, "utf-8");
19497
19607
  } catch {
19498
19608
  }
19499
19609
  }
19500
- var import_fs39, import_path38, import_os36, DAEMON_STARTUP_LOG, MAX_STARTUP_LOG_BYTES, DAEMON_STARTUP_STATE, MAX_DETAIL, STARTING_GRACE_MS;
19610
+ var import_fs40, import_path39, import_os36, DAEMON_STARTUP_LOG, MAX_STARTUP_LOG_BYTES, DAEMON_STARTUP_STATE, MAX_DETAIL, STARTING_GRACE_MS;
19501
19611
  var init_startup_log = __esm({
19502
19612
  "src/daemon/startup-log.ts"() {
19503
19613
  "use strict";
19504
- import_fs39 = __toESM(require("fs"));
19505
- import_path38 = __toESM(require("path"));
19614
+ import_fs40 = __toESM(require("fs"));
19615
+ import_path39 = __toESM(require("path"));
19506
19616
  import_os36 = __toESM(require("os"));
19507
- DAEMON_STARTUP_LOG = () => import_path38.default.join(import_os36.default.homedir(), ".node9", "daemon-startup.log");
19617
+ DAEMON_STARTUP_LOG = () => import_path39.default.join(import_os36.default.homedir(), ".node9", "daemon-startup.log");
19508
19618
  MAX_STARTUP_LOG_BYTES = 256 * 1024;
19509
- DAEMON_STARTUP_STATE = () => import_path38.default.join(import_os36.default.homedir(), ".node9", "daemon-startup-state.json");
19619
+ DAEMON_STARTUP_STATE = () => import_path39.default.join(import_os36.default.homedir(), ".node9", "daemon-startup-state.json");
19510
19620
  MAX_DETAIL = 200;
19511
19621
  STARTING_GRACE_MS = 90 * 1e3;
19512
19622
  }
@@ -19602,6 +19712,7 @@ function startDaemon() {
19602
19712
  }
19603
19713
  const internalToken = (0, import_crypto11.randomUUID)();
19604
19714
  const validToken = (req) => req.headers["x-node9-internal"] === internalToken || req.headers["x-node9-token"] === internalToken;
19715
+ const startedAt = (/* @__PURE__ */ new Date()).toISOString();
19605
19716
  const IDLE_TIMEOUT_MS = 12 * 60 * 60 * 1e3;
19606
19717
  const watchMode = process.env.NODE9_WATCH_MODE === "1";
19607
19718
  let idleTimer;
@@ -19611,7 +19722,7 @@ function startDaemon() {
19611
19722
  idleTimer = setTimeout(() => {
19612
19723
  if (autoStarted) {
19613
19724
  try {
19614
- import_fs40.default.unlinkSync(DAEMON_PID_FILE);
19725
+ import_fs41.default.unlinkSync(DAEMON_PID_FILE);
19615
19726
  } catch {
19616
19727
  }
19617
19728
  }
@@ -19756,7 +19867,7 @@ data: ${JSON.stringify(item.data)}
19756
19867
  mcpServer: entry.mcpServer
19757
19868
  });
19758
19869
  }
19759
- const projectCwd = typeof cwd === "string" && import_path39.default.isAbsolute(cwd) ? cwd : void 0;
19870
+ const projectCwd = typeof cwd === "string" && import_path40.default.isAbsolute(cwd) ? cwd : void 0;
19760
19871
  const projectConfig = getConfig(projectCwd);
19761
19872
  const browserEnabled = projectConfig.settings.approvers?.browser !== false;
19762
19873
  const terminalEnabled = projectConfig.settings.approvers?.terminal !== false;
@@ -19974,6 +20085,35 @@ data: ${JSON.stringify(item.data)}
19974
20085
  res.writeHead(200, { "Content-Type": "application/json" });
19975
20086
  return res.end(JSON.stringify({ interactive: hasInteractiveClient() }));
19976
20087
  }
20088
+ if (req.method === "POST" && pathname === "/shutdown") {
20089
+ if (!validToken(req)) {
20090
+ res.writeHead(401, { "Content-Type": "application/json" });
20091
+ return res.end(JSON.stringify({ error: "unauthorized" }));
20092
+ }
20093
+ res.writeHead(200, { "Content-Type": "application/json" });
20094
+ res.end(JSON.stringify({ ok: true }));
20095
+ logDaemonStartup("shutdown", "yielding on authenticated /shutdown (takeover or restart)");
20096
+ setImmediate(() => {
20097
+ try {
20098
+ server.close();
20099
+ } catch {
20100
+ }
20101
+ process.exit(0);
20102
+ });
20103
+ return;
20104
+ }
20105
+ if (req.method === "GET" && pathname === "/health") {
20106
+ res.writeHead(200, { "Content-Type": "application/json" });
20107
+ return res.end(
20108
+ JSON.stringify({
20109
+ version: CURRENT_BUILD.version,
20110
+ buildId: buildIdString(CURRENT_BUILD),
20111
+ pid: process.pid,
20112
+ startedAt,
20113
+ autoStarted
20114
+ })
20115
+ );
20116
+ }
19977
20117
  if (req.method === "GET" && pathname === "/state/check") {
19978
20118
  const predicatesParam = reqUrl.searchParams.get("predicates") ?? "";
19979
20119
  const predicates = predicatesParam.split(",").filter(Boolean);
@@ -20052,8 +20192,8 @@ data: ${JSON.stringify(item.data)}
20052
20192
  if (!validToken(req)) return res.writeHead(403).end();
20053
20193
  const periodParam = reqUrl.searchParams.get("period") || "7d";
20054
20194
  const period = ["today", "7d", "30d", "month"].includes(periodParam) ? periodParam : "7d";
20055
- const logPath = import_path39.default.join(import_os37.default.homedir(), ".node9", "audit.log");
20056
- if (!import_fs40.default.existsSync(logPath)) {
20195
+ const logPath = import_path40.default.join(import_os37.default.homedir(), ".node9", "audit.log");
20196
+ if (!import_fs41.default.existsSync(logPath)) {
20057
20197
  res.writeHead(200, { "Content-Type": "application/json" });
20058
20198
  return res.end(
20059
20199
  JSON.stringify({
@@ -20066,7 +20206,7 @@ data: ${JSON.stringify(item.data)}
20066
20206
  );
20067
20207
  }
20068
20208
  try {
20069
- const raw = import_fs40.default.readFileSync(logPath, "utf-8");
20209
+ const raw = import_fs41.default.readFileSync(logPath, "utf-8");
20070
20210
  const allEntries = raw.split("\n").flatMap((line) => {
20071
20211
  if (!line.trim()) return [];
20072
20212
  try {
@@ -20381,34 +20521,114 @@ data: ${JSON.stringify(item.data)}
20381
20521
  setDaemonServer(server);
20382
20522
  let bindAttempts = 0;
20383
20523
  const MAX_BIND_ATTEMPTS = 3;
20524
+ let tookDownHolder = false;
20384
20525
  function retryListen() {
20385
20526
  if (++bindAttempts >= MAX_BIND_ATTEMPTS) {
20527
+ if (tookDownHolder) {
20528
+ logDaemonStartup(
20529
+ "takeover-bind-failed",
20530
+ `shut down the previous daemon but could not bind :${DAEMON_PORT} \u2014 the port was taken during handover`
20531
+ );
20532
+ recordStartupState(
20533
+ "failed",
20534
+ "takeover-bind-failed",
20535
+ `took over :${DAEMON_PORT} but could not rebind (the port was claimed during handover) \u2014 no daemon is serving; run: node9 daemon restart`
20536
+ );
20537
+ } else {
20538
+ logDaemonStartup(
20539
+ "port-unavailable",
20540
+ `:${DAEMON_PORT} is held by something that is not a node9 daemon`
20541
+ );
20542
+ recordStartupState(
20543
+ "failed",
20544
+ "port-unavailable",
20545
+ `:${DAEMON_PORT} is held by another process that is not a node9 daemon \u2014 free the port, then: node9 daemon --background`
20546
+ );
20547
+ }
20548
+ return process.exit(0);
20549
+ }
20550
+ server.listen(DAEMON_PORT, DAEMON_HOST);
20551
+ }
20552
+ async function decideAgainstHolder(holderPid, holderToken) {
20553
+ let holderBuildId = null;
20554
+ try {
20555
+ const res = await fetch(`http://${DAEMON_HOST}:${DAEMON_PORT}/health`, {
20556
+ signal: AbortSignal.timeout(800)
20557
+ });
20558
+ if (res.ok) {
20559
+ const j = await res.json().catch(() => null);
20560
+ if (j && typeof j.buildId === "string") holderBuildId = j.buildId;
20561
+ }
20562
+ } catch {
20563
+ }
20564
+ const holderBuild = holderBuildId ? parseBuildId(holderBuildId) : null;
20565
+ if (holderBuild && compareBuild(CURRENT_BUILD, holderBuild) > 0 && holderToken) {
20566
+ try {
20567
+ const r = await fetch(`http://${DAEMON_HOST}:${DAEMON_PORT}/shutdown`, {
20568
+ method: "POST",
20569
+ headers: { "x-node9-internal": holderToken },
20570
+ signal: AbortSignal.timeout(2e3)
20571
+ });
20572
+ if (r.ok) {
20573
+ for (let i = 0; i < 10; i++) {
20574
+ await new Promise((resolve2) => setTimeout(resolve2, 200));
20575
+ const stillUp = await fetch(`http://${DAEMON_HOST}:${DAEMON_PORT}/health`, {
20576
+ signal: AbortSignal.timeout(300)
20577
+ }).then(
20578
+ () => true,
20579
+ () => false
20580
+ );
20581
+ if (!stillUp) break;
20582
+ }
20583
+ logDaemonStartup(
20584
+ "takeover",
20585
+ `took over :${DAEMON_PORT} from older build ${holderBuildId} (pid ${holderPid})`
20586
+ );
20587
+ tookDownHolder = true;
20588
+ retryListen();
20589
+ return;
20590
+ }
20591
+ recordStartupState(
20592
+ "failed",
20593
+ "version-skew-unauthenticated",
20594
+ `an older-build daemon (${holderBuildId}) holds :${DAEMON_PORT} but could not be authenticated for takeover \u2014 run: node9 daemon restart`
20595
+ );
20596
+ logDaemonStartup("port-in-use", `older build on :${DAEMON_PORT}, /shutdown refused`);
20597
+ return process.exit(0);
20598
+ } catch {
20599
+ }
20600
+ }
20601
+ if (holderBuild && compareBuild(holderBuild, CURRENT_BUILD) > 0) {
20386
20602
  logDaemonStartup(
20387
- "port-unavailable",
20388
- `:${DAEMON_PORT} is held by something that is not a node9 daemon`
20389
- );
20390
- recordStartupState(
20391
- "failed",
20392
- "port-unavailable",
20393
- `:${DAEMON_PORT} is held by another process that is not a node9 daemon \u2014 free the port, then: node9 daemon --background`
20603
+ "port-in-use",
20604
+ `a NEWER daemon (${holderBuildId}, pid ${holderPid}) owns :${DAEMON_PORT} \u2014 yielding`
20394
20605
  );
20606
+ recordStartupState("ok-elsewhere", "newer-daemon-running");
20395
20607
  return process.exit(0);
20396
20608
  }
20397
- server.listen(DAEMON_PORT, DAEMON_HOST);
20609
+ logDaemonStartup("port-in-use", `another daemon (pid ${holderPid}) owns :${DAEMON_PORT}`);
20610
+ recordStartupState("ok-elsewhere");
20611
+ return process.exit(0);
20398
20612
  }
20399
20613
  server.on("error", (e) => {
20400
20614
  if (e.code === "EADDRINUSE") {
20401
20615
  try {
20402
- if (import_fs40.default.existsSync(DAEMON_PID_FILE)) {
20403
- const { pid } = JSON.parse(import_fs40.default.readFileSync(DAEMON_PID_FILE, "utf-8"));
20616
+ if (import_fs41.default.existsSync(DAEMON_PID_FILE)) {
20617
+ const parsed = JSON.parse(import_fs41.default.readFileSync(DAEMON_PID_FILE, "utf-8"));
20618
+ const pid = parsed.pid;
20619
+ if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0 || pid > 4194304) {
20620
+ throw new Error("invalid pid in daemon.pid");
20621
+ }
20404
20622
  process.kill(pid, 0);
20405
- logDaemonStartup("port-in-use", `another daemon (pid ${pid}) owns :${DAEMON_PORT}`);
20406
- recordStartupState("ok-elsewhere");
20407
- return process.exit(0);
20623
+ void decideAgainstHolder(
20624
+ pid,
20625
+ typeof parsed.internalToken === "string" ? parsed.internalToken : null
20626
+ );
20627
+ return;
20408
20628
  }
20409
20629
  } catch {
20410
20630
  try {
20411
- import_fs40.default.unlinkSync(DAEMON_PID_FILE);
20631
+ import_fs41.default.unlinkSync(DAEMON_PID_FILE);
20412
20632
  } catch {
20413
20633
  }
20414
20634
  retryListen();
@@ -20443,7 +20663,12 @@ data: ${JSON.stringify(item.data)}
20443
20663
  process.kill(orphanPid, 0);
20444
20664
  atomicWriteSync2(
20445
20665
  DAEMON_PID_FILE,
20446
- JSON.stringify({ pid: orphanPid, port: DAEMON_PORT, internalToken, autoStarted }),
20666
+ JSON.stringify({
20667
+ pid: orphanPid,
20668
+ port: DAEMON_PORT,
20669
+ internalToken: null,
20670
+ autoStarted
20671
+ }),
20447
20672
  { mode: 384 }
20448
20673
  );
20449
20674
  adopted = true;
@@ -20491,7 +20716,15 @@ data: ${JSON.stringify(item.data)}
20491
20716
  server.listen(DAEMON_PORT, DAEMON_HOST, () => {
20492
20717
  atomicWriteSync2(
20493
20718
  DAEMON_PID_FILE,
20494
- JSON.stringify({ pid: process.pid, port: DAEMON_PORT, internalToken, autoStarted }),
20719
+ JSON.stringify({
20720
+ pid: process.pid,
20721
+ port: DAEMON_PORT,
20722
+ internalToken,
20723
+ autoStarted,
20724
+ version: CURRENT_BUILD.version,
20725
+ buildId: buildIdString(CURRENT_BUILD),
20726
+ startedAt
20727
+ }),
20495
20728
  { mode: 384 }
20496
20729
  );
20497
20730
  console.error(import_chalk6.default.green(`\u{1F6E1}\uFE0F Node9 Guard LIVE on 127.0.0.1:${DAEMON_PORT}`));
@@ -20503,13 +20736,13 @@ data: ${JSON.stringify(item.data)}
20503
20736
  }
20504
20737
  startActivitySocket();
20505
20738
  }
20506
- var import_http3, import_fs40, import_path39, import_os37, import_crypto11, import_child_process2, import_chalk6;
20739
+ var import_http3, import_fs41, import_path40, import_os37, import_crypto11, import_child_process2, import_chalk6;
20507
20740
  var init_server = __esm({
20508
20741
  "src/daemon/server.ts"() {
20509
20742
  "use strict";
20510
20743
  import_http3 = __toESM(require("http"));
20511
- import_fs40 = __toESM(require("fs"));
20512
- import_path39 = __toESM(require("path"));
20744
+ import_fs41 = __toESM(require("fs"));
20745
+ import_path40 = __toESM(require("path"));
20513
20746
  import_os37 = __toESM(require("os"));
20514
20747
  import_crypto11 = require("crypto");
20515
20748
  import_child_process2 = require("child_process");
@@ -20517,6 +20750,7 @@ var init_server = __esm({
20517
20750
  init_core();
20518
20751
  init_scan();
20519
20752
  init_scan_summary();
20753
+ init_build_id();
20520
20754
  init_state2();
20521
20755
  init_state();
20522
20756
  init_costSync();
@@ -20535,8 +20769,8 @@ var init_server = __esm({
20535
20769
  function resolveNode9Binary() {
20536
20770
  try {
20537
20771
  const script = process.argv[1];
20538
- if (typeof script === "string" && import_path40.default.isAbsolute(script) && import_fs41.default.existsSync(script)) {
20539
- return import_fs41.default.realpathSync(script);
20772
+ if (typeof script === "string" && import_path41.default.isAbsolute(script) && import_fs42.default.existsSync(script)) {
20773
+ return import_fs42.default.realpathSync(script);
20540
20774
  }
20541
20775
  } catch {
20542
20776
  }
@@ -20554,11 +20788,11 @@ function xmlEscape(s) {
20554
20788
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
20555
20789
  }
20556
20790
  function launchdPlist(binaryPath) {
20557
- const logDir = import_path40.default.join(import_os38.default.homedir(), ".node9");
20791
+ const logDir = import_path41.default.join(import_os38.default.homedir(), ".node9");
20558
20792
  const nodePath = xmlEscape(process.execPath);
20559
20793
  const scriptPath = xmlEscape(binaryPath);
20560
- const outLog = xmlEscape(import_path40.default.join(logDir, "daemon.log"));
20561
- const errLog = xmlEscape(import_path40.default.join(logDir, "daemon-error.log"));
20794
+ const outLog = xmlEscape(import_path41.default.join(logDir, "daemon.log"));
20795
+ const errLog = xmlEscape(import_path41.default.join(logDir, "daemon-error.log"));
20562
20796
  return `<?xml version="1.0" encoding="UTF-8"?>
20563
20797
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
20564
20798
  <plist version="1.0">
@@ -20591,9 +20825,9 @@ function launchdPlist(binaryPath) {
20591
20825
  `;
20592
20826
  }
20593
20827
  function installLaunchd(binaryPath) {
20594
- const dir = import_path40.default.dirname(LAUNCHD_PLIST);
20595
- if (!import_fs41.default.existsSync(dir)) import_fs41.default.mkdirSync(dir, { recursive: true });
20596
- import_fs41.default.writeFileSync(LAUNCHD_PLIST, launchdPlist(binaryPath), "utf-8");
20828
+ const dir = import_path41.default.dirname(LAUNCHD_PLIST);
20829
+ if (!import_fs42.default.existsSync(dir)) import_fs42.default.mkdirSync(dir, { recursive: true });
20830
+ import_fs42.default.writeFileSync(LAUNCHD_PLIST, launchdPlist(binaryPath), "utf-8");
20597
20831
  (0, import_child_process3.spawnSync)("launchctl", ["unload", LAUNCHD_PLIST], { encoding: "utf8" });
20598
20832
  const r = (0, import_child_process3.spawnSync)("launchctl", ["load", "-w", LAUNCHD_PLIST], {
20599
20833
  encoding: "utf8",
@@ -20604,13 +20838,13 @@ function installLaunchd(binaryPath) {
20604
20838
  }
20605
20839
  }
20606
20840
  function uninstallLaunchd() {
20607
- if (import_fs41.default.existsSync(LAUNCHD_PLIST)) {
20841
+ if (import_fs42.default.existsSync(LAUNCHD_PLIST)) {
20608
20842
  (0, import_child_process3.spawnSync)("launchctl", ["unload", "-w", LAUNCHD_PLIST], { encoding: "utf8", timeout: 5e3 });
20609
- import_fs41.default.unlinkSync(LAUNCHD_PLIST);
20843
+ import_fs42.default.unlinkSync(LAUNCHD_PLIST);
20610
20844
  }
20611
20845
  }
20612
20846
  function isLaunchdInstalled() {
20613
- return import_fs41.default.existsSync(LAUNCHD_PLIST);
20847
+ return import_fs42.default.existsSync(LAUNCHD_PLIST);
20614
20848
  }
20615
20849
  function systemdUnit(binaryPath) {
20616
20850
  return `[Unit]
@@ -20629,10 +20863,10 @@ WantedBy=default.target
20629
20863
  `;
20630
20864
  }
20631
20865
  function installSystemd(binaryPath) {
20632
- if (!import_fs41.default.existsSync(SYSTEMD_UNIT_DIR)) {
20633
- import_fs41.default.mkdirSync(SYSTEMD_UNIT_DIR, { recursive: true });
20866
+ if (!import_fs42.default.existsSync(SYSTEMD_UNIT_DIR)) {
20867
+ import_fs42.default.mkdirSync(SYSTEMD_UNIT_DIR, { recursive: true });
20634
20868
  }
20635
- import_fs41.default.writeFileSync(SYSTEMD_UNIT, systemdUnit(binaryPath), "utf-8");
20869
+ import_fs42.default.writeFileSync(SYSTEMD_UNIT, systemdUnit(binaryPath), "utf-8");
20636
20870
  try {
20637
20871
  (0, import_child_process3.execFileSync)("loginctl", ["enable-linger", import_os38.default.userInfo().username], { timeout: 3e3 });
20638
20872
  } catch {
@@ -20654,23 +20888,23 @@ function installSystemd(binaryPath) {
20654
20888
  }
20655
20889
  }
20656
20890
  function uninstallSystemd() {
20657
- if (import_fs41.default.existsSync(SYSTEMD_UNIT)) {
20891
+ if (import_fs42.default.existsSync(SYSTEMD_UNIT)) {
20658
20892
  (0, import_child_process3.spawnSync)("systemctl", ["--user", "disable", "--now", "node9-daemon"], {
20659
20893
  encoding: "utf8",
20660
20894
  timeout: 5e3
20661
20895
  });
20662
20896
  (0, import_child_process3.spawnSync)("systemctl", ["--user", "daemon-reload"], { encoding: "utf8", timeout: 5e3 });
20663
- import_fs41.default.unlinkSync(SYSTEMD_UNIT);
20897
+ import_fs42.default.unlinkSync(SYSTEMD_UNIT);
20664
20898
  }
20665
20899
  }
20666
20900
  function isSystemdInstalled() {
20667
- return import_fs41.default.existsSync(SYSTEMD_UNIT);
20901
+ return import_fs42.default.existsSync(SYSTEMD_UNIT);
20668
20902
  }
20669
20903
  function stopRunningDaemon() {
20670
- const pidFile = import_path40.default.join(import_os38.default.homedir(), ".node9", "daemon.pid");
20671
- if (!import_fs41.default.existsSync(pidFile)) return;
20904
+ const pidFile = import_path41.default.join(import_os38.default.homedir(), ".node9", "daemon.pid");
20905
+ if (!import_fs42.default.existsSync(pidFile)) return;
20672
20906
  try {
20673
- const data = JSON.parse(import_fs41.default.readFileSync(pidFile, "utf-8"));
20907
+ const data = JSON.parse(import_fs42.default.readFileSync(pidFile, "utf-8"));
20674
20908
  const pid = data.pid;
20675
20909
  const MAX_PID2 = 4194304;
20676
20910
  if (typeof pid === "number" && Number.isInteger(pid) && pid > 0 && pid <= MAX_PID2) {
@@ -20690,7 +20924,7 @@ function stopRunningDaemon() {
20690
20924
  }
20691
20925
  }
20692
20926
  try {
20693
- import_fs41.default.unlinkSync(pidFile);
20927
+ import_fs42.default.unlinkSync(pidFile);
20694
20928
  } catch {
20695
20929
  }
20696
20930
  } catch {
@@ -20829,26 +21063,26 @@ function isDaemonServiceEnabled() {
20829
21063
  }
20830
21064
  return false;
20831
21065
  }
20832
- var import_fs41, import_path40, import_os38, import_child_process3, LAUNCHD_LABEL, LAUNCHD_PLIST, SYSTEMD_UNIT_DIR, SYSTEMD_UNIT;
21066
+ var import_fs42, import_path41, import_os38, import_child_process3, LAUNCHD_LABEL, LAUNCHD_PLIST, SYSTEMD_UNIT_DIR, SYSTEMD_UNIT;
20833
21067
  var init_service = __esm({
20834
21068
  "src/daemon/service.ts"() {
20835
21069
  "use strict";
20836
- import_fs41 = __toESM(require("fs"));
20837
- import_path40 = __toESM(require("path"));
21070
+ import_fs42 = __toESM(require("fs"));
21071
+ import_path41 = __toESM(require("path"));
20838
21072
  import_os38 = __toESM(require("os"));
20839
21073
  import_child_process3 = require("child_process");
20840
21074
  LAUNCHD_LABEL = "ai.node9.daemon";
20841
- LAUNCHD_PLIST = import_path40.default.join(import_os38.default.homedir(), "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
20842
- SYSTEMD_UNIT_DIR = import_path40.default.join(import_os38.default.homedir(), ".config", "systemd", "user");
20843
- SYSTEMD_UNIT = import_path40.default.join(SYSTEMD_UNIT_DIR, "node9-daemon.service");
21075
+ LAUNCHD_PLIST = import_path41.default.join(import_os38.default.homedir(), "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
21076
+ SYSTEMD_UNIT_DIR = import_path41.default.join(import_os38.default.homedir(), ".config", "systemd", "user");
21077
+ SYSTEMD_UNIT = import_path41.default.join(SYSTEMD_UNIT_DIR, "node9-daemon.service");
20844
21078
  }
20845
21079
  });
20846
21080
 
20847
21081
  // src/daemon/index.ts
20848
21082
  function stopDaemon() {
20849
- if (!import_fs42.default.existsSync(DAEMON_PID_FILE)) return console.log(import_chalk7.default.yellow("Not running."));
21083
+ if (!import_fs43.default.existsSync(DAEMON_PID_FILE)) return console.log(import_chalk7.default.yellow("Not running."));
20850
21084
  try {
20851
- const data = JSON.parse(import_fs42.default.readFileSync(DAEMON_PID_FILE, "utf-8"));
21085
+ const data = JSON.parse(import_fs43.default.readFileSync(DAEMON_PID_FILE, "utf-8"));
20852
21086
  const pid = data.pid;
20853
21087
  if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0 || pid > MAX_PID) {
20854
21088
  console.log(import_chalk7.default.gray("Cleaned up invalid PID file."));
@@ -20860,7 +21094,7 @@ function stopDaemon() {
20860
21094
  console.log(import_chalk7.default.gray("Cleaned up stale PID file."));
20861
21095
  } finally {
20862
21096
  try {
20863
- import_fs42.default.unlinkSync(DAEMON_PID_FILE);
21097
+ import_fs43.default.unlinkSync(DAEMON_PID_FILE);
20864
21098
  } catch {
20865
21099
  }
20866
21100
  }
@@ -20869,9 +21103,9 @@ function daemonStatus() {
20869
21103
  const serviceInstalled = isDaemonServiceInstalled();
20870
21104
  const serviceLabel = serviceInstalled ? import_chalk7.default.green("installed (starts on login)") : import_chalk7.default.yellow("not installed \u2014 run: node9 daemon install");
20871
21105
  let processStatus;
20872
- if (import_fs42.default.existsSync(DAEMON_PID_FILE)) {
21106
+ if (import_fs43.default.existsSync(DAEMON_PID_FILE)) {
20873
21107
  try {
20874
- const data = JSON.parse(import_fs42.default.readFileSync(DAEMON_PID_FILE, "utf-8"));
21108
+ const data = JSON.parse(import_fs43.default.readFileSync(DAEMON_PID_FILE, "utf-8"));
20875
21109
  const pid = data.pid;
20876
21110
  const port = data.port;
20877
21111
  if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0 || pid > MAX_PID) {
@@ -20893,11 +21127,11 @@ function daemonStatus() {
20893
21127
  console.log(` Service : ${serviceLabel}
20894
21128
  `);
20895
21129
  }
20896
- var import_fs42, import_chalk7, MAX_PID;
21130
+ var import_fs43, import_chalk7, MAX_PID;
20897
21131
  var init_daemon2 = __esm({
20898
21132
  "src/daemon/index.ts"() {
20899
21133
  "use strict";
20900
- import_fs42 = __toESM(require("fs"));
21134
+ import_fs43 = __toESM(require("fs"));
20901
21135
  import_chalk7 = __toESM(require("chalk"));
20902
21136
  init_server();
20903
21137
  init_state2();
@@ -22016,14 +22250,14 @@ var require_util = __commonJS({
22016
22250
  }
22017
22251
  const port = url.port != null ? url.port : url.protocol === "https:" ? 443 : 80;
22018
22252
  let origin = url.origin != null ? url.origin : `${url.protocol || ""}//${url.hostname || ""}:${port}`;
22019
- let path71 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`;
22253
+ let path72 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`;
22020
22254
  if (origin[origin.length - 1] === "/") {
22021
22255
  origin = origin.slice(0, origin.length - 1);
22022
22256
  }
22023
- if (path71 && path71[0] !== "/") {
22024
- path71 = `/${path71}`;
22257
+ if (path72 && path72[0] !== "/") {
22258
+ path72 = `/${path72}`;
22025
22259
  }
22026
- return new URL(`${origin}${path71}`);
22260
+ return new URL(`${origin}${path72}`);
22027
22261
  }
22028
22262
  if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) {
22029
22263
  throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`.");
@@ -22844,9 +23078,9 @@ var require_diagnostics = __commonJS({
22844
23078
  "undici:client:sendHeaders",
22845
23079
  (evt) => {
22846
23080
  const {
22847
- request: { method, path: path71, origin }
23081
+ request: { method, path: path72, origin }
22848
23082
  } = evt;
22849
- debugLog("sending request to %s %s%s", method, origin, path71);
23083
+ debugLog("sending request to %s %s%s", method, origin, path72);
22850
23084
  }
22851
23085
  );
22852
23086
  }
@@ -22864,14 +23098,14 @@ var require_diagnostics = __commonJS({
22864
23098
  "undici:request:headers",
22865
23099
  (evt) => {
22866
23100
  const {
22867
- request: { method, path: path71, origin },
23101
+ request: { method, path: path72, origin },
22868
23102
  response: { statusCode }
22869
23103
  } = evt;
22870
23104
  debugLog(
22871
23105
  "received response to %s %s%s - HTTP %d",
22872
23106
  method,
22873
23107
  origin,
22874
- path71,
23108
+ path72,
22875
23109
  statusCode
22876
23110
  );
22877
23111
  }
@@ -22880,23 +23114,23 @@ var require_diagnostics = __commonJS({
22880
23114
  "undici:request:trailers",
22881
23115
  (evt) => {
22882
23116
  const {
22883
- request: { method, path: path71, origin }
23117
+ request: { method, path: path72, origin }
22884
23118
  } = evt;
22885
- debugLog("trailers received from %s %s%s", method, origin, path71);
23119
+ debugLog("trailers received from %s %s%s", method, origin, path72);
22886
23120
  }
22887
23121
  );
22888
23122
  diagnosticsChannel.subscribe(
22889
23123
  "undici:request:error",
22890
23124
  (evt) => {
22891
23125
  const {
22892
- request: { method, path: path71, origin },
23126
+ request: { method, path: path72, origin },
22893
23127
  error
22894
23128
  } = evt;
22895
23129
  debugLog(
22896
23130
  "request to %s %s%s errored - %s",
22897
23131
  method,
22898
23132
  origin,
22899
- path71,
23133
+ path72,
22900
23134
  error.message
22901
23135
  );
22902
23136
  }
@@ -22999,7 +23233,7 @@ var require_request = __commonJS({
22999
23233
  var kHandler = /* @__PURE__ */ Symbol("handler");
23000
23234
  var Request = class {
23001
23235
  constructor(origin, {
23002
- path: path71,
23236
+ path: path72,
23003
23237
  method,
23004
23238
  body,
23005
23239
  headers,
@@ -23016,11 +23250,11 @@ var require_request = __commonJS({
23016
23250
  maxRedirections,
23017
23251
  typeOfService
23018
23252
  }, handler) {
23019
- if (typeof path71 !== "string") {
23253
+ if (typeof path72 !== "string") {
23020
23254
  throw new InvalidArgumentError("path must be a string");
23021
- } else if (path71[0] !== "/" && !(path71.startsWith("http://") || path71.startsWith("https://")) && method !== "CONNECT") {
23255
+ } else if (path72[0] !== "/" && !(path72.startsWith("http://") || path72.startsWith("https://")) && method !== "CONNECT") {
23022
23256
  throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
23023
- } else if (invalidPathRegex.test(path71)) {
23257
+ } else if (invalidPathRegex.test(path72)) {
23024
23258
  throw new InvalidArgumentError("invalid request path");
23025
23259
  }
23026
23260
  if (typeof method !== "string") {
@@ -23095,7 +23329,7 @@ var require_request = __commonJS({
23095
23329
  this.completed = false;
23096
23330
  this.aborted = false;
23097
23331
  this.upgrade = upgrade || null;
23098
- this.path = query ? serializePathWithQuery(path71, query) : path71;
23332
+ this.path = query ? serializePathWithQuery(path72, query) : path72;
23099
23333
  this.origin = origin;
23100
23334
  this.protocol = getProtocolFromUrlString(origin);
23101
23335
  this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent;
@@ -28134,7 +28368,7 @@ var require_client_h1 = __commonJS({
28134
28368
  return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT";
28135
28369
  }
28136
28370
  function writeH1(client, request2) {
28137
- const { method, path: path71, host, upgrade, blocking, reset } = request2;
28371
+ const { method, path: path72, host, upgrade, blocking, reset } = request2;
28138
28372
  let { body, headers, contentLength } = request2;
28139
28373
  const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH" || method === "QUERY" || method === "PROPFIND" || method === "PROPPATCH";
28140
28374
  if (util.isFormDataLike(body)) {
@@ -28203,7 +28437,7 @@ var require_client_h1 = __commonJS({
28203
28437
  if (socket.setTypeOfService) {
28204
28438
  socket.setTypeOfService(request2.typeOfService);
28205
28439
  }
28206
- let header = `${method} ${path71} HTTP/1.1\r
28440
+ let header = `${method} ${path72} HTTP/1.1\r
28207
28441
  `;
28208
28442
  if (typeof host === "string") {
28209
28443
  header += `host: ${host}\r
@@ -28856,7 +29090,7 @@ var require_client_h2 = __commonJS({
28856
29090
  function writeH2(client, request2) {
28857
29091
  const requestTimeout = request2.bodyTimeout ?? client[kBodyTimeout];
28858
29092
  const session = client[kHTTP2Session];
28859
- const { method, path: path71, host, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request2;
29093
+ const { method, path: path72, host, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request2;
28860
29094
  let { body } = request2;
28861
29095
  if (upgrade != null && upgrade !== "websocket") {
28862
29096
  util.errorRequest(client, request2, new InvalidArgumentError(`Custom upgrade "${upgrade}" not supported over HTTP/2`));
@@ -28924,7 +29158,7 @@ var require_client_h2 = __commonJS({
28924
29158
  }
28925
29159
  headers[HTTP2_HEADER_METHOD] = "CONNECT";
28926
29160
  headers[HTTP2_HEADER_PROTOCOL] = "websocket";
28927
- headers[HTTP2_HEADER_PATH] = path71;
29161
+ headers[HTTP2_HEADER_PATH] = path72;
28928
29162
  if (protocol === "ws:" || protocol === "wss:") {
28929
29163
  headers[HTTP2_HEADER_SCHEME] = protocol === "ws:" ? "http" : "https";
28930
29164
  } else {
@@ -28965,7 +29199,7 @@ var require_client_h2 = __commonJS({
28965
29199
  stream.setTimeout(requestTimeout);
28966
29200
  return true;
28967
29201
  }
28968
- headers[HTTP2_HEADER_PATH] = path71;
29202
+ headers[HTTP2_HEADER_PATH] = path72;
28969
29203
  headers[HTTP2_HEADER_SCHEME] = protocol === "http:" ? "http" : "https";
28970
29204
  const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
28971
29205
  if (body && typeof body.read === "function") {
@@ -31267,10 +31501,10 @@ var require_proxy_agent = __commonJS({
31267
31501
  };
31268
31502
  const {
31269
31503
  origin,
31270
- path: path71 = "/",
31504
+ path: path72 = "/",
31271
31505
  headers = {}
31272
31506
  } = opts;
31273
- opts.path = origin + path71;
31507
+ opts.path = origin + path72;
31274
31508
  if (!("host" in headers) && !("Host" in headers)) {
31275
31509
  const { host } = new URL(origin);
31276
31510
  headers.host = host;
@@ -33333,20 +33567,20 @@ var require_mock_utils = __commonJS({
33333
33567
  }
33334
33568
  return normalizedQp;
33335
33569
  }
33336
- function safeUrl(path71) {
33337
- if (typeof path71 !== "string") {
33338
- return path71;
33570
+ function safeUrl(path72) {
33571
+ if (typeof path72 !== "string") {
33572
+ return path72;
33339
33573
  }
33340
- const pathSegments = path71.split("?", 3);
33574
+ const pathSegments = path72.split("?", 3);
33341
33575
  if (pathSegments.length !== 2) {
33342
- return path71;
33576
+ return path72;
33343
33577
  }
33344
33578
  const qp = new URLSearchParams(pathSegments.pop());
33345
33579
  qp.sort();
33346
33580
  return [...pathSegments, qp.toString()].join("?");
33347
33581
  }
33348
- function matchKey(mockDispatch2, { path: path71, method, body, headers }) {
33349
- const pathMatch = matchValue(mockDispatch2.path, path71);
33582
+ function matchKey(mockDispatch2, { path: path72, method, body, headers }) {
33583
+ const pathMatch = matchValue(mockDispatch2.path, path72);
33350
33584
  const methodMatch = matchValue(mockDispatch2.method, method);
33351
33585
  const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true;
33352
33586
  const headersMatch = matchHeaders(mockDispatch2, headers);
@@ -33371,8 +33605,8 @@ var require_mock_utils = __commonJS({
33371
33605
  const basePath = key.query ? serializePathWithQuery(key.path, key.query) : key.path;
33372
33606
  const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
33373
33607
  const resolvedPathWithoutTrailingSlash = removeTrailingSlash(resolvedPath);
33374
- let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path71, ignoreTrailingSlash }) => {
33375
- return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(path71)), resolvedPathWithoutTrailingSlash) : matchValue(safeUrl(path71), resolvedPath);
33608
+ let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path72, ignoreTrailingSlash }) => {
33609
+ return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(path72)), resolvedPathWithoutTrailingSlash) : matchValue(safeUrl(path72), resolvedPath);
33376
33610
  });
33377
33611
  if (matchedMockDispatches.length === 0) {
33378
33612
  throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
@@ -33411,19 +33645,19 @@ var require_mock_utils = __commonJS({
33411
33645
  mockDispatches.splice(index, 1);
33412
33646
  }
33413
33647
  }
33414
- function removeTrailingSlash(path71) {
33415
- while (path71.endsWith("/")) {
33416
- path71 = path71.slice(0, -1);
33648
+ function removeTrailingSlash(path72) {
33649
+ while (path72.endsWith("/")) {
33650
+ path72 = path72.slice(0, -1);
33417
33651
  }
33418
- if (path71.length === 0) {
33419
- path71 = "/";
33652
+ if (path72.length === 0) {
33653
+ path72 = "/";
33420
33654
  }
33421
- return path71;
33655
+ return path72;
33422
33656
  }
33423
33657
  function buildKey(opts) {
33424
- const { path: path71, method, body, headers, query } = opts;
33658
+ const { path: path72, method, body, headers, query } = opts;
33425
33659
  return {
33426
- path: path71,
33660
+ path: path72,
33427
33661
  method,
33428
33662
  body,
33429
33663
  headers,
@@ -34113,10 +34347,10 @@ var require_pending_interceptors_formatter = __commonJS({
34113
34347
  }
34114
34348
  format(pendingInterceptors) {
34115
34349
  const withPrettyHeaders = pendingInterceptors.map(
34116
- ({ method, path: path71, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
34350
+ ({ method, path: path72, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
34117
34351
  Method: method,
34118
34352
  Origin: origin,
34119
- Path: path71,
34353
+ Path: path72,
34120
34354
  "Status code": statusCode,
34121
34355
  Persistent: persist ? PERSISTENT : NOT_PERSISTENT,
34122
34356
  Invocations: timesInvoked,
@@ -34198,9 +34432,9 @@ var require_mock_agent = __commonJS({
34198
34432
  const acceptNonStandardSearchParameters = this[kMockAgentAcceptsNonStandardSearchParameters];
34199
34433
  const dispatchOpts = { ...opts };
34200
34434
  if (acceptNonStandardSearchParameters && dispatchOpts.path) {
34201
- const [path71, searchParams] = dispatchOpts.path.split("?");
34435
+ const [path72, searchParams] = dispatchOpts.path.split("?");
34202
34436
  const normalizedSearchParams = normalizeSearchParams(searchParams, acceptNonStandardSearchParameters);
34203
- dispatchOpts.path = `${path71}?${normalizedSearchParams}`;
34437
+ dispatchOpts.path = `${path72}?${normalizedSearchParams}`;
34204
34438
  }
34205
34439
  return this[kAgent].dispatch(dispatchOpts, handler);
34206
34440
  }
@@ -34601,12 +34835,12 @@ var require_snapshot_recorder = __commonJS({
34601
34835
  * @return {Promise<void>} - Resolves when snapshots are loaded
34602
34836
  */
34603
34837
  async loadSnapshots(filePath) {
34604
- const path71 = filePath || this.#snapshotPath;
34605
- if (!path71) {
34838
+ const path72 = filePath || this.#snapshotPath;
34839
+ if (!path72) {
34606
34840
  throw new InvalidArgumentError("Snapshot path is required");
34607
34841
  }
34608
34842
  try {
34609
- const data = await readFile(resolve2(path71), "utf8");
34843
+ const data = await readFile(resolve2(path72), "utf8");
34610
34844
  const parsed = JSON.parse(data);
34611
34845
  if (Array.isArray(parsed)) {
34612
34846
  this.#snapshots.clear();
@@ -34620,7 +34854,7 @@ var require_snapshot_recorder = __commonJS({
34620
34854
  if (error.code === "ENOENT") {
34621
34855
  this.#snapshots.clear();
34622
34856
  } else {
34623
- throw new UndiciError(`Failed to load snapshots from ${path71}`, { cause: error });
34857
+ throw new UndiciError(`Failed to load snapshots from ${path72}`, { cause: error });
34624
34858
  }
34625
34859
  }
34626
34860
  }
@@ -34631,11 +34865,11 @@ var require_snapshot_recorder = __commonJS({
34631
34865
  * @returns {Promise<void>} - Resolves when snapshots are saved
34632
34866
  */
34633
34867
  async saveSnapshots(filePath) {
34634
- const path71 = filePath || this.#snapshotPath;
34635
- if (!path71) {
34868
+ const path72 = filePath || this.#snapshotPath;
34869
+ if (!path72) {
34636
34870
  throw new InvalidArgumentError("Snapshot path is required");
34637
34871
  }
34638
- const resolvedPath = resolve2(path71);
34872
+ const resolvedPath = resolve2(path72);
34639
34873
  await mkdir(dirname2(resolvedPath), { recursive: true });
34640
34874
  const data = Array.from(this.#snapshots.entries()).map(([hash, snapshot]) => ({
34641
34875
  hash,
@@ -35260,15 +35494,15 @@ var require_redirect_handler = __commonJS({
35260
35494
  return;
35261
35495
  }
35262
35496
  const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)));
35263
- const path71 = search ? `${pathname}${search}` : pathname;
35264
- const redirectUrlString = `${origin}${path71}`;
35497
+ const path72 = search ? `${pathname}${search}` : pathname;
35498
+ const redirectUrlString = `${origin}${path72}`;
35265
35499
  for (const historyUrl of this.history) {
35266
35500
  if (historyUrl.toString() === redirectUrlString) {
35267
35501
  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.`);
35268
35502
  }
35269
35503
  }
35270
35504
  this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin);
35271
- this.opts.path = path71;
35505
+ this.opts.path = path72;
35272
35506
  this.opts.origin = origin;
35273
35507
  this.opts.query = null;
35274
35508
  }
@@ -41475,11 +41709,11 @@ var require_fetch = __commonJS({
41475
41709
  function dispatch({ body }) {
41476
41710
  const url = requestCurrentURL(request2);
41477
41711
  const agent = fetchParams.controller.dispatcher;
41478
- const path71 = url.pathname + url.search;
41712
+ const path72 = url.pathname + url.search;
41479
41713
  const hasTrailingQuestionMark = url.search.length === 0 && url.href[url.href.length - url.hash.length - 1] === "?";
41480
41714
  return new Promise((resolve2, reject) => agent.dispatch(
41481
41715
  {
41482
- path: hasTrailingQuestionMark ? `${path71}?` : path71,
41716
+ path: hasTrailingQuestionMark ? `${path72}?` : path72,
41483
41717
  origin: url.origin,
41484
41718
  method: request2.method,
41485
41719
  body: agent.isMockActive ? request2.body && (request2.body.source || request2.body.stream) : body,
@@ -42410,9 +42644,9 @@ var require_util4 = __commonJS({
42410
42644
  }
42411
42645
  }
42412
42646
  }
42413
- function validateCookiePath(path71) {
42414
- for (let i = 0; i < path71.length; ++i) {
42415
- const code = path71.charCodeAt(i);
42647
+ function validateCookiePath(path72) {
42648
+ for (let i = 0; i < path72.length; ++i) {
42649
+ const code = path72.charCodeAt(i);
42416
42650
  if (code < 32 || // exclude CTLs (0-31)
42417
42651
  code === 127 || // DEL
42418
42652
  code === 59) {
@@ -45582,11 +45816,11 @@ var require_undici = __commonJS({
45582
45816
  if (typeof opts.path !== "string") {
45583
45817
  throw new InvalidArgumentError("invalid opts.path");
45584
45818
  }
45585
- let path71 = opts.path;
45819
+ let path72 = opts.path;
45586
45820
  if (!opts.path.startsWith("/")) {
45587
- path71 = `/${path71}`;
45821
+ path72 = `/${path72}`;
45588
45822
  }
45589
- url = new URL(util.parseOrigin(url).origin + path71);
45823
+ url = new URL(util.parseOrigin(url).origin + path72);
45590
45824
  } else {
45591
45825
  if (!opts) {
45592
45826
  opts = typeof url === "object" ? url : {};
@@ -45699,10 +45933,14 @@ ${captureLines}` : capture.stack;
45699
45933
  var tail_exports = {};
45700
45934
  __export(tail_exports, {
45701
45935
  agentLabel: () => agentLabel,
45936
+ eventsUrl: () => eventsUrl,
45702
45937
  sessionTag: () => sessionTag,
45703
45938
  shortenPathSummary: () => shortenPathSummary,
45704
45939
  startTail: () => startTail
45705
45940
  });
45941
+ function eventsUrl(port, canApprove) {
45942
+ return `http://127.0.0.1:${port}/events${canApprove ? "?capabilities=input" : ""}`;
45943
+ }
45706
45944
  function shortenPathSummary(s) {
45707
45945
  if (!s || !s.startsWith("/")) return s;
45708
45946
  const parts = s.split("/").filter(Boolean);
@@ -45724,20 +45962,20 @@ function getModelContextLimit(model) {
45724
45962
  return 2e5;
45725
45963
  }
45726
45964
  function readSessionUsage() {
45727
- const projectsDir = import_path67.default.join(import_os60.default.homedir(), ".claude", "projects");
45728
- if (!import_fs71.default.existsSync(projectsDir)) return null;
45965
+ const projectsDir = import_path68.default.join(import_os60.default.homedir(), ".claude", "projects");
45966
+ if (!import_fs72.default.existsSync(projectsDir)) return null;
45729
45967
  let latestFile = null;
45730
45968
  let latestMtime = 0;
45731
45969
  try {
45732
- for (const dir of import_fs71.default.readdirSync(projectsDir)) {
45733
- const dirPath = import_path67.default.join(projectsDir, dir);
45970
+ for (const dir of import_fs72.default.readdirSync(projectsDir)) {
45971
+ const dirPath = import_path68.default.join(projectsDir, dir);
45734
45972
  try {
45735
- if (!import_fs71.default.statSync(dirPath).isDirectory()) continue;
45736
- for (const file of import_fs71.default.readdirSync(dirPath)) {
45973
+ if (!import_fs72.default.statSync(dirPath).isDirectory()) continue;
45974
+ for (const file of import_fs72.default.readdirSync(dirPath)) {
45737
45975
  if (!file.endsWith(".jsonl") || file.startsWith("agent-")) continue;
45738
- const filePath = import_path67.default.join(dirPath, file);
45976
+ const filePath = import_path68.default.join(dirPath, file);
45739
45977
  try {
45740
- const mtime = import_fs71.default.statSync(filePath).mtimeMs;
45978
+ const mtime = import_fs72.default.statSync(filePath).mtimeMs;
45741
45979
  if (mtime > latestMtime) {
45742
45980
  latestMtime = mtime;
45743
45981
  latestFile = filePath;
@@ -45752,7 +45990,7 @@ function readSessionUsage() {
45752
45990
  }
45753
45991
  if (!latestFile) return null;
45754
45992
  try {
45755
- const lines = import_fs71.default.readFileSync(latestFile, "utf-8").split("\n");
45993
+ const lines = import_fs72.default.readFileSync(latestFile, "utf-8").split("\n");
45756
45994
  let lastModel = "";
45757
45995
  let lastInput = 0;
45758
45996
  let lastOutput = 0;
@@ -45852,9 +46090,9 @@ function renderPending(activity) {
45852
46090
  }
45853
46091
  async function ensureDaemon() {
45854
46092
  let pidPort = null;
45855
- if (import_fs71.default.existsSync(PID_FILE)) {
46093
+ if (import_fs72.default.existsSync(PID_FILE)) {
45856
46094
  try {
45857
- const { port } = JSON.parse(import_fs71.default.readFileSync(PID_FILE, "utf-8"));
46095
+ const { port } = JSON.parse(import_fs72.default.readFileSync(PID_FILE, "utf-8"));
45858
46096
  pidPort = port;
45859
46097
  } catch {
45860
46098
  console.error(import_chalk40.default.dim("\u26A0\uFE0F Could not read PID file; falling back to default port."));
@@ -45880,7 +46118,7 @@ async function ensureDaemon() {
45880
46118
  child.unref();
45881
46119
  if (startupFd !== void 0) {
45882
46120
  try {
45883
- import_fs71.default.closeSync(startupFd);
46121
+ import_fs72.default.closeSync(startupFd);
45884
46122
  } catch {
45885
46123
  }
45886
46124
  }
@@ -46019,9 +46257,9 @@ function buildRecoveryCardLines(req) {
46019
46257
  ];
46020
46258
  }
46021
46259
  function readApproversFromDisk() {
46022
- const configPath = import_path67.default.join(import_os60.default.homedir(), ".node9", "config.json");
46260
+ const configPath = import_path68.default.join(import_os60.default.homedir(), ".node9", "config.json");
46023
46261
  try {
46024
- const raw = JSON.parse(import_fs71.default.readFileSync(configPath, "utf-8"));
46262
+ const raw = JSON.parse(import_fs72.default.readFileSync(configPath, "utf-8"));
46025
46263
  const settings = raw.settings ?? {};
46026
46264
  return settings.approvers ?? {};
46027
46265
  } catch {
@@ -46037,15 +46275,15 @@ function approverStatusLine() {
46037
46275
  return `${fmt("native", "native")} ${fmt("cloud", "cloud")} ${fmt("terminal", "terminal")}`;
46038
46276
  }
46039
46277
  function toggleApprover(channel) {
46040
- const configPath = import_path67.default.join(import_os60.default.homedir(), ".node9", "config.json");
46278
+ const configPath = import_path68.default.join(import_os60.default.homedir(), ".node9", "config.json");
46041
46279
  try {
46042
- const raw = JSON.parse(import_fs71.default.readFileSync(configPath, "utf-8"));
46280
+ const raw = JSON.parse(import_fs72.default.readFileSync(configPath, "utf-8"));
46043
46281
  const settings = raw.settings ?? {};
46044
46282
  const approvers = settings.approvers ?? {};
46045
46283
  approvers[channel] = approvers[channel] === false;
46046
46284
  settings.approvers = approvers;
46047
46285
  raw.settings = settings;
46048
- import_fs71.default.writeFileSync(configPath, JSON.stringify(raw, null, 2) + "\n");
46286
+ import_fs72.default.writeFileSync(configPath, JSON.stringify(raw, null, 2) + "\n");
46049
46287
  } catch (err2) {
46050
46288
  process.stderr.write(`[node9] toggleApprover failed: ${String(err2)}
46051
46289
  `);
@@ -46217,8 +46455,8 @@ async function startTail(options = {}) {
46217
46455
  }
46218
46456
  postDecisionHttp(req2.id, httpDecision, authToken, port, httpOpts).catch((err2) => {
46219
46457
  try {
46220
- import_fs71.default.appendFileSync(
46221
- import_path67.default.join(import_os60.default.homedir(), ".node9", "hook-debug.log"),
46458
+ import_fs72.default.appendFileSync(
46459
+ import_path68.default.join(import_os60.default.homedir(), ".node9", "hook-debug.log"),
46222
46460
  `[tail] POST /decision failed: ${String(err2)}
46223
46461
  `
46224
46462
  );
@@ -46282,9 +46520,9 @@ async function startTail(options = {}) {
46282
46520
  };
46283
46521
  process.stdin.on("keypress", onKeypress);
46284
46522
  }
46285
- const auditLog = import_path67.default.join(import_os60.default.homedir(), ".node9", "audit.log");
46523
+ const auditLog = import_path68.default.join(import_os60.default.homedir(), ".node9", "audit.log");
46286
46524
  try {
46287
- const unackedDlp = import_fs71.default.readFileSync(auditLog, "utf-8").split("\n").filter((l) => l.includes('"response-dlp"')).length;
46525
+ const unackedDlp = import_fs72.default.readFileSync(auditLog, "utf-8").split("\n").filter((l) => l.includes('"response-dlp"')).length;
46288
46526
  if (unackedDlp > 0) {
46289
46527
  console.log("");
46290
46528
  console.log(
@@ -46324,7 +46562,7 @@ async function startTail(options = {}) {
46324
46562
  if (stallWarned) return;
46325
46563
  if (Date.now() - lastActivityFromDaemon < STALL_THRESHOLD_MS) return;
46326
46564
  try {
46327
- const auditMtime = import_fs71.default.statSync(auditLog).mtimeMs;
46565
+ const auditMtime = import_fs72.default.statSync(auditLog).mtimeMs;
46328
46566
  if (Date.now() - auditMtime >= STALL_THRESHOLD_MS) return;
46329
46567
  console.log("");
46330
46568
  console.log(
@@ -46337,7 +46575,7 @@ async function startTail(options = {}) {
46337
46575
  }
46338
46576
  }, STALL_THRESHOLD_MS / 2);
46339
46577
  stallWatchdog.unref();
46340
- const sseUrl = `http://127.0.0.1:${port}/events?capabilities=input`;
46578
+ const sseUrl = eventsUrl(port, canApprove);
46341
46579
  const req = import_http5.default.get(
46342
46580
  sseUrl,
46343
46581
  {
@@ -46509,21 +46747,21 @@ async function startTail(options = {}) {
46509
46747
  process.exit(1);
46510
46748
  });
46511
46749
  }
46512
- var import_http5, import_chalk40, import_fs71, import_os60, import_path67, import_readline6, import_child_process14, PID_FILE, ICONS, MODEL_CONTEXT_LIMITS, RESET2, BOLD2, RED, YELLOW, CYAN, GRAY, GREEN, HIDE_CURSOR, SHOW_CURSOR, ERASE_DOWN, pendingShownForId, pendingWrappedLines, DIVIDER;
46750
+ var import_http5, import_chalk40, import_fs72, import_os60, import_path68, import_readline6, import_child_process14, PID_FILE, ICONS, MODEL_CONTEXT_LIMITS, RESET2, BOLD2, RED, YELLOW, CYAN, GRAY, GREEN, HIDE_CURSOR, SHOW_CURSOR, ERASE_DOWN, pendingShownForId, pendingWrappedLines, DIVIDER;
46513
46751
  var init_tail = __esm({
46514
46752
  "src/tui/tail.ts"() {
46515
46753
  "use strict";
46516
46754
  import_http5 = __toESM(require("http"));
46517
46755
  import_chalk40 = __toESM(require("chalk"));
46518
- import_fs71 = __toESM(require("fs"));
46756
+ import_fs72 = __toESM(require("fs"));
46519
46757
  import_os60 = __toESM(require("os"));
46520
- import_path67 = __toESM(require("path"));
46758
+ import_path68 = __toESM(require("path"));
46521
46759
  import_readline6 = __toESM(require("readline"));
46522
46760
  import_child_process14 = require("child_process");
46523
46761
  init_startup_log();
46524
46762
  init_daemon2();
46525
46763
  init_daemon();
46526
- PID_FILE = import_path67.default.join(import_os60.default.homedir(), ".node9", "daemon.pid");
46764
+ PID_FILE = import_path68.default.join(import_os60.default.homedir(), ".node9", "daemon.pid");
46527
46765
  ICONS = {
46528
46766
  bash: "\u{1F4BB}",
46529
46767
  shell: "\u{1F4BB}",
@@ -46645,9 +46883,9 @@ function formatTimeLeft(resetsAt) {
46645
46883
  return ` (${m}m left)`;
46646
46884
  }
46647
46885
  function safeReadJson(filePath) {
46648
- if (!import_fs72.default.existsSync(filePath)) return null;
46886
+ if (!import_fs73.default.existsSync(filePath)) return null;
46649
46887
  try {
46650
- return JSON.parse(import_fs72.default.readFileSync(filePath, "utf-8"));
46888
+ return JSON.parse(import_fs73.default.readFileSync(filePath, "utf-8"));
46651
46889
  } catch {
46652
46890
  return null;
46653
46891
  }
@@ -46668,12 +46906,12 @@ function countHooksInFile(filePath) {
46668
46906
  return Object.keys(cfg.hooks).length;
46669
46907
  }
46670
46908
  function countRulesInDir(rulesDir) {
46671
- if (!import_fs72.default.existsSync(rulesDir)) return 0;
46909
+ if (!import_fs73.default.existsSync(rulesDir)) return 0;
46672
46910
  let count = 0;
46673
46911
  try {
46674
- for (const entry of import_fs72.default.readdirSync(rulesDir, { withFileTypes: true })) {
46912
+ for (const entry of import_fs73.default.readdirSync(rulesDir, { withFileTypes: true })) {
46675
46913
  if (entry.isDirectory()) {
46676
- count += countRulesInDir(import_path68.default.join(rulesDir, entry.name));
46914
+ count += countRulesInDir(import_path69.default.join(rulesDir, entry.name));
46677
46915
  } else if (entry.isFile() && entry.name.endsWith(".md")) {
46678
46916
  count++;
46679
46917
  }
@@ -46684,46 +46922,46 @@ function countRulesInDir(rulesDir) {
46684
46922
  }
46685
46923
  function isSamePath(a, b) {
46686
46924
  try {
46687
- return import_path68.default.resolve(a) === import_path68.default.resolve(b);
46925
+ return import_path69.default.resolve(a) === import_path69.default.resolve(b);
46688
46926
  } catch {
46689
46927
  return false;
46690
46928
  }
46691
46929
  }
46692
46930
  function countConfigs(cwd) {
46693
46931
  const homeDir2 = import_os61.default.homedir();
46694
- const claudeDir = import_path68.default.join(homeDir2, ".claude");
46932
+ const claudeDir = import_path69.default.join(homeDir2, ".claude");
46695
46933
  let claudeMdCount = 0;
46696
46934
  let rulesCount = 0;
46697
46935
  let hooksCount = 0;
46698
46936
  const userMcpServers = /* @__PURE__ */ new Set();
46699
46937
  const projectMcpServers = /* @__PURE__ */ new Set();
46700
- if (import_fs72.default.existsSync(import_path68.default.join(claudeDir, "CLAUDE.md"))) claudeMdCount++;
46701
- rulesCount += countRulesInDir(import_path68.default.join(claudeDir, "rules"));
46702
- const userSettings = import_path68.default.join(claudeDir, "settings.json");
46938
+ if (import_fs73.default.existsSync(import_path69.default.join(claudeDir, "CLAUDE.md"))) claudeMdCount++;
46939
+ rulesCount += countRulesInDir(import_path69.default.join(claudeDir, "rules"));
46940
+ const userSettings = import_path69.default.join(claudeDir, "settings.json");
46703
46941
  for (const name of getMcpServerNames(userSettings)) userMcpServers.add(name);
46704
46942
  hooksCount += countHooksInFile(userSettings);
46705
- const userClaudeJson = import_path68.default.join(homeDir2, ".claude.json");
46943
+ const userClaudeJson = import_path69.default.join(homeDir2, ".claude.json");
46706
46944
  for (const name of getMcpServerNames(userClaudeJson)) userMcpServers.add(name);
46707
46945
  for (const name of getDisabledMcpServers(userClaudeJson, "disabledMcpServers")) {
46708
46946
  userMcpServers.delete(name);
46709
46947
  }
46710
46948
  if (cwd) {
46711
- if (import_fs72.default.existsSync(import_path68.default.join(cwd, "CLAUDE.md"))) claudeMdCount++;
46712
- if (import_fs72.default.existsSync(import_path68.default.join(cwd, "CLAUDE.local.md"))) claudeMdCount++;
46713
- const projectClaudeDir = import_path68.default.join(cwd, ".claude");
46949
+ if (import_fs73.default.existsSync(import_path69.default.join(cwd, "CLAUDE.md"))) claudeMdCount++;
46950
+ if (import_fs73.default.existsSync(import_path69.default.join(cwd, "CLAUDE.local.md"))) claudeMdCount++;
46951
+ const projectClaudeDir = import_path69.default.join(cwd, ".claude");
46714
46952
  const overlapsUserScope = isSamePath(projectClaudeDir, claudeDir);
46715
46953
  if (!overlapsUserScope) {
46716
- if (import_fs72.default.existsSync(import_path68.default.join(projectClaudeDir, "CLAUDE.md"))) claudeMdCount++;
46717
- rulesCount += countRulesInDir(import_path68.default.join(projectClaudeDir, "rules"));
46718
- const projSettings = import_path68.default.join(projectClaudeDir, "settings.json");
46954
+ if (import_fs73.default.existsSync(import_path69.default.join(projectClaudeDir, "CLAUDE.md"))) claudeMdCount++;
46955
+ rulesCount += countRulesInDir(import_path69.default.join(projectClaudeDir, "rules"));
46956
+ const projSettings = import_path69.default.join(projectClaudeDir, "settings.json");
46719
46957
  for (const name of getMcpServerNames(projSettings)) projectMcpServers.add(name);
46720
46958
  hooksCount += countHooksInFile(projSettings);
46721
46959
  }
46722
- if (import_fs72.default.existsSync(import_path68.default.join(projectClaudeDir, "CLAUDE.local.md"))) claudeMdCount++;
46723
- const localSettings = import_path68.default.join(projectClaudeDir, "settings.local.json");
46960
+ if (import_fs73.default.existsSync(import_path69.default.join(projectClaudeDir, "CLAUDE.local.md"))) claudeMdCount++;
46961
+ const localSettings = import_path69.default.join(projectClaudeDir, "settings.local.json");
46724
46962
  for (const name of getMcpServerNames(localSettings)) projectMcpServers.add(name);
46725
46963
  hooksCount += countHooksInFile(localSettings);
46726
- const mcpJsonServers = getMcpServerNames(import_path68.default.join(cwd, ".mcp.json"));
46964
+ const mcpJsonServers = getMcpServerNames(import_path69.default.join(cwd, ".mcp.json"));
46727
46965
  const disabledMcpJson = getDisabledMcpServers(localSettings, "disabledMcpjsonServers");
46728
46966
  for (const name of disabledMcpJson) mcpJsonServers.delete(name);
46729
46967
  for (const name of mcpJsonServers) projectMcpServers.add(name);
@@ -46756,12 +46994,12 @@ function readActiveShieldsHud() {
46756
46994
  return shieldsCache.value;
46757
46995
  }
46758
46996
  try {
46759
- const shieldsPath = import_path68.default.join(import_os61.default.homedir(), ".node9", "shields.json");
46760
- if (!import_fs72.default.existsSync(shieldsPath)) {
46997
+ const shieldsPath = import_path69.default.join(import_os61.default.homedir(), ".node9", "shields.json");
46998
+ if (!import_fs73.default.existsSync(shieldsPath)) {
46761
46999
  shieldsCache = { value: [], ts: now };
46762
47000
  return [];
46763
47001
  }
46764
- const parsed = JSON.parse(import_fs72.default.readFileSync(shieldsPath, "utf-8"));
47002
+ const parsed = JSON.parse(import_fs73.default.readFileSync(shieldsPath, "utf-8"));
46765
47003
  if (!Array.isArray(parsed.active)) {
46766
47004
  shieldsCache = { value: [], ts: now };
46767
47005
  return [];
@@ -46863,17 +47101,17 @@ function renderContextLine(stdin) {
46863
47101
  async function main() {
46864
47102
  try {
46865
47103
  const [stdin, daemonStatus2] = await Promise.all([readStdin(), queryDaemon()]);
46866
- if (import_fs72.default.existsSync(import_path68.default.join(import_os61.default.homedir(), ".node9", "hud-debug"))) {
47104
+ if (import_fs73.default.existsSync(import_path69.default.join(import_os61.default.homedir(), ".node9", "hud-debug"))) {
46867
47105
  try {
46868
- const logPath = import_path68.default.join(import_os61.default.homedir(), ".node9", "hud-debug.log");
47106
+ const logPath = import_path69.default.join(import_os61.default.homedir(), ".node9", "hud-debug.log");
46869
47107
  const MAX_LOG_SIZE = 10 * 1024 * 1024;
46870
47108
  let size = 0;
46871
47109
  try {
46872
- size = import_fs72.default.statSync(logPath).size;
47110
+ size = import_fs73.default.statSync(logPath).size;
46873
47111
  } catch {
46874
47112
  }
46875
47113
  if (size < MAX_LOG_SIZE) {
46876
- import_fs72.default.appendFileSync(
47114
+ import_fs73.default.appendFileSync(
46877
47115
  logPath,
46878
47116
  JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), stdin }) + "\n"
46879
47117
  );
@@ -46894,11 +47132,11 @@ async function main() {
46894
47132
  try {
46895
47133
  const cwd = stdin.cwd ?? process.cwd();
46896
47134
  for (const configPath of [
46897
- import_path68.default.join(cwd, "node9.config.json"),
46898
- import_path68.default.join(import_os61.default.homedir(), ".node9", "config.json")
47135
+ import_path69.default.join(cwd, "node9.config.json"),
47136
+ import_path69.default.join(import_os61.default.homedir(), ".node9", "config.json")
46899
47137
  ]) {
46900
- if (!import_fs72.default.existsSync(configPath)) continue;
46901
- const cfg = JSON.parse(import_fs72.default.readFileSync(configPath, "utf-8"));
47138
+ if (!import_fs73.default.existsSync(configPath)) continue;
47139
+ const cfg = JSON.parse(import_fs73.default.readFileSync(configPath, "utf-8"));
46902
47140
  const hud = cfg.settings?.hud;
46903
47141
  if (hud && "showEnvironmentCounts" in hud) return hud.showEnvironmentCounts !== false;
46904
47142
  }
@@ -46916,12 +47154,12 @@ async function main() {
46916
47154
  renderOffline();
46917
47155
  }
46918
47156
  }
46919
- var import_fs72, import_path68, import_os61, import_http6, RESET3, BOLD3, DIM, RED2, GREEN2, YELLOW2, BLUE, MAGENTA, CYAN2, WHITE, BAR_FILLED, BAR_EMPTY, BAR_WIDTH, shieldsCache, SHIELDS_CACHE_TTL_MS;
47157
+ var import_fs73, import_path69, import_os61, import_http6, RESET3, BOLD3, DIM, RED2, GREEN2, YELLOW2, BLUE, MAGENTA, CYAN2, WHITE, BAR_FILLED, BAR_EMPTY, BAR_WIDTH, shieldsCache, SHIELDS_CACHE_TTL_MS;
46920
47158
  var init_hud = __esm({
46921
47159
  "src/cli/hud.ts"() {
46922
47160
  "use strict";
46923
- import_fs72 = __toESM(require("fs"));
46924
- import_path68 = __toESM(require("path"));
47161
+ import_fs73 = __toESM(require("fs"));
47162
+ import_path69 = __toESM(require("path"));
46925
47163
  import_os61 = __toESM(require("os"));
46926
47164
  import_http6 = __toESM(require("http"));
46927
47165
  init_daemon();
@@ -47044,8 +47282,8 @@ function writeCredentialsAndConfig(apiKey, opts = {}) {
47044
47282
  // src/cli.ts
47045
47283
  init_daemon2();
47046
47284
  var import_chalk41 = __toESM(require("chalk"));
47047
- var import_fs73 = __toESM(require("fs"));
47048
- var import_path69 = __toESM(require("path"));
47285
+ var import_fs74 = __toESM(require("fs"));
47286
+ var import_path70 = __toESM(require("path"));
47049
47287
  var import_os62 = __toESM(require("os"));
47050
47288
  var import_child_process15 = require("child_process");
47051
47289
  var import_prompts2 = require("@inquirer/prompts");
@@ -47233,28 +47471,28 @@ async function runProxy(targetCommand) {
47233
47471
 
47234
47472
  // src/cli/daemon-starter.ts
47235
47473
  var import_child_process5 = require("child_process");
47236
- var import_path41 = __toESM(require("path"));
47237
- var import_fs43 = __toESM(require("fs"));
47474
+ var import_path42 = __toESM(require("path"));
47475
+ var import_fs44 = __toESM(require("fs"));
47238
47476
  var import_os39 = __toESM(require("os"));
47239
47477
  init_daemon();
47240
47478
  init_startup_log();
47241
47479
  function isTestingMode() {
47242
47480
  return /^(1|true|yes)$/i.test(process.env.NODE9_TESTING ?? "");
47243
47481
  }
47244
- var SKIP_STAMP = () => import_path41.default.join(import_os39.default.homedir(), ".node9", ".autostart-skip-stamp");
47482
+ var SKIP_STAMP = () => import_path42.default.join(import_os39.default.homedir(), ".node9", ".autostart-skip-stamp");
47245
47483
  var SKIP_THROTTLE_MS = 60 * 60 * 1e3;
47246
47484
  function logAutostartSkipThrottled(reason) {
47247
47485
  try {
47248
47486
  const stamp = SKIP_STAMP();
47249
47487
  try {
47250
- if (Date.now() - import_fs43.default.statSync(stamp).mtimeMs < SKIP_THROTTLE_MS) return;
47488
+ if (Date.now() - import_fs44.default.statSync(stamp).mtimeMs < SKIP_THROTTLE_MS) return;
47251
47489
  } catch {
47252
47490
  }
47253
- const dir = import_path41.default.join(import_os39.default.homedir(), ".node9");
47254
- if (!import_fs43.default.existsSync(dir)) import_fs43.default.mkdirSync(dir, { recursive: true });
47255
- import_fs43.default.writeFileSync(stamp, "", "utf-8");
47256
- import_fs43.default.appendFileSync(
47257
- import_path41.default.join(dir, "hook-debug.log"),
47491
+ const dir = import_path42.default.join(import_os39.default.homedir(), ".node9");
47492
+ if (!import_fs44.default.existsSync(dir)) import_fs44.default.mkdirSync(dir, { recursive: true });
47493
+ import_fs44.default.writeFileSync(stamp, "", "utf-8");
47494
+ import_fs44.default.appendFileSync(
47495
+ import_path42.default.join(dir, "hook-debug.log"),
47258
47496
  `[${(/* @__PURE__ */ new Date()).toISOString()}] daemon-autostart-skip: ${reason}
47259
47497
  `,
47260
47498
  "utf-8"
@@ -47263,11 +47501,20 @@ function logAutostartSkipThrottled(reason) {
47263
47501
  }
47264
47502
  }
47265
47503
  async function autoStartDaemonAndWait() {
47504
+ let alreadyServing = false;
47505
+ try {
47506
+ alreadyServing = await isDaemonReachable();
47507
+ } catch {
47508
+ }
47509
+ if (alreadyServing) {
47510
+ logAutostartSkipThrottled("already-serving");
47511
+ return true;
47512
+ }
47266
47513
  if (isTestingMode()) return false;
47267
- if (!import_path41.default.isAbsolute(process.argv[1])) return false;
47514
+ if (!import_path42.default.isAbsolute(process.argv[1])) return false;
47268
47515
  let resolvedArgv1;
47269
47516
  try {
47270
- resolvedArgv1 = import_fs43.default.realpathSync(process.argv[1]);
47517
+ resolvedArgv1 = import_fs44.default.realpathSync(process.argv[1]);
47271
47518
  } catch {
47272
47519
  return false;
47273
47520
  }
@@ -47305,7 +47552,7 @@ async function autoStartDaemonAndWait() {
47305
47552
  } finally {
47306
47553
  if (startupFd !== void 0) {
47307
47554
  try {
47308
- import_fs43.default.closeSync(startupFd);
47555
+ import_fs44.default.closeSync(startupFd);
47309
47556
  } catch {
47310
47557
  }
47311
47558
  }
@@ -47318,9 +47565,9 @@ init_service();
47318
47565
 
47319
47566
  // src/cli/commands/check.ts
47320
47567
  var import_chalk9 = __toESM(require("chalk"));
47321
- var import_fs47 = __toESM(require("fs"));
47568
+ var import_fs48 = __toESM(require("fs"));
47322
47569
  var import_child_process7 = require("child_process");
47323
- var import_path45 = __toESM(require("path"));
47570
+ var import_path46 = __toESM(require("path"));
47324
47571
  var import_os43 = __toESM(require("os"));
47325
47572
  init_orchestrator();
47326
47573
  init_state();
@@ -47332,11 +47579,11 @@ init_policy();
47332
47579
  // src/undo.ts
47333
47580
  var import_child_process6 = require("child_process");
47334
47581
  var import_crypto12 = __toESM(require("crypto"));
47335
- var import_fs44 = __toESM(require("fs"));
47582
+ var import_fs45 = __toESM(require("fs"));
47336
47583
  var import_net3 = __toESM(require("net"));
47337
- var import_path42 = __toESM(require("path"));
47584
+ var import_path43 = __toESM(require("path"));
47338
47585
  var import_os40 = __toESM(require("os"));
47339
- var ACTIVITY_SOCKET_PATH3 = process.platform === "win32" ? "\\\\.\\pipe\\node9-activity" : import_path42.default.join(import_os40.default.tmpdir(), "node9-activity.sock");
47586
+ var ACTIVITY_SOCKET_PATH3 = process.platform === "win32" ? "\\\\.\\pipe\\node9-activity" : import_path43.default.join(import_os40.default.tmpdir(), "node9-activity.sock");
47340
47587
  function notifySnapshotTaken(hash, tool, argsSummary, fileCount) {
47341
47588
  try {
47342
47589
  const payload = JSON.stringify({
@@ -47356,22 +47603,22 @@ function notifySnapshotTaken(hash, tool, argsSummary, fileCount) {
47356
47603
  } catch {
47357
47604
  }
47358
47605
  }
47359
- var SNAPSHOT_STACK_PATH = import_path42.default.join(import_os40.default.homedir(), ".node9", "snapshots.json");
47360
- var UNDO_LATEST_PATH = import_path42.default.join(import_os40.default.homedir(), ".node9", "undo_latest.txt");
47606
+ var SNAPSHOT_STACK_PATH = import_path43.default.join(import_os40.default.homedir(), ".node9", "snapshots.json");
47607
+ var UNDO_LATEST_PATH = import_path43.default.join(import_os40.default.homedir(), ".node9", "undo_latest.txt");
47361
47608
  var MAX_SNAPSHOTS = 10;
47362
47609
  var GIT_TIMEOUT = 15e3;
47363
47610
  function readStack() {
47364
47611
  try {
47365
- if (import_fs44.default.existsSync(SNAPSHOT_STACK_PATH))
47366
- return JSON.parse(import_fs44.default.readFileSync(SNAPSHOT_STACK_PATH, "utf-8"));
47612
+ if (import_fs45.default.existsSync(SNAPSHOT_STACK_PATH))
47613
+ return JSON.parse(import_fs45.default.readFileSync(SNAPSHOT_STACK_PATH, "utf-8"));
47367
47614
  } catch {
47368
47615
  }
47369
47616
  return [];
47370
47617
  }
47371
47618
  function writeStack(stack) {
47372
- const dir = import_path42.default.dirname(SNAPSHOT_STACK_PATH);
47373
- if (!import_fs44.default.existsSync(dir)) import_fs44.default.mkdirSync(dir, { recursive: true });
47374
- import_fs44.default.writeFileSync(SNAPSHOT_STACK_PATH, JSON.stringify(stack, null, 2));
47619
+ const dir = import_path43.default.dirname(SNAPSHOT_STACK_PATH);
47620
+ if (!import_fs45.default.existsSync(dir)) import_fs45.default.mkdirSync(dir, { recursive: true });
47621
+ import_fs45.default.writeFileSync(SNAPSHOT_STACK_PATH, JSON.stringify(stack, null, 2));
47375
47622
  }
47376
47623
  function extractFilePath(args) {
47377
47624
  if (!args || typeof args !== "object") return null;
@@ -47391,12 +47638,12 @@ function buildArgsSummary(tool, args) {
47391
47638
  return "";
47392
47639
  }
47393
47640
  function findProjectRoot(filePath) {
47394
- let dir = import_path42.default.dirname(filePath);
47641
+ let dir = import_path43.default.dirname(filePath);
47395
47642
  while (true) {
47396
- if (import_fs44.default.existsSync(import_path42.default.join(dir, ".git")) || import_fs44.default.existsSync(import_path42.default.join(dir, "package.json"))) {
47643
+ if (import_fs45.default.existsSync(import_path43.default.join(dir, ".git")) || import_fs45.default.existsSync(import_path43.default.join(dir, "package.json"))) {
47397
47644
  return dir;
47398
47645
  }
47399
- const parent = import_path42.default.dirname(dir);
47646
+ const parent = import_path43.default.dirname(dir);
47400
47647
  if (parent === dir) return process.cwd();
47401
47648
  dir = parent;
47402
47649
  }
@@ -47404,7 +47651,7 @@ function findProjectRoot(filePath) {
47404
47651
  function normalizeCwdForHash(cwd) {
47405
47652
  let normalized;
47406
47653
  try {
47407
- normalized = import_fs44.default.realpathSync(cwd);
47654
+ normalized = import_fs45.default.realpathSync(cwd);
47408
47655
  } catch {
47409
47656
  normalized = cwd;
47410
47657
  }
@@ -47414,16 +47661,16 @@ function normalizeCwdForHash(cwd) {
47414
47661
  }
47415
47662
  function getShadowRepoDir(cwd) {
47416
47663
  const hash = import_crypto12.default.createHash("sha256").update(normalizeCwdForHash(cwd)).digest("hex").slice(0, 16);
47417
- return import_path42.default.join(import_os40.default.homedir(), ".node9", "snapshots", hash);
47664
+ return import_path43.default.join(import_os40.default.homedir(), ".node9", "snapshots", hash);
47418
47665
  }
47419
47666
  function cleanOrphanedIndexFiles(shadowDir) {
47420
47667
  try {
47421
47668
  const cutoff = Date.now() - 6e4;
47422
- for (const f of import_fs44.default.readdirSync(shadowDir)) {
47669
+ for (const f of import_fs45.default.readdirSync(shadowDir)) {
47423
47670
  if (f.startsWith("index_")) {
47424
- const fp = import_path42.default.join(shadowDir, f);
47671
+ const fp = import_path43.default.join(shadowDir, f);
47425
47672
  try {
47426
- if (import_fs44.default.statSync(fp).mtimeMs < cutoff) import_fs44.default.unlinkSync(fp);
47673
+ if (import_fs45.default.statSync(fp).mtimeMs < cutoff) import_fs45.default.unlinkSync(fp);
47427
47674
  } catch {
47428
47675
  }
47429
47676
  }
@@ -47435,7 +47682,7 @@ function writeShadowExcludes(shadowDir, ignorePaths) {
47435
47682
  const hardcoded = [".git", ".node9"];
47436
47683
  const lines = [...hardcoded, ...ignorePaths].join("\n");
47437
47684
  try {
47438
- import_fs44.default.writeFileSync(import_path42.default.join(shadowDir, "info", "exclude"), lines + "\n", "utf8");
47685
+ import_fs45.default.writeFileSync(import_path43.default.join(shadowDir, "info", "exclude"), lines + "\n", "utf8");
47439
47686
  } catch {
47440
47687
  }
47441
47688
  }
@@ -47448,25 +47695,25 @@ function ensureShadowRepo(shadowDir, cwd) {
47448
47695
  timeout: 3e3
47449
47696
  });
47450
47697
  if (check.status === 0) {
47451
- const ptPath = import_path42.default.join(shadowDir, "project-path.txt");
47698
+ const ptPath = import_path43.default.join(shadowDir, "project-path.txt");
47452
47699
  try {
47453
- const stored = import_fs44.default.readFileSync(ptPath, "utf8").trim();
47700
+ const stored = import_fs45.default.readFileSync(ptPath, "utf8").trim();
47454
47701
  if (stored === normalizedCwd) return true;
47455
47702
  if (process.env.NODE9_DEBUG === "1")
47456
47703
  console.error(
47457
47704
  `[Node9] Shadow repo path mismatch: stored="${stored}" expected="${normalizedCwd}" \u2014 reinitializing`
47458
47705
  );
47459
- import_fs44.default.rmSync(shadowDir, { recursive: true, force: true });
47706
+ import_fs45.default.rmSync(shadowDir, { recursive: true, force: true });
47460
47707
  } catch {
47461
47708
  try {
47462
- import_fs44.default.writeFileSync(ptPath, normalizedCwd, "utf8");
47709
+ import_fs45.default.writeFileSync(ptPath, normalizedCwd, "utf8");
47463
47710
  } catch {
47464
47711
  }
47465
47712
  return true;
47466
47713
  }
47467
47714
  }
47468
47715
  try {
47469
- import_fs44.default.mkdirSync(shadowDir, { recursive: true });
47716
+ import_fs45.default.mkdirSync(shadowDir, { recursive: true });
47470
47717
  } catch {
47471
47718
  }
47472
47719
  const init = (0, import_child_process6.spawnSync)("git", ["init", "--bare", shadowDir], { timeout: 5e3 });
@@ -47475,7 +47722,7 @@ function ensureShadowRepo(shadowDir, cwd) {
47475
47722
  if (process.env.NODE9_DEBUG === "1") console.error("[Node9] git init --bare failed:", reason);
47476
47723
  return false;
47477
47724
  }
47478
- const configFile = import_path42.default.join(shadowDir, "config");
47725
+ const configFile = import_path43.default.join(shadowDir, "config");
47479
47726
  (0, import_child_process6.spawnSync)("git", ["config", "--file", configFile, "core.untrackedCache", "true"], {
47480
47727
  timeout: 3e3
47481
47728
  });
@@ -47483,7 +47730,7 @@ function ensureShadowRepo(shadowDir, cwd) {
47483
47730
  timeout: 3e3
47484
47731
  });
47485
47732
  try {
47486
- import_fs44.default.writeFileSync(import_path42.default.join(shadowDir, "project-path.txt"), normalizedCwd, "utf8");
47733
+ import_fs45.default.writeFileSync(import_path43.default.join(shadowDir, "project-path.txt"), normalizedCwd, "utf8");
47487
47734
  } catch {
47488
47735
  }
47489
47736
  return true;
@@ -47506,12 +47753,12 @@ async function createShadowSnapshot(tool = "unknown", args = {}, ignorePaths = [
47506
47753
  let indexFile = null;
47507
47754
  try {
47508
47755
  const rawFilePath = extractFilePath(args);
47509
- const absFilePath = rawFilePath && import_path42.default.isAbsolute(rawFilePath) ? rawFilePath : null;
47756
+ const absFilePath = rawFilePath && import_path43.default.isAbsolute(rawFilePath) ? rawFilePath : null;
47510
47757
  const cwd = absFilePath ? findProjectRoot(absFilePath) : process.cwd();
47511
47758
  const shadowDir = getShadowRepoDir(cwd);
47512
47759
  if (!ensureShadowRepo(shadowDir, cwd)) return null;
47513
47760
  writeShadowExcludes(shadowDir, ignorePaths);
47514
- indexFile = import_path42.default.join(shadowDir, `index_${process.pid}_${Date.now()}`);
47761
+ indexFile = import_path43.default.join(shadowDir, `index_${process.pid}_${Date.now()}`);
47515
47762
  const shadowEnv = {
47516
47763
  ...process.env,
47517
47764
  GIT_DIR: shadowDir,
@@ -47583,7 +47830,7 @@ async function createShadowSnapshot(tool = "unknown", args = {}, ignorePaths = [
47583
47830
  writeStack(stack);
47584
47831
  const entry = stack[stack.length - 1];
47585
47832
  notifySnapshotTaken(commitHash.slice(0, 7), tool, entry.argsSummary, capturedFiles.length);
47586
- import_fs44.default.writeFileSync(UNDO_LATEST_PATH, commitHash);
47833
+ import_fs45.default.writeFileSync(UNDO_LATEST_PATH, commitHash);
47587
47834
  if (shouldGc) {
47588
47835
  (0, import_child_process6.spawn)("git", ["gc", "--auto"], { env: shadowEnv, detached: true, stdio: "ignore" }).unref();
47589
47836
  }
@@ -47594,7 +47841,7 @@ async function createShadowSnapshot(tool = "unknown", args = {}, ignorePaths = [
47594
47841
  } finally {
47595
47842
  if (indexFile) {
47596
47843
  try {
47597
- import_fs44.default.unlinkSync(indexFile);
47844
+ import_fs45.default.unlinkSync(indexFile);
47598
47845
  } catch {
47599
47846
  }
47600
47847
  }
@@ -47670,9 +47917,9 @@ function applyUndo(hash, cwd) {
47670
47917
  timeout: GIT_TIMEOUT
47671
47918
  }).stdout?.toString().trim().split("\n").filter(Boolean) ?? [];
47672
47919
  for (const file of [...tracked, ...untracked]) {
47673
- const fullPath = import_path42.default.join(dir, file);
47674
- if (!snapshotFiles.has(file) && import_fs44.default.existsSync(fullPath)) {
47675
- import_fs44.default.unlinkSync(fullPath);
47920
+ const fullPath = import_path43.default.join(dir, file);
47921
+ if (!snapshotFiles.has(file) && import_fs45.default.existsSync(fullPath)) {
47922
+ import_fs45.default.unlinkSync(fullPath);
47676
47923
  }
47677
47924
  }
47678
47925
  return true;
@@ -47682,12 +47929,12 @@ function applyUndo(hash, cwd) {
47682
47929
  }
47683
47930
 
47684
47931
  // src/skill-pin.ts
47685
- var import_fs45 = __toESM(require("fs"));
47686
- var import_path43 = __toESM(require("path"));
47932
+ var import_fs46 = __toESM(require("fs"));
47933
+ var import_path44 = __toESM(require("path"));
47687
47934
  var import_os41 = __toESM(require("os"));
47688
47935
  var import_crypto13 = __toESM(require("crypto"));
47689
47936
  function getPinsFilePath2() {
47690
- return import_path43.default.join(import_os41.default.homedir(), ".node9", "skill-pins.json");
47937
+ return import_path44.default.join(import_os41.default.homedir(), ".node9", "skill-pins.json");
47691
47938
  }
47692
47939
  var MAX_FILES = 5e3;
47693
47940
  var MAX_TOTAL_BYTES = 50 * 1024 * 1024;
@@ -47701,18 +47948,18 @@ function walkDir(root) {
47701
47948
  if (out.length >= MAX_FILES) return;
47702
47949
  let entries;
47703
47950
  try {
47704
- entries = import_fs45.default.readdirSync(dir, { withFileTypes: true });
47951
+ entries = import_fs46.default.readdirSync(dir, { withFileTypes: true });
47705
47952
  } catch {
47706
47953
  return;
47707
47954
  }
47708
47955
  entries.sort((a, b) => a.name.localeCompare(b.name));
47709
47956
  for (const entry of entries) {
47710
47957
  if (out.length >= MAX_FILES) return;
47711
- const full = import_path43.default.join(dir, entry.name);
47712
- const rel = relDir ? import_path43.default.posix.join(relDir, entry.name) : entry.name;
47958
+ const full = import_path44.default.join(dir, entry.name);
47959
+ const rel = relDir ? import_path44.default.posix.join(relDir, entry.name) : entry.name;
47713
47960
  let lst;
47714
47961
  try {
47715
- lst = import_fs45.default.lstatSync(full);
47962
+ lst = import_fs46.default.lstatSync(full);
47716
47963
  } catch {
47717
47964
  continue;
47718
47965
  }
@@ -47724,7 +47971,7 @@ function walkDir(root) {
47724
47971
  if (!lst.isFile()) continue;
47725
47972
  if (totalBytes + lst.size > MAX_TOTAL_BYTES) continue;
47726
47973
  try {
47727
- const buf = import_fs45.default.readFileSync(full);
47974
+ const buf = import_fs46.default.readFileSync(full);
47728
47975
  totalBytes += buf.length;
47729
47976
  out.push({ rel, hash: sha256Bytes(buf) });
47730
47977
  } catch {
@@ -47738,14 +47985,14 @@ function walkDir(root) {
47738
47985
  function hashSkillRoot(absPath) {
47739
47986
  let lst;
47740
47987
  try {
47741
- lst = import_fs45.default.lstatSync(absPath);
47988
+ lst = import_fs46.default.lstatSync(absPath);
47742
47989
  } catch {
47743
47990
  return { exists: false, contentHash: "", fileCount: 0 };
47744
47991
  }
47745
47992
  if (lst.isSymbolicLink()) return { exists: false, contentHash: "", fileCount: 0 };
47746
47993
  if (lst.isFile()) {
47747
47994
  try {
47748
- return { exists: true, contentHash: sha256Bytes(import_fs45.default.readFileSync(absPath)), fileCount: 1 };
47995
+ return { exists: true, contentHash: sha256Bytes(import_fs46.default.readFileSync(absPath)), fileCount: 1 };
47749
47996
  } catch {
47750
47997
  return { exists: false, contentHash: "", fileCount: 0 };
47751
47998
  }
@@ -47763,7 +48010,7 @@ function getRootKey(absPath) {
47763
48010
  function readSkillPinsSafe() {
47764
48011
  const filePath = getPinsFilePath2();
47765
48012
  try {
47766
- const raw = import_fs45.default.readFileSync(filePath, "utf-8");
48013
+ const raw = import_fs46.default.readFileSync(filePath, "utf-8");
47767
48014
  if (!raw.trim()) return { ok: false, reason: "corrupt", detail: "empty file" };
47768
48015
  const parsed = JSON.parse(raw);
47769
48016
  if (!parsed.roots || typeof parsed.roots !== "object" || Array.isArray(parsed.roots)) {
@@ -47783,10 +48030,10 @@ function readSkillPins() {
47783
48030
  }
47784
48031
  function writeSkillPins(data) {
47785
48032
  const filePath = getPinsFilePath2();
47786
- import_fs45.default.mkdirSync(import_path43.default.dirname(filePath), { recursive: true });
48033
+ import_fs46.default.mkdirSync(import_path44.default.dirname(filePath), { recursive: true });
47787
48034
  const tmp = `${filePath}.${import_crypto13.default.randomBytes(6).toString("hex")}.tmp`;
47788
- import_fs45.default.writeFileSync(tmp, JSON.stringify(data, null, 2), { mode: 384 });
47789
- import_fs45.default.renameSync(tmp, filePath);
48035
+ import_fs46.default.writeFileSync(tmp, JSON.stringify(data, null, 2), { mode: 384 });
48036
+ import_fs46.default.renameSync(tmp, filePath);
47790
48037
  }
47791
48038
  function removePin2(rootKey) {
47792
48039
  const pins = readSkillPins();
@@ -47830,36 +48077,36 @@ function verifyAndPinRoots(roots) {
47830
48077
  return { kind: "verified" };
47831
48078
  }
47832
48079
  function defaultSkillRoots(_cwd) {
47833
- const marketplaces = import_path43.default.join(import_os41.default.homedir(), ".claude", "plugins", "marketplaces");
48080
+ const marketplaces = import_path44.default.join(import_os41.default.homedir(), ".claude", "plugins", "marketplaces");
47834
48081
  const roots = [];
47835
48082
  let registries;
47836
48083
  try {
47837
- registries = import_fs45.default.readdirSync(marketplaces, { withFileTypes: true });
48084
+ registries = import_fs46.default.readdirSync(marketplaces, { withFileTypes: true });
47838
48085
  } catch {
47839
48086
  return [];
47840
48087
  }
47841
48088
  for (const registry of registries) {
47842
48089
  if (!registry.isDirectory()) continue;
47843
- const pluginsDir = import_path43.default.join(marketplaces, registry.name, "plugins");
48090
+ const pluginsDir = import_path44.default.join(marketplaces, registry.name, "plugins");
47844
48091
  let plugins;
47845
48092
  try {
47846
- plugins = import_fs45.default.readdirSync(pluginsDir, { withFileTypes: true });
48093
+ plugins = import_fs46.default.readdirSync(pluginsDir, { withFileTypes: true });
47847
48094
  } catch {
47848
48095
  continue;
47849
48096
  }
47850
48097
  for (const plugin of plugins) {
47851
48098
  if (!plugin.isDirectory()) continue;
47852
- roots.push(import_path43.default.join(pluginsDir, plugin.name));
48099
+ roots.push(import_path44.default.join(pluginsDir, plugin.name));
47853
48100
  }
47854
48101
  }
47855
48102
  return roots;
47856
48103
  }
47857
48104
  function resolveUserSkillRoot(entry, cwd) {
47858
48105
  if (!entry) return null;
47859
- if (entry.startsWith("~/") || entry === "~") return import_path43.default.join(import_os41.default.homedir(), entry.slice(1));
47860
- if (import_path43.default.isAbsolute(entry)) return entry;
47861
- if (!cwd || !import_path43.default.isAbsolute(cwd)) return null;
47862
- return import_path43.default.join(cwd, entry);
48106
+ if (entry.startsWith("~/") || entry === "~") return import_path44.default.join(import_os41.default.homedir(), entry.slice(1));
48107
+ if (import_path44.default.isAbsolute(entry)) return entry;
48108
+ if (!cwd || !import_path44.default.isAbsolute(cwd)) return null;
48109
+ return import_path44.default.join(cwd, entry);
47863
48110
  }
47864
48111
 
47865
48112
  // src/cli/commands/check.ts
@@ -47867,12 +48114,12 @@ init_dlp();
47867
48114
  init_audit();
47868
48115
 
47869
48116
  // src/review-pending.ts
47870
- var import_fs46 = __toESM(require("fs"));
48117
+ var import_fs47 = __toESM(require("fs"));
47871
48118
  var import_os42 = __toESM(require("os"));
47872
- var import_path44 = __toESM(require("path"));
48119
+ var import_path45 = __toESM(require("path"));
47873
48120
  init_hasher();
47874
48121
  function storePath() {
47875
- return process.env.NODE9_PENDING_STORE || import_path44.default.join(import_os42.default.homedir(), ".node9", "pending-reviews.json");
48122
+ return process.env.NODE9_PENDING_STORE || import_path45.default.join(import_os42.default.homedir(), ".node9", "pending-reviews.json");
47876
48123
  }
47877
48124
  var TTL_MS2 = 6 * 60 * 60 * 1e3;
47878
48125
  var MAX_ENTRIES = 500;
@@ -47889,7 +48136,7 @@ function reviewCorrelationKey(payload) {
47889
48136
  }
47890
48137
  function read() {
47891
48138
  try {
47892
- const parsed = JSON.parse(import_fs46.default.readFileSync(storePath(), "utf-8"));
48139
+ const parsed = JSON.parse(import_fs47.default.readFileSync(storePath(), "utf-8"));
47893
48140
  if (parsed && Array.isArray(parsed.entries)) return parsed;
47894
48141
  } catch {
47895
48142
  }
@@ -47898,11 +48145,11 @@ function read() {
47898
48145
  function write(store) {
47899
48146
  try {
47900
48147
  const p = storePath();
47901
- const dir = import_path44.default.dirname(p);
47902
- if (!import_fs46.default.existsSync(dir)) import_fs46.default.mkdirSync(dir, { recursive: true });
48148
+ const dir = import_path45.default.dirname(p);
48149
+ if (!import_fs47.default.existsSync(dir)) import_fs47.default.mkdirSync(dir, { recursive: true });
47903
48150
  const tmp = `${p}.${process.pid}.tmp`;
47904
- import_fs46.default.writeFileSync(tmp, JSON.stringify(store));
47905
- import_fs46.default.renameSync(tmp, p);
48151
+ import_fs47.default.writeFileSync(tmp, JSON.stringify(store));
48152
+ import_fs47.default.renameSync(tmp, p);
47906
48153
  } catch {
47907
48154
  }
47908
48155
  }
@@ -48015,9 +48262,9 @@ function registerCheckCommand(program2) {
48015
48262
  } catch (err2) {
48016
48263
  const tempConfig = getConfig();
48017
48264
  if (process.env.NODE9_DEBUG === "1" || tempConfig.settings.enableHookLogDebug) {
48018
- const logPath = import_path45.default.join(import_os43.default.homedir(), ".node9", "hook-debug.log");
48265
+ const logPath = import_path46.default.join(import_os43.default.homedir(), ".node9", "hook-debug.log");
48019
48266
  const errMsg = err2 instanceof Error ? err2.message : String(err2);
48020
- import_fs47.default.appendFileSync(
48267
+ import_fs48.default.appendFileSync(
48021
48268
  logPath,
48022
48269
  `[${(/* @__PURE__ */ new Date()).toISOString()}] JSON_PARSE_ERROR: ${errMsg}
48023
48270
  RAW: ${raw}
@@ -48030,14 +48277,14 @@ RAW: ${raw}
48030
48277
  const prompt = typeof payload.prompt === "string" ? payload.prompt : "";
48031
48278
  if (process.env.NODE9_DEBUG === "1") {
48032
48279
  try {
48033
- const logPath = import_path45.default.join(import_os43.default.homedir(), ".node9", "hook-debug.log");
48034
- if (!import_fs47.default.existsSync(import_path45.default.dirname(logPath)))
48035
- import_fs47.default.mkdirSync(import_path45.default.dirname(logPath), { recursive: true });
48280
+ const logPath = import_path46.default.join(import_os43.default.homedir(), ".node9", "hook-debug.log");
48281
+ if (!import_fs48.default.existsSync(import_path46.default.dirname(logPath)))
48282
+ import_fs48.default.mkdirSync(import_path46.default.dirname(logPath), { recursive: true });
48036
48283
  const sanitized = JSON.stringify({
48037
48284
  ...payload,
48038
48285
  prompt: `<redacted, ${prompt.length} bytes>`
48039
48286
  });
48040
- import_fs47.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] STDIN: ${sanitized}
48287
+ import_fs48.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] STDIN: ${sanitized}
48041
48288
  `);
48042
48289
  } catch {
48043
48290
  }
@@ -48058,8 +48305,8 @@ RAW: ${raw}
48058
48305
  );
48059
48306
  const reason = `\u{1F6A8} Node9 DLP: ${dlpMatch.patternName} detected in prompt (${dlpMatch.redactedSample}). Prompt was not submitted \u2014 remove the credential and try again.`;
48060
48307
  try {
48061
- const ttyFd = import_fs47.default.openSync("/dev/tty", "w");
48062
- import_fs47.default.writeSync(
48308
+ const ttyFd = import_fs48.default.openSync("/dev/tty", "w");
48309
+ import_fs48.default.writeSync(
48063
48310
  ttyFd,
48064
48311
  import_chalk9.default.bgRed.white.bold(`
48065
48312
  \u{1F6A8} NODE9 DLP \u2014 PROMPT BLOCKED
@@ -48069,7 +48316,7 @@ RAW: ${raw}
48069
48316
 
48070
48317
  `)
48071
48318
  );
48072
- import_fs47.default.closeSync(ttyFd);
48319
+ import_fs48.default.closeSync(ttyFd);
48073
48320
  } catch {
48074
48321
  }
48075
48322
  const isCodex = agent2 === "Codex";
@@ -48088,17 +48335,17 @@ RAW: ${raw}
48088
48335
  process.exit(2);
48089
48336
  }
48090
48337
  const payloadCwd = typeof payload.cwd === "string" ? payload.cwd : Array.isArray(payload.workspacePaths) && typeof payload.workspacePaths[0] === "string" ? payload.workspacePaths[0] : void 0;
48091
- const safeCwdForConfig = typeof payloadCwd === "string" && import_path45.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
48338
+ const safeCwdForConfig = typeof payloadCwd === "string" && import_path46.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
48092
48339
  const config = getConfig(safeCwdForConfig);
48093
48340
  const daemonDown = !isDaemonRunning();
48094
48341
  if (config.settings.autoStartDaemon && daemonDown && !process.env.NODE9_NO_AUTO_DAEMON) {
48095
48342
  try {
48096
48343
  const scriptPath = process.argv[1];
48097
- if (typeof scriptPath !== "string" || !import_path45.default.isAbsolute(scriptPath))
48344
+ if (typeof scriptPath !== "string" || !import_path46.default.isAbsolute(scriptPath))
48098
48345
  throw new Error("node9: argv[1] is not an absolute path");
48099
- const resolvedScript = import_fs47.default.realpathSync(scriptPath);
48100
- const packageDist = import_fs47.default.realpathSync(import_path45.default.resolve(__dirname, "../.."));
48101
- if (!resolvedScript.startsWith(packageDist + import_path45.default.sep) && resolvedScript !== packageDist)
48346
+ const resolvedScript = import_fs48.default.realpathSync(scriptPath);
48347
+ const packageDist = import_fs48.default.realpathSync(import_path46.default.resolve(__dirname, "../.."));
48348
+ if (!resolvedScript.startsWith(packageDist + import_path46.default.sep) && resolvedScript !== packageDist)
48102
48349
  throw new Error(
48103
48350
  `node9: daemon spawn aborted \u2014 argv[1] (${resolvedScript}) is outside package dist (${packageDist})`
48104
48351
  );
@@ -48128,17 +48375,17 @@ RAW: ${raw}
48128
48375
  } finally {
48129
48376
  if (startupFd !== void 0) {
48130
48377
  try {
48131
- import_fs47.default.closeSync(startupFd);
48378
+ import_fs48.default.closeSync(startupFd);
48132
48379
  } catch {
48133
48380
  }
48134
48381
  }
48135
48382
  }
48136
48383
  } catch (spawnErr) {
48137
- const logPath = import_path45.default.join(import_os43.default.homedir(), ".node9", "hook-debug.log");
48384
+ const logPath = import_path46.default.join(import_os43.default.homedir(), ".node9", "hook-debug.log");
48138
48385
  const msg = spawnErr instanceof Error ? spawnErr.message : String(spawnErr);
48139
48386
  recordStartupState("failed", "spawn-aborted", msg);
48140
48387
  try {
48141
- import_fs47.default.appendFileSync(
48388
+ import_fs48.default.appendFileSync(
48142
48389
  logPath,
48143
48390
  `[${(/* @__PURE__ */ new Date()).toISOString()}] daemon-autostart-failed: ${msg}
48144
48391
  `
@@ -48152,10 +48399,10 @@ RAW: ${raw}
48152
48399
  );
48153
48400
  }
48154
48401
  if (process.env.NODE9_DEBUG === "1" || config.settings.enableHookLogDebug) {
48155
- const logPath = import_path45.default.join(import_os43.default.homedir(), ".node9", "hook-debug.log");
48156
- if (!import_fs47.default.existsSync(import_path45.default.dirname(logPath)))
48157
- import_fs47.default.mkdirSync(import_path45.default.dirname(logPath), { recursive: true });
48158
- import_fs47.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] STDIN: ${raw}
48402
+ const logPath = import_path46.default.join(import_os43.default.homedir(), ".node9", "hook-debug.log");
48403
+ if (!import_fs48.default.existsSync(import_path46.default.dirname(logPath)))
48404
+ import_fs48.default.mkdirSync(import_path46.default.dirname(logPath), { recursive: true });
48405
+ import_fs48.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] STDIN: ${raw}
48159
48406
  `);
48160
48407
  }
48161
48408
  const rawToolName = sanitize2(extractToolName(payload));
@@ -48169,8 +48416,8 @@ RAW: ${raw}
48169
48416
  const isHumanDecision = blockedByContext.toLowerCase().includes("user") || blockedByContext.toLowerCase().includes("daemon") || blockedByContext.toLowerCase().includes("decision");
48170
48417
  let ttyFd = null;
48171
48418
  try {
48172
- ttyFd = import_fs47.default.openSync("/dev/tty", "w");
48173
- const writeTty = (line) => import_fs47.default.writeSync(ttyFd, line + "\n");
48419
+ ttyFd = import_fs48.default.openSync("/dev/tty", "w");
48420
+ const writeTty = (line) => import_fs48.default.writeSync(ttyFd, line + "\n");
48174
48421
  if (blockedByContext.includes("DLP") || blockedByContext.includes("Secret Detected") || blockedByContext.includes("Credential Review")) {
48175
48422
  writeTty(import_chalk9.default.bgRed.white.bold(`
48176
48423
  \u{1F6A8} NODE9 DLP ALERT \u2014 CREDENTIAL DETECTED `));
@@ -48189,7 +48436,7 @@ RAW: ${raw}
48189
48436
  } finally {
48190
48437
  if (ttyFd !== null)
48191
48438
  try {
48192
- import_fs47.default.closeSync(ttyFd);
48439
+ import_fs48.default.closeSync(ttyFd);
48193
48440
  } catch {
48194
48441
  }
48195
48442
  }
@@ -48246,8 +48493,8 @@ RAW: ${raw}
48246
48493
  } catch {
48247
48494
  }
48248
48495
  try {
48249
- const ttyFd = import_fs47.default.openSync("/dev/tty", "w");
48250
- import_fs47.default.writeSync(
48496
+ const ttyFd = import_fs48.default.openSync("/dev/tty", "w");
48497
+ import_fs48.default.writeSync(
48251
48498
  ttyFd,
48252
48499
  import_chalk9.default.yellow(
48253
48500
  `
@@ -48255,7 +48502,7 @@ RAW: ${raw}
48255
48502
  `
48256
48503
  )
48257
48504
  );
48258
- import_fs47.default.closeSync(ttyFd);
48505
+ import_fs48.default.closeSync(ttyFd);
48259
48506
  } catch {
48260
48507
  }
48261
48508
  if (agent === "GitHub Copilot") {
@@ -48287,17 +48534,17 @@ RAW: ${raw}
48287
48534
  const safeSessionId = /^[A-Za-z0-9_\-]{1,128}$/.test(rawSessionId) ? rawSessionId : "";
48288
48535
  if (skillPinCfg.enabled && safeSessionId) {
48289
48536
  try {
48290
- const sessionsDir = import_path45.default.join(import_os43.default.homedir(), ".node9", "skill-sessions");
48291
- const flagPath = import_path45.default.join(sessionsDir, `${safeSessionId}.json`);
48537
+ const sessionsDir = import_path46.default.join(import_os43.default.homedir(), ".node9", "skill-sessions");
48538
+ const flagPath = import_path46.default.join(sessionsDir, `${safeSessionId}.json`);
48292
48539
  let flag = null;
48293
48540
  try {
48294
- flag = JSON.parse(import_fs47.default.readFileSync(flagPath, "utf-8"));
48541
+ flag = JSON.parse(import_fs48.default.readFileSync(flagPath, "utf-8"));
48295
48542
  } catch {
48296
48543
  }
48297
48544
  const writeFlag = (data2) => {
48298
48545
  try {
48299
- import_fs47.default.mkdirSync(sessionsDir, { recursive: true });
48300
- import_fs47.default.writeFileSync(
48546
+ import_fs48.default.mkdirSync(sessionsDir, { recursive: true });
48547
+ import_fs48.default.writeFileSync(
48301
48548
  flagPath,
48302
48549
  JSON.stringify({ ...data2, timestamp: (/* @__PURE__ */ new Date()).toISOString() }, null, 2),
48303
48550
  { mode: 384 }
@@ -48308,8 +48555,8 @@ RAW: ${raw}
48308
48555
  const sendSkillWarn = (detail, recoveryCmd) => {
48309
48556
  let ttyFd = null;
48310
48557
  try {
48311
- ttyFd = import_fs47.default.openSync("/dev/tty", "w");
48312
- const w = (line) => import_fs47.default.writeSync(ttyFd, line + "\n");
48558
+ ttyFd = import_fs48.default.openSync("/dev/tty", "w");
48559
+ const w = (line) => import_fs48.default.writeSync(ttyFd, line + "\n");
48313
48560
  w(import_chalk9.default.yellow(`
48314
48561
  \u26A0\uFE0F Node9: installed skill drift detected`));
48315
48562
  w(import_chalk9.default.gray(` ${detail}`));
@@ -48324,7 +48571,7 @@ RAW: ${raw}
48324
48571
  } finally {
48325
48572
  if (ttyFd !== null)
48326
48573
  try {
48327
- import_fs47.default.closeSync(ttyFd);
48574
+ import_fs48.default.closeSync(ttyFd);
48328
48575
  } catch {
48329
48576
  }
48330
48577
  }
@@ -48340,7 +48587,7 @@ RAW: ${raw}
48340
48587
  return;
48341
48588
  }
48342
48589
  if (!flag || flag.state !== "verified" && flag.state !== "warned") {
48343
- const absoluteCwd = typeof payloadCwd === "string" && import_path45.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
48590
+ const absoluteCwd = typeof payloadCwd === "string" && import_path46.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
48344
48591
  const extraRoots = skillPinCfg.roots;
48345
48592
  const resolvedExtra = extraRoots.map((r) => resolveUserSkillRoot(r, absoluteCwd)).filter((r) => typeof r === "string");
48346
48593
  const roots = [...defaultSkillRoots(absoluteCwd), ...resolvedExtra];
@@ -48381,10 +48628,10 @@ RAW: ${raw}
48381
48628
  }
48382
48629
  try {
48383
48630
  const cutoff = Date.now() - 7 * 24 * 60 * 60 * 1e3;
48384
- for (const name of import_fs47.default.readdirSync(sessionsDir)) {
48385
- const p = import_path45.default.join(sessionsDir, name);
48631
+ for (const name of import_fs48.default.readdirSync(sessionsDir)) {
48632
+ const p = import_path46.default.join(sessionsDir, name);
48386
48633
  try {
48387
- if (import_fs47.default.statSync(p).mtimeMs < cutoff) import_fs47.default.unlinkSync(p);
48634
+ if (import_fs48.default.statSync(p).mtimeMs < cutoff) import_fs48.default.unlinkSync(p);
48388
48635
  } catch {
48389
48636
  }
48390
48637
  }
@@ -48394,9 +48641,9 @@ RAW: ${raw}
48394
48641
  } catch (err2) {
48395
48642
  if (process.env.NODE9_DEBUG === "1") {
48396
48643
  try {
48397
- const dbg = import_path45.default.join(import_os43.default.homedir(), ".node9", "hook-debug.log");
48644
+ const dbg = import_path46.default.join(import_os43.default.homedir(), ".node9", "hook-debug.log");
48398
48645
  const msg = err2 instanceof Error ? err2.message : String(err2);
48399
- import_fs47.default.appendFileSync(dbg, `[${(/* @__PURE__ */ new Date()).toISOString()}] SKILL_PIN_ERROR: ${msg}
48646
+ import_fs48.default.appendFileSync(dbg, `[${(/* @__PURE__ */ new Date()).toISOString()}] SKILL_PIN_ERROR: ${msg}
48400
48647
  `);
48401
48648
  } catch {
48402
48649
  }
@@ -48406,7 +48653,7 @@ RAW: ${raw}
48406
48653
  if (shouldSnapshot(toolName, toolInput, config)) {
48407
48654
  await createShadowSnapshot(toolName, toolInput, config.policy.snapshot.ignorePaths);
48408
48655
  }
48409
- const safeCwdForAuth = typeof payloadCwd === "string" && import_path45.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
48656
+ const safeCwdForAuth = typeof payloadCwd === "string" && import_path46.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
48410
48657
  const askMode = resolveAskMode(agent, opts, config);
48411
48658
  const result = await authorizeHeadless(toolName, toolInput, meta, {
48412
48659
  cwd: safeCwdForAuth,
@@ -48424,12 +48671,12 @@ RAW: ${raw}
48424
48671
  }
48425
48672
  if (result.noApprovalMechanism && !isDaemonRunning() && !process.env.NODE9_NO_AUTO_DAEMON && !process.stdout.isTTY && config.settings.autoStartDaemon) {
48426
48673
  try {
48427
- const tty = import_fs47.default.openSync("/dev/tty", "w");
48428
- import_fs47.default.writeSync(
48674
+ const tty = import_fs48.default.openSync("/dev/tty", "w");
48675
+ import_fs48.default.writeSync(
48429
48676
  tty,
48430
48677
  import_chalk9.default.cyan("\n\u{1F6E1}\uFE0F Node9: Starting approval daemon automatically...\n")
48431
48678
  );
48432
- import_fs47.default.closeSync(tty);
48679
+ import_fs48.default.closeSync(tty);
48433
48680
  } catch {
48434
48681
  }
48435
48682
  const daemonReady = await autoStartDaemonAndWait();
@@ -48456,9 +48703,9 @@ RAW: ${raw}
48456
48703
  });
48457
48704
  } catch (err2) {
48458
48705
  if (process.env.NODE9_DEBUG === "1") {
48459
- const logPath = import_path45.default.join(import_os43.default.homedir(), ".node9", "hook-debug.log");
48706
+ const logPath = import_path46.default.join(import_os43.default.homedir(), ".node9", "hook-debug.log");
48460
48707
  const errMsg = err2 instanceof Error ? err2.message : String(err2);
48461
- import_fs47.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] ERROR: ${errMsg}
48708
+ import_fs48.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] ERROR: ${errMsg}
48462
48709
  `);
48463
48710
  }
48464
48711
  process.exit(0);
@@ -48492,8 +48739,8 @@ RAW: ${raw}
48492
48739
  }
48493
48740
 
48494
48741
  // src/cli/commands/log.ts
48495
- var import_fs48 = __toESM(require("fs"));
48496
- var import_path46 = __toESM(require("path"));
48742
+ var import_fs49 = __toESM(require("fs"));
48743
+ var import_path47 = __toESM(require("path"));
48497
48744
  var import_os44 = __toESM(require("os"));
48498
48745
  init_audit();
48499
48746
  init_config();
@@ -48604,10 +48851,10 @@ function registerLogCommand(program2) {
48604
48851
  if (rawToolName !== tool) entry.agentToolName = rawToolName;
48605
48852
  const payloadSessionId = payload.session_id ?? payload.conversationId;
48606
48853
  if (payloadSessionId) entry.sessionId = payloadSessionId;
48607
- const logPath = import_path46.default.join(import_os44.default.homedir(), ".node9", "audit.log");
48608
- if (!import_fs48.default.existsSync(import_path46.default.dirname(logPath)))
48609
- import_fs48.default.mkdirSync(import_path46.default.dirname(logPath), { recursive: true });
48610
- import_fs48.default.appendFileSync(logPath, JSON.stringify(entry) + "\n");
48854
+ const logPath = import_path47.default.join(import_os44.default.homedir(), ".node9", "audit.log");
48855
+ if (!import_fs49.default.existsSync(import_path47.default.dirname(logPath)))
48856
+ import_fs49.default.mkdirSync(import_path47.default.dirname(logPath), { recursive: true });
48857
+ import_fs49.default.appendFileSync(logPath, JSON.stringify(entry) + "\n");
48611
48858
  if ((tool === "Bash" || tool === "bash") && isDaemonRunning()) {
48612
48859
  const command = typeof rawInput === "object" && rawInput !== null && "command" in rawInput && typeof rawInput.command === "string" ? rawInput.command : null;
48613
48860
  if (command) {
@@ -48641,7 +48888,7 @@ function registerLogCommand(program2) {
48641
48888
  }
48642
48889
  }
48643
48890
  const payloadCwd = typeof payload.cwd === "string" ? payload.cwd : Array.isArray(payload.workspacePaths) && typeof payload.workspacePaths[0] === "string" ? payload.workspacePaths[0] : void 0;
48644
- const safeCwd = typeof payloadCwd === "string" && import_path46.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
48891
+ const safeCwd = typeof payloadCwd === "string" && import_path47.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
48645
48892
  const config = getConfig(safeCwd);
48646
48893
  {
48647
48894
  const toolOutput = payload.tool_response?.output;
@@ -48718,9 +48965,9 @@ function registerLogCommand(program2) {
48718
48965
  const msg = err2 instanceof Error ? err2.message : String(err2);
48719
48966
  process.stderr.write(`[Node9] audit log error: ${msg}
48720
48967
  `);
48721
- const debugPath = import_path46.default.join(import_os44.default.homedir(), ".node9", "hook-debug.log");
48968
+ const debugPath = import_path47.default.join(import_os44.default.homedir(), ".node9", "hook-debug.log");
48722
48969
  try {
48723
- import_fs48.default.appendFileSync(debugPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] LOG_ERROR: ${msg}
48970
+ import_fs49.default.appendFileSync(debugPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] LOG_ERROR: ${msg}
48724
48971
  `);
48725
48972
  } catch {
48726
48973
  }
@@ -48745,15 +48992,15 @@ function registerLogCommand(program2) {
48745
48992
 
48746
48993
  // src/cli/commands/shield.ts
48747
48994
  var import_chalk10 = __toESM(require("chalk"));
48748
- var import_fs50 = __toESM(require("fs"));
48749
- var import_path48 = __toESM(require("path"));
48995
+ var import_fs51 = __toESM(require("fs"));
48996
+ var import_path49 = __toESM(require("path"));
48750
48997
  var import_os45 = __toESM(require("os"));
48751
48998
  init_shields();
48752
48999
  init_build();
48753
49000
 
48754
49001
  // src/shields/create.ts
48755
- var import_fs49 = __toESM(require("fs"));
48756
- var import_path47 = __toESM(require("path"));
49002
+ var import_fs50 = __toESM(require("fs"));
49003
+ var import_path48 = __toESM(require("path"));
48757
49004
  init_dist();
48758
49005
  init_shields();
48759
49006
  init_audit();
@@ -48773,8 +49020,8 @@ function createShield(def, opts = {}) {
48773
49020
  error: `"${name}" is a built-in shield \u2014 choose a different name (a user shield with this name would shadow the built-in).`
48774
49021
  };
48775
49022
  }
48776
- const filePath = import_path47.default.join(USER_SHIELDS_DIR_PATH, `${name}.json`);
48777
- if (!opts.overwrite && import_fs49.default.existsSync(filePath)) {
49023
+ const filePath = import_path48.default.join(USER_SHIELDS_DIR_PATH, `${name}.json`);
49024
+ if (!opts.overwrite && import_fs50.default.existsSync(filePath)) {
48778
49025
  return {
48779
49026
  ok: false,
48780
49027
  error: `Shield "${name}" already exists at ${filePath}. Pass --overwrite to replace it.`
@@ -48839,8 +49086,8 @@ var COMMUNITY_INDEX_URL = "https://raw.githubusercontent.com/node9ai/node9-proxy
48839
49086
  function readCloudShields() {
48840
49087
  const out = /* @__PURE__ */ new Set();
48841
49088
  try {
48842
- const file = import_path48.default.join(import_os45.default.homedir(), ".node9", "rules-cache.json");
48843
- const raw = JSON.parse(import_fs50.default.readFileSync(file, "utf-8"));
49089
+ const file = import_path49.default.join(import_os45.default.homedir(), ".node9", "rules-cache.json");
49090
+ const raw = JSON.parse(import_fs51.default.readFileSync(file, "utf-8"));
48844
49091
  for (const r of raw.rules ?? []) {
48845
49092
  const rule = r;
48846
49093
  const fromSource = rule.source?.startsWith("SHIELD:") ? rule.source.slice("SHIELD:".length).toLowerCase() : void 0;
@@ -49157,7 +49404,7 @@ function registerShieldCommand(program2) {
49157
49404
  if (opts.fromFile) {
49158
49405
  let raw;
49159
49406
  try {
49160
- raw = JSON.parse(import_fs50.default.readFileSync(opts.fromFile, "utf-8"));
49407
+ raw = JSON.parse(import_fs51.default.readFileSync(opts.fromFile, "utf-8"));
49161
49408
  } catch (err2) {
49162
49409
  console.error(
49163
49410
  import_chalk10.default.red(`
@@ -49277,11 +49524,12 @@ function registerConfigShowCommand(program2) {
49277
49524
 
49278
49525
  // src/cli/commands/doctor.ts
49279
49526
  var import_chalk11 = __toESM(require("chalk"));
49280
- var import_fs51 = __toESM(require("fs"));
49281
- var import_path49 = __toESM(require("path"));
49527
+ var import_fs52 = __toESM(require("fs"));
49528
+ var import_path50 = __toESM(require("path"));
49282
49529
  var import_os46 = __toESM(require("os"));
49283
49530
  var import_child_process8 = require("child_process");
49284
49531
  init_daemon();
49532
+ init_build_id();
49285
49533
  init_config();
49286
49534
  init_agent_wiring();
49287
49535
  init_sync();
@@ -49350,10 +49598,10 @@ function registerDoctorCommand(program2, version2) {
49350
49598
  );
49351
49599
  }
49352
49600
  section("Configuration");
49353
- const globalConfigPath = import_path49.default.join(homeDir2, ".node9", "config.json");
49354
- if (import_fs51.default.existsSync(globalConfigPath)) {
49601
+ const globalConfigPath = import_path50.default.join(homeDir2, ".node9", "config.json");
49602
+ if (import_fs52.default.existsSync(globalConfigPath)) {
49355
49603
  try {
49356
- JSON.parse(import_fs51.default.readFileSync(globalConfigPath, "utf-8"));
49604
+ JSON.parse(import_fs52.default.readFileSync(globalConfigPath, "utf-8"));
49357
49605
  pass("~/.node9/config.json found and valid");
49358
49606
  } catch {
49359
49607
  fail("~/.node9/config.json is invalid JSON", "Run: node9 init --force");
@@ -49361,10 +49609,10 @@ function registerDoctorCommand(program2, version2) {
49361
49609
  } else {
49362
49610
  warn("~/.node9/config.json not found (using defaults)", "Run: node9 init");
49363
49611
  }
49364
- const projectConfigPath = import_path49.default.join(process.cwd(), "node9.config.json");
49365
- if (import_fs51.default.existsSync(projectConfigPath)) {
49612
+ const projectConfigPath = import_path50.default.join(process.cwd(), "node9.config.json");
49613
+ if (import_fs52.default.existsSync(projectConfigPath)) {
49366
49614
  try {
49367
- JSON.parse(import_fs51.default.readFileSync(projectConfigPath, "utf-8"));
49615
+ JSON.parse(import_fs52.default.readFileSync(projectConfigPath, "utf-8"));
49368
49616
  pass("node9.config.json found and valid (project)");
49369
49617
  } catch {
49370
49618
  fail(
@@ -49373,8 +49621,8 @@ function registerDoctorCommand(program2, version2) {
49373
49621
  );
49374
49622
  }
49375
49623
  }
49376
- const credsPath = import_path49.default.join(homeDir2, ".node9", "credentials.json");
49377
- if (import_fs51.default.existsSync(credsPath)) {
49624
+ const credsPath = import_path50.default.join(homeDir2, ".node9", "credentials.json");
49625
+ if (import_fs52.default.existsSync(credsPath)) {
49378
49626
  pass("Cloud credentials found (~/.node9/credentials.json)");
49379
49627
  } else {
49380
49628
  warn(
@@ -49408,6 +49656,17 @@ function registerDoctorCommand(program2, version2) {
49408
49656
  pass(
49409
49657
  `Daemon running on ${DAEMON_HOST}:${DAEMON_PORT} \u2014 terminal & native approvals enabled`
49410
49658
  );
49659
+ const probe = await probeDaemonHealth();
49660
+ const drift = describeBuildDrift(
49661
+ probe.kind === "health" ? probe.health : probe.kind === "no-health" ? "no-health" : null,
49662
+ CURRENT_BUILD
49663
+ );
49664
+ if (drift) {
49665
+ warn(
49666
+ drift,
49667
+ "Stop the running daemon (pid in ~/.node9/daemon.pid), then: node9 daemon --background"
49668
+ );
49669
+ }
49411
49670
  } else {
49412
49671
  warn(
49413
49672
  "Daemon not running \u2014 terminal & native approvals unavailable",
@@ -49429,7 +49688,7 @@ function registerDoctorCommand(program2, version2) {
49429
49688
  cloudEnabled: !!getConfig().settings.approvers?.cloud
49430
49689
  });
49431
49690
  if (autostart) warn(autostart.message, autostart.hint);
49432
- if (import_fs51.default.existsSync(import_path49.default.join(import_os46.default.homedir(), ".node9", "credentials.json")) && getConfig().settings.approvers?.cloud) {
49691
+ if (import_fs52.default.existsSync(import_path50.default.join(import_os46.default.homedir(), ".node9", "credentials.json")) && getConfig().settings.approvers?.cloud) {
49433
49692
  section("Policy sync");
49434
49693
  const health = readSyncHealth();
49435
49694
  if (isPolicyStale(Date.now(), health)) {
@@ -49447,7 +49706,7 @@ function registerDoctorCommand(program2, version2) {
49447
49706
  try {
49448
49707
  const { shipLagBytes: shipLagBytes2, readWatermark: readWatermark2, AUDIT_SHIP_WATERMARK: AUDIT_SHIP_WATERMARK2 } = await Promise.resolve().then(() => (init_audit_shipper(), audit_shipper_exports));
49449
49708
  const cfg = getConfig();
49450
- const creds = import_fs51.default.existsSync(import_path49.default.join(import_os46.default.homedir(), ".node9", "credentials.json"));
49709
+ const creds = import_fs52.default.existsSync(import_path50.default.join(import_os46.default.homedir(), ".node9", "credentials.json"));
49451
49710
  if (!creds) {
49452
49711
  warn("Not logged in \u2014 audit rows stay local", "Run: node9 login <api-key>");
49453
49712
  } else if (!cfg.settings.approvers.cloud) {
@@ -49497,8 +49756,8 @@ function registerDoctorCommand(program2, version2) {
49497
49756
 
49498
49757
  // src/cli/commands/audit.ts
49499
49758
  var import_chalk12 = __toESM(require("chalk"));
49500
- var import_fs52 = __toESM(require("fs"));
49501
- var import_path50 = __toESM(require("path"));
49759
+ var import_fs53 = __toESM(require("fs"));
49760
+ var import_path51 = __toESM(require("path"));
49502
49761
  init_decision();
49503
49762
  var import_os47 = __toESM(require("os"));
49504
49763
  function formatRelativeTime(timestamp) {
@@ -49513,14 +49772,14 @@ function formatRelativeTime(timestamp) {
49513
49772
  }
49514
49773
  function registerAuditCommand(program2) {
49515
49774
  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) => {
49516
- const logPath = import_path50.default.join(import_os47.default.homedir(), ".node9", "audit.log");
49517
- if (!import_fs52.default.existsSync(logPath)) {
49775
+ const logPath = import_path51.default.join(import_os47.default.homedir(), ".node9", "audit.log");
49776
+ if (!import_fs53.default.existsSync(logPath)) {
49518
49777
  console.log(
49519
49778
  import_chalk12.default.yellow("No audit logs found. Run node9 with an agent to generate entries.")
49520
49779
  );
49521
49780
  return;
49522
49781
  }
49523
- const raw = import_fs52.default.readFileSync(logPath, "utf-8");
49782
+ const raw = import_fs53.default.readFileSync(logPath, "utf-8");
49524
49783
  const lines = raw.split("\n").filter((l) => l.trim() !== "");
49525
49784
  let entries = lines.flatMap((line) => {
49526
49785
  try {
@@ -49582,9 +49841,9 @@ function registerAuditCommand(program2) {
49582
49841
  var import_chalk13 = __toESM(require("chalk"));
49583
49842
 
49584
49843
  // src/cli/aggregate/report-audit.ts
49585
- var import_fs53 = __toESM(require("fs"));
49844
+ var import_fs54 = __toESM(require("fs"));
49586
49845
  var import_os48 = __toESM(require("os"));
49587
- var import_path51 = __toESM(require("path"));
49846
+ var import_path52 = __toESM(require("path"));
49588
49847
  init_costSync();
49589
49848
  init_litellm();
49590
49849
  init_cost_codex();
@@ -49668,8 +49927,8 @@ function getDateRange(period, now) {
49668
49927
  }
49669
49928
  }
49670
49929
  function parseAuditLog(logPath) {
49671
- if (!import_fs53.default.existsSync(logPath)) return [];
49672
- const raw = import_fs53.default.readFileSync(logPath, "utf-8");
49930
+ if (!import_fs54.default.existsSync(logPath)) return [];
49931
+ const raw = import_fs54.default.readFileSync(logPath, "utf-8");
49673
49932
  return raw.split("\n").flatMap((line) => {
49674
49933
  if (!line.trim()) return [];
49675
49934
  try {
@@ -49723,25 +49982,25 @@ function freezeClaudeCost(acc) {
49723
49982
  };
49724
49983
  }
49725
49984
  function processClaudeCostProject(proj, projectsDir, start, end, acc) {
49726
- const projPath = import_path51.default.join(projectsDir, proj);
49985
+ const projPath = import_path52.default.join(projectsDir, proj);
49727
49986
  let files;
49728
49987
  try {
49729
- const stat = import_fs53.default.statSync(projPath);
49988
+ const stat = import_fs54.default.statSync(projPath);
49730
49989
  if (!stat.isDirectory()) return;
49731
- files = import_fs53.default.readdirSync(projPath).filter((f) => f.endsWith(".jsonl") && !f.startsWith("agent-"));
49990
+ files = import_fs54.default.readdirSync(projPath).filter((f) => f.endsWith(".jsonl") && !f.startsWith("agent-"));
49732
49991
  } catch {
49733
49992
  return;
49734
49993
  }
49735
49994
  const startMs = start.getTime();
49736
49995
  for (const file of files) {
49737
- const filePath = import_path51.default.join(projPath, file);
49996
+ const filePath = import_path52.default.join(projPath, file);
49738
49997
  try {
49739
- if (import_fs53.default.statSync(filePath).mtimeMs < startMs) continue;
49998
+ if (import_fs54.default.statSync(filePath).mtimeMs < startMs) continue;
49740
49999
  } catch {
49741
50000
  continue;
49742
50001
  }
49743
50002
  try {
49744
- const raw = import_fs53.default.readFileSync(filePath, "utf-8");
50003
+ const raw = import_fs54.default.readFileSync(filePath, "utf-8");
49745
50004
  for (const line of raw.split("\n")) {
49746
50005
  if (!line.trim()) continue;
49747
50006
  let entry;
@@ -49791,10 +50050,10 @@ function processClaudeCostProject(proj, projectsDir, start, end, acc) {
49791
50050
  }
49792
50051
  function loadClaudeCost(start, end, projectsDir) {
49793
50052
  const acc = emptyClaudeCostAccumulator();
49794
- if (!import_fs53.default.existsSync(projectsDir)) return freezeClaudeCost(acc);
50053
+ if (!import_fs54.default.existsSync(projectsDir)) return freezeClaudeCost(acc);
49795
50054
  let dirs;
49796
50055
  try {
49797
- dirs = import_fs53.default.readdirSync(projectsDir);
50056
+ dirs = import_fs54.default.readdirSync(projectsDir);
49798
50057
  } catch {
49799
50058
  return freezeClaudeCost(acc);
49800
50059
  }
@@ -49806,7 +50065,7 @@ function loadClaudeCost(start, end, projectsDir) {
49806
50065
  function processCodexCostFile(filePath, start, end, acc) {
49807
50066
  let lines;
49808
50067
  try {
49809
- lines = import_fs53.default.readFileSync(filePath, "utf-8").split("\n");
50068
+ lines = import_fs54.default.readFileSync(filePath, "utf-8").split("\n");
49810
50069
  } catch {
49811
50070
  return;
49812
50071
  }
@@ -49861,31 +50120,31 @@ function processCodexCostFile(filePath, start, end, acc) {
49861
50120
  }
49862
50121
  function listCodexSessionFiles2(sessionsBase) {
49863
50122
  const jsonlFiles = [];
49864
- if (!import_fs53.default.existsSync(sessionsBase)) return jsonlFiles;
50123
+ if (!import_fs54.default.existsSync(sessionsBase)) return jsonlFiles;
49865
50124
  try {
49866
- for (const year of import_fs53.default.readdirSync(sessionsBase)) {
49867
- const yearPath = import_path51.default.join(sessionsBase, year);
50125
+ for (const year of import_fs54.default.readdirSync(sessionsBase)) {
50126
+ const yearPath = import_path52.default.join(sessionsBase, year);
49868
50127
  try {
49869
- if (!import_fs53.default.statSync(yearPath).isDirectory()) continue;
50128
+ if (!import_fs54.default.statSync(yearPath).isDirectory()) continue;
49870
50129
  } catch {
49871
50130
  continue;
49872
50131
  }
49873
- for (const month of import_fs53.default.readdirSync(yearPath)) {
49874
- const monthPath = import_path51.default.join(yearPath, month);
50132
+ for (const month of import_fs54.default.readdirSync(yearPath)) {
50133
+ const monthPath = import_path52.default.join(yearPath, month);
49875
50134
  try {
49876
- if (!import_fs53.default.statSync(monthPath).isDirectory()) continue;
50135
+ if (!import_fs54.default.statSync(monthPath).isDirectory()) continue;
49877
50136
  } catch {
49878
50137
  continue;
49879
50138
  }
49880
- for (const day of import_fs53.default.readdirSync(monthPath)) {
49881
- const dayPath = import_path51.default.join(monthPath, day);
50139
+ for (const day of import_fs54.default.readdirSync(monthPath)) {
50140
+ const dayPath = import_path52.default.join(monthPath, day);
49882
50141
  try {
49883
- if (!import_fs53.default.statSync(dayPath).isDirectory()) continue;
50142
+ if (!import_fs54.default.statSync(dayPath).isDirectory()) continue;
49884
50143
  } catch {
49885
50144
  continue;
49886
50145
  }
49887
- for (const file of import_fs53.default.readdirSync(dayPath)) {
49888
- if (file.endsWith(".jsonl")) jsonlFiles.push(import_path51.default.join(dayPath, file));
50146
+ for (const file of import_fs54.default.readdirSync(dayPath)) {
50147
+ if (file.endsWith(".jsonl")) jsonlFiles.push(import_path52.default.join(dayPath, file));
49889
50148
  }
49890
50149
  }
49891
50150
  }
@@ -49950,13 +50209,13 @@ function freezeGeminiCost(acc) {
49950
50209
  function processGeminiCostFile(filePath, projectKey, start, end, acc) {
49951
50210
  const startMs = start.getTime();
49952
50211
  try {
49953
- if (import_fs53.default.statSync(filePath).mtimeMs < startMs) return;
50212
+ if (import_fs54.default.statSync(filePath).mtimeMs < startMs) return;
49954
50213
  } catch {
49955
50214
  return;
49956
50215
  }
49957
50216
  let raw;
49958
50217
  try {
49959
- raw = import_fs53.default.readFileSync(filePath, "utf-8");
50218
+ raw = import_fs54.default.readFileSync(filePath, "utf-8");
49960
50219
  } catch {
49961
50220
  return;
49962
50221
  }
@@ -50005,30 +50264,30 @@ function listGeminiSessionFiles2(geminiTmpDir2) {
50005
50264
  const out = [];
50006
50265
  let dirs;
50007
50266
  try {
50008
- if (!import_fs53.default.statSync(geminiTmpDir2).isDirectory()) return out;
50009
- dirs = import_fs53.default.readdirSync(geminiTmpDir2);
50267
+ if (!import_fs54.default.statSync(geminiTmpDir2).isDirectory()) return out;
50268
+ dirs = import_fs54.default.readdirSync(geminiTmpDir2);
50010
50269
  } catch {
50011
50270
  return out;
50012
50271
  }
50013
50272
  for (const proj of dirs) {
50014
- const chatsDir = import_path51.default.join(geminiTmpDir2, proj, "chats");
50273
+ const chatsDir = import_path52.default.join(geminiTmpDir2, proj, "chats");
50015
50274
  let files;
50016
50275
  try {
50017
- if (!import_fs53.default.statSync(chatsDir).isDirectory()) continue;
50018
- files = import_fs53.default.readdirSync(chatsDir);
50276
+ if (!import_fs54.default.statSync(chatsDir).isDirectory()) continue;
50277
+ files = import_fs54.default.readdirSync(chatsDir);
50019
50278
  } catch {
50020
50279
  continue;
50021
50280
  }
50022
50281
  for (const f of files) {
50023
50282
  if (!f.endsWith(".jsonl")) continue;
50024
- out.push({ projectKey: proj, file: import_path51.default.join(chatsDir, f) });
50283
+ out.push({ projectKey: proj, file: import_path52.default.join(chatsDir, f) });
50025
50284
  }
50026
50285
  }
50027
50286
  return out;
50028
50287
  }
50029
50288
  function loadGeminiCost(start, end, geminiTmpDir2) {
50030
50289
  const acc = emptyGeminiAccumulator();
50031
- if (!import_fs53.default.existsSync(geminiTmpDir2)) return freezeGeminiCost(acc);
50290
+ if (!import_fs54.default.existsSync(geminiTmpDir2)) return freezeGeminiCost(acc);
50032
50291
  for (const { projectKey, file } of listGeminiSessionFiles2(geminiTmpDir2)) {
50033
50292
  processGeminiCostFile(file, projectKey, start, end, acc);
50034
50293
  }
@@ -50046,11 +50305,11 @@ function dimensionOfBlock(checkedBy, ruleName) {
50046
50305
  }
50047
50306
  function aggregateReportFromAudit(period, opts = {}) {
50048
50307
  const now = opts.now ?? /* @__PURE__ */ new Date();
50049
- const auditLogPath = opts.auditLogPath ?? import_path51.default.join(import_os48.default.homedir(), ".node9", "audit.log");
50050
- const claudeProjectsDir = opts.claudeProjectsDir ?? import_path51.default.join(import_os48.default.homedir(), ".claude", "projects");
50051
- const codexSessionsDir2 = opts.codexSessionsDir ?? import_path51.default.join(import_os48.default.homedir(), ".codex", "sessions");
50052
- const geminiTmpDir2 = opts.geminiTmpDir ?? import_path51.default.join(import_os48.default.homedir(), ".gemini", "tmp");
50053
- const hasAuditFile = import_fs53.default.existsSync(auditLogPath);
50308
+ const auditLogPath = opts.auditLogPath ?? import_path52.default.join(import_os48.default.homedir(), ".node9", "audit.log");
50309
+ const claudeProjectsDir = opts.claudeProjectsDir ?? import_path52.default.join(import_os48.default.homedir(), ".claude", "projects");
50310
+ const codexSessionsDir2 = opts.codexSessionsDir ?? import_path52.default.join(import_os48.default.homedir(), ".codex", "sessions");
50311
+ const geminiTmpDir2 = opts.geminiTmpDir ?? import_path52.default.join(import_os48.default.homedir(), ".gemini", "tmp");
50312
+ const hasAuditFile = import_fs54.default.existsSync(auditLogPath);
50054
50313
  const allEntries = opts.preloadedAuditEntries ?? parseAuditLog(auditLogPath);
50055
50314
  const unackedDlp = allEntries.filter((e) => e.source === "response-dlp");
50056
50315
  const { start, end } = getDateRange(period, now);
@@ -50759,7 +51018,8 @@ function renderTerminalReport(data, responseDlpEntries, excludeTests) {
50759
51018
  // src/cli/commands/daemon-cmd.ts
50760
51019
  var import_chalk14 = __toESM(require("chalk"));
50761
51020
  var import_child_process9 = require("child_process");
50762
- var import_fs54 = __toESM(require("fs"));
51021
+ init_daemon();
51022
+ var import_fs55 = __toESM(require("fs"));
50763
51023
  init_startup_log();
50764
51024
  init_daemon2();
50765
51025
  var VALID_ACTIONS = "start | stop | restart | status | install | uninstall";
@@ -50798,7 +51058,10 @@ function registerDaemonCommand(program2) {
50798
51058
  if (cmd === "stop") return stopDaemon();
50799
51059
  if (cmd === "restart") {
50800
51060
  stopDaemon();
50801
- await new Promise((r) => setTimeout(r, 500));
51061
+ for (let i = 0; i < 15; i++) {
51062
+ if (!await isDaemonReachable(300)) break;
51063
+ await new Promise((r) => setTimeout(r, 200));
51064
+ }
50802
51065
  const restartFd = openStartupLogFd();
50803
51066
  recordStartupState("starting");
50804
51067
  const child = (0, import_child_process9.spawn)(process.execPath, [process.argv[1], "daemon"], {
@@ -50813,7 +51076,7 @@ function registerDaemonCommand(program2) {
50813
51076
  child.unref();
50814
51077
  if (restartFd !== void 0) {
50815
51078
  try {
50816
- import_fs54.default.closeSync(restartFd);
51079
+ import_fs55.default.closeSync(restartFd);
50817
51080
  } catch {
50818
51081
  }
50819
51082
  }
@@ -50864,7 +51127,7 @@ function registerDaemonCommand(program2) {
50864
51127
  } finally {
50865
51128
  if (startupFd !== void 0) {
50866
51129
  try {
50867
- import_fs54.default.closeSync(startupFd);
51130
+ import_fs55.default.closeSync(startupFd);
50868
51131
  } catch {
50869
51132
  }
50870
51133
  }
@@ -50878,11 +51141,12 @@ function registerDaemonCommand(program2) {
50878
51141
 
50879
51142
  // src/cli/commands/status.ts
50880
51143
  var import_chalk15 = __toESM(require("chalk"));
50881
- var import_fs55 = __toESM(require("fs"));
50882
- var import_path52 = __toESM(require("path"));
51144
+ var import_fs56 = __toESM(require("fs"));
51145
+ var import_path53 = __toESM(require("path"));
50883
51146
  var import_os49 = __toESM(require("os"));
50884
51147
  init_core();
50885
51148
  init_daemon();
51149
+ init_build_id();
50886
51150
  init_agent_wiring();
50887
51151
  init_sync();
50888
51152
  init_service();
@@ -50906,7 +51170,7 @@ function printAgentSection(label2, hookPairs, wrapped) {
50906
51170
  }
50907
51171
  }
50908
51172
  function registerStatusCommand(program2) {
50909
- program2.command("status").description("Show current Node9 mode, policy source, and persistent decisions").action(() => {
51173
+ program2.command("status").description("Show current Node9 mode, policy source, and persistent decisions").action(async () => {
50910
51174
  const creds = getCredentials();
50911
51175
  const daemonRunning = isDaemonRunning();
50912
51176
  const mergedConfig = getConfig();
@@ -50937,6 +51201,14 @@ function registerStatusCommand(program2) {
50937
51201
  console.log(
50938
51202
  import_chalk15.default.green(" \u25CF Daemon running") + import_chalk15.default.gray(` \u2192 http://127.0.0.1:${DAEMON_PORT}/`)
50939
51203
  );
51204
+ const probe = await probeDaemonHealth();
51205
+ const drift = describeBuildDrift(
51206
+ probe.kind === "health" ? probe.health : probe.kind === "no-health" ? "no-health" : null,
51207
+ CURRENT_BUILD
51208
+ );
51209
+ if (drift) {
51210
+ console.log(import_chalk15.default.yellow(` \u26A0 ${drift}`) + import_chalk15.default.gray(" \u2014 run: node9 doctor"));
51211
+ }
50940
51212
  } else {
50941
51213
  console.log(import_chalk15.default.gray(" \u25CB Daemon stopped"));
50942
51214
  }
@@ -50958,13 +51230,13 @@ function registerStatusCommand(program2) {
50958
51230
  console.log("");
50959
51231
  const modeLabel = settings.mode === "audit" ? import_chalk15.default.blue("audit") : settings.mode === "strict" ? import_chalk15.default.red("strict") : import_chalk15.default.white("standard");
50960
51232
  console.log(` Mode: ${modeLabel}`);
50961
- const projectConfig = import_path52.default.join(process.cwd(), "node9.config.json");
50962
- const globalConfig = import_path52.default.join(import_os49.default.homedir(), ".node9", "config.json");
51233
+ const projectConfig = import_path53.default.join(process.cwd(), "node9.config.json");
51234
+ const globalConfig = import_path53.default.join(import_os49.default.homedir(), ".node9", "config.json");
50963
51235
  console.log(
50964
- ` Local: ${import_fs55.default.existsSync(projectConfig) ? import_chalk15.default.green("Active (node9.config.json)") : import_chalk15.default.gray("Not present")}`
51236
+ ` Local: ${import_fs56.default.existsSync(projectConfig) ? import_chalk15.default.green("Active (node9.config.json)") : import_chalk15.default.gray("Not present")}`
50965
51237
  );
50966
51238
  console.log(
50967
- ` Global: ${import_fs55.default.existsSync(globalConfig) ? import_chalk15.default.green("Active (~/.node9/config.json)") : import_chalk15.default.gray("Not present")}`
51239
+ ` Global: ${import_fs56.default.existsSync(globalConfig) ? import_chalk15.default.green("Active (~/.node9/config.json)") : import_chalk15.default.gray("Not present")}`
50968
51240
  );
50969
51241
  if (mergedConfig.policy.sandboxPaths.length > 0) {
50970
51242
  console.log(
@@ -51006,8 +51278,8 @@ function registerStatusCommand(program2) {
51006
51278
 
51007
51279
  // src/cli/commands/init.ts
51008
51280
  var import_chalk16 = __toESM(require("chalk"));
51009
- var import_fs56 = __toESM(require("fs"));
51010
- var import_path53 = __toESM(require("path"));
51281
+ var import_fs57 = __toESM(require("fs"));
51282
+ var import_path54 = __toESM(require("path"));
51011
51283
  var import_os50 = __toESM(require("os"));
51012
51284
  var import_https6 = __toESM(require("https"));
51013
51285
  init_core();
@@ -51099,16 +51371,16 @@ function registerInitCommand(program2) {
51099
51371
  }
51100
51372
  console.log("");
51101
51373
  }
51102
- const configPath = import_path53.default.join(import_os50.default.homedir(), ".node9", "config.json");
51103
- const isFirstInstall = !import_fs56.default.existsSync(configPath);
51104
- if (import_fs56.default.existsSync(configPath) && !options.force) {
51374
+ const configPath = import_path54.default.join(import_os50.default.homedir(), ".node9", "config.json");
51375
+ const isFirstInstall = !import_fs57.default.existsSync(configPath);
51376
+ if (import_fs57.default.existsSync(configPath) && !options.force) {
51105
51377
  try {
51106
- const existing = JSON.parse(import_fs56.default.readFileSync(configPath, "utf-8"));
51378
+ const existing = JSON.parse(import_fs57.default.readFileSync(configPath, "utf-8"));
51107
51379
  const settings = existing.settings ?? {};
51108
51380
  if (settings.mode !== chosenMode) {
51109
51381
  settings.mode = chosenMode;
51110
51382
  existing.settings = settings;
51111
- import_fs56.default.writeFileSync(configPath, JSON.stringify(existing, null, 2) + "\n");
51383
+ import_fs57.default.writeFileSync(configPath, JSON.stringify(existing, null, 2) + "\n");
51112
51384
  console.log(import_chalk16.default.green(`\u2705 Mode updated: ${chosenMode}`));
51113
51385
  } else {
51114
51386
  console.log(import_chalk16.default.blue(`\u2139\uFE0F Config already exists: ${configPath}`));
@@ -51121,9 +51393,9 @@ function registerInitCommand(program2) {
51121
51393
  ...DEFAULT_CONFIG,
51122
51394
  settings: { ...DEFAULT_CONFIG.settings, mode: chosenMode }
51123
51395
  };
51124
- const dir = import_path53.default.dirname(configPath);
51125
- if (!import_fs56.default.existsSync(dir)) import_fs56.default.mkdirSync(dir, { recursive: true });
51126
- import_fs56.default.writeFileSync(configPath, JSON.stringify(configToSave, null, 2) + "\n");
51396
+ const dir = import_path54.default.dirname(configPath);
51397
+ if (!import_fs57.default.existsSync(dir)) import_fs57.default.mkdirSync(dir, { recursive: true });
51398
+ import_fs57.default.writeFileSync(configPath, JSON.stringify(configToSave, null, 2) + "\n");
51127
51399
  console.log(import_chalk16.default.green(`\u2705 Config created: ${configPath}`));
51128
51400
  console.log(import_chalk16.default.gray(` Mode: ${chosenMode}`));
51129
51401
  }
@@ -51223,14 +51495,14 @@ function registerInitCommand(program2) {
51223
51495
 
51224
51496
  // src/cli/commands/heal.ts
51225
51497
  var import_chalk17 = __toESM(require("chalk"));
51226
- var import_fs57 = __toESM(require("fs"));
51498
+ var import_fs58 = __toESM(require("fs"));
51227
51499
  init_agent_wiring();
51228
51500
  init_setup();
51229
51501
  init_hook_baseline();
51230
51502
  var hasHookSurface = (a) => a.hooks.length > 0;
51231
51503
  function backupForHeal(file) {
51232
51504
  try {
51233
- if (file && import_fs57.default.existsSync(file)) import_fs57.default.copyFileSync(file, `${file}.node9-heal-bak`);
51505
+ if (file && import_fs58.default.existsSync(file)) import_fs58.default.copyFileSync(file, `${file}.node9-heal-bak`);
51234
51506
  } catch {
51235
51507
  }
51236
51508
  }
@@ -51397,7 +51669,7 @@ function registerConnectCommand(program2) {
51397
51669
  }
51398
51670
 
51399
51671
  // src/cli/commands/undo.ts
51400
- var import_path54 = __toESM(require("path"));
51672
+ var import_path55 = __toESM(require("path"));
51401
51673
  var import_chalk20 = __toESM(require("chalk"));
51402
51674
 
51403
51675
  // src/tui/undo-navigator.ts
@@ -51556,7 +51828,7 @@ function findMatchingCwd(startDir, history) {
51556
51828
  let dir = startDir;
51557
51829
  while (true) {
51558
51830
  if (cwds.has(dir)) return dir;
51559
- const parent = import_path54.default.dirname(dir);
51831
+ const parent = import_path55.default.dirname(dir);
51560
51832
  if (parent === dir) return null;
51561
51833
  dir = parent;
51562
51834
  }
@@ -52190,9 +52462,9 @@ function registerMcpGatewayCommand(program2) {
52190
52462
 
52191
52463
  // src/mcp-server/index.ts
52192
52464
  var import_readline5 = __toESM(require("readline"));
52193
- var import_fs59 = __toESM(require("fs"));
52465
+ var import_fs60 = __toESM(require("fs"));
52194
52466
  var import_os52 = __toESM(require("os"));
52195
- var import_path56 = __toESM(require("path"));
52467
+ var import_path57 = __toESM(require("path"));
52196
52468
  var import_child_process11 = require("child_process");
52197
52469
  init_decision();
52198
52470
  init_core();
@@ -52200,9 +52472,9 @@ init_daemon();
52200
52472
  init_shields();
52201
52473
 
52202
52474
  // src/auth/egress-config.ts
52203
- var import_fs58 = __toESM(require("fs"));
52475
+ var import_fs59 = __toESM(require("fs"));
52204
52476
  var import_os51 = __toESM(require("os"));
52205
- var import_path55 = __toESM(require("path"));
52477
+ var import_path56 = __toESM(require("path"));
52206
52478
  var DEFAULT_EGRESS = {
52207
52479
  enabled: false,
52208
52480
  mode: "review",
@@ -52211,12 +52483,12 @@ var DEFAULT_EGRESS = {
52211
52483
  allowPrivate: true
52212
52484
  };
52213
52485
  function egressConfigPath() {
52214
- return import_path55.default.join(import_os51.default.homedir(), ".node9", "config.json");
52486
+ return import_path56.default.join(import_os51.default.homedir(), ".node9", "config.json");
52215
52487
  }
52216
52488
  function readEgressRawConfig() {
52217
52489
  let text;
52218
52490
  try {
52219
- text = import_fs58.default.readFileSync(egressConfigPath(), "utf8");
52491
+ text = import_fs59.default.readFileSync(egressConfigPath(), "utf8");
52220
52492
  } catch (err2) {
52221
52493
  if (err2.code === "ENOENT") return {};
52222
52494
  throw err2;
@@ -52231,8 +52503,8 @@ function readEgressRawConfig() {
52231
52503
  }
52232
52504
  function writeEgressRawConfig(config) {
52233
52505
  const p = egressConfigPath();
52234
- import_fs58.default.mkdirSync(import_path55.default.dirname(p), { recursive: true });
52235
- import_fs58.default.writeFileSync(p, JSON.stringify(config, null, 2) + "\n", { mode: 384 });
52506
+ import_fs59.default.mkdirSync(import_path56.default.dirname(p), { recursive: true });
52507
+ import_fs59.default.writeFileSync(p, JSON.stringify(config, null, 2) + "\n", { mode: 384 });
52236
52508
  }
52237
52509
  function applyEgress(config, change) {
52238
52510
  const policy = config.policy = config.policy ?? {};
@@ -52617,13 +52889,13 @@ function handleStatus() {
52617
52889
  lines.push(`Active shields: ${activeShields.length > 0 ? activeShields.join(", ") : "none"}`);
52618
52890
  lines.push(`Smart rules: ${config.policy.smartRules.length} loaded`);
52619
52891
  lines.push(`DLP: ${config.policy.dlp?.enabled !== false ? "enabled" : "disabled"}`);
52620
- const projectConfig = import_path56.default.join(process.cwd(), "node9.config.json");
52621
- const globalConfig = import_path56.default.join(import_os52.default.homedir(), ".node9", "config.json");
52892
+ const projectConfig = import_path57.default.join(process.cwd(), "node9.config.json");
52893
+ const globalConfig = import_path57.default.join(import_os52.default.homedir(), ".node9", "config.json");
52622
52894
  lines.push(
52623
- `Project config (node9.config.json): ${import_fs59.default.existsSync(projectConfig) ? "present" : "not found"}`
52895
+ `Project config (node9.config.json): ${import_fs60.default.existsSync(projectConfig) ? "present" : "not found"}`
52624
52896
  );
52625
52897
  lines.push(
52626
- `Global config (~/.node9/config.json): ${import_fs59.default.existsSync(globalConfig) ? "present" : "not found"}`
52898
+ `Global config (~/.node9/config.json): ${import_fs60.default.existsSync(globalConfig) ? "present" : "not found"}`
52627
52899
  );
52628
52900
  return lines.join("\n");
52629
52901
  }
@@ -52729,21 +53001,21 @@ function handleEgressDeny(args) {
52729
53001
  addEgressHost("deny", host);
52730
53002
  return `Denied egress to ${host} (deny always wins over allow).`;
52731
53003
  }
52732
- var GLOBAL_CONFIG_PATH = import_path56.default.join(import_os52.default.homedir(), ".node9", "config.json");
53004
+ var GLOBAL_CONFIG_PATH = import_path57.default.join(import_os52.default.homedir(), ".node9", "config.json");
52733
53005
  var APPROVER_CHANNELS = ["native", "browser", "cloud", "terminal"];
52734
53006
  function readGlobalConfigRaw() {
52735
53007
  try {
52736
- if (import_fs59.default.existsSync(GLOBAL_CONFIG_PATH)) {
52737
- return JSON.parse(import_fs59.default.readFileSync(GLOBAL_CONFIG_PATH, "utf-8"));
53008
+ if (import_fs60.default.existsSync(GLOBAL_CONFIG_PATH)) {
53009
+ return JSON.parse(import_fs60.default.readFileSync(GLOBAL_CONFIG_PATH, "utf-8"));
52738
53010
  }
52739
53011
  } catch {
52740
53012
  }
52741
53013
  return {};
52742
53014
  }
52743
53015
  function writeGlobalConfigRaw(data) {
52744
- const dir = import_path56.default.dirname(GLOBAL_CONFIG_PATH);
52745
- if (!import_fs59.default.existsSync(dir)) import_fs59.default.mkdirSync(dir, { recursive: true });
52746
- import_fs59.default.writeFileSync(GLOBAL_CONFIG_PATH, JSON.stringify(data, null, 2) + "\n");
53016
+ const dir = import_path57.default.dirname(GLOBAL_CONFIG_PATH);
53017
+ if (!import_fs60.default.existsSync(dir)) import_fs60.default.mkdirSync(dir, { recursive: true });
53018
+ import_fs60.default.writeFileSync(GLOBAL_CONFIG_PATH, JSON.stringify(data, null, 2) + "\n");
52747
53019
  }
52748
53020
  function handleApproverList() {
52749
53021
  const config = getConfig();
@@ -52787,9 +53059,9 @@ function handleApproverSet(args) {
52787
53059
  function handleAuditGet(args) {
52788
53060
  const limit = Math.min(typeof args.limit === "number" ? args.limit : 20, 100);
52789
53061
  const filter = typeof args.filter === "string" && args.filter !== "all" ? args.filter : null;
52790
- const auditPath = import_path56.default.join(import_os52.default.homedir(), ".node9", "audit.log");
52791
- if (!import_fs59.default.existsSync(auditPath)) return "No audit log found.";
52792
- const rawLines = import_fs59.default.readFileSync(auditPath, "utf-8").trim().split("\n").filter(Boolean);
53062
+ const auditPath = import_path57.default.join(import_os52.default.homedir(), ".node9", "audit.log");
53063
+ if (!import_fs60.default.existsSync(auditPath)) return "No audit log found.";
53064
+ const rawLines = import_fs60.default.readFileSync(auditPath, "utf-8").trim().split("\n").filter(Boolean);
52793
53065
  const wanted = filter === "block" ? "deny" : filter;
52794
53066
  const parsed = [];
52795
53067
  for (const line of rawLines) {
@@ -53165,7 +53437,7 @@ function registerTrustCommand(program2) {
53165
53437
  // src/cli/commands/mcp-pin.ts
53166
53438
  var import_chalk24 = __toESM(require("chalk"));
53167
53439
  init_mcp_pin();
53168
- var import_fs60 = __toESM(require("fs"));
53440
+ var import_fs61 = __toESM(require("fs"));
53169
53441
 
53170
53442
  // src/cli/commands/mcp-gateway-cmd.ts
53171
53443
  var import_chalk23 = __toESM(require("chalk"));
@@ -53373,7 +53645,7 @@ function registerMcpPinCommand(program2) {
53373
53645
  let repoCorrupt = false;
53374
53646
  if (found.source === "repo") {
53375
53647
  try {
53376
- const raw = import_fs60.default.readFileSync(found.path, "utf-8");
53648
+ const raw = import_fs61.default.readFileSync(found.path, "utf-8");
53377
53649
  const parsed = JSON.parse(raw);
53378
53650
  repoEntries = parsed.servers ?? {};
53379
53651
  } catch {
@@ -53966,8 +54238,8 @@ function registerPostureCommand(program2) {
53966
54238
  var import_chalk30 = __toESM(require("chalk"));
53967
54239
 
53968
54240
  // src/ci-check/fetch.ts
53969
- var import_fs61 = __toESM(require("fs"));
53970
- var import_path57 = __toESM(require("path"));
54241
+ var import_fs62 = __toESM(require("fs"));
54242
+ var import_path58 = __toESM(require("path"));
53971
54243
  var import_node_child_process = require("child_process");
53972
54244
  var import_undici = __toESM(require_undici());
53973
54245
  var cachedGhToken;
@@ -54051,7 +54323,7 @@ function parseRepoUrl(input) {
54051
54323
  function isLocalPath(input) {
54052
54324
  if (input.startsWith(".") || input.startsWith("/") || input.startsWith("~")) return true;
54053
54325
  try {
54054
- return import_fs61.default.existsSync(input) && import_fs61.default.statSync(input).isDirectory();
54326
+ return import_fs62.default.existsSync(input) && import_fs62.default.statSync(input).isDirectory();
54055
54327
  } catch {
54056
54328
  return false;
54057
54329
  }
@@ -54166,10 +54438,10 @@ function readLocalTree(dir) {
54166
54438
  const files = [];
54167
54439
  const notes = [];
54168
54440
  const add = (rel) => {
54169
- const abs = import_path57.default.join(root, rel);
54441
+ const abs = import_path58.default.join(root, rel);
54170
54442
  try {
54171
- if (import_fs61.default.existsSync(abs) && import_fs61.default.statSync(abs).isFile()) {
54172
- files.push({ path: rel, content: import_fs61.default.readFileSync(abs, "utf8") });
54443
+ if (import_fs62.default.existsSync(abs) && import_fs62.default.statSync(abs).isFile()) {
54444
+ files.push({ path: rel, content: import_fs62.default.readFileSync(abs, "utf8") });
54173
54445
  }
54174
54446
  } catch {
54175
54447
  }
@@ -54189,7 +54461,7 @@ function readLocalTree(dir) {
54189
54461
  dirsVisited++;
54190
54462
  let entries;
54191
54463
  try {
54192
- entries = import_fs61.default.readdirSync(import_path57.default.join(root, relDir), { withFileTypes: true });
54464
+ entries = import_fs62.default.readdirSync(import_path58.default.join(root, relDir), { withFileTypes: true });
54193
54465
  } catch {
54194
54466
  return;
54195
54467
  }
@@ -54210,11 +54482,11 @@ function readLocalTree(dir) {
54210
54482
  `repo is large \u2014 some agent-surface files may be INCOMPLETE (capped at ${MAX_SURFACE_FILES} files / ${MAX_DIRS} dirs).`
54211
54483
  );
54212
54484
  for (const rel of matches) collect(rel);
54213
- const wfDir = import_path57.default.join(root, WORKFLOW_DIR);
54485
+ const wfDir = import_path58.default.join(root, WORKFLOW_DIR);
54214
54486
  try {
54215
- if (import_fs61.default.existsSync(wfDir)) {
54216
- for (const name of import_fs61.default.readdirSync(wfDir)) {
54217
- if (/\.ya?ml$/.test(name)) add(import_path57.default.join(WORKFLOW_DIR, name));
54487
+ if (import_fs62.default.existsSync(wfDir)) {
54488
+ for (const name of import_fs62.default.readdirSync(wfDir)) {
54489
+ if (/\.ya?ml$/.test(name)) add(import_path58.default.join(WORKFLOW_DIR, name));
54218
54490
  }
54219
54491
  }
54220
54492
  } catch {
@@ -54519,7 +54791,7 @@ function severityFromScore(score) {
54519
54791
  if (score >= 1) return "advisory";
54520
54792
  return null;
54521
54793
  }
54522
- function analyzeWorkflow(path71, content) {
54794
+ function analyzeWorkflow(path72, content) {
54523
54795
  let raw;
54524
54796
  try {
54525
54797
  raw = (0, import_yaml.parse)(content) ?? {};
@@ -54645,7 +54917,7 @@ function analyzeWorkflow(path71, content) {
54645
54917
  dimension: "workflows",
54646
54918
  severity,
54647
54919
  title,
54648
- file: path71,
54920
+ file: path72,
54649
54921
  signals,
54650
54922
  mitigations: mitigations.length ? mitigations : void 0,
54651
54923
  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) \u2014 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 \u2014 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."
@@ -54721,7 +54993,7 @@ function evalAgentJob(job, wf, raw, untrustedTrigger, reusable) {
54721
54993
  if (reusable && !loadedGun && SEVERITY_RANK2[severity] > SEVERITY_RANK2.medium) severity = "medium";
54722
54994
  return { severity, secrets, injectable, canReadEnv };
54723
54995
  }
54724
- function analyzeWorkflowSecrets(path71, content) {
54996
+ function analyzeWorkflowSecrets(path72, content) {
54725
54997
  let raw;
54726
54998
  try {
54727
54999
  raw = (0, import_yaml.parse)(content) ?? {};
@@ -54741,7 +55013,7 @@ function analyzeWorkflowSecrets(path71, content) {
54741
55013
  dimension: "data",
54742
55014
  severity: worst.severity,
54743
55015
  title: worst.severity === "advisory" ? "Secrets reachable by the agent \u2014 hardening" : "Exfiltratable secrets reachable by an injectable agent",
54744
- file: path71,
55016
+ file: path72,
54745
55017
  signals: [
54746
55018
  `agent can reach: ${worst.secrets.map((s) => s.name).join(", ")}`,
54747
55019
  worst.injectable ? "the agent is externally triggerable (untrusted trigger, no gate)" : "gated / not externally triggerable \u2014 latent risk only",
@@ -54768,7 +55040,7 @@ function hookCommands(hooks) {
54768
55040
  }
54769
55041
  return out;
54770
55042
  }
54771
- function analyzeAgentConfig(path71, content) {
55043
+ function analyzeAgentConfig(path72, content) {
54772
55044
  let cfg;
54773
55045
  try {
54774
55046
  cfg = JSON.parse(content);
@@ -54787,7 +55059,7 @@ function analyzeAgentConfig(path71, content) {
54787
55059
  dimension: "toolRules",
54788
55060
  severity: high ? "high" : "medium",
54789
55061
  title: high ? "Agent hook runs UNPINNED/remote third-party code on every action" : "Agent hook runs third-party code in the agent hot path",
54790
- file: path71,
55062
+ file: path72,
54791
55063
  signals: [
54792
55064
  `hook command: \`${cmd.slice(0, 120)}\``,
54793
55065
  remoteExec ? "fetch-and-run (curl|wget / pipe-to-shell) \u2014 unpinnable remote code execution on every contributor" : unpinned ? "unpinned \u2014 a compromised/yanked package = code execution on every contributor" : "pinned, but still a standing supply-chain dependency in the agent hot path"
@@ -54807,7 +55079,7 @@ function analyzeAgentConfig(path71, content) {
54807
55079
  dimension: "toolRules",
54808
55080
  severity: hasBackstop ? "medium" : "high",
54809
55081
  title: hasBackstop ? "Committed agent config pre-authorizes broad tools" : "Committed agent config pre-authorizes broad tools with no deny backstop",
54810
- file: path71,
55082
+ file: path72,
54811
55083
  signals: [
54812
55084
  `broad allow(s): ${broad.slice(0, 5).join(", ")}`,
54813
55085
  hasBackstop ? "a `deny` list backstops the broad allow" : "no `deny` entry covers Bash/Write/Edit \u2014 every contributor is pre-authorized for catastrophic tools"
@@ -54820,16 +55092,16 @@ function analyzeAgentConfig(path71, content) {
54820
55092
 
54821
55093
  // src/ci-check/mcp.ts
54822
55094
  init_dist();
54823
- function analyzeMcp(path71, content) {
55095
+ function analyzeMcp(path72, content) {
54824
55096
  let cfg;
54825
55097
  try {
54826
55098
  cfg = JSON.parse(content);
54827
55099
  } catch {
54828
55100
  return [];
54829
55101
  }
54830
- return analyzeMcpServers(cfg.mcpServers ?? {}, path71);
55102
+ return analyzeMcpServers(cfg.mcpServers ?? {}, path72);
54831
55103
  }
54832
- function analyzeMcpServers(servers, path71) {
55104
+ function analyzeMcpServers(servers, path72) {
54833
55105
  const findings = [];
54834
55106
  for (const [name, srv] of Object.entries(servers ?? {})) {
54835
55107
  if (!srv || srv.disabled) continue;
@@ -54840,7 +55112,7 @@ function analyzeMcpServers(servers, path71) {
54840
55112
  dimension: "mcp",
54841
55113
  severity: "medium",
54842
55114
  title: `MCP server "${name}" runs an unpinned executable`,
54843
- file: path71,
55115
+ file: path72,
54844
55116
  signals: [`\`${argv.slice(0, 120)}\` \u2014 unversioned/@latest npx`],
54845
55117
  fix: "Pin the MCP server package to an exact version so a PR (or a registry compromise) can\u2019t swap the toolchain."
54846
55118
  });
@@ -54854,7 +55126,7 @@ function analyzeMcpServers(servers, path71) {
54854
55126
  dimension: "mcp",
54855
55127
  severity: "high",
54856
55128
  title: `MCP server "${name}" has an inline credential`,
54857
- file: path71,
55129
+ file: path72,
54858
55130
  signals: [
54859
55131
  `env.${k} matches ${hit.patternName} \u2014 agent-reachable secret committed to the repo`
54860
55132
  ],
@@ -54868,7 +55140,7 @@ function analyzeMcpServers(servers, path71) {
54868
55140
 
54869
55141
  // src/ci-check/codex.ts
54870
55142
  var import_smol_toml5 = require("smol-toml");
54871
- function analyzeCodexConfig(path71, content) {
55143
+ function analyzeCodexConfig(path72, content) {
54872
55144
  let cfg;
54873
55145
  try {
54874
55146
  cfg = (0, import_smol_toml5.parse)(content);
@@ -54876,7 +55148,7 @@ function analyzeCodexConfig(path71, content) {
54876
55148
  return [];
54877
55149
  }
54878
55150
  const findings = [];
54879
- findings.push(...analyzeMcpServers(cfg.mcp_servers ?? {}, path71));
55151
+ findings.push(...analyzeMcpServers(cfg.mcp_servers ?? {}, path72));
54880
55152
  const sandbox = typeof cfg.sandbox_mode === "string" ? cfg.sandbox_mode : "";
54881
55153
  const approval = typeof cfg.approval_policy === "string" ? cfg.approval_policy : "";
54882
55154
  const fullAccess = /danger-full-access/i.test(sandbox);
@@ -54891,7 +55163,7 @@ function analyzeCodexConfig(path71, content) {
54891
55163
  dimension: "toolRules",
54892
55164
  severity: fullAccess ? "high" : "medium",
54893
55165
  title: fullAccess ? "Codex config grants a full-access sandbox" : "Codex config never requires approval",
54894
- file: path71,
55166
+ file: path72,
54895
55167
  signals,
54896
55168
  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.'
54897
55169
  });
@@ -54947,10 +55219,10 @@ function decodeSuspiciousBase64(text) {
54947
55219
  }
54948
55220
  return out;
54949
55221
  }
54950
- function mk(severity, title, signals, fix, path71) {
54951
- return { check: "CI-6", dimension: "instructions", severity, title, file: path71, signals, fix };
55222
+ function mk(severity, title, signals, fix, path72) {
55223
+ return { check: "CI-6", dimension: "instructions", severity, title, file: path72, signals, fix };
54952
55224
  }
54953
- function analyzeInstructionFile(path71, content) {
55225
+ function analyzeInstructionFile(path72, content) {
54954
55226
  const findings = [];
54955
55227
  const decoded = decodeSuspiciousBase64(content);
54956
55228
  if (TAG_CHARS.test(content))
@@ -54962,7 +55234,7 @@ function analyzeInstructionFile(path71, content) {
54962
55234
  "contains Unicode tag characters (U+E0000\u2013E007F) \u2014 an invisible instruction-smuggling channel with no legitimate use in text"
54963
55235
  ],
54964
55236
  "Remove the tag characters. Instruction files must be plain, reviewable text.",
54965
- path71
55237
+ path72
54966
55238
  )
54967
55239
  );
54968
55240
  if (BIDI_OVERRIDE.test(content))
@@ -54974,7 +55246,7 @@ function analyzeInstructionFile(path71, content) {
54974
55246
  "contains a bidi override (U+202D/U+202E) \u2014 a Trojan-Source technique that visually reorders text so a human reads something different from what the agent parses"
54975
55247
  ],
54976
55248
  "Remove the bidi override characters.",
54977
- path71
55249
+ path72
54978
55250
  )
54979
55251
  );
54980
55252
  else if (BIDI_EMBED_ISOLATE.test(content))
@@ -54986,7 +55258,7 @@ function analyzeInstructionFile(path71, content) {
54986
55258
  "contains bidi embed/isolate characters (U+202A\u2013202C / U+2066\u20132069) \u2014 legitimate in right-to-left text, but confirm they are not being used to hide or reorder instructions"
54987
55259
  ],
54988
55260
  "Confirm the bidi marks are legitimate RTL formatting; remove otherwise.",
54989
- path71
55261
+ path72
54990
55262
  )
54991
55263
  );
54992
55264
  const zw = suspiciousZeroWidth(content);
@@ -55000,7 +55272,7 @@ function analyzeInstructionFile(path71, content) {
55000
55272
  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 \u2014 a concealment technique (hides text from human review while the agent reads it as contiguous)"
55001
55273
  ],
55002
55274
  "Remove the zero-width characters. Instruction files must be plain, reviewable text.",
55003
- path71
55275
+ path72
55004
55276
  )
55005
55277
  );
55006
55278
  }
@@ -55016,7 +55288,7 @@ function analyzeInstructionFile(path71, content) {
55016
55288
  `contains a prompt-override / role-impersonation directive (\`${m[0].slice(0, 60).trim()}\`)${ovEnc ? " \u2014 concealed in a base64 blob" : ""}`
55017
55289
  ],
55018
55290
  "Remove the override text. An instruction file should not tell the agent to ignore its own rules.",
55019
- path71
55291
+ path72
55020
55292
  )
55021
55293
  );
55022
55294
  }
@@ -55028,7 +55300,7 @@ function analyzeInstructionFile(path71, content) {
55028
55300
  "Instruction directs the agent to fetch and run remote code",
55029
55301
  [`\`${fo[0].slice(0, 70).trim()}\` \u2014 fetch-and-obey, outside an install/setup section`],
55030
55302
  "Do not instruct the agent to pipe remote content into a shell; pin and vendor scripts instead.",
55031
- path71
55303
+ path72
55032
55304
  )
55033
55305
  );
55034
55306
  }
@@ -55040,7 +55312,7 @@ function analyzeInstructionFile(path71, content) {
55040
55312
  "Instruction points the agent at credential material",
55041
55313
  [`references \`${sp[0].slice(0, 50).trim()}\` \u2014 directs the agent toward secrets`],
55042
55314
  "Do not reference credential files or paths in agent instructions.",
55043
- path71
55315
+ path72
55044
55316
  )
55045
55317
  );
55046
55318
  }
@@ -55052,7 +55324,7 @@ function analyzeInstructionFile(path71, content) {
55052
55324
  "Instruction directs the agent to send data to an external endpoint",
55053
55325
  [`\`${ex[0].slice(0, 70).trim()}\` \u2014 possible exfiltration directive`],
55054
55326
  "Remove external post/upload directives from agent instructions.",
55055
- path71
55327
+ path72
55056
55328
  )
55057
55329
  );
55058
55330
  }
@@ -55352,19 +55624,19 @@ function registerEgressCommand(program2) {
55352
55624
  var import_chalk32 = __toESM(require("chalk"));
55353
55625
 
55354
55626
  // src/shields/jail.ts
55355
- var import_fs62 = __toESM(require("fs"));
55627
+ var import_fs63 = __toESM(require("fs"));
55356
55628
  var import_os53 = __toESM(require("os"));
55357
- var import_path58 = __toESM(require("path"));
55629
+ var import_path59 = __toESM(require("path"));
55358
55630
  init_build();
55359
55631
  init_shields();
55360
55632
  var USER_JAIL_SHIELD = "user-jail";
55361
55633
  function jailStorePath() {
55362
- return import_path58.default.join(import_os53.default.homedir(), ".node9", "jail-paths.json");
55634
+ return import_path59.default.join(import_os53.default.homedir(), ".node9", "jail-paths.json");
55363
55635
  }
55364
55636
  function readJailPaths() {
55365
55637
  let text;
55366
55638
  try {
55367
- text = import_fs62.default.readFileSync(jailStorePath(), "utf8");
55639
+ text = import_fs63.default.readFileSync(jailStorePath(), "utf8");
55368
55640
  } catch (err2) {
55369
55641
  if (err2.code === "ENOENT") return [];
55370
55642
  throw err2;
@@ -55382,8 +55654,8 @@ function readJailPaths() {
55382
55654
  }
55383
55655
  function writeJailPaths(paths) {
55384
55656
  const p = jailStorePath();
55385
- import_fs62.default.mkdirSync(import_path58.default.dirname(p), { recursive: true });
55386
- import_fs62.default.writeFileSync(p, JSON.stringify({ paths }, null, 2) + "\n", { mode: 384 });
55657
+ import_fs63.default.mkdirSync(import_path59.default.dirname(p), { recursive: true });
55658
+ import_fs63.default.writeFileSync(p, JSON.stringify({ paths }, null, 2) + "\n", { mode: 384 });
55387
55659
  }
55388
55660
  function addJailPath(rawPath, verdict) {
55389
55661
  const norm = rawPath.trim();
@@ -55405,14 +55677,14 @@ function removeJailPath(rawPath) {
55405
55677
  return { removed, paths: after };
55406
55678
  }
55407
55679
  function regenerateUserJail(paths) {
55408
- const file = import_path58.default.join(USER_SHIELDS_DIR_PATH, `${USER_JAIL_SHIELD}.json`);
55680
+ const file = import_path59.default.join(USER_SHIELDS_DIR_PATH, `${USER_JAIL_SHIELD}.json`);
55409
55681
  if (paths.length === 0) {
55410
55682
  const active2 = readActiveShields();
55411
55683
  if (active2.includes(USER_JAIL_SHIELD)) {
55412
55684
  writeActiveShields(active2.filter((s) => s !== USER_JAIL_SHIELD));
55413
55685
  }
55414
55686
  try {
55415
- import_fs62.default.rmSync(file, { force: true });
55687
+ import_fs63.default.rmSync(file, { force: true });
55416
55688
  } catch {
55417
55689
  }
55418
55690
  return;
@@ -55526,14 +55798,14 @@ function registerJailCommand(program2) {
55526
55798
 
55527
55799
  // src/cli/commands/sandbox.ts
55528
55800
  var import_chalk33 = __toESM(require("chalk"));
55529
- var import_fs65 = __toESM(require("fs"));
55530
- var import_path61 = __toESM(require("path"));
55801
+ var import_fs66 = __toESM(require("fs"));
55802
+ var import_path62 = __toESM(require("path"));
55531
55803
  var import_child_process13 = require("child_process");
55532
55804
  init_config();
55533
55805
 
55534
55806
  // src/sandbox/config.ts
55535
- var import_fs63 = __toESM(require("fs"));
55536
- var import_path59 = __toESM(require("path"));
55807
+ var import_fs64 = __toESM(require("fs"));
55808
+ var import_path60 = __toESM(require("path"));
55537
55809
  var import_yaml2 = require("yaml");
55538
55810
  var SANDBOX_CONFIG_FILE = "node9.sandbox.yaml";
55539
55811
  var FORBIDDEN_ENV = /* @__PURE__ */ new Set(["NODE9_API_KEY", "NODE9_API_URL"]);
@@ -55606,16 +55878,16 @@ function scaffoldSandboxYaml(agent) {
55606
55878
  return header + (0, import_yaml2.stringify)(defaultSandboxConfig(agent));
55607
55879
  }
55608
55880
  function sandboxConfigPath(cwd = process.cwd()) {
55609
- return import_path59.default.join(cwd, SANDBOX_CONFIG_FILE);
55881
+ return import_path60.default.join(cwd, SANDBOX_CONFIG_FILE);
55610
55882
  }
55611
55883
  function loadSandboxConfig(cwd = process.cwd(), fallbackAgent = "claude") {
55612
55884
  const p = sandboxConfigPath(cwd);
55613
- if (!import_fs63.default.existsSync(p)) {
55885
+ if (!import_fs64.default.existsSync(p)) {
55614
55886
  throw new Error(`sandbox: ${SANDBOX_CONFIG_FILE} not found \u2014 run \`node9 sandbox new\` first.`);
55615
55887
  }
55616
55888
  let raw;
55617
55889
  try {
55618
- raw = (0, import_yaml2.parse)(import_fs63.default.readFileSync(p, "utf-8"));
55890
+ raw = (0, import_yaml2.parse)(import_fs64.default.readFileSync(p, "utf-8"));
55619
55891
  } catch (err2) {
55620
55892
  throw new Error(
55621
55893
  `sandbox: ${SANDBOX_CONFIG_FILE} is not valid YAML \u2014 ${err2.message}`
@@ -55673,14 +55945,14 @@ function compileAllowlist(input) {
55673
55945
  init_templates();
55674
55946
 
55675
55947
  // src/sandbox/runtime.ts
55676
- var import_fs64 = __toESM(require("fs"));
55948
+ var import_fs65 = __toESM(require("fs"));
55677
55949
  var import_os54 = __toESM(require("os"));
55678
- var import_path60 = __toESM(require("path"));
55950
+ var import_path61 = __toESM(require("path"));
55679
55951
  var import_crypto14 = __toESM(require("crypto"));
55680
55952
  var import_child_process12 = require("child_process");
55681
55953
  init_templates();
55682
55954
  function sandboxDataDir(cwd = process.cwd()) {
55683
- return import_path60.default.join(cwd, ".node9", "sandbox", "data");
55955
+ return import_path61.default.join(cwd, ".node9", "sandbox", "data");
55684
55956
  }
55685
55957
  function detectEngine(engine) {
55686
55958
  const r = (0, import_child_process12.spawnSync)(engine, ["--version"], { encoding: "utf-8" });
@@ -55691,7 +55963,7 @@ function detectEngine(engine) {
55691
55963
  }
55692
55964
  function agentCredentialsMount(agent) {
55693
55965
  const rel = agent === "codex" ? ".codex/auth.json" : ".claude/.credentials.json";
55694
- return { hostPath: import_path60.default.join(import_os54.default.homedir(), rel), target: `/home/${RUN_AS_USER}/${rel}` };
55966
+ return { hostPath: import_path61.default.join(import_os54.default.homedir(), rel), target: `/home/${RUN_AS_USER}/${rel}` };
55695
55967
  }
55696
55968
  function buildRunArgs(opts) {
55697
55969
  const { config, workspaceHostPath, dataHostPath, allowlistHostPath, agentArgs } = opts;
@@ -55701,7 +55973,7 @@ function buildRunArgs(opts) {
55701
55973
  args.push("-v", `${allowlistHostPath}:${ALLOWED_DOMAINS_PATH}:ro`);
55702
55974
  if (config.node9.mountAgentCredentials) {
55703
55975
  const creds = agentCredentialsMount(config.agent);
55704
- if (import_fs64.default.existsSync(creds.hostPath)) {
55976
+ if (import_fs65.default.existsSync(creds.hostPath)) {
55705
55977
  args.push("-v", `${creds.hostPath}:${creds.target}`);
55706
55978
  }
55707
55979
  }
@@ -55719,30 +55991,30 @@ function imageContentHash(dockerfile, entrypoint) {
55719
55991
  return import_crypto14.default.createHash("sha256").update(dockerfile).update("\0").update(entrypoint).digest("hex").slice(0, 16);
55720
55992
  }
55721
55993
  function sandboxBuildDir(cwd = process.cwd()) {
55722
- return import_path60.default.join(cwd, ".node9", "sandbox", "build");
55994
+ return import_path61.default.join(cwd, ".node9", "sandbox", "build");
55723
55995
  }
55724
55996
  function writeBuildContext(cwd, dockerfile, entrypoint) {
55725
55997
  const dir = sandboxBuildDir(cwd);
55726
- import_fs64.default.mkdirSync(dir, { recursive: true });
55727
- import_fs64.default.writeFileSync(import_path60.default.join(dir, "Dockerfile"), dockerfile);
55728
- import_fs64.default.writeFileSync(import_path60.default.join(dir, "entrypoint.sh"), entrypoint);
55998
+ import_fs65.default.mkdirSync(dir, { recursive: true });
55999
+ import_fs65.default.writeFileSync(import_path61.default.join(dir, "Dockerfile"), dockerfile);
56000
+ import_fs65.default.writeFileSync(import_path61.default.join(dir, "entrypoint.sh"), entrypoint);
55729
56001
  return dir;
55730
56002
  }
55731
56003
  function writeAllowlist(cwd, hosts) {
55732
- const dir = import_path60.default.join(cwd, ".node9", "sandbox");
55733
- import_fs64.default.mkdirSync(dir, { recursive: true });
55734
- const p = import_path60.default.join(dir, "allowed-domains.txt");
55735
- import_fs64.default.writeFileSync(p, hosts.join("\n") + "\n");
56004
+ const dir = import_path61.default.join(cwd, ".node9", "sandbox");
56005
+ import_fs65.default.mkdirSync(dir, { recursive: true });
56006
+ const p = import_path61.default.join(dir, "allowed-domains.txt");
56007
+ import_fs65.default.writeFileSync(p, hosts.join("\n") + "\n");
55736
56008
  return p;
55737
56009
  }
55738
56010
  function resolveHomePath(p) {
55739
- return p.startsWith("~") ? import_path60.default.join(import_os54.default.homedir(), p.slice(1)) : import_path60.default.resolve(p);
56011
+ return p.startsWith("~") ? import_path61.default.join(import_os54.default.homedir(), p.slice(1)) : import_path61.default.resolve(p);
55740
56012
  }
55741
56013
 
55742
56014
  // src/cli/commands/sandbox.ts
55743
56015
  function seedDataDirConfig(dataDir, sandbox) {
55744
- import_fs65.default.mkdirSync(dataDir, { recursive: true });
55745
- const configPath = import_path61.default.join(dataDir, "config.json");
56016
+ import_fs66.default.mkdirSync(dataDir, { recursive: true });
56017
+ const configPath = import_path62.default.join(dataDir, "config.json");
55746
56018
  const seed = {
55747
56019
  settings: {
55748
56020
  approvers: {
@@ -55753,7 +56025,7 @@ function seedDataDirConfig(dataDir, sandbox) {
55753
56025
  }
55754
56026
  }
55755
56027
  };
55756
- import_fs65.default.writeFileSync(configPath, JSON.stringify(seed, null, 2), { mode: 384 });
56028
+ import_fs66.default.writeFileSync(configPath, JSON.stringify(seed, null, 2), { mode: 384 });
55757
56029
  }
55758
56030
  function registerSandboxCommand(program2, version2) {
55759
56031
  const node9Version2 = pinnedNode9Version(version2);
@@ -55761,13 +56033,13 @@ function registerSandboxCommand(program2, version2) {
55761
56033
  cmd.command("new").description(`Scaffold ${SANDBOX_CONFIG_FILE} in this project`).option("--agent <agent>", "claude (default) or codex", "claude").action((opts) => {
55762
56034
  const agent = opts.agent === "codex" ? "codex" : "claude";
55763
56035
  const p = sandboxConfigPath();
55764
- if (import_fs65.default.existsSync(p)) {
56036
+ if (import_fs66.default.existsSync(p)) {
55765
56037
  console.log(
55766
56038
  import_chalk33.default.yellow(` ${SANDBOX_CONFIG_FILE} already exists \u2014 leaving it untouched.`)
55767
56039
  );
55768
56040
  return;
55769
56041
  }
55770
- import_fs65.default.writeFileSync(p, scaffoldSandboxYaml(agent));
56042
+ import_fs66.default.writeFileSync(p, scaffoldSandboxYaml(agent));
55771
56043
  console.log(
55772
56044
  import_chalk33.default.green(` \u2713 wrote ${SANDBOX_CONFIG_FILE}`) + import_chalk33.default.dim(` (agent: ${agent})`)
55773
56045
  );
@@ -55807,8 +56079,8 @@ function registerSandboxCommand(program2, version2) {
55807
56079
  const buildDir = writeBuildContext(cwd, dockerfile, entrypoint);
55808
56080
  const hash = imageContentHash(dockerfile, entrypoint);
55809
56081
  const image = sandbox.runtime.image;
55810
- const hashFile = import_path61.default.join(sandboxBuildDir(cwd), ".image-hash");
55811
- const lastHash = import_fs65.default.existsSync(hashFile) ? import_fs65.default.readFileSync(hashFile, "utf-8").trim() : "";
56082
+ const hashFile = import_path62.default.join(sandboxBuildDir(cwd), ".image-hash");
56083
+ const lastHash = import_fs66.default.existsSync(hashFile) ? import_fs66.default.readFileSync(hashFile, "utf-8").trim() : "";
55812
56084
  const imageExists = (0, import_child_process13.spawnSync)(sandbox.runtime.engine, ["image", "inspect", image], { stdio: "ignore" }).status === 0;
55813
56085
  const needBuild = sandbox.runtime.rebuild === "always" || !imageExists || sandbox.runtime.rebuild !== "never" && lastHash !== hash;
55814
56086
  if (needBuild) {
@@ -55820,7 +56092,7 @@ function registerSandboxCommand(program2, version2) {
55820
56092
  console.error(import_chalk33.default.red(" build failed."));
55821
56093
  process.exit(b.status ?? 1);
55822
56094
  }
55823
- import_fs65.default.writeFileSync(hashFile, hash);
56095
+ import_fs66.default.writeFileSync(hashFile, hash);
55824
56096
  }
55825
56097
  const dataDir = sandboxDataDir(cwd);
55826
56098
  seedDataDirConfig(dataDir, sandbox);
@@ -55834,7 +56106,7 @@ function registerSandboxCommand(program2, version2) {
55834
56106
  });
55835
56107
  if (sandbox.node9.mountAgentCredentials) {
55836
56108
  const creds = agentCredentialsMount(sandbox.agent);
55837
- if (import_fs65.default.existsSync(creds.hostPath)) {
56109
+ if (import_fs66.default.existsSync(creds.hostPath)) {
55838
56110
  console.log(import_chalk33.default.dim(` mounting ${creds.hostPath} (agent credentials, rw)`));
55839
56111
  } else {
55840
56112
  console.log(
@@ -55850,20 +56122,20 @@ function registerSandboxCommand(program2, version2) {
55850
56122
  process.exit(r.status ?? 0);
55851
56123
  });
55852
56124
  cmd.command("tail").description("Stream the sandbox's audit log (host-side)").action(() => {
55853
- const auditPath = import_path61.default.join(sandboxDataDir(), "audit.log");
55854
- if (!import_fs65.default.existsSync(auditPath)) {
56125
+ const auditPath = import_path62.default.join(sandboxDataDir(), "audit.log");
56126
+ if (!import_fs66.default.existsSync(auditPath)) {
55855
56127
  console.log(import_chalk33.default.dim(" no sandbox audit yet."));
55856
56128
  return;
55857
56129
  }
55858
56130
  (0, import_child_process13.spawnSync)("tail", ["-f", auditPath], { stdio: "inherit" });
55859
56131
  });
55860
56132
  cmd.command("logs").description("Dump the sandbox's audit log").action(() => {
55861
- const auditPath = import_path61.default.join(sandboxDataDir(), "audit.log");
55862
- if (!import_fs65.default.existsSync(auditPath)) {
56133
+ const auditPath = import_path62.default.join(sandboxDataDir(), "audit.log");
56134
+ if (!import_fs66.default.existsSync(auditPath)) {
55863
56135
  console.log(import_chalk33.default.dim(" no sandbox audit yet."));
55864
56136
  return;
55865
56137
  }
55866
- process.stdout.write(import_fs65.default.readFileSync(auditPath, "utf-8"));
56138
+ process.stdout.write(import_fs66.default.readFileSync(auditPath, "utf-8"));
55867
56139
  });
55868
56140
  cmd.command("clean").description("Remove the sandbox image, build context, and data").action(() => {
55869
56141
  const cwd = process.cwd();
@@ -55877,15 +56149,15 @@ function registerSandboxCommand(program2, version2) {
55877
56149
  stdio: "ignore"
55878
56150
  });
55879
56151
  }
55880
- import_fs65.default.rmSync(import_path61.default.join(cwd, ".node9", "sandbox"), { recursive: true, force: true });
56152
+ import_fs66.default.rmSync(import_path62.default.join(cwd, ".node9", "sandbox"), { recursive: true, force: true });
55881
56153
  console.log(import_chalk33.default.green(" \u2713 sandbox image + build + data removed."));
55882
56154
  });
55883
56155
  }
55884
56156
 
55885
56157
  // src/cli/commands/sessions.ts
55886
56158
  var import_chalk34 = __toESM(require("chalk"));
55887
- var import_fs66 = __toESM(require("fs"));
55888
- var import_path62 = __toESM(require("path"));
56159
+ var import_fs67 = __toESM(require("fs"));
56160
+ var import_path63 = __toESM(require("path"));
55889
56161
  init_decision();
55890
56162
  var import_os55 = __toESM(require("os"));
55891
56163
  init_scan_summary();
@@ -55908,7 +56180,7 @@ function encodeProjectPath(projectPath) {
55908
56180
  }
55909
56181
  function sessionJsonlPath(projectPath, sessionId) {
55910
56182
  const encoded = encodeProjectPath(projectPath);
55911
- return import_path62.default.join(import_os55.default.homedir(), ".claude", "projects", encoded, `${sessionId}.jsonl`);
56183
+ return import_path63.default.join(import_os55.default.homedir(), ".claude", "projects", encoded, `${sessionId}.jsonl`);
55912
56184
  }
55913
56185
  function projectLabel(projectPath) {
55914
56186
  return projectPath.replace(import_os55.default.homedir(), "~");
@@ -55980,10 +56252,10 @@ function parseSessionLines(lines) {
55980
56252
  return { toolCalls, costUSD, hasSnapshot, modifiedFiles };
55981
56253
  }
55982
56254
  function loadAuditEntries(auditPath) {
55983
- const aPath = auditPath ?? import_path62.default.join(import_os55.default.homedir(), ".node9", "audit.log");
56255
+ const aPath = auditPath ?? import_path63.default.join(import_os55.default.homedir(), ".node9", "audit.log");
55984
56256
  let raw;
55985
56257
  try {
55986
- raw = import_fs66.default.readFileSync(aPath, "utf-8");
56258
+ raw = import_fs67.default.readFileSync(aPath, "utf-8");
55987
56259
  } catch {
55988
56260
  return [];
55989
56261
  }
@@ -56019,8 +56291,8 @@ function auditEntriesInWindow(entries, windowStart, windowEnd) {
56019
56291
  return result;
56020
56292
  }
56021
56293
  function buildGeminiSessions(days, allAuditEntries) {
56022
- const tmpDir = import_path62.default.join(import_os55.default.homedir(), ".gemini", "tmp");
56023
- if (!import_fs66.default.existsSync(tmpDir)) return [];
56294
+ const tmpDir = import_path63.default.join(import_os55.default.homedir(), ".gemini", "tmp");
56295
+ if (!import_fs67.default.existsSync(tmpDir)) return [];
56024
56296
  const cutoff = days !== null ? (() => {
56025
56297
  const d = /* @__PURE__ */ new Date();
56026
56298
  d.setDate(d.getDate() - days);
@@ -56029,35 +56301,35 @@ function buildGeminiSessions(days, allAuditEntries) {
56029
56301
  })() : null;
56030
56302
  let slugDirs;
56031
56303
  try {
56032
- slugDirs = import_fs66.default.readdirSync(tmpDir);
56304
+ slugDirs = import_fs67.default.readdirSync(tmpDir);
56033
56305
  } catch {
56034
56306
  return [];
56035
56307
  }
56036
56308
  const summaries = [];
56037
56309
  for (const slug2 of slugDirs) {
56038
- const slugPath = import_path62.default.join(tmpDir, slug2);
56310
+ const slugPath = import_path63.default.join(tmpDir, slug2);
56039
56311
  try {
56040
- if (!import_fs66.default.statSync(slugPath).isDirectory()) continue;
56312
+ if (!import_fs67.default.statSync(slugPath).isDirectory()) continue;
56041
56313
  } catch {
56042
56314
  continue;
56043
56315
  }
56044
- let projectRoot = import_path62.default.join(import_os55.default.homedir(), slug2);
56316
+ let projectRoot = import_path63.default.join(import_os55.default.homedir(), slug2);
56045
56317
  try {
56046
- projectRoot = import_fs66.default.readFileSync(import_path62.default.join(slugPath, ".project_root"), "utf-8").trim();
56318
+ projectRoot = import_fs67.default.readFileSync(import_path63.default.join(slugPath, ".project_root"), "utf-8").trim();
56047
56319
  } catch {
56048
56320
  }
56049
- const chatsDir = import_path62.default.join(slugPath, "chats");
56050
- if (!import_fs66.default.existsSync(chatsDir)) continue;
56321
+ const chatsDir = import_path63.default.join(slugPath, "chats");
56322
+ if (!import_fs67.default.existsSync(chatsDir)) continue;
56051
56323
  let chatFiles;
56052
56324
  try {
56053
- chatFiles = import_fs66.default.readdirSync(chatsDir).filter((f) => f.endsWith(".json"));
56325
+ chatFiles = import_fs67.default.readdirSync(chatsDir).filter((f) => f.endsWith(".json"));
56054
56326
  } catch {
56055
56327
  continue;
56056
56328
  }
56057
56329
  for (const chatFile of chatFiles) {
56058
56330
  let raw;
56059
56331
  try {
56060
- raw = import_fs66.default.readFileSync(import_path62.default.join(chatsDir, chatFile), "utf-8");
56332
+ raw = import_fs67.default.readFileSync(import_path63.default.join(chatsDir, chatFile), "utf-8");
56061
56333
  } catch {
56062
56334
  continue;
56063
56335
  }
@@ -56137,8 +56409,8 @@ function buildGeminiSessions(days, allAuditEntries) {
56137
56409
  return summaries;
56138
56410
  }
56139
56411
  function buildCodexSessions(days, allAuditEntries) {
56140
- const sessionsBase = import_path62.default.join(import_os55.default.homedir(), ".codex", "sessions");
56141
- if (!import_fs66.default.existsSync(sessionsBase)) return [];
56412
+ const sessionsBase = import_path63.default.join(import_os55.default.homedir(), ".codex", "sessions");
56413
+ if (!import_fs67.default.existsSync(sessionsBase)) return [];
56142
56414
  const cutoff = days !== null ? (() => {
56143
56415
  const d = /* @__PURE__ */ new Date();
56144
56416
  d.setDate(d.getDate() - days);
@@ -56147,29 +56419,29 @@ function buildCodexSessions(days, allAuditEntries) {
56147
56419
  })() : null;
56148
56420
  const jsonlFiles = [];
56149
56421
  try {
56150
- for (const year of import_fs66.default.readdirSync(sessionsBase)) {
56151
- const yearPath = import_path62.default.join(sessionsBase, year);
56422
+ for (const year of import_fs67.default.readdirSync(sessionsBase)) {
56423
+ const yearPath = import_path63.default.join(sessionsBase, year);
56152
56424
  try {
56153
- if (!import_fs66.default.statSync(yearPath).isDirectory()) continue;
56425
+ if (!import_fs67.default.statSync(yearPath).isDirectory()) continue;
56154
56426
  } catch {
56155
56427
  continue;
56156
56428
  }
56157
- for (const month of import_fs66.default.readdirSync(yearPath)) {
56158
- const monthPath = import_path62.default.join(yearPath, month);
56429
+ for (const month of import_fs67.default.readdirSync(yearPath)) {
56430
+ const monthPath = import_path63.default.join(yearPath, month);
56159
56431
  try {
56160
- if (!import_fs66.default.statSync(monthPath).isDirectory()) continue;
56432
+ if (!import_fs67.default.statSync(monthPath).isDirectory()) continue;
56161
56433
  } catch {
56162
56434
  continue;
56163
56435
  }
56164
- for (const day of import_fs66.default.readdirSync(monthPath)) {
56165
- const dayPath = import_path62.default.join(monthPath, day);
56436
+ for (const day of import_fs67.default.readdirSync(monthPath)) {
56437
+ const dayPath = import_path63.default.join(monthPath, day);
56166
56438
  try {
56167
- if (!import_fs66.default.statSync(dayPath).isDirectory()) continue;
56439
+ if (!import_fs67.default.statSync(dayPath).isDirectory()) continue;
56168
56440
  } catch {
56169
56441
  continue;
56170
56442
  }
56171
- for (const file of import_fs66.default.readdirSync(dayPath)) {
56172
- if (file.endsWith(".jsonl")) jsonlFiles.push(import_path62.default.join(dayPath, file));
56443
+ for (const file of import_fs67.default.readdirSync(dayPath)) {
56444
+ if (file.endsWith(".jsonl")) jsonlFiles.push(import_path63.default.join(dayPath, file));
56173
56445
  }
56174
56446
  }
56175
56447
  }
@@ -56181,7 +56453,7 @@ function buildCodexSessions(days, allAuditEntries) {
56181
56453
  for (const filePath of jsonlFiles) {
56182
56454
  let lines;
56183
56455
  try {
56184
- lines = import_fs66.default.readFileSync(filePath, "utf-8").split("\n");
56456
+ lines = import_fs67.default.readFileSync(filePath, "utf-8").split("\n");
56185
56457
  } catch {
56186
56458
  continue;
56187
56459
  }
@@ -56267,10 +56539,10 @@ function buildCodexSessions(days, allAuditEntries) {
56267
56539
  return summaries;
56268
56540
  }
56269
56541
  function buildSessions(days, historyPath) {
56270
- const hPath = historyPath ?? import_path62.default.join(import_os55.default.homedir(), ".claude", "history.jsonl");
56542
+ const hPath = historyPath ?? import_path63.default.join(import_os55.default.homedir(), ".claude", "history.jsonl");
56271
56543
  let historyRaw = "";
56272
56544
  try {
56273
- historyRaw = import_fs66.default.readFileSync(hPath, "utf-8");
56545
+ historyRaw = import_fs67.default.readFileSync(hPath, "utf-8");
56274
56546
  } catch {
56275
56547
  }
56276
56548
  const cutoff = days !== null ? (() => {
@@ -56294,7 +56566,7 @@ function buildSessions(days, historyPath) {
56294
56566
  const jsonlFile = sessionJsonlPath(entry.project, entry.sessionId);
56295
56567
  let sessionLines = [];
56296
56568
  try {
56297
- sessionLines = import_fs66.default.readFileSync(jsonlFile, "utf-8").split("\n");
56569
+ sessionLines = import_fs67.default.readFileSync(jsonlFile, "utf-8").split("\n");
56298
56570
  } catch {
56299
56571
  }
56300
56572
  const { toolCalls, costUSD, hasSnapshot, modifiedFiles } = parseSessionLines(sessionLines);
@@ -56688,12 +56960,12 @@ function registerSessionTaintCommand(program2) {
56688
56960
 
56689
56961
  // src/cli/commands/skill-pin.ts
56690
56962
  var import_chalk36 = __toESM(require("chalk"));
56691
- var import_fs67 = __toESM(require("fs"));
56963
+ var import_fs68 = __toESM(require("fs"));
56692
56964
  var import_os56 = __toESM(require("os"));
56693
- var import_path63 = __toESM(require("path"));
56965
+ var import_path64 = __toESM(require("path"));
56694
56966
  function wipeSkillSessions() {
56695
56967
  try {
56696
- import_fs67.default.rmSync(import_path63.default.join(import_os56.default.homedir(), ".node9", "skill-sessions"), {
56968
+ import_fs68.default.rmSync(import_path64.default.join(import_os56.default.homedir(), ".node9", "skill-sessions"), {
56697
56969
  recursive: true,
56698
56970
  force: true
56699
56971
  });
@@ -56775,15 +57047,15 @@ function registerSkillPinCommand(program2) {
56775
57047
  }
56776
57048
 
56777
57049
  // src/cli/commands/decisions.ts
56778
- var import_fs68 = __toESM(require("fs"));
57050
+ var import_fs69 = __toESM(require("fs"));
56779
57051
  var import_os57 = __toESM(require("os"));
56780
- var import_path64 = __toESM(require("path"));
57052
+ var import_path65 = __toESM(require("path"));
56781
57053
  var import_chalk37 = __toESM(require("chalk"));
56782
- var DECISIONS_FILE2 = import_path64.default.join(import_os57.default.homedir(), ".node9", "decisions.json");
57054
+ var DECISIONS_FILE2 = import_path65.default.join(import_os57.default.homedir(), ".node9", "decisions.json");
56783
57055
  function readDecisions() {
56784
57056
  try {
56785
- if (!import_fs68.default.existsSync(DECISIONS_FILE2)) return {};
56786
- const raw = import_fs68.default.readFileSync(DECISIONS_FILE2, "utf-8");
57057
+ if (!import_fs69.default.existsSync(DECISIONS_FILE2)) return {};
57058
+ const raw = import_fs69.default.readFileSync(DECISIONS_FILE2, "utf-8");
56787
57059
  const parsed = JSON.parse(raw);
56788
57060
  const out = {};
56789
57061
  for (const [k, v] of Object.entries(parsed)) {
@@ -56795,11 +57067,11 @@ function readDecisions() {
56795
57067
  }
56796
57068
  }
56797
57069
  function writeDecisions(d) {
56798
- const dir = import_path64.default.dirname(DECISIONS_FILE2);
56799
- if (!import_fs68.default.existsSync(dir)) import_fs68.default.mkdirSync(dir, { recursive: true });
57070
+ const dir = import_path65.default.dirname(DECISIONS_FILE2);
57071
+ if (!import_fs69.default.existsSync(dir)) import_fs69.default.mkdirSync(dir, { recursive: true });
56800
57072
  const tmp = `${DECISIONS_FILE2}.${process.pid}.tmp`;
56801
- import_fs68.default.writeFileSync(tmp, JSON.stringify(d, null, 2));
56802
- import_fs68.default.renameSync(tmp, DECISIONS_FILE2);
57073
+ import_fs69.default.writeFileSync(tmp, JSON.stringify(d, null, 2));
57074
+ import_fs69.default.renameSync(tmp, DECISIONS_FILE2);
56803
57075
  }
56804
57076
  function registerDecisionsCommand(program2) {
56805
57077
  const cmd = program2.command("decisions").description('Manage persistent "Always Allow" / "Always Deny" tool decisions');
@@ -56856,18 +57128,18 @@ Persistent decisions (${entries.length})
56856
57128
 
56857
57129
  // src/cli/commands/dlp.ts
56858
57130
  var import_chalk38 = __toESM(require("chalk"));
56859
- var import_fs69 = __toESM(require("fs"));
56860
- var import_path65 = __toESM(require("path"));
57131
+ var import_fs70 = __toESM(require("fs"));
57132
+ var import_path66 = __toESM(require("path"));
56861
57133
  var import_os58 = __toESM(require("os"));
56862
- var AUDIT_LOG = import_path65.default.join(import_os58.default.homedir(), ".node9", "audit.log");
56863
- var RESOLVED_FILE = import_path65.default.join(import_os58.default.homedir(), ".node9", "dlp-resolved.json");
57134
+ var AUDIT_LOG = import_path66.default.join(import_os58.default.homedir(), ".node9", "audit.log");
57135
+ var RESOLVED_FILE = import_path66.default.join(import_os58.default.homedir(), ".node9", "dlp-resolved.json");
56864
57136
  var ANSI_RE = /\x1b(?:\[[0-9;?]*[a-zA-Z]|\][^\x07\x1b]*(?:\x07|\x1b\\)|[@-_])/g;
56865
57137
  function stripAnsi(s) {
56866
57138
  return s.replace(ANSI_RE, "");
56867
57139
  }
56868
57140
  function loadResolved() {
56869
57141
  try {
56870
- const raw = JSON.parse(import_fs69.default.readFileSync(RESOLVED_FILE, "utf-8"));
57142
+ const raw = JSON.parse(import_fs70.default.readFileSync(RESOLVED_FILE, "utf-8"));
56871
57143
  return new Set(raw);
56872
57144
  } catch {
56873
57145
  return /* @__PURE__ */ new Set();
@@ -56875,13 +57147,13 @@ function loadResolved() {
56875
57147
  }
56876
57148
  function saveResolved(resolved) {
56877
57149
  try {
56878
- import_fs69.default.writeFileSync(RESOLVED_FILE, JSON.stringify([...resolved], null, 2), { mode: 384 });
57150
+ import_fs70.default.writeFileSync(RESOLVED_FILE, JSON.stringify([...resolved], null, 2), { mode: 384 });
56879
57151
  } catch {
56880
57152
  }
56881
57153
  }
56882
57154
  function loadDlpFindings() {
56883
- if (!import_fs69.default.existsSync(AUDIT_LOG)) return [];
56884
- return import_fs69.default.readFileSync(AUDIT_LOG, "utf-8").split("\n").flatMap((line) => {
57155
+ if (!import_fs70.default.existsSync(AUDIT_LOG)) return [];
57156
+ return import_fs70.default.readFileSync(AUDIT_LOG, "utf-8").split("\n").flatMap((line) => {
56885
57157
  if (!line.trim()) return [];
56886
57158
  try {
56887
57159
  const e = JSON.parse(line);
@@ -56979,15 +57251,15 @@ function registerDlpCommand(program2) {
56979
57251
 
56980
57252
  // src/cli/commands/mask.ts
56981
57253
  var import_chalk39 = __toESM(require("chalk"));
56982
- var import_fs70 = __toESM(require("fs"));
56983
- var import_path66 = __toESM(require("path"));
57254
+ var import_fs71 = __toESM(require("fs"));
57255
+ var import_path67 = __toESM(require("path"));
56984
57256
  var import_os59 = __toESM(require("os"));
56985
57257
  init_dlp();
56986
57258
  function findJsonlFiles(dir) {
56987
57259
  const results = [];
56988
- if (!import_fs70.default.existsSync(dir)) return results;
56989
- for (const entry of import_fs70.default.readdirSync(dir, { withFileTypes: true })) {
56990
- const full = import_path66.default.join(dir, entry.name);
57260
+ if (!import_fs71.default.existsSync(dir)) return results;
57261
+ for (const entry of import_fs71.default.readdirSync(dir, { withFileTypes: true })) {
57262
+ const full = import_path67.default.join(dir, entry.name);
56991
57263
  if (entry.isDirectory()) results.push(...findJsonlFiles(full));
56992
57264
  else if (entry.isFile() && entry.name.endsWith(".jsonl")) results.push(full);
56993
57265
  }
@@ -57030,7 +57302,7 @@ function redactJson(obj) {
57030
57302
  function processFile(filePath, dryRun) {
57031
57303
  let raw;
57032
57304
  try {
57033
- raw = import_fs70.default.readFileSync(filePath, "utf-8");
57305
+ raw = import_fs71.default.readFileSync(filePath, "utf-8");
57034
57306
  } catch {
57035
57307
  return { redactedLines: 0, patterns: [] };
57036
57308
  }
@@ -57062,14 +57334,14 @@ function processFile(filePath, dryRun) {
57062
57334
  }
57063
57335
  }
57064
57336
  if (!dryRun && redactedLines > 0) {
57065
- import_fs70.default.writeFileSync(filePath, newLines.join("\n"), "utf-8");
57337
+ import_fs71.default.writeFileSync(filePath, newLines.join("\n"), "utf-8");
57066
57338
  }
57067
57339
  return { redactedLines, patterns };
57068
57340
  }
57069
57341
  function processJsonFile(filePath, dryRun) {
57070
57342
  let raw;
57071
57343
  try {
57072
- raw = import_fs70.default.readFileSync(filePath, "utf-8");
57344
+ raw = import_fs71.default.readFileSync(filePath, "utf-8");
57073
57345
  } catch {
57074
57346
  return { redactedLines: 0, patterns: [] };
57075
57347
  }
@@ -57082,15 +57354,15 @@ function processJsonFile(filePath, dryRun) {
57082
57354
  const { value, modified, found } = redactJson(parsed);
57083
57355
  if (!modified) return { redactedLines: 0, patterns: [] };
57084
57356
  if (!dryRun) {
57085
- import_fs70.default.writeFileSync(filePath, JSON.stringify(value, null, 2), "utf-8");
57357
+ import_fs71.default.writeFileSync(filePath, JSON.stringify(value, null, 2), "utf-8");
57086
57358
  }
57087
57359
  return { redactedLines: 1, patterns: found };
57088
57360
  }
57089
57361
  function findJsonFiles(dir) {
57090
57362
  const results = [];
57091
- if (!import_fs70.default.existsSync(dir)) return results;
57092
- for (const entry of import_fs70.default.readdirSync(dir, { withFileTypes: true })) {
57093
- const full = import_path66.default.join(dir, entry.name);
57363
+ if (!import_fs71.default.existsSync(dir)) return results;
57364
+ for (const entry of import_fs71.default.readdirSync(dir, { withFileTypes: true })) {
57365
+ const full = import_path67.default.join(dir, entry.name);
57094
57366
  if (entry.isDirectory()) results.push(...findJsonFiles(full));
57095
57367
  else if (entry.isFile() && entry.name.endsWith(".json")) results.push(full);
57096
57368
  }
@@ -57100,8 +57372,8 @@ function registerMaskCommand(program2) {
57100
57372
  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) => {
57101
57373
  const dryRun = !!options.dryRun;
57102
57374
  const home = import_os59.default.homedir();
57103
- const claudeDir = import_path66.default.join(home, ".claude", "projects");
57104
- const geminiDir = import_path66.default.join(home, ".gemini", "tmp");
57375
+ const claudeDir = import_path67.default.join(home, ".claude", "projects");
57376
+ const geminiDir = import_path67.default.join(home, ".gemini", "tmp");
57105
57377
  const allFiles = [
57106
57378
  ...findJsonlFiles(claudeDir).map((p) => ({ path: p, type: "jsonl" })),
57107
57379
  ...findJsonFiles(geminiDir).map((p) => ({ path: p, type: "json" }))
@@ -57109,7 +57381,7 @@ function registerMaskCommand(program2) {
57109
57381
  const cutoff = options.all ? null : new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3);
57110
57382
  const filtered = cutoff ? allFiles.filter((f) => {
57111
57383
  try {
57112
- return import_fs70.default.statSync(f.path).mtime >= cutoff;
57384
+ return import_fs71.default.statSync(f.path).mtime >= cutoff;
57113
57385
  } catch {
57114
57386
  return false;
57115
57387
  }
@@ -57165,7 +57437,7 @@ function registerMaskCommand(program2) {
57165
57437
  // src/cli.ts
57166
57438
  init_blast();
57167
57439
  var { version } = JSON.parse(
57168
- import_fs73.default.readFileSync(import_path69.default.join(__dirname, "../package.json"), "utf-8")
57440
+ import_fs74.default.readFileSync(import_path70.default.join(__dirname, "../package.json"), "utf-8")
57169
57441
  );
57170
57442
  var program = new import_commander.Command();
57171
57443
  program.name("node9").description("The Sudo Command for AI Agents").version(version);
@@ -57344,15 +57616,15 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
57344
57616
  } catch {
57345
57617
  }
57346
57618
  if (options.purge) {
57347
- const node9Dir = import_path69.default.join(import_os62.default.homedir(), ".node9");
57348
- if (import_fs73.default.existsSync(node9Dir)) {
57619
+ const node9Dir = import_path70.default.join(import_os62.default.homedir(), ".node9");
57620
+ if (import_fs74.default.existsSync(node9Dir)) {
57349
57621
  const confirmed = await (0, import_prompts2.confirm)({
57350
57622
  message: `Permanently delete ${node9Dir} (config, audit log, credentials)?`,
57351
57623
  default: false
57352
57624
  });
57353
57625
  if (confirmed) {
57354
- import_fs73.default.rmSync(node9Dir, { recursive: true });
57355
- if (import_fs73.default.existsSync(node9Dir)) {
57626
+ import_fs74.default.rmSync(node9Dir, { recursive: true });
57627
+ if (import_fs74.default.existsSync(node9Dir)) {
57356
57628
  console.error(
57357
57629
  import_chalk41.default.red("\n \u26A0\uFE0F ~/.node9/ could not be fully deleted \u2014 remove it manually.")
57358
57630
  );
@@ -57477,7 +57749,7 @@ program.command("tail").description("Stream live agent activity to the terminal"
57477
57749
  });
57478
57750
  program.command("monitor").description("Live interactive dashboard \u2014 activity feed, approvals, security signals").action(async () => {
57479
57751
  try {
57480
- const dashboardPath = import_path69.default.join(__dirname, "dashboard.mjs");
57752
+ const dashboardPath = import_path70.default.join(__dirname, "dashboard.mjs");
57481
57753
  const dynamicImport = new Function("id", "return import(id)");
57482
57754
  const mod = await dynamicImport(`file://${dashboardPath}`);
57483
57755
  await mod.startMonitor();
@@ -57515,14 +57787,14 @@ Claude Code spawns this command every ~300ms and writes a JSON payload to stdin.
57515
57787
  Run "node9 addto claude" to register it as the statusLine.`
57516
57788
  ).argument("[subcommand]", 'Optional: "debug on" / "debug off" to toggle stdin logging').argument("[state]", 'on|off \u2014 used with "debug" subcommand').action(async (subcommand, state) => {
57517
57789
  if (subcommand === "debug") {
57518
- const flagFile = import_path69.default.join(import_os62.default.homedir(), ".node9", "hud-debug");
57790
+ const flagFile = import_path70.default.join(import_os62.default.homedir(), ".node9", "hud-debug");
57519
57791
  if (state === "on") {
57520
- import_fs73.default.mkdirSync(import_path69.default.dirname(flagFile), { recursive: true });
57521
- import_fs73.default.writeFileSync(flagFile, "");
57792
+ import_fs74.default.mkdirSync(import_path70.default.dirname(flagFile), { recursive: true });
57793
+ import_fs74.default.writeFileSync(flagFile, "");
57522
57794
  console.log("HUD debug logging enabled \u2192 ~/.node9/hud-debug.log");
57523
57795
  console.log("Tail it with: tail -f ~/.node9/hud-debug.log");
57524
57796
  } else if (state === "off") {
57525
- if (import_fs73.default.existsSync(flagFile)) import_fs73.default.unlinkSync(flagFile);
57797
+ if (import_fs74.default.existsSync(flagFile)) import_fs74.default.unlinkSync(flagFile);
57526
57798
  console.log("HUD debug logging disabled.");
57527
57799
  } else {
57528
57800
  console.error("Usage: node9 hud debug on|off");
@@ -57645,9 +57917,9 @@ if (process.argv[2] !== "daemon") {
57645
57917
  const isCheckHook = process.argv[2] === "check";
57646
57918
  if (isCheckHook) {
57647
57919
  if (process.env.NODE9_DEBUG === "1" || getConfig().settings.enableHookLogDebug) {
57648
- const logPath = import_path69.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
57920
+ const logPath = import_path70.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
57649
57921
  const msg = reason instanceof Error ? reason.message : String(reason);
57650
- import_fs73.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] UNHANDLED: ${msg}
57922
+ import_fs74.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] UNHANDLED: ${msg}
57651
57923
  `);
57652
57924
  }
57653
57925
  process.exit(0);