caveat-cli 0.16.1 → 0.16.3

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.
@@ -2721,7 +2721,7 @@ var require_dumper = __commonJS({
2721
2721
  var hasFoldableLine = false;
2722
2722
  var shouldTrackWidth = lineWidth !== -1;
2723
2723
  var previousLineBreak = -1;
2724
- var plain = isPlainSafeFirst2(string.charCodeAt(0)) && !isWhitespace2(string.charCodeAt(string.length - 1));
2724
+ var plain2 = isPlainSafeFirst2(string.charCodeAt(0)) && !isWhitespace2(string.charCodeAt(string.length - 1));
2725
2725
  if (singleLineOnly) {
2726
2726
  for (i2 = 0; i2 < string.length; i2++) {
2727
2727
  char = string.charCodeAt(i2);
@@ -2729,7 +2729,7 @@ var require_dumper = __commonJS({
2729
2729
  return STYLE_DOUBLE2;
2730
2730
  }
2731
2731
  prev_char = i2 > 0 ? string.charCodeAt(i2 - 1) : null;
2732
- plain = plain && isPlainSafe2(char, prev_char);
2732
+ plain2 = plain2 && isPlainSafe2(char, prev_char);
2733
2733
  }
2734
2734
  } else {
2735
2735
  for (i2 = 0; i2 < string.length; i2++) {
@@ -2745,12 +2745,12 @@ var require_dumper = __commonJS({
2745
2745
  return STYLE_DOUBLE2;
2746
2746
  }
2747
2747
  prev_char = i2 > 0 ? string.charCodeAt(i2 - 1) : null;
2748
- plain = plain && isPlainSafe2(char, prev_char);
2748
+ plain2 = plain2 && isPlainSafe2(char, prev_char);
2749
2749
  }
2750
2750
  hasFoldableLine = hasFoldableLine || shouldTrackWidth && (i2 - previousLineBreak - 1 > lineWidth && string[previousLineBreak + 1] !== " ");
2751
2751
  }
2752
2752
  if (!hasLineBreak && !hasFoldableLine) {
2753
- return plain && !testAmbiguousType(string) ? STYLE_PLAIN2 : STYLE_SINGLE2;
2753
+ return plain2 && !testAmbiguousType(string) ? STYLE_PLAIN2 : STYLE_SINGLE2;
2754
2754
  }
2755
2755
  if (indentPerLevel > 9 && needIndentIndicator2(string)) {
2756
2756
  return STYLE_DOUBLE2;
@@ -6112,7 +6112,7 @@ var require_semver2 = __commonJS({
6112
6112
  "../../node_modules/.pnpm/semver@7.7.4/node_modules/semver/index.js"(exports2, module2) {
6113
6113
  "use strict";
6114
6114
  var internalRe = require_re();
6115
- var constants = require_constants();
6115
+ var constants2 = require_constants();
6116
6116
  var SemVer = require_semver();
6117
6117
  var identifiers = require_identifiers();
6118
6118
  var parse2 = require_parse2();
@@ -6194,8 +6194,8 @@ var require_semver2 = __commonJS({
6194
6194
  re: internalRe.re,
6195
6195
  src: internalRe.src,
6196
6196
  tokens: internalRe.t,
6197
- SEMVER_SPEC_VERSION: constants.SEMVER_SPEC_VERSION,
6198
- RELEASE_TYPES: constants.RELEASE_TYPES,
6197
+ SEMVER_SPEC_VERSION: constants2.SEMVER_SPEC_VERSION,
6198
+ RELEASE_TYPES: constants2.RELEASE_TYPES,
6199
6199
  compareIdentifiers: identifiers.compareIdentifiers,
6200
6200
  rcompareIdentifiers: identifiers.rcompareIdentifiers
6201
6201
  };
@@ -8367,14 +8367,14 @@ function chooseScalarStyle(string, singleLineOnly, indentPerLevel, lineWidth, te
8367
8367
  var hasFoldableLine = false;
8368
8368
  var shouldTrackWidth = lineWidth !== -1;
8369
8369
  var previousLineBreak = -1;
8370
- var plain = isPlainSafeFirst(codePointAt(string, 0)) && isPlainSafeLast(codePointAt(string, string.length - 1));
8370
+ var plain2 = isPlainSafeFirst(codePointAt(string, 0)) && isPlainSafeLast(codePointAt(string, string.length - 1));
8371
8371
  if (singleLineOnly || forceQuotes) {
8372
8372
  for (i2 = 0; i2 < string.length; char >= 65536 ? i2 += 2 : i2++) {
8373
8373
  char = codePointAt(string, i2);
8374
8374
  if (!isPrintable(char)) {
8375
8375
  return STYLE_DOUBLE;
8376
8376
  }
8377
- plain = plain && isPlainSafe(char, prevChar, inblock);
8377
+ plain2 = plain2 && isPlainSafe(char, prevChar, inblock);
8378
8378
  prevChar = char;
8379
8379
  }
8380
8380
  } else {
@@ -8390,13 +8390,13 @@ function chooseScalarStyle(string, singleLineOnly, indentPerLevel, lineWidth, te
8390
8390
  } else if (!isPrintable(char)) {
8391
8391
  return STYLE_DOUBLE;
8392
8392
  }
8393
- plain = plain && isPlainSafe(char, prevChar, inblock);
8393
+ plain2 = plain2 && isPlainSafe(char, prevChar, inblock);
8394
8394
  prevChar = char;
8395
8395
  }
8396
8396
  hasFoldableLine = hasFoldableLine || shouldTrackWidth && (i2 - previousLineBreak - 1 > lineWidth && string[previousLineBreak + 1] !== " ");
8397
8397
  }
8398
8398
  if (!hasLineBreak && !hasFoldableLine) {
8399
- if (plain && !forceQuotes && !testAmbiguousType(string)) {
8399
+ if (plain2 && !forceQuotes && !testAmbiguousType(string)) {
8400
8400
  return STYLE_PLAIN;
8401
8401
  }
8402
8402
  return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE;
@@ -8963,7 +8963,7 @@ import { readFileSync as readFileSync2, readdirSync as readdirSync2, statSync, e
8963
8963
  import { join as join2, relative } from "node:path";
8964
8964
  function scanSource(opts) {
8965
8965
  const { db, source, entriesRoot } = opts;
8966
- const now = opts.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
8966
+ const now2 = opts.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
8967
8967
  db.exec("DROP TABLE IF EXISTS temp.touched");
8968
8968
  db.exec("CREATE TEMP TABLE touched(rowid INTEGER PRIMARY KEY)");
8969
8969
  const insertTouched = db.prepare("INSERT INTO touched (rowid) VALUES (?)");
@@ -8981,7 +8981,7 @@ function scanSource(opts) {
8981
8981
  path: rel,
8982
8982
  content: src,
8983
8983
  file_mtime: mtime,
8984
- indexed_at: now()
8984
+ indexed_at: now2()
8985
8985
  });
8986
8986
  const existing = db.prepare("SELECT rowid, file_mtime, path FROM entries WHERE source = ? AND id = ?").get(source, row.id);
8987
8987
  if (existing && existing.file_mtime === mtime && existing.path === rel) {
@@ -9351,7 +9351,7 @@ async function prewarmSealedKeys(opts) {
9351
9351
  return failures;
9352
9352
  }
9353
9353
  function scanSealedSource(opts) {
9354
- const now = opts.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
9354
+ const now2 = opts.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
9355
9355
  const bundle = readFileSync3(opts.bundlePath);
9356
9356
  const { header } = readSealedHeader(bundle);
9357
9357
  const contentKey = opts.keyProvider.resolveContentKey(header.keyId, header.keyserverUrl);
@@ -9370,7 +9370,7 @@ function scanSealedSource(opts) {
9370
9370
  path: file.relPath,
9371
9371
  content: file.content.toString("utf-8"),
9372
9372
  file_mtime: bundleMtime,
9373
- indexed_at: now()
9373
+ indexed_at: now2()
9374
9374
  });
9375
9375
  const existing = opts.db.prepare("SELECT rowid FROM entries WHERE source = ? AND id = ?").get(opts.source, row.id);
9376
9376
  const rowid = upsertEntry(opts.db, row);
@@ -9496,9 +9496,9 @@ function acquireFileLock(lockFilePath) {
9496
9496
  }
9497
9497
  return tryCreateLock(lockFilePath) ? { path: lockFilePath } : null;
9498
9498
  }
9499
- function releaseFileLock(lock) {
9499
+ function releaseFileLock(lock2) {
9500
9500
  try {
9501
- unlinkSync(lock.path);
9501
+ unlinkSync(lock2.path);
9502
9502
  } catch (err) {
9503
9503
  if (err.code !== "ENOENT") throw err;
9504
9504
  }
@@ -9506,8 +9506,8 @@ function releaseFileLock(lock) {
9506
9506
  function acquireReindexLock(caveatHome) {
9507
9507
  return acquireFileLock(lockPath(caveatHome));
9508
9508
  }
9509
- function releaseReindexLock(lock) {
9510
- releaseFileLock(lock);
9509
+ function releaseReindexLock(lock2) {
9510
+ releaseFileLock(lock2);
9511
9511
  }
9512
9512
  function reindexAllSources(opts) {
9513
9513
  const { db, paths, logger, keyProvider } = opts;
@@ -14699,6 +14699,10 @@ import {
14699
14699
  mkdirSync as mkdirSync3,
14700
14700
  readdirSync as readdirSync6,
14701
14701
  readFileSync as readFileSync5,
14702
+ linkSync,
14703
+ openSync,
14704
+ closeSync,
14705
+ chmodSync,
14702
14706
  rmSync as rmSync2,
14703
14707
  statSync as statSync5,
14704
14708
  unlinkSync as unlinkSync2,
@@ -14706,21 +14710,182 @@ import {
14706
14710
  } from "node:fs";
14707
14711
  import { join as join6 } from "node:path";
14708
14712
  import { randomBytes } from "node:crypto";
14713
+ import { createHash as createHash2 } from "node:crypto";
14714
+ import { DatabaseSync as DatabaseSync2 } from "node:sqlite";
14709
14715
  function sanitizeSessionId(raw) {
14710
14716
  const clean = raw.replace(/[^A-Za-z0-9_-]/g, "");
14711
14717
  return clean.length > 0 ? clean : "_unknown";
14712
14718
  }
14713
14719
  var GLOBAL_PENDING_SESSION = "_global";
14720
+ var PENDING_LOCK_BUSY_TIMEOUT_MS = 1e3;
14721
+ function withPendingQueueLock(caveatHome, operation) {
14722
+ const root = join6(caveatHome, "pending");
14723
+ mkdirSync3(root, { recursive: true, mode: 448 });
14724
+ const lockPath2 = join6(root, ".queue-lock.sqlite");
14725
+ const db = new DatabaseSync2(lockPath2);
14726
+ let transactionOpen = false;
14727
+ try {
14728
+ chmodSync(lockPath2, 384);
14729
+ db.exec(`PRAGMA busy_timeout = ${PENDING_LOCK_BUSY_TIMEOUT_MS}`);
14730
+ db.exec("BEGIN IMMEDIATE");
14731
+ transactionOpen = true;
14732
+ const result = operation();
14733
+ db.exec("COMMIT");
14734
+ transactionOpen = false;
14735
+ return result;
14736
+ } catch (error) {
14737
+ if (transactionOpen) {
14738
+ try {
14739
+ db.exec("ROLLBACK");
14740
+ } catch {
14741
+ }
14742
+ }
14743
+ throw error;
14744
+ } finally {
14745
+ db.close();
14746
+ }
14747
+ }
14714
14748
  function pendingDirFor(caveatHome, sessionId) {
14715
14749
  return join6(caveatHome, "pending", sanitizeSessionId(sessionId));
14716
14750
  }
14717
14751
  function appendPendingReminder(caveatHome, sessionId, text) {
14718
- const dir = pendingDirFor(caveatHome, sessionId);
14719
- mkdirSync3(dir, { recursive: true });
14720
- const name = `${Date.now()}-${randomBytes(4).toString("hex")}.txt`;
14721
- const path = join6(dir, name);
14722
- writeFileSync2(path, text, "utf-8");
14723
- return path;
14752
+ return withPendingQueueLock(caveatHome, () => {
14753
+ const dir = pendingDirFor(caveatHome, sessionId);
14754
+ mkdirSync3(dir, { recursive: true, mode: 448 });
14755
+ const name = `${Date.now()}-${randomBytes(4).toString("hex")}.txt`;
14756
+ const path = join6(dir, name);
14757
+ writeFileSync2(path, text, { encoding: "utf-8", mode: 384, flag: "wx" });
14758
+ return path;
14759
+ });
14760
+ }
14761
+ function buildPendingSemanticKey(input) {
14762
+ const refs = [...input.refs].map(({ source, id }) => ({ source, id })).sort((a, b2) => a.source.localeCompare(b2.source) || a.id.localeCompare(b2.id)).filter((ref, index, all) => index === 0 || ref.source !== all[index - 1].source || ref.id !== all[index - 1].id).map(({ source, id }) => [source, id]);
14763
+ return createHash2("sha256").update(JSON.stringify({
14764
+ agent: input.agent,
14765
+ surface: input.surface,
14766
+ refs,
14767
+ stopSignalDigest: input.stopSignalDigest ?? null
14768
+ })).digest("hex");
14769
+ }
14770
+ var CLAIM_TTL_MS = 5 * 60 * 1e3;
14771
+ function hasNonExpiredPendingClaim(sessionDir, nowMs) {
14772
+ const claimsDir = join6(sessionDir, ".claims");
14773
+ let claims;
14774
+ try {
14775
+ claims = readdirSync6(claimsDir).filter((entry) => entry.endsWith(".claim"));
14776
+ } catch (error) {
14777
+ if (error && typeof error === "object" && error.code === "ENOENT") return false;
14778
+ return true;
14779
+ }
14780
+ for (const claim of claims) {
14781
+ const path = join6(claimsDir, claim);
14782
+ try {
14783
+ let createdAt = statSync5(path).mtimeMs;
14784
+ try {
14785
+ const parsed = JSON.parse(readFileSync5(path, "utf-8"));
14786
+ if (typeof parsed.createdAt === "number") createdAt = parsed.createdAt;
14787
+ } catch {
14788
+ }
14789
+ if (nowMs - createdAt <= CLAIM_TTL_MS) return true;
14790
+ } catch {
14791
+ return true;
14792
+ }
14793
+ }
14794
+ return false;
14795
+ }
14796
+ function acquirePendingClaim(caveatHome, sessionId, key, options2 = {}) {
14797
+ return withPendingQueueLock(caveatHome, () => {
14798
+ if (!/^[a-f0-9]{64}$/.test(key)) throw new Error("pending semantic key is invalid");
14799
+ if (existsSync6(join6(pendingDirFor(caveatHome, sessionId), `${key}.ready`))) return null;
14800
+ const dir = join6(pendingDirFor(caveatHome, sessionId), ".claims");
14801
+ mkdirSync3(dir, { recursive: true, mode: 448 });
14802
+ const path = join6(dir, `${key}.claim`);
14803
+ const now2 = options2.now ?? Date.now();
14804
+ const ttlMs = options2.ttlMs ?? CLAIM_TTL_MS;
14805
+ for (let attempt = 0; attempt < 2; attempt++) {
14806
+ const ownerToken = randomBytes(16).toString("hex");
14807
+ try {
14808
+ const fd = openSync(path, "wx", 384);
14809
+ try {
14810
+ writeFileSync2(fd, JSON.stringify({ ownerToken, createdAt: now2 }), "utf-8");
14811
+ } finally {
14812
+ closeSync(fd);
14813
+ }
14814
+ if (existsSync6(join6(pendingDirFor(caveatHome, sessionId), `${key}.ready`))) {
14815
+ unlinkSync2(path);
14816
+ return null;
14817
+ }
14818
+ return { caveatHome, key, ownerToken, path };
14819
+ } catch (error) {
14820
+ if (!(error && typeof error === "object" && error.code === "EEXIST")) throw error;
14821
+ try {
14822
+ let createdAt = statSync5(path).mtimeMs;
14823
+ try {
14824
+ const parsed = JSON.parse(readFileSync5(path, "utf-8"));
14825
+ if (typeof parsed.createdAt === "number") createdAt = parsed.createdAt;
14826
+ } catch {
14827
+ }
14828
+ if (now2 - createdAt <= ttlMs) return null;
14829
+ unlinkSync2(path);
14830
+ } catch (retryError) {
14831
+ if (retryError && typeof retryError === "object" && retryError.code === "ENOENT") continue;
14832
+ return null;
14833
+ }
14834
+ }
14835
+ }
14836
+ return null;
14837
+ });
14838
+ }
14839
+ function releasePendingClaim(claim) {
14840
+ withPendingQueueLock(claim.caveatHome, () => {
14841
+ try {
14842
+ const parsed = JSON.parse(readFileSync5(claim.path, "utf-8"));
14843
+ if (parsed.ownerToken !== claim.ownerToken) return;
14844
+ unlinkSync2(claim.path);
14845
+ } catch (error) {
14846
+ if (error && typeof error === "object" && error.code === "ENOENT") return;
14847
+ throw error;
14848
+ }
14849
+ });
14850
+ }
14851
+ function publishPendingReminder(caveatHome, sessionId, semanticKey, text) {
14852
+ if (!/^[a-f0-9]{64}$/.test(semanticKey)) throw new Error("pending semantic key is invalid");
14853
+ const ready = join6(pendingDirFor(caveatHome, sessionId), `${semanticKey}.ready`);
14854
+ if (existsSync6(ready)) return { path: ready, published: false };
14855
+ try {
14856
+ return withPendingQueueLock(caveatHome, () => {
14857
+ const dir = pendingDirFor(caveatHome, sessionId);
14858
+ mkdirSync3(dir, { recursive: true, mode: 448 });
14859
+ const temp = join6(dir, `.${semanticKey}.${randomBytes(12).toString("hex")}.tmp`);
14860
+ writeFileSync2(temp, text, { encoding: "utf-8", mode: 384, flag: "wx" });
14861
+ try {
14862
+ linkSync(temp, ready);
14863
+ return { path: ready, published: true };
14864
+ } catch (error) {
14865
+ if (error && typeof error === "object" && error.code === "EEXIST") return { path: ready, published: false };
14866
+ throw error;
14867
+ } finally {
14868
+ try {
14869
+ unlinkSync2(temp);
14870
+ } catch (error) {
14871
+ if (!(error && typeof error === "object" && error.code === "ENOENT")) throw error;
14872
+ }
14873
+ }
14874
+ });
14875
+ } catch (error) {
14876
+ if (existsSync6(ready)) return { path: ready, published: false };
14877
+ throw error;
14878
+ }
14879
+ }
14880
+ function buildAndPublishPendingReminder(caveatHome, sessionId, semanticKey, build) {
14881
+ const claim = acquirePendingClaim(caveatHome, sessionId, semanticKey);
14882
+ if (!claim) return { ran: false, published: false };
14883
+ try {
14884
+ const result = publishPendingReminder(caveatHome, sessionId, claim.key, build());
14885
+ return { ran: true, published: result.published };
14886
+ } finally {
14887
+ releasePendingClaim(claim);
14888
+ }
14724
14889
  }
14725
14890
  function appendGlobalPendingReminder(caveatHome, text) {
14726
14891
  return appendPendingReminder(caveatHome, GLOBAL_PENDING_SESSION, text);
@@ -14730,55 +14895,61 @@ function cleanupStalePendingDirs(caveatHome, options2 = {}) {
14730
14895
  if (staleDays < 0) {
14731
14896
  throw new Error(`cleanupStalePendingDirs: staleDays must be >= 0 (got ${staleDays})`);
14732
14897
  }
14733
- const now = options2.now ?? /* @__PURE__ */ new Date();
14734
- const cutoffMs = now.getTime() - staleDays * 24 * 60 * 60 * 1e3;
14898
+ const now2 = options2.now ?? /* @__PURE__ */ new Date();
14899
+ const cutoffMs = now2.getTime() - staleDays * 24 * 60 * 60 * 1e3;
14735
14900
  const root = join6(caveatHome, "pending");
14736
14901
  if (!existsSync6(root)) return { removed: [], kept: 0 };
14737
- let entries;
14738
- try {
14739
- entries = readdirSync6(root);
14740
- } catch {
14741
- return { removed: [], kept: 0 };
14742
- }
14743
- const removed = [];
14744
- let kept = 0;
14745
- for (const entry of entries) {
14746
- const sub = join6(root, entry);
14747
- let subStat;
14902
+ return withPendingQueueLock(caveatHome, () => {
14903
+ let entries;
14748
14904
  try {
14749
- subStat = statSync5(sub);
14905
+ entries = readdirSync6(root);
14750
14906
  } catch {
14751
- continue;
14907
+ return { removed: [], kept: 0 };
14752
14908
  }
14753
- if (!subStat.isDirectory()) continue;
14754
- let newest = subStat.mtimeMs;
14755
- let scanFailed = false;
14756
- try {
14757
- for (const f of readdirSync6(sub)) {
14758
- const fp = join6(sub, f);
14759
- try {
14760
- const fs = statSync5(fp);
14761
- if (fs.mtimeMs > newest) newest = fs.mtimeMs;
14762
- } catch {
14763
- scanFailed = true;
14764
- break;
14909
+ const removed = [];
14910
+ let kept = 0;
14911
+ for (const entry of entries) {
14912
+ const sub = join6(root, entry);
14913
+ let subStat;
14914
+ try {
14915
+ subStat = statSync5(sub);
14916
+ } catch {
14917
+ continue;
14918
+ }
14919
+ if (!subStat.isDirectory()) continue;
14920
+ if (hasNonExpiredPendingClaim(sub, now2.getTime())) {
14921
+ kept++;
14922
+ continue;
14923
+ }
14924
+ let newest = subStat.mtimeMs;
14925
+ let scanFailed = false;
14926
+ try {
14927
+ for (const f of readdirSync6(sub)) {
14928
+ const fp = join6(sub, f);
14929
+ try {
14930
+ const fileStat = statSync5(fp);
14931
+ if (fileStat.mtimeMs > newest) newest = fileStat.mtimeMs;
14932
+ } catch {
14933
+ scanFailed = true;
14934
+ break;
14935
+ }
14765
14936
  }
14937
+ } catch {
14938
+ scanFailed = true;
14939
+ }
14940
+ if (scanFailed || newest >= cutoffMs) {
14941
+ kept++;
14942
+ continue;
14943
+ }
14944
+ try {
14945
+ rmSync2(sub, { recursive: true, force: true });
14946
+ removed.push(sub);
14947
+ } catch {
14948
+ kept++;
14766
14949
  }
14767
- } catch {
14768
- scanFailed = true;
14769
- }
14770
- if (scanFailed || newest >= cutoffMs) {
14771
- kept++;
14772
- continue;
14773
- }
14774
- try {
14775
- rmSync2(sub, { recursive: true, force: true });
14776
- removed.push(sub);
14777
- } catch {
14778
- kept++;
14779
14950
  }
14780
- }
14781
- return { removed, kept };
14951
+ return { removed, kept };
14952
+ });
14782
14953
  }
14783
14954
  function maybeSweepPendingDirs(caveatHome, options2 = {}) {
14784
14955
  if (process.env.CAVEAT_PENDING_SWEEP === "off") {
@@ -14791,55 +14962,70 @@ function maybeSweepPendingDirs(caveatHome, options2 = {}) {
14791
14962
  `maybeSweepPendingDirs: debounceDays must be >= 0 (got ${debounceDays})`
14792
14963
  );
14793
14964
  }
14794
- const now = options2.now ?? /* @__PURE__ */ new Date();
14965
+ const now2 = options2.now ?? /* @__PURE__ */ new Date();
14795
14966
  const pendingRoot = join6(caveatHome, "pending");
14796
14967
  if (!existsSync6(pendingRoot)) return { skipped: "no_pending_dir" };
14797
14968
  const marker = join6(pendingRoot, ".last-sweep");
14798
14969
  try {
14799
14970
  const m = statSync5(marker);
14800
- const ageMs = now.getTime() - m.mtimeMs;
14971
+ const ageMs = now2.getTime() - m.mtimeMs;
14801
14972
  if (ageMs < debounceDays * 24 * 60 * 60 * 1e3) {
14802
14973
  return { skipped: "debounced" };
14803
14974
  }
14804
14975
  } catch {
14805
14976
  }
14806
- const result = cleanupStalePendingDirs(caveatHome, { staleDays, now });
14977
+ const result = cleanupStalePendingDirs(caveatHome, { staleDays, now: now2 });
14807
14978
  try {
14808
14979
  writeFileSync2(marker, "", "utf-8");
14809
14980
  } catch {
14810
14981
  }
14811
14982
  return { swept: result };
14812
14983
  }
14813
- function drainPendingReminders(caveatHome, sessionId) {
14984
+ function drainPendingRemindersDetailed(caveatHome, sessionId, fs = {}) {
14814
14985
  const dir = pendingDirFor(caveatHome, sessionId);
14815
- if (!existsSync6(dir)) return [];
14816
- let entries;
14986
+ if (!existsSync6(dir)) return { reminders: [], cleanupFailures: [] };
14817
14987
  try {
14818
- entries = readdirSync6(dir).filter((f) => f.endsWith(".txt")).sort();
14988
+ return withPendingQueueLock(caveatHome, () => {
14989
+ let entries;
14990
+ try {
14991
+ entries = readdirSync6(dir).filter((f) => f.endsWith(".txt") || f.endsWith(".ready"));
14992
+ } catch {
14993
+ return { reminders: [], cleanupFailures: ["pending directory read failed"] };
14994
+ }
14995
+ const cleanupFailures = [];
14996
+ entries.sort((a, b2) => {
14997
+ try {
14998
+ const diff = statSync5(join6(dir, a)).mtimeMs - statSync5(join6(dir, b2)).mtimeMs;
14999
+ return diff || a.localeCompare(b2);
15000
+ } catch {
15001
+ return a.localeCompare(b2);
15002
+ }
15003
+ });
15004
+ const reminders = [];
15005
+ for (const entry of entries) {
15006
+ const path = join6(dir, entry);
15007
+ try {
15008
+ reminders.push(fs.read ? fs.read(path) : readFileSync5(path, "utf-8"));
15009
+ } catch {
15010
+ cleanupFailures.push(entry);
15011
+ continue;
15012
+ }
15013
+ try {
15014
+ if (fs.unlink) fs.unlink(path);
15015
+ else unlinkSync2(path);
15016
+ } catch {
15017
+ cleanupFailures.push(entry);
15018
+ }
15019
+ }
15020
+ return { reminders, cleanupFailures };
15021
+ });
14819
15022
  } catch {
14820
- return [];
15023
+ return { reminders: [], cleanupFailures: ["pending queue lock unavailable"] };
14821
15024
  }
14822
- const out = [];
14823
- for (const entry of entries) {
14824
- const path = join6(dir, entry);
14825
- try {
14826
- out.push(readFileSync5(path, "utf-8"));
14827
- } catch {
14828
- continue;
14829
- }
14830
- try {
14831
- unlinkSync2(path);
14832
- } catch {
14833
- }
14834
- }
14835
- return out;
14836
- }
14837
- function drainGlobalPendingReminders(caveatHome) {
14838
- return drainPendingReminders(caveatHome, GLOBAL_PENDING_SESSION);
14839
15025
  }
14840
15026
 
14841
15027
  // ../../packages/core/dist/sealedKeys.js
14842
- import { createHash as createHash2, randomBytes as randomBytes2 } from "node:crypto";
15028
+ import { createHash as createHash3, randomBytes as randomBytes2 } from "node:crypto";
14843
15029
  import {
14844
15030
  existsSync as existsSync7,
14845
15031
  mkdirSync as mkdirSync4,
@@ -14891,7 +15077,7 @@ function memoryKey(keyserverUrl, keyId) {
14891
15077
  ${keyId}`;
14892
15078
  }
14893
15079
  function cacheFilePath(caveatHome, keyserverUrl, keyId) {
14894
- const digest = createHash2("sha256").update(`${keyserverUrl}
15080
+ const digest = createHash3("sha256").update(`${keyserverUrl}
14895
15081
  ${keyId}`).digest("hex").slice(0, 32);
14896
15082
  return join7(caveatHome, "keys", `${digest}.json`);
14897
15083
  }
@@ -15248,7 +15434,7 @@ function errorMessage2(err) {
15248
15434
  }
15249
15435
 
15250
15436
  // ../../packages/core/dist/autoSync.js
15251
- import { createHash as createHash3 } from "node:crypto";
15437
+ import { createHash as createHash4 } from "node:crypto";
15252
15438
  import { mkdirSync as mkdirSync6, readFileSync as readFileSync7, renameSync as renameSync3, writeFileSync as writeFileSync5 } from "node:fs";
15253
15439
  import { dirname as dirname5, join as join9 } from "node:path";
15254
15440
  var AUTO_SYNC_DEBOUNCE_MS = 24 * 60 * 60 * 1e3;
@@ -15346,8 +15532,8 @@ function autoSyncNotification(outcome) {
15346
15532
  }
15347
15533
  async function runAutoSync(opts) {
15348
15534
  if (process.env[CAVEAT_AUTO_SYNC_ENV] === "off") return { ran: false };
15349
- const lock = acquireFileLock(autoSyncLockPath(opts.caveatHome));
15350
- if (!lock) return { ran: false };
15535
+ const lock2 = acquireFileLock(autoSyncLockPath(opts.caveatHome));
15536
+ if (!lock2) return { ran: false };
15351
15537
  let reindexLock = null;
15352
15538
  try {
15353
15539
  reindexLock = acquireReindexLock(opts.caveatHome);
@@ -15428,7 +15614,7 @@ async function runAutoSync(opts) {
15428
15614
  }
15429
15615
  }
15430
15616
  try {
15431
- releaseFileLock(lock);
15617
+ releaseFileLock(lock2);
15432
15618
  } catch (err) {
15433
15619
  opts.logger.warn(`autosync lock release failed: ${errorMessage3(err)}`);
15434
15620
  }
@@ -15450,7 +15636,7 @@ async function reindexAndMark2(opts) {
15450
15636
  }
15451
15637
  }
15452
15638
  function sha256(input) {
15453
- return createHash3("sha256").update(input).digest("hex");
15639
+ return createHash4("sha256").update(input).digest("hex");
15454
15640
  }
15455
15641
  function errorMessage3(err) {
15456
15642
  return err instanceof Error ? err.message : String(err);
@@ -15707,7 +15893,40 @@ function toSearchResult2(row) {
15707
15893
  environment: fm.environment ?? {}
15708
15894
  };
15709
15895
  }
15710
- function findCaveatsForPrompt(db, prompt, opts = {}) {
15896
+ function findCaveatsForHook(db, input, opts = {}) {
15897
+ if (input.surface === "user_prompt") {
15898
+ const prompt = input.topicText || input.failureText;
15899
+ return findCaveatsForText(db, prompt, opts);
15900
+ }
15901
+ if (input.surface === "stop") {
15902
+ return findCaveatsForText(db, input.failureText, opts);
15903
+ }
15904
+ const failureTokens = new Set(
15905
+ buildPromptCandidates(input.failureText).map((candidate) => candidate.token.toLowerCase())
15906
+ );
15907
+ return findCaveatsForText(
15908
+ db,
15909
+ [input.topicText, input.failureText].filter(Boolean).join("\n"),
15910
+ opts,
15911
+ failureTokens
15912
+ );
15913
+ }
15914
+ function findCaveatsForHookSegments(db, inputs, opts = {}) {
15915
+ const limit = opts.limit ?? DEFAULT_REMINDER_HIT_LIMIT;
15916
+ const out = [];
15917
+ const seen = /* @__PURE__ */ new Set();
15918
+ for (const input of inputs) {
15919
+ for (const hit of findCaveatsForHook(db, input, { ...opts, limit })) {
15920
+ const key = `${hit.source}\0${hit.id}`;
15921
+ if (seen.has(key)) continue;
15922
+ seen.add(key);
15923
+ out.push(hit);
15924
+ if (out.length >= limit) return out;
15925
+ }
15926
+ }
15927
+ return out;
15928
+ }
15929
+ function findCaveatsForText(db, prompt, opts = {}, symptomEvidenceTokens) {
15711
15930
  if (typeof prompt !== "string" || prompt.length === 0) return [];
15712
15931
  const candidates = buildPromptCandidates(prompt);
15713
15932
  if (candidates.length === 0) return [];
@@ -15746,7 +15965,7 @@ function findCaveatsForPrompt(db, prompt, opts = {}) {
15746
15965
  perEntry.set(row.rowid, entry);
15747
15966
  }
15748
15967
  entry.groups.add(cand.group);
15749
- if (entry.symptomLower !== null && tokenAppearsIn(tokLower, entry.symptomLower)) {
15968
+ if (entry.symptomLower !== null && (symptomEvidenceTokens === void 0 || symptomEvidenceTokens.has(tokLower)) && tokenAppearsIn(tokLower, entry.symptomLower)) {
15750
15969
  entry.symptomTokens.add(tokLower);
15751
15970
  }
15752
15971
  if (entry.topicalLower !== null && tokenAppearsIn(tokLower, entry.topicalLower)) {
@@ -16152,9 +16371,9 @@ function readCodexSessionSignals(transcriptPath) {
16152
16371
  }
16153
16372
 
16154
16373
  // ../../packages/core/dist/markHit.js
16155
- function markHit(db, keys, now = () => (/* @__PURE__ */ new Date()).toISOString()) {
16374
+ function markHit(db, keys, now2 = () => (/* @__PURE__ */ new Date()).toISOString()) {
16156
16375
  if (keys.length === 0) return;
16157
- const ts = now();
16376
+ const ts = now2();
16158
16377
  const stmt = db.prepare(
16159
16378
  "UPDATE entries SET last_hit_at = ? WHERE source = ? AND id = ?"
16160
16379
  );
@@ -16164,14 +16383,14 @@ function markHit(db, keys, now = () => (/* @__PURE__ */ new Date()).toISOString(
16164
16383
  }
16165
16384
 
16166
16385
  // ../../packages/core/dist/hookQueryLog.js
16167
- import { appendFileSync, chmodSync, mkdirSync as mkdirSync7, renameSync as renameSync4, statSync as statSync6, unlinkSync as unlinkSync3 } from "node:fs";
16386
+ import { appendFileSync, chmodSync as chmodSync2, mkdirSync as mkdirSync7, renameSync as renameSync4, statSync as statSync6, unlinkSync as unlinkSync3 } from "node:fs";
16168
16387
  import { join as join11, resolve as resolve3 } from "node:path";
16169
16388
  var CAVEAT_HOOK_QUERY_LOG_ENV = "CAVEAT_HOOK_QUERY_LOG";
16170
16389
  var HOOK_QUERY_LOG_MAX_BYTES = 1024 * 1024;
16171
16390
  var HOOK_QUERY_LOG_MAX_QUERY_CODE_UNITS = 1e3;
16172
16391
  var fsDependencies = {
16173
16392
  appendFileSync,
16174
- chmodSync,
16393
+ chmodSync: chmodSync2,
16175
16394
  mkdirSync: mkdirSync7,
16176
16395
  renameSync: renameSync4,
16177
16396
  statSync: statSync6,
@@ -16234,8 +16453,8 @@ function logHookQueryMiss(miss, dependencies = fsDependencies) {
16234
16453
  function listStale(db, opts = {}) {
16235
16454
  const days = opts.days ?? 90;
16236
16455
  const limit = opts.limit ?? 50;
16237
- const now = (opts.now ?? (() => /* @__PURE__ */ new Date()))();
16238
- const cutoff = new Date(now.getTime() - days * 24 * 60 * 60 * 1e3).toISOString();
16456
+ const now2 = (opts.now ?? (() => /* @__PURE__ */ new Date()))();
16457
+ const cutoff = new Date(now2.getTime() - days * 24 * 60 * 60 * 1e3).toISOString();
16239
16458
  const conditions = ["(last_hit_at IS NULL OR last_hit_at < ?)"];
16240
16459
  const params = [cutoff];
16241
16460
  if (opts.visibility === "public" || opts.visibility === "private") {
@@ -16261,7 +16480,7 @@ function listStale(db, opts = {}) {
16261
16480
  }
16262
16481
 
16263
16482
  // ../../packages/core/dist/publishScan.js
16264
- import { createHash as createHash4 } from "node:crypto";
16483
+ import { createHash as createHash5 } from "node:crypto";
16265
16484
  import { existsSync as existsSync13, readFileSync as readFileSync11, writeFileSync as writeFileSync7 } from "node:fs";
16266
16485
  import { join as join12, basename as basename2 } from "node:path";
16267
16486
  import { homedir as homedir2, userInfo as userInfo2 } from "node:os";
@@ -16292,7 +16511,7 @@ var WIN_UNC_PATH_RE = /\\\\[^\\\s"'`<>()|]+\\[^\\\s"'`<>()|]+(?:\\[^\\\s"'`<>()|
16292
16511
  var PRIVATE_IP_RE = /\b(?:10\.(?:\d{1,3}\.){2}\d{1,3}|172\.(?:1[6-9]|2\d|3[01])\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3}|127\.\d{1,3}\.\d{1,3}\.\d{1,3}|169\.254\.\d{1,3}\.\d{1,3})\b/g;
16293
16512
  var EMAIL_RE = /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g;
16294
16513
  function sha2562(raw) {
16295
- return createHash4("sha256").update(raw).digest("hex");
16514
+ return createHash5("sha256").update(raw).digest("hex");
16296
16515
  }
16297
16516
  function findingDigest(opts) {
16298
16517
  const pemContext = opts.rule === "pem-private-key" ? `\0${opts.fileDigest}\0${opts.lineNumber}\0${opts.index}` : "";
@@ -16522,7 +16741,7 @@ var PublishScanError = class extends Error {
16522
16741
  };
16523
16742
 
16524
16743
  // ../../packages/core/dist/publish.js
16525
- import { createHash as createHash5 } from "node:crypto";
16744
+ import { createHash as createHash6 } from "node:crypto";
16526
16745
  import { existsSync as existsSync14, mkdirSync as mkdirSync8, readFileSync as readFileSync12, readdirSync as readdirSync8, rmSync as rmSync5, writeFileSync as writeFileSync8 } from "node:fs";
16527
16746
  import { dirname as dirname7, join as join13, relative as relative3 } from "node:path";
16528
16747
 
@@ -16661,7 +16880,7 @@ ${bad.join("\n")}`);
16661
16880
  return { fileCount: unsealed.files.length };
16662
16881
  }
16663
16882
  function sha2563(content) {
16664
- return createHash5("sha256").update(content).digest("hex");
16883
+ return createHash6("sha256").update(content).digest("hex");
16665
16884
  }
16666
16885
  function diffFiles(previous, next) {
16667
16886
  const before = new Map(previous.map((file) => [file.relPath, sha2563(file.content)]));
@@ -17022,9 +17241,321 @@ function boundedCount(value) {
17022
17241
  return Math.min(1e4, Math.max(0, Math.floor(value)));
17023
17242
  }
17024
17243
 
17244
+ // ../../packages/core/dist/runtimeErrors.js
17245
+ import { spawnSync } from "node:child_process";
17246
+ import { createHash as createHash7, randomBytes as randomBytes3 } from "node:crypto";
17247
+ import { closeSync as closeSync2, constants, existsSync as existsSync15, fstatSync, lstatSync, mkdirSync as mkdirSync9, openSync as openSync2, readFileSync as readFileSync13, renameSync as renameSync5, rmSync as rmSync6, statSync as statSync7, writeFileSync as writeFileSync9 } from "node:fs";
17248
+ import { arch as hostArch, homedir as homedir3, platform as hostPlatform } from "node:os";
17249
+ import { dirname as dirname8, join as join14 } from "node:path";
17250
+ import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
17251
+ var RUNTIME_ERRORS_SCHEMA = "caveat.runtime_errors.v1";
17252
+ var STATE_VERSION = "1.0";
17253
+ var MAX_RECORDS = 256;
17254
+ var RETENTION_MS = 30 * 864e5;
17255
+ var MAX_CONFIG_BYTES = 64 * 1024;
17256
+ var definitions = {
17257
+ "CAVEAT.DATABASE_OPEN_FAILED": { component: "database", severity: "high", template: "Caveat database open failed" },
17258
+ "CAVEAT.INDEX_FAILED": { component: "index", severity: "high", template: "Caveat index operation failed" },
17259
+ "CAVEAT.SYNC_FAILED": { component: "sync", severity: "high", template: "Caveat own sync failed" },
17260
+ "CAVEAT.MCP_SERVER_FAILED": { component: "mcp", severity: "high", template: "Caveat MCP server failed" },
17261
+ "CAVEAT.MCP_TOOL_FAILED": { component: "mcp_tool", severity: "high", template: "Caveat MCP tool handler failed" },
17262
+ "CAVEAT.CLAUDE_HOOK_FAILED": { component: "claude_hook", severity: "high", template: "Caveat Claude hook failed" },
17263
+ "CAVEAT.CODEX_HOOK_FAILED": { component: "codex_hook", severity: "high", template: "Caveat Codex hook failed" }
17264
+ };
17265
+ function normalizeOptions(options2 = {}) {
17266
+ return "env" in options2 || "configPath" in options2 || "storePath" in options2 || "version" in options2 || "isWindows" in options2 ? options2 : { env: options2 };
17267
+ }
17268
+ var plain = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
17269
+ var exact = (v, keys) => Object.keys(v).length === keys.length && keys.every((key) => Object.hasOwn(v, key));
17270
+ var validTime = (v) => typeof v === "string" && Number.isFinite(Date.parse(v)) && new Date(v).toISOString() === v;
17271
+ var validVersion = (v) => typeof v === "string" && /^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/.test(v);
17272
+ var validOs = (v) => typeof v === "string" && ["darwin", "linux", "windows"].includes(v);
17273
+ var validArch = (v) => typeof v === "string" && ["x64", "arm64", "arm", "ia32"].includes(v);
17274
+ var windows = (env) => env.OS === "Windows_NT" || hostPlatform() === "win32";
17275
+ function defaultFactoryReporterConfigPath(env = process.env) {
17276
+ const home = env.HOME || env.USERPROFILE || homedir3();
17277
+ return windows(env) ? join14(env.LOCALAPPDATA || join14(home, "AppData", "Local"), "dotagents", "factory-reporter", "config.json") : join14(env.XDG_CONFIG_HOME || join14(home, ".config"), "dotagents", "factory-reporter.json");
17278
+ }
17279
+ function runtimeErrorsStatePath(env = process.env) {
17280
+ const home = env.HOME || env.USERPROFILE || homedir3();
17281
+ return windows(env) ? join14(env.LOCALAPPDATA || join14(home, "AppData", "Local"), "caveat", "runtime-errors.json") : join14(env.XDG_STATE_HOME || join14(home, ".local", "state"), "caveat", "runtime-errors.json");
17282
+ }
17283
+ function collectionEnabled(options2 = {}) {
17284
+ const env = options2.env ?? process.env;
17285
+ try {
17286
+ const path = options2.configPath ?? defaultFactoryReporterConfigPath(env);
17287
+ const isWin = (options2.isWindows ?? windows)(env);
17288
+ const before = lstatSync(path);
17289
+ if (!before.isFile() || before.isSymbolicLink() || before.size > MAX_CONFIG_BYTES) return false;
17290
+ if (isWin) secureWindowsAcl(path, options2.aclRunner);
17291
+ else assertPosix(before, 384);
17292
+ const fd = openSync2(path, constants.O_RDONLY | constants.O_NONBLOCK | (constants.O_NOFOLLOW ?? 0));
17293
+ let text;
17294
+ try {
17295
+ const after = fstatSync(fd);
17296
+ if (before.dev !== after.dev || before.ino !== after.ino || after.size > MAX_CONFIG_BYTES) return false;
17297
+ if (!isWin) assertPosix(after, 384);
17298
+ text = readFileSync13(fd, "utf8");
17299
+ } finally {
17300
+ closeSync2(fd);
17301
+ }
17302
+ const config = JSON.parse(text);
17303
+ return plain(config) && exact(config, ["schema_version", "host", "collection", "reporting"]) && config.schema_version === "1.0" && plain(config.host) && exact(config.host, ["id", "profile"]) && typeof config.host.id === "string" && /^[a-z0-9][a-z0-9._-]{0,63}$/.test(config.host.id) && ["server", "mac", "wsl", "windows-native"].includes(config.host.profile) && plain(config.collection) && exact(config.collection, ["enabled"]) && config.collection.enabled === true && canonicalReporting(config.reporting);
17304
+ } catch {
17305
+ return false;
17306
+ }
17307
+ }
17308
+ var empty = () => ({ schema: RUNTIME_ERRORS_SCHEMA, next_sequence: 1, acknowledged_through: 0, records: [] });
17309
+ function fingerprint(code) {
17310
+ const d = definitions[code];
17311
+ return createHash7("sha256").update(`caveat\0${d.component}\0${code}\0${d.template}`).digest("hex");
17312
+ }
17313
+ function ensureSafeDir(dir, isWin, options2 = {}) {
17314
+ const existed = existsSync15(dir);
17315
+ mkdirSync9(dir, { recursive: true, mode: 448 });
17316
+ const s = lstatSync(dir);
17317
+ if (!s.isDirectory() || s.isSymbolicLink()) throw Error("store_unsafe");
17318
+ if (isWin) secureWindowsAcl(dir, options2.aclRunner, true, !existed);
17319
+ else assertPosix(s, 448);
17320
+ }
17321
+ function canonicalReporting(value) {
17322
+ if (!plain(value) || !Object.keys(value).every((key) => ["enabled", "endpoint", "credential_file"].includes(key)) || typeof value.enabled !== "boolean") return false;
17323
+ if (value.endpoint !== void 0) {
17324
+ if (typeof value.endpoint !== "string" || value.endpoint.length > 2048) return false;
17325
+ try {
17326
+ if (!["http:", "https:"].includes(new URL(value.endpoint).protocol)) return false;
17327
+ } catch {
17328
+ return false;
17329
+ }
17330
+ }
17331
+ if (value.credential_file !== void 0 && (typeof value.credential_file !== "string" || value.credential_file.length < 1 || value.credential_file.length > 4096)) return false;
17332
+ return !value.enabled || value.endpoint !== void 0 && value.credential_file !== void 0;
17333
+ }
17334
+ var WINDOWS_ACL_VERIFY = String.raw`$p=$env:CAVEAT_ACL_PATH;$isDir=$env:CAVEAT_ACL_DIRECTORY -eq '1';$sid=[System.Security.Principal.WindowsIdentity]::GetCurrent().User.Value;$acl=if($isDir){[System.IO.Directory]::GetAccessControl($p)}else{[System.IO.File]::GetAccessControl($p)};$owner=$acl.GetOwner([System.Security.Principal.SecurityIdentifier]).Value;if($owner -ne $sid){exit 41};$rules=@($acl.GetAccessRules($true,$true,[System.Security.Principal.SecurityIdentifier]));if($rules.Count -ne 1){exit 42};$r=$rules[0];if($r.IdentityReference.Value -ne $sid -or $r.AccessControlType -ne 'Allow' -or $r.IsInherited -or ($r.FileSystemRights -band [System.Security.AccessControl.FileSystemRights]::FullControl) -ne [System.Security.AccessControl.FileSystemRights]::FullControl){exit 43}`;
17335
+ var WINDOWS_ACL_APPLY = String.raw`$p=$env:CAVEAT_ACL_PATH;$isDir=$env:CAVEAT_ACL_DIRECTORY -eq '1';$sid=[System.Security.Principal.WindowsIdentity]::GetCurrent().User;$acl=if($isDir){New-Object System.Security.AccessControl.DirectorySecurity}else{New-Object System.Security.AccessControl.FileSecurity};$acl.SetAccessRuleProtection($true,$false);$flags=if($isDir){[System.Security.AccessControl.InheritanceFlags]'ContainerInherit, ObjectInherit'}else{[System.Security.AccessControl.InheritanceFlags]::None};$rule=New-Object System.Security.AccessControl.FileSystemAccessRule($sid,'FullControl',$flags,[System.Security.AccessControl.PropagationFlags]::None,[System.Security.AccessControl.AccessControlType]::Allow);$acl.SetOwner($sid);$acl.AddAccessRule($rule);if($isDir){[System.IO.Directory]::SetAccessControl($p,$acl)}else{[System.IO.File]::SetAccessControl($p,$acl)};` + WINDOWS_ACL_VERIFY;
17336
+ function runWindowsAcl(path, directory, apply) {
17337
+ const result = spawnSync("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", apply ? WINDOWS_ACL_APPLY : WINDOWS_ACL_VERIFY], { env: { ...process.env, CAVEAT_ACL_PATH: path, CAVEAT_ACL_DIRECTORY: directory ? "1" : "0" }, stdio: "ignore", timeout: 3e3, windowsHide: true });
17338
+ if (result.status !== 0) throw Error("store_unsafe");
17339
+ }
17340
+ function secureWindowsAcl(path, runner, directory = false, apply = false) {
17341
+ try {
17342
+ (runner ?? runWindowsAcl)(path, directory, apply);
17343
+ } catch {
17344
+ throw Error("store_unsafe");
17345
+ }
17346
+ }
17347
+ function assertPosix(info, mode) {
17348
+ if ((info.mode & 511) !== mode || typeof process.getuid === "function" && info.uid !== process.getuid()) throw Error("store_unsafe");
17349
+ }
17350
+ function ensureSafeFile(path, isWin, options2 = {}) {
17351
+ const s = lstatSync(path);
17352
+ if (!s.isFile() || s.isSymbolicLink()) throw Error("store_unsafe");
17353
+ if (isWin) secureWindowsAcl(path, options2.aclRunner);
17354
+ else assertPosix(statSync7(path), 384);
17355
+ }
17356
+ function validate(store) {
17357
+ if (!plain(store) || !exact(store, ["schema", "next_sequence", "acknowledged_through", "records"])) throw Error("state_invalid");
17358
+ const checked = store;
17359
+ if (checked.schema !== RUNTIME_ERRORS_SCHEMA || !Number.isSafeInteger(checked.next_sequence) || checked.next_sequence < 1 || !Number.isSafeInteger(checked.acknowledged_through) || checked.acknowledged_through < 0 || checked.acknowledged_through >= checked.next_sequence || !Array.isArray(checked.records) || checked.records.length > MAX_RECORDS) throw Error("state_invalid");
17360
+ const seen = /* @__PURE__ */ new Set();
17361
+ let previous = 0;
17362
+ for (const record of checked.records) {
17363
+ if (!plain(record) || !exact(record, ["product", "product_version", "component", "error_code", "message_template", "severity", "fingerprint", "count", "first_seen", "last_seen", "state_schema_version", "os", "arch", "status", "resolved_at", "reason_code", "sequence"])) throw Error("state_invalid");
17364
+ const code = typeof record.error_code === "string" ? record.error_code : void 0;
17365
+ const d = code && definitions[code];
17366
+ if (!d || record.product !== "caveat" || !validVersion(record.product_version) || record.component !== d.component || record.message_template !== d.template || record.severity !== d.severity || record.fingerprint !== fingerprint(code) || seen.has(record.fingerprint) || !Number.isSafeInteger(record.count) || record.count < 1 || !validTime(record.first_seen) || !validTime(record.last_seen) || Date.parse(record.first_seen) > Date.parse(record.last_seen) || record.state_schema_version !== STATE_VERSION || !validOs(record.os) || !validArch(record.arch) || !Number.isSafeInteger(record.sequence) || record.sequence <= previous || record.sequence >= checked.next_sequence || !["open", "resolved"].includes(record.status) || record.status === "open" && (record.resolved_at !== null || record.reason_code !== null) || record.status === "resolved" && (typeof record.resolved_at !== "string" || !validTime(record.resolved_at) || Date.parse(record.resolved_at) < Date.parse(record.last_seen) || record.reason_code !== "operator_resolved")) throw Error("state_invalid");
17367
+ seen.add(record.fingerprint);
17368
+ previous = record.sequence;
17369
+ }
17370
+ }
17371
+ function readStore(path, isWin, options2 = {}) {
17372
+ if (!existsSync15(path)) return empty();
17373
+ ensureSafeFile(path, isWin, options2);
17374
+ const value = JSON.parse(readFileSync13(path, "utf8"));
17375
+ validate(value);
17376
+ return value;
17377
+ }
17378
+ function lock(path, isWin, fn, options2 = {}) {
17379
+ ensureSafeDir(dirname8(path), isWin, options2);
17380
+ const lockPath2 = `${path}.lock.sqlite`;
17381
+ let created = false;
17382
+ try {
17383
+ writeFileSync9(lockPath2, "", { mode: 384, flag: "wx" });
17384
+ created = true;
17385
+ } catch (error) {
17386
+ if (!plain(error) || error.code !== "EEXIST") throw error;
17387
+ }
17388
+ if (created) {
17389
+ if (isWin) secureWindowsAcl(lockPath2, options2.aclRunner, false, true);
17390
+ else assertPosix(statSync7(lockPath2), 384);
17391
+ } else ensureSafeFile(lockPath2, isWin, options2);
17392
+ const db = new DatabaseSync3(lockPath2);
17393
+ let begun = false;
17394
+ try {
17395
+ ensureSafeFile(lockPath2, isWin, options2);
17396
+ db.exec("PRAGMA busy_timeout=5000; PRAGMA synchronous=FULL; BEGIN IMMEDIATE");
17397
+ begun = true;
17398
+ const result = fn();
17399
+ db.exec("COMMIT");
17400
+ begun = false;
17401
+ return result;
17402
+ } finally {
17403
+ if (begun) try {
17404
+ db.exec("ROLLBACK");
17405
+ } catch {
17406
+ }
17407
+ db.close();
17408
+ }
17409
+ }
17410
+ function writeStore(path, store, isWin, options2 = {}) {
17411
+ validate(store);
17412
+ ensureSafeDir(dirname8(path), isWin, options2);
17413
+ const temporary = join14(dirname8(path), `.runtime-errors-${process.pid}-${randomBytes3(6).toString("hex")}`);
17414
+ try {
17415
+ writeFileSync9(temporary, `${JSON.stringify(store)}
17416
+ `, { mode: 384, flag: "wx" });
17417
+ if (isWin) secureWindowsAcl(temporary, options2.aclRunner, false, true);
17418
+ else assertPosix(statSync7(temporary), 384);
17419
+ renameSync5(temporary, path);
17420
+ ensureSafeFile(path, isWin, options2);
17421
+ } finally {
17422
+ rmSync6(temporary, { force: true });
17423
+ }
17424
+ }
17425
+ function now(options2) {
17426
+ const value = options2.now ? new Date(options2.now) : /* @__PURE__ */ new Date();
17427
+ if (Number.isNaN(value.valueOf())) throw Error("invalid_time");
17428
+ return value.toISOString();
17429
+ }
17430
+ function normalizeOs(value) {
17431
+ return value === "win32" ? "windows" : value;
17432
+ }
17433
+ function optionsFor(options2) {
17434
+ const env = options2.env ?? process.env;
17435
+ const isWin = (options2.isWindows ?? windows)(env);
17436
+ return { env, isWin, path: options2.storePath ?? runtimeErrorsStatePath(env) };
17437
+ }
17438
+ function requireCursor(value) {
17439
+ if (!Number.isSafeInteger(value) || value < 0) throw Error("invalid_cursor");
17440
+ }
17441
+ function requireLimit(value) {
17442
+ if (!Number.isSafeInteger(value) || value < 1 || value > MAX_RECORDS) throw Error("invalid_limit");
17443
+ }
17444
+ function snapshot(options2 = {}) {
17445
+ const afterCursor = options2.afterCursor ?? 0, limit = options2.limit ?? MAX_RECORDS;
17446
+ requireCursor(afterCursor);
17447
+ requireLimit(limit);
17448
+ const enabled = collectionEnabled(options2);
17449
+ const { path, isWin } = optionsFor(options2);
17450
+ const store = enabled ? readStore(path, isWin, options2) : empty();
17451
+ if (afterCursor > store.next_sequence - 1) throw Error("invalid_cursor");
17452
+ const all = store.records.filter((r2) => r2.sequence > afterCursor);
17453
+ const rows = all.slice(0, limit);
17454
+ return { schema: RUNTIME_ERRORS_SCHEMA, product: "caveat", version: options2.version ?? "unknown", state_schema_version: STATE_VERSION, cursor: { high_watermark: store.next_sequence - 1, acknowledged_through: store.acknowledged_through, next: rows.at(-1)?.sequence ?? afterCursor }, runtime_errors: rows.filter((r2) => r2.status === "open").map(({ error_code, component, status, severity, fingerprint: fingerprint22, message_template, count, first_seen, last_seen, state_schema_version }) => ({ error_code, component, status, severity, fingerprint: fingerprint22, message_template, occurrence_count: count, first_seen, last_seen, state_schema_version })), resolutions: rows.filter((r2) => r2.status === "resolved").map(({ fingerprint: fingerprint22, resolved_at, reason_code }) => ({ fingerprint: fingerprint22, resolved_at, reason_code })), diagnostics: { collection: enabled ? "enabled" : "disabled", status: enabled ? "ready" : "not_applicable", total_count: store.records.length, pending_count: store.records.filter((r2) => r2.sequence > store.acknowledged_through).length, truncated: all.length > rows.length } };
17455
+ }
17456
+ function runtimeErrorsDiagnostics(options2 = {}) {
17457
+ if (!collectionEnabled(options2)) return { schema: "caveat.runtime_error_diagnostics.v1", collection: "disabled", status: "not_applicable", total_count: 0, open_count: 0, pending_count: 0, high_watermark: 0, acknowledged_through: 0 };
17458
+ try {
17459
+ const { path, isWin } = optionsFor(options2);
17460
+ const store = readStore(path, isWin, options2);
17461
+ return { schema: "caveat.runtime_error_diagnostics.v1", collection: "enabled", status: "ready", total_count: store.records.length, open_count: store.records.filter((record) => record.status === "open").length, pending_count: store.records.filter((record) => record.sequence > store.acknowledged_through).length, high_watermark: store.next_sequence - 1, acknowledged_through: store.acknowledged_through };
17462
+ } catch {
17463
+ return { schema: "caveat.runtime_error_diagnostics.v1", collection: "enabled", status: "unavailable", total_count: 0, open_count: 0, pending_count: 0, high_watermark: 0, acknowledged_through: 0 };
17464
+ }
17465
+ }
17466
+ function recordRuntimeError(code, options2 = {}) {
17467
+ if (!collectionEnabled(options2)) return { status: "disabled" };
17468
+ const { path, isWin } = optionsFor(options2);
17469
+ return lock(path, isWin, () => {
17470
+ const store = readStore(path, isWin, options2);
17471
+ const definition = definitions[code];
17472
+ if (!definition) throw Error("unknown_runtime_code");
17473
+ const key = fingerprint(code);
17474
+ const sequence = store.next_sequence++;
17475
+ const time = now(options2);
17476
+ const existing = store.records.find((r2) => r2.fingerprint === key);
17477
+ const version = options2.version ?? "0.0.0";
17478
+ const os = normalizeOs(options2.os ?? hostPlatform());
17479
+ const arch = options2.arch ?? hostArch();
17480
+ if (!validVersion(version) || !validOs(os) || !validArch(arch)) throw Error("invalid_runtime_metadata");
17481
+ if (existing) {
17482
+ existing.product_version = version;
17483
+ existing.os = os;
17484
+ existing.arch = arch;
17485
+ existing.count += 1;
17486
+ existing.last_seen = time;
17487
+ existing.sequence = sequence;
17488
+ existing.status = "open";
17489
+ existing.resolved_at = null;
17490
+ existing.reason_code = null;
17491
+ } else {
17492
+ if (store.records.length >= MAX_RECORDS) throw Error("store_overflow");
17493
+ store.records.push({ product: "caveat", product_version: version, component: definition.component, error_code: code, message_template: definition.template, severity: definition.severity, fingerprint: key, count: 1, first_seen: time, last_seen: time, state_schema_version: STATE_VERSION, os, arch, status: "open", resolved_at: null, reason_code: null, sequence });
17494
+ }
17495
+ store.records.sort((a, b2) => a.sequence - b2.sequence);
17496
+ writeStore(path, store, isWin, options2);
17497
+ return { status: "recorded", fingerprint: key, sequence };
17498
+ }, options2);
17499
+ }
17500
+ function observeRuntimeError(code, options2 = {}) {
17501
+ try {
17502
+ recordRuntimeError(code, options2);
17503
+ } catch {
17504
+ try {
17505
+ process.stderr.write("[caveat:runtime-errors] store_unavailable\n");
17506
+ } catch {
17507
+ }
17508
+ }
17509
+ }
17510
+ var runtimeErrorsSnapshot = (afterCursor = 0, limit = MAX_RECORDS, options2 = {}) => snapshot({ ...normalizeOptions(options2), afterCursor, limit });
17511
+ function acknowledgeRuntimeErrors(cursor, options2 = {}) {
17512
+ const normalized = normalizeOptions(options2);
17513
+ requireCursor(cursor);
17514
+ if (!collectionEnabled(normalized)) return snapshot({ ...normalized, afterCursor: cursor });
17515
+ const { path, isWin } = optionsFor(normalized);
17516
+ lock(path, isWin, () => {
17517
+ const store = readStore(path, isWin, normalized);
17518
+ if (cursor >= store.next_sequence) throw Error("invalid_cursor");
17519
+ store.acknowledged_through = Math.max(store.acknowledged_through, cursor);
17520
+ writeStore(path, store, isWin, normalized);
17521
+ }, normalized);
17522
+ return snapshot(normalized);
17523
+ }
17524
+ function setRuntimeErrorStatus(fingerprintValue, status, options2 = {}) {
17525
+ const normalized = normalizeOptions(options2);
17526
+ if (!/^[0-9a-f]{64}$/.test(fingerprintValue)) throw Error("invalid_fingerprint");
17527
+ if (!collectionEnabled(normalized)) return snapshot(normalized);
17528
+ const { path, isWin } = optionsFor(normalized);
17529
+ lock(path, isWin, () => {
17530
+ const store = readStore(path, isWin, normalized);
17531
+ const record = store.records.find((r2) => r2.fingerprint === fingerprintValue);
17532
+ if (!record) throw Error("fingerprint_not_found");
17533
+ if (record.status === status) return;
17534
+ record.status = status;
17535
+ record.resolved_at = status === "resolved" ? now(normalized) : null;
17536
+ record.reason_code = status === "resolved" ? "operator_resolved" : null;
17537
+ record.sequence = store.next_sequence++;
17538
+ store.records.sort((a, b2) => a.sequence - b2.sequence);
17539
+ writeStore(path, store, isWin, normalized);
17540
+ }, normalized);
17541
+ return snapshot(normalized);
17542
+ }
17543
+ function compactRuntimeErrors(options2 = {}) {
17544
+ const normalized = normalizeOptions(options2);
17545
+ if (!collectionEnabled(normalized)) return snapshot(normalized);
17546
+ const { path, isWin } = optionsFor(normalized);
17547
+ lock(path, isWin, () => {
17548
+ const store = readStore(path, isWin, normalized);
17549
+ const cutoff = Date.parse(now(normalized)) - RETENTION_MS;
17550
+ store.records = store.records.filter((record) => !(record.status === "resolved" && record.sequence <= store.acknowledged_through && record.resolved_at !== null && Date.parse(record.resolved_at) <= cutoff));
17551
+ writeStore(path, store, isWin, normalized);
17552
+ }, normalized);
17553
+ return snapshot(normalized);
17554
+ }
17555
+
17025
17556
  // ../../packages/core/dist/env.js
17026
17557
  var import_semver = __toESM(require_semver2(), 1);
17027
- function fingerprint() {
17558
+ function fingerprint2() {
17028
17559
  return {
17029
17560
  os: process.platform,
17030
17561
  arch: process.arch,
@@ -17033,16 +17564,16 @@ function fingerprint() {
17033
17564
  }
17034
17565
 
17035
17566
  // ../../packages/core/dist/id.js
17036
- import { randomBytes as randomBytes3 } from "node:crypto";
17567
+ import { randomBytes as randomBytes4 } from "node:crypto";
17037
17568
  function randomHex(hexChars) {
17038
17569
  const bytes = Math.ceil(hexChars / 2);
17039
- return randomBytes3(bytes).toString("hex").slice(0, hexChars);
17570
+ return randomBytes4(bytes).toString("hex").slice(0, hexChars);
17040
17571
  }
17041
- function slugify(title, now = () => /* @__PURE__ */ new Date()) {
17572
+ function slugify(title, now2 = () => /* @__PURE__ */ new Date()) {
17042
17573
  const lowered = title.toLowerCase();
17043
17574
  const sluggy = lowered.replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
17044
17575
  if (!sluggy || !/^[a-z0-9]/.test(sluggy)) {
17045
- const d = now();
17576
+ const d = now2();
17046
17577
  const yyyy = d.getUTCFullYear().toString().padStart(4, "0");
17047
17578
  const mm = (d.getUTCMonth() + 1).toString().padStart(2, "0");
17048
17579
  const dd = d.getUTCDate().toString().padStart(2, "0");
@@ -17056,13 +17587,13 @@ function resolveCollision(baseId, exists2) {
17056
17587
  while (exists2(`${baseId}-${n}`)) n++;
17057
17588
  return `${baseId}-${n}`;
17058
17589
  }
17059
- function generateSourceSession(now = () => /* @__PURE__ */ new Date()) {
17060
- return `${now().toISOString()}/${randomHex(12)}`;
17590
+ function generateSourceSession(now2 = () => /* @__PURE__ */ new Date()) {
17591
+ return `${now2().toISOString()}/${randomHex(12)}`;
17061
17592
  }
17062
17593
 
17063
17594
  // ../../packages/core/dist/writer.js
17064
- import { existsSync as existsSync15, mkdirSync as mkdirSync9, writeFileSync as writeFileSync9 } from "node:fs";
17065
- import { dirname as dirname8 } from "node:path";
17595
+ import { existsSync as existsSync16, mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "node:fs";
17596
+ import { dirname as dirname9 } from "node:path";
17066
17597
  function buildEntry(frontmatter, sections) {
17067
17598
  const bodyParts = [];
17068
17599
  for (const [heading, content2] of Object.entries(sections)) {
@@ -17080,24 +17611,24 @@ ${body}${body ? "\n" : ""}`;
17080
17611
  return { content, body };
17081
17612
  }
17082
17613
  function writeEntryFile(filePath, content) {
17083
- const dir = dirname8(filePath);
17084
- if (!existsSync15(dir)) mkdirSync9(dir, { recursive: true });
17085
- writeFileSync9(filePath, content, "utf-8");
17614
+ const dir = dirname9(filePath);
17615
+ if (!existsSync16(dir)) mkdirSync10(dir, { recursive: true });
17616
+ writeFileSync10(filePath, content, "utf-8");
17086
17617
  }
17087
17618
 
17088
17619
  // ../../packages/core/dist/record.js
17089
- import { statSync as statSync7 } from "node:fs";
17090
- import { join as join14 } from "node:path";
17620
+ import { statSync as statSync8 } from "node:fs";
17621
+ import { join as join15 } from "node:path";
17091
17622
  var DEFAULT_CATEGORY = "misc";
17092
17623
  function recordEntry(input, opts) {
17093
- const now = opts.now ?? (() => /* @__PURE__ */ new Date());
17624
+ const now2 = opts.now ?? (() => /* @__PURE__ */ new Date());
17094
17625
  const source = opts.source ?? "own";
17095
- const nowDate = now();
17626
+ const nowDate = now2();
17096
17627
  const ymd = formatYmd(nowDate);
17097
- const baseId = input.id ?? slugify(input.title, now);
17628
+ const baseId = input.id ?? slugify(input.title, now2);
17098
17629
  const id = resolveCollision(baseId, (candidate) => entryExists(opts.db, source, candidate));
17099
17630
  const mergedEnv = {
17100
- ...fingerprint(),
17631
+ ...fingerprint2(),
17101
17632
  ...input.environment ?? {}
17102
17633
  };
17103
17634
  const frontmatter = {
@@ -17109,7 +17640,7 @@ function recordEntry(input, opts) {
17109
17640
  tags: input.tags ?? [],
17110
17641
  environment: mergedEnv,
17111
17642
  source_project: null,
17112
- source_session: generateSourceSession(now),
17643
+ source_session: generateSourceSession(now2),
17113
17644
  created_at: ymd,
17114
17645
  updated_at: ymd,
17115
17646
  last_verified: ymd
@@ -17123,9 +17654,9 @@ function recordEntry(input, opts) {
17123
17654
  const built = buildEntry(frontmatter, sections);
17124
17655
  const category = input.category ?? DEFAULT_CATEGORY;
17125
17656
  const relPath = `${category}/${id}.md`;
17126
- const filePath = join14(opts.entriesRoot, relPath);
17657
+ const filePath = join15(opts.entriesRoot, relPath);
17127
17658
  writeEntryFile(filePath, built.content);
17128
- const stat = statSync7(filePath);
17659
+ const stat = statSync8(filePath);
17129
17660
  upsertEntry(opts.db, {
17130
17661
  id,
17131
17662
  source,
@@ -17153,8 +17684,8 @@ function formatYmd(d) {
17153
17684
  }
17154
17685
 
17155
17686
  // ../../packages/core/dist/update.js
17156
- import { readFileSync as readFileSync13, statSync as statSync8, writeFileSync as writeFileSync10 } from "node:fs";
17157
- import { join as join15 } from "node:path";
17687
+ import { readFileSync as readFileSync14, statSync as statSync9, writeFileSync as writeFileSync11 } from "node:fs";
17688
+ import { join as join16 } from "node:path";
17158
17689
  var IMMUTABLE_KEYS = /* @__PURE__ */ new Set([
17159
17690
  "id",
17160
17691
  "created_at",
@@ -17166,15 +17697,15 @@ function updateEntry(id, patch, opts) {
17166
17697
  if (source !== "own") {
17167
17698
  throw new Error("community \u30A8\u30F3\u30C8\u30EA\u306F\u8CFC\u8AAD\u7269\u3067\u3059; \u7DE8\u96C6\u306F\u4E0A\u6D41\u3067\u884C\u3063\u3066\u304F\u3060\u3055\u3044");
17168
17699
  }
17169
- const now = opts.now ?? (() => /* @__PURE__ */ new Date());
17170
- const nowDate = now();
17700
+ const now2 = opts.now ?? (() => /* @__PURE__ */ new Date());
17701
+ const nowDate = now2();
17171
17702
  const row = opts.db.prepare("SELECT path FROM entries WHERE source = ? AND id = ?").get(source, id);
17172
17703
  if (!row) {
17173
17704
  throw new Error(`caveat not found: id=${id} source=${source}`);
17174
17705
  }
17175
17706
  const relPath = row.path;
17176
- const filePath = join15(opts.entriesRoot, relPath);
17177
- const raw = readFileSync13(filePath, "utf-8");
17707
+ const filePath = join16(opts.entriesRoot, relPath);
17708
+ const raw = readFileSync14(filePath, "utf-8");
17178
17709
  const parsed = parseMarkdown(raw);
17179
17710
  if (patch.frontmatter) {
17180
17711
  for (const key of Object.keys(patch.frontmatter)) {
@@ -17215,8 +17746,8 @@ function updateEntry(id, patch, opts) {
17215
17746
  }
17216
17747
  }
17217
17748
  const built = buildEntry(mergedFrontmatter, mergedSections);
17218
- writeFileSync10(filePath, built.content, "utf-8");
17219
- const stat = statSync8(filePath);
17749
+ writeFileSync11(filePath, built.content, "utf-8");
17750
+ const stat = statSync9(filePath);
17220
17751
  upsertEntry(opts.db, {
17221
17752
  id,
17222
17753
  source,
@@ -17240,15 +17771,15 @@ function formatYmd2(d) {
17240
17771
  }
17241
17772
 
17242
17773
  // ../../packages/core/dist/proposalEval.js
17243
- import { createHash as createHash6 } from "node:crypto";
17774
+ import { createHash as createHash8 } from "node:crypto";
17244
17775
  import { isAbsolute as isAbsolute2, relative as relative4, resolve as resolve4, sep } from "node:path";
17245
17776
 
17246
17777
  // ../../packages/core/dist/proposalExecution.js
17247
- import { createHash as createHash7 } from "node:crypto";
17778
+ import { createHash as createHash9 } from "node:crypto";
17248
17779
  import { basename as basename3, isAbsolute as isAbsolute3 } from "node:path";
17249
17780
 
17250
17781
  // ../../packages/core/dist/proposalExecutionCompiler.js
17251
- import { createHash as createHash8 } from "node:crypto";
17782
+ import { createHash as createHash10 } from "node:crypto";
17252
17783
 
17253
17784
  export {
17254
17785
  __commonJS,
@@ -17268,11 +17799,11 @@ export {
17268
17799
  communityPull,
17269
17800
  communityList,
17270
17801
  communityRemove,
17271
- appendPendingReminder,
17802
+ buildPendingSemanticKey,
17803
+ buildAndPublishPendingReminder,
17272
17804
  cleanupStalePendingDirs,
17273
17805
  maybeSweepPendingDirs,
17274
- drainPendingReminders,
17275
- drainGlobalPendingReminders,
17806
+ drainPendingRemindersDetailed,
17276
17807
  createKeyserverKeyProvider,
17277
17808
  SyncError,
17278
17809
  syncOwn,
@@ -17293,7 +17824,8 @@ export {
17293
17824
  ensureUserConfig,
17294
17825
  writeUserConfigPatch,
17295
17826
  defaultSelfIdentityTokens,
17296
- findCaveatsForPrompt,
17827
+ findCaveatsForHook,
17828
+ findCaveatsForHookSegments,
17297
17829
  toolErrorReminderText,
17298
17830
  userPromptSubmitReminderText,
17299
17831
  stopReminderText,
@@ -17311,7 +17843,13 @@ export {
17311
17843
  decideCodexSidecarExecution,
17312
17844
  buildCodexSidecarDiagnosticsCommand,
17313
17845
  buildCodexSidecarReadOnlySmokeCommand,
17314
- buildCodexSidecarRunCommand
17846
+ buildCodexSidecarRunCommand,
17847
+ runtimeErrorsDiagnostics,
17848
+ observeRuntimeError,
17849
+ runtimeErrorsSnapshot,
17850
+ acknowledgeRuntimeErrors,
17851
+ setRuntimeErrorStatus,
17852
+ compactRuntimeErrors
17315
17853
  };
17316
17854
  /*! Bundled license information:
17317
17855
 
@@ -17334,4 +17872,4 @@ strip-bom-string/index.js:
17334
17872
  js-yaml/dist/js-yaml.mjs:
17335
17873
  (*! js-yaml 4.1.1 https://github.com/nodeca/js-yaml @license MIT *)
17336
17874
  */
17337
- //# sourceMappingURL=chunk-HCLEIAGO.js.map
17875
+ //# sourceMappingURL=chunk-PD5E6TFL.js.map