token-goat 2.9.26 → 2.9.29

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.
Files changed (78) hide show
  1. package/README.md +30 -88
  2. package/SECURITY.md +14 -0
  3. package/dist/{token-goat-chunk-OZRSREKR.mjs → token-goat-chunk-2AWQ2R5X.mjs} +2 -2
  4. package/dist/{token-goat-chunk-BH4ZVRB2.mjs → token-goat-chunk-2NNUA2LR.mjs} +4 -4
  5. package/dist/token-goat-chunk-2WOUYWLM.mjs +955 -0
  6. package/dist/{token-goat-chunk-IKZLSRII.mjs → token-goat-chunk-435UQTKD.mjs} +5 -3
  7. package/dist/{token-goat-chunk-62IHOU6L.mjs → token-goat-chunk-44BM7DDQ.mjs} +5 -3
  8. package/dist/token-goat-chunk-52NSDWYY.mjs +96 -0
  9. package/dist/{token-goat-chunk-CXBOFPF4.mjs → token-goat-chunk-67BNIKKO.mjs} +32 -18
  10. package/dist/{token-goat-chunk-XBESNWEX.mjs → token-goat-chunk-6AK46ZT7.mjs} +2 -3
  11. package/dist/{token-goat-chunk-7SXPJOSZ.mjs → token-goat-chunk-7CPMDFGB.mjs} +166 -40
  12. package/dist/token-goat-chunk-ASLWOQ3I.mjs +14 -0
  13. package/dist/{token-goat-chunk-MWID3YOY.mjs → token-goat-chunk-BGYOZ6DO.mjs} +6 -4
  14. package/dist/{token-goat-chunk-PAV6NNY7.mjs → token-goat-chunk-C5YPNZKQ.mjs} +22 -8
  15. package/dist/{token-goat-chunk-D2X7XN5M.mjs → token-goat-chunk-CIQ2FTY3.mjs} +23 -242
  16. package/dist/token-goat-chunk-D4ETHJD6.mjs +246 -0
  17. package/dist/{token-goat-chunk-7Y6GWTII.mjs → token-goat-chunk-DNRPXHYH.mjs} +25 -17
  18. package/dist/{token-goat-chunk-L43RKNHA.mjs → token-goat-chunk-DNSPXQXQ.mjs} +2 -2
  19. package/dist/token-goat-chunk-DPNLUJWB.mjs +220 -0
  20. package/dist/token-goat-chunk-E4ZOJIZK.mjs +1382 -0
  21. package/dist/token-goat-chunk-E5TK5DNO.mjs +718 -0
  22. package/dist/{token-goat-chunk-VVROQBQJ.mjs → token-goat-chunk-EUSDXRXU.mjs} +62 -12
  23. package/dist/{token-goat-chunk-POOI26O6.mjs → token-goat-chunk-FTP4U4QA.mjs} +12 -8
  24. package/dist/token-goat-chunk-G23DWHV4.mjs +142 -0
  25. package/dist/{token-goat-chunk-MDV5VWF4.mjs → token-goat-chunk-G7IWXCFF.mjs} +223 -15
  26. package/dist/{token-goat-chunk-C2PG4K5D.mjs → token-goat-chunk-GLXRTTLE.mjs} +7 -5
  27. package/dist/{token-goat-chunk-M6CVNHTW.mjs → token-goat-chunk-H5J3C56Q.mjs} +95 -573
  28. package/dist/{token-goat-chunk-BAWKGODL.mjs → token-goat-chunk-HNFZZHFW.mjs} +2 -2
  29. package/dist/{token-goat-chunk-TG5ZPD6B.mjs → token-goat-chunk-HUYUHODZ.mjs} +1036 -759
  30. package/dist/token-goat-chunk-IVE6U7KV.mjs +53 -0
  31. package/dist/{token-goat-chunk-ZZT6PVB3.mjs → token-goat-chunk-IVWI2OCK.mjs} +72 -45
  32. package/dist/{token-goat-chunk-GMOUBOX4.mjs → token-goat-chunk-JTKCQMQA.mjs} +37 -5
  33. package/dist/{token-goat-chunk-H2CPLEMP.mjs → token-goat-chunk-KOPIR3KZ.mjs} +46 -23
  34. package/dist/token-goat-chunk-L7H3U27L.mjs +35 -0
  35. package/dist/{token-goat-chunk-FLEYOCAS.mjs → token-goat-chunk-LZNBQTDK.mjs} +6 -4
  36. package/dist/token-goat-chunk-MELOKFDJ.mjs +199 -0
  37. package/dist/{token-goat-chunk-RH27ZSPF.mjs → token-goat-chunk-NMBWLRHW.mjs} +164 -50
  38. package/dist/{token-goat-chunk-43JFN26X.mjs → token-goat-chunk-O6I2XU4P.mjs} +27 -967
  39. package/dist/{token-goat-chunk-G6EYO5CD.mjs → token-goat-chunk-ONXH6NZ5.mjs} +2 -87
  40. package/dist/token-goat-chunk-ORNFMIER.mjs +295 -0
  41. package/dist/{token-goat-chunk-LHUP4DXZ.mjs → token-goat-chunk-PGTH2U4C.mjs} +1 -1
  42. package/dist/{token-goat-chunk-5BQ7W7D7.mjs → token-goat-chunk-PKRWMHVP.mjs} +76 -59
  43. package/dist/{token-goat-chunk-DA43OE7L.mjs → token-goat-chunk-PQ53BSCF.mjs} +1 -1
  44. package/dist/{token-goat-chunk-STYRLQIW.mjs → token-goat-chunk-PYSUADX4.mjs} +2 -2
  45. package/dist/{token-goat-chunk-JALB3KWJ.mjs → token-goat-chunk-QO3LXVVR.mjs} +4247 -5005
  46. package/dist/{token-goat-chunk-L45IWWMC.mjs → token-goat-chunk-RLP6J7WR.mjs} +6 -6
  47. package/dist/token-goat-chunk-RQGGMPCR.mjs +205 -0
  48. package/dist/{token-goat-chunk-MBDJR6HU.mjs → token-goat-chunk-RTMVLHWX.mjs} +3708 -4003
  49. package/dist/{token-goat-chunk-E3K3BTEQ.mjs → token-goat-chunk-S4VSXURL.mjs} +8 -6
  50. package/dist/{token-goat-chunk-LKSXAMJB.mjs → token-goat-chunk-SE6E4BKJ.mjs} +1 -1
  51. package/dist/token-goat-chunk-TCQANXYC.mjs +351 -0
  52. package/dist/token-goat-chunk-TDUT2CL6.mjs +564 -0
  53. package/dist/{token-goat-chunk-LRIZ7K3F.mjs → token-goat-chunk-TGOXNAHW.mjs} +54 -111
  54. package/dist/{token-goat-chunk-WNBSCSAI.mjs → token-goat-chunk-UA5BKWWQ.mjs} +1 -1
  55. package/dist/{token-goat-chunk-RIB6XY2V.mjs → token-goat-chunk-UXSXQQIY.mjs} +1 -1
  56. package/dist/{token-goat-chunk-7EPYB34H.mjs → token-goat-chunk-VMFWNHGR.mjs} +84 -73
  57. package/dist/token-goat-chunk-VQ6F6T7X.mjs +36 -0
  58. package/dist/{token-goat-chunk-5M3NRJD2.mjs → token-goat-chunk-VZQEWRVH.mjs} +6 -4
  59. package/dist/{token-goat-chunk-OSUFN2FV.mjs → token-goat-chunk-XB5KKOCG.mjs} +5 -25
  60. package/dist/{token-goat-chunk-6E2IDLHF.mjs → token-goat-chunk-XYWPOSCN.mjs} +57 -615
  61. package/dist/{token-goat-chunk-CQHY4SL7.mjs → token-goat-chunk-YAGLESS3.mjs} +8 -5
  62. package/dist/token-goat-chunk-YKSRAWUU.mjs +33 -0
  63. package/dist/{token-goat-chunk-F2ARFHLJ.mjs → token-goat-chunk-YOOVFPTP.mjs} +2 -2
  64. package/dist/{token-goat-chunk-EEIDFMEM.mjs → token-goat-chunk-YZAAZU2S.mjs} +12 -3
  65. package/dist/token-goat-chunk-Z6KBMOBI.mjs +53 -0
  66. package/dist/{token-goat-chunk-4GEDH2WU.mjs → token-goat-chunk-ZER6EAXZ.mjs} +81 -70
  67. package/dist/token-goat-hook-client.cjs +475 -0
  68. package/dist/token-goat-hook-client.mjs +26 -0
  69. package/dist/token-goat-hook.mjs +31 -21
  70. package/dist/token-goat.core.mjs +9 -39
  71. package/docs/C4_RUNTIME_ARCHITECTURE.md +2 -2
  72. package/docs/cli.md +35 -23
  73. package/docs/install.md +18 -14
  74. package/package.json +1 -1
  75. package/dist/token-goat-chunk-ADMR3QVF.mjs +0 -41
  76. package/dist/token-goat-chunk-E6B2UFDF.mjs +0 -30
  77. package/dist/token-goat-chunk-GKZ2US5B.mjs +0 -187
  78. package/dist/token-goat-chunk-MZTO4FXH.mjs +0 -26
@@ -5,7 +5,7 @@ import {
5
5
  isTextHeavy,
6
6
  ocrImage,
7
7
  ocrIntegrityFailed
8
- } from "./token-goat-chunk-5M3NRJD2.mjs";
8
+ } from "./token-goat-chunk-VZQEWRVH.mjs";
9
9
  import {
10
10
  formatSqliteQueryTable,
11
11
  formatSqliteSchema,
@@ -13,7 +13,7 @@ import {
13
13
  getSqliteSchema,
14
14
  getSqliteTables,
15
15
  runReadOnlySqliteQuery
16
- } from "./token-goat-chunk-DA43OE7L.mjs";
16
+ } from "./token-goat-chunk-PQ53BSCF.mjs";
17
17
  import {
18
18
  ImageDecodeError,
19
19
  LARGE_SYMBOL_LINE_THRESHOLD,
@@ -42,37 +42,42 @@ import {
42
42
  urlPolicyDenialReason,
43
43
  virtualIndexedScopeNote,
44
44
  walkProject
45
- } from "./token-goat-chunk-MBDJR6HU.mjs";
45
+ } from "./token-goat-chunk-RTMVLHWX.mjs";
46
+ import {
47
+ deliveredOutputBytes
48
+ } from "./token-goat-chunk-L7H3U27L.mjs";
49
+ import {
50
+ isBlobStale,
51
+ loadBlob,
52
+ storeBlob
53
+ } from "./token-goat-chunk-D4ETHJD6.mjs";
46
54
  import {
47
55
  capJsonRows,
48
56
  estimateTokens,
49
57
  trimToBudget
50
- } from "./token-goat-chunk-G6EYO5CD.mjs";
58
+ } from "./token-goat-chunk-52NSDWYY.mjs";
51
59
  import {
52
60
  BYTES_PER_TOKEN,
53
61
  colorStdout,
54
- isBlobStale,
55
- loadBlob,
56
62
  recordStat,
57
63
  redactSecrets,
58
64
  savedTokensFromBytes,
59
- storeBlob,
60
65
  stripAnsiEscapes
61
- } from "./token-goat-chunk-D2X7XN5M.mjs";
66
+ } from "./token-goat-chunk-CIQ2FTY3.mjs";
62
67
  import {
63
68
  extractPdfMeta,
64
69
  extractPdfOutline,
65
70
  extractPdfText,
66
71
  locatePdfPages,
67
72
  readPdfFileWithinBounds
68
- } from "./token-goat-chunk-LKSXAMJB.mjs";
73
+ } from "./token-goat-chunk-SE6E4BKJ.mjs";
69
74
  import {
70
75
  formatCsvProfile,
71
76
  formatCsvTable,
72
77
  parseWhereSpecs,
73
78
  profileCsv,
74
79
  queryCsv
75
- } from "./token-goat-chunk-L43RKNHA.mjs";
80
+ } from "./token-goat-chunk-DNSPXQXQ.mjs";
76
81
  import {
77
82
  MAX_ZIP_INPUT_BYTES,
78
83
  MAX_ZIP_OUTPUT_BYTES,
@@ -107,7 +112,7 @@ import {
107
112
  extractSolidity,
108
113
  extractThrift,
109
114
  stripLeadingAttributes
110
- } from "./token-goat-chunk-LHUP4DXZ.mjs";
115
+ } from "./token-goat-chunk-PGTH2U4C.mjs";
111
116
  import {
112
117
  MAX_OVER_FETCH,
113
118
  OVER_FETCH_FACTOR,
@@ -121,7 +126,7 @@ import {
121
126
  mergeNearbyHits,
122
127
  readSection,
123
128
  searchSemantic
124
- } from "./token-goat-chunk-7EPYB34H.mjs";
129
+ } from "./token-goat-chunk-VMFWNHGR.mjs";
125
130
  import {
126
131
  DEFAULT_QUERY_LIMIT,
127
132
  countRefs,
@@ -134,7 +139,7 @@ import {
134
139
  queryRefsByContext,
135
140
  querySymbols,
136
141
  searchSymbolsFts
137
- } from "./token-goat-chunk-IKZLSRII.mjs";
142
+ } from "./token-goat-chunk-435UQTKD.mjs";
138
143
  import {
139
144
  FILENAME_LANGUAGE,
140
145
  TREE_SITTER_LANGUAGES,
@@ -149,11 +154,12 @@ import {
149
154
  isPascalSource,
150
155
  isPerlSource,
151
156
  isPrologSource,
157
+ isReadOnlyDb,
152
158
  languageLabel,
153
159
  partialRefsReason,
154
160
  redactIfDotenv,
155
161
  unsupportedLanguageName
156
- } from "./token-goat-chunk-7SXPJOSZ.mjs";
162
+ } from "./token-goat-chunk-7CPMDFGB.mjs";
157
163
  import {
158
164
  fileIsAbsent,
159
165
  findProject,
@@ -163,40 +169,38 @@ import {
163
169
  loadConfig,
164
170
  resolveProjectRoot,
165
171
  shortFingerprint
166
- } from "./token-goat-chunk-LRIZ7K3F.mjs";
172
+ } from "./token-goat-chunk-TGOXNAHW.mjs";
167
173
  import {
168
174
  registerReset
169
- } from "./token-goat-chunk-EEIDFMEM.mjs";
175
+ } from "./token-goat-chunk-YZAAZU2S.mjs";
170
176
  import {
171
177
  PER_FILE_COUNTERFACTUAL_CEILING,
172
- SKELETON_SYMBOL_CAP,
173
178
  atomicWriteBytes,
174
179
  compileGrepMatcher,
175
180
  countNoun,
176
- dataDir,
177
181
  decodeSource,
178
182
  ensureNewline,
179
183
  escapeRegExp,
180
184
  excludeTestsHiddenNote,
181
185
  extractErrorMessage,
182
186
  filtersFilteredToEmptyNotice,
183
- foldCaseForContainment,
184
- foldPath,
185
- globalDbPath,
186
187
  grepFilteredToEmptyNotice,
187
- isInsideRoot,
188
188
  isTestFile,
189
189
  pushAll,
190
190
  redactUrlQuery,
191
191
  requireNonNegativeStrictInt,
192
192
  requirePositiveStrictInt,
193
- resolveOnPath,
194
193
  runGit,
195
194
  stripBom,
196
- supportRequestLine,
197
- windowsCmdQuoteArg,
198
195
  withExtension
199
- } from "./token-goat-chunk-6E2IDLHF.mjs";
196
+ } from "./token-goat-chunk-XYWPOSCN.mjs";
197
+ import {
198
+ foldCaseForContainment,
199
+ foldPath,
200
+ isInsideRoot,
201
+ resolveOnPath,
202
+ windowsCmdQuoteArg
203
+ } from "./token-goat-chunk-TCQANXYC.mjs";
200
204
  import {
201
205
  UNTRUSTED_FILE_TAG,
202
206
  UNTRUSTED_GITHUB_TAG,
@@ -209,9 +213,15 @@ import {
209
213
  resolveIndexPath,
210
214
  toDisplayPath
211
215
  } from "./token-goat-chunk-NMTKNYGF.mjs";
216
+ import {
217
+ SKELETON_SYMBOL_CAP,
218
+ dataDir,
219
+ globalDbPath,
220
+ supportRequestLine
221
+ } from "./token-goat-chunk-MELOKFDJ.mjs";
212
222
  import {
213
223
  compileGuardedRegex
214
- } from "./token-goat-chunk-GMOUBOX4.mjs";
224
+ } from "./token-goat-chunk-JTKCQMQA.mjs";
215
225
  import {
216
226
  init_define_import_meta_env
217
227
  } from "./token-goat-chunk-A37V4PBF.mjs";
@@ -253,15 +263,22 @@ function outlineJson(data, opts = {}) {
253
263
  }
254
264
  if (type === "object") {
255
265
  const obj = data;
256
- return { kind: "object", fields: Object.keys(obj).map((k) => fieldSummary(k, obj[k])) };
266
+ const keys = Object.keys(obj);
267
+ const needle = opts.keyFilter?.toLowerCase();
268
+ if (needle === void 0) return { kind: "object", fields: keys.map((k) => fieldSummary(k, obj[k])) };
269
+ const kept = keys.filter((k) => k.toLowerCase().includes(needle));
270
+ return { kind: "object", fields: kept.map((k) => fieldSummary(k, obj[k])), filter: { needle: opts.keyFilter, total: keys.length } };
257
271
  }
258
272
  return { kind: "primitive", type };
259
273
  }
260
274
  function formatJsonOutline(outline) {
261
275
  if (outline.kind === "primitive") return `(scalar ${outline.type})`;
262
276
  if (outline.kind === "object") {
263
- if (outline.fields.length === 0) return "(empty object)";
264
- return outline.fields.map((f) => `${displaySafeText(f.name)}: ${f.type}${f.size !== void 0 ? ` (${f.size})` : ""}`).join("\n");
277
+ const { filter } = outline;
278
+ const tally = filter === void 0 ? "" : `(${outline.fields.length} of ${filter.total} keys contain "${displaySafeText(filter.needle)}")`;
279
+ if (outline.fields.length === 0) return filter === void 0 ? "(empty object)" : tally;
280
+ const lines2 = outline.fields.map((f) => `${displaySafeText(f.name)}: ${f.type}${f.size !== void 0 ? ` (${f.size})` : ""}`);
281
+ return (filter === void 0 ? lines2 : [...lines2, tally]).join("\n");
265
282
  }
266
283
  const lines = [`array of ${outline.length} element${outline.length === 1 ? "" : "s"} (${outline.elementType})`];
267
284
  if (outline.sampleKeys !== void 0) {
@@ -371,6 +388,9 @@ function parseJsonPath(spec) {
371
388
  const inner = spec.slice(i + 1, close);
372
389
  if (inner === "*") {
373
390
  ops.push({ kind: "wildcard" });
391
+ } else if (/^\s*(["'])(?:\\.|(?!\1)[^\\])*\1\s*$/.test(inner)) {
392
+ const quoted = inner.trim();
393
+ ops.push({ kind: "key", name: quoted.slice(1, -1).replace(/\\(["'\\])/g, "$1") });
374
394
  } else if (/^-?\d+$/.test(inner)) {
375
395
  ops.push({ kind: "index", index: Number(inner) });
376
396
  } else {
@@ -387,7 +407,7 @@ function parseJsonPath(spec) {
387
407
  if (bareOperator !== null) {
388
408
  throw new Error(`unsupported comparison operator '${bareOperator[0]}' in '[${inner}]' of path spec '${spec}': this grammar filters by equality only ([field=value])`);
389
409
  }
390
- throw new Error(`invalid bracket expression '[${inner}]' in path spec: '${spec}' (expected [n], [*], or [field=value])`);
410
+ throw new Error(`invalid bracket expression '[${inner}]' in path spec: '${spec}' (expected [n], [*], ["key"], or [field=value])`);
391
411
  }
392
412
  let field = m[1].trim();
393
413
  if (field.startsWith("@.")) field = field.slice(2).trim();
@@ -7467,7 +7487,11 @@ function runOutlineCommand(opts, parse, formatLabel, kind) {
7467
7487
  emitErr(`Failed to parse ${formatLabel}: ${opts.file}`);
7468
7488
  return 1;
7469
7489
  }
7470
- const outline = outlineJson(data);
7490
+ const outline = outlineJson(data, opts.filter === void 0 ? {} : { keyFilter: opts.filter });
7491
+ if (opts.filter !== void 0 && outline.kind !== "object") {
7492
+ emitErr(`--filter narrows an object's keys, and the top level of ${opts.file} is ${outline.kind === "array" ? "an array" : "a scalar"}`);
7493
+ return 1;
7494
+ }
7471
7495
  const fullSourceBytes = sumFileSizes([opts.file]);
7472
7496
  if (opts.json === true) {
7473
7497
  const jsonText = displaySafeJson(outline, 0);
@@ -8081,8 +8105,11 @@ function filterSimilarHeadings(available, query) {
8081
8105
  return sortByLengthCloseness(matched, query);
8082
8106
  }
8083
8107
  function didYouMean(candidates) {
8108
+ return didYouMeanLines(candidates).join("\n");
8109
+ }
8110
+ function didYouMeanLines(candidates) {
8084
8111
  const unique = [...new Set(candidates)];
8085
- if (unique.length === 0) return "";
8112
+ if (unique.length === 0) return [];
8086
8113
  const lines = ["Did you mean:"];
8087
8114
  for (const c of unique.slice(0, DIDYOUMEAN_LIMIT)) {
8088
8115
  lines.push(` - ${c}`);
@@ -8090,7 +8117,7 @@ function didYouMean(candidates) {
8090
8117
  if (unique.length > DIDYOUMEAN_LIMIT) {
8091
8118
  lines.push(` (${unique.length - DIDYOUMEAN_LIMIT} more not shown)`);
8092
8119
  }
8093
- return lines.join("\n");
8120
+ return lines;
8094
8121
  }
8095
8122
  function unknownSymbolSuggestion(name, rootDir) {
8096
8123
  const names = /* @__PURE__ */ new Set();
@@ -8916,7 +8943,7 @@ function changedDiffBaselineBytes(cwd, ref, files) {
8916
8943
  if (files.length === 0) return 0;
8917
8944
  try {
8918
8945
  const result = runGit(["diff", ref, "--unified=0", "--", ...files], { cwd });
8919
- if (result.exitCode === 0) return Buffer.byteLength(result.stdout, "utf8");
8946
+ if (result.exitCode === 0) return deliveredOutputBytes(Buffer.byteLength(result.stdout, "utf8"));
8920
8947
  } catch {
8921
8948
  }
8922
8949
  return 0;
@@ -8988,7 +9015,7 @@ function runChanged(opts = {}) {
8988
9015
  const diffResult = runGit(["diff", ref, "--unified=0", "--", ...changedFiles], { cwd });
8989
9016
  if (diffResult.exitCode === 0) {
8990
9017
  hunksByFile = parseDiffHunks(diffResult.stdout);
8991
- symbolDiffBaselineBytes = Buffer.byteLength(diffResult.stdout, "utf8");
9018
+ symbolDiffBaselineBytes = deliveredOutputBytes(Buffer.byteLength(diffResult.stdout, "utf8"));
8992
9019
  }
8993
9020
  } catch {
8994
9021
  }
@@ -10681,6 +10708,7 @@ function verifyPin(p, pinned) {
10681
10708
  verifyPinnedIdentity(p, pinned);
10682
10709
  }
10683
10710
  function indexFileSyncPinned(resolvedPath, dbPath) {
10711
+ if (isReadOnlyDb(dbPath)) return;
10684
10712
  recordKnownRootThrottled(resolvedPath, dataDir(), dbPath);
10685
10713
  const pinned = activePins?.get(pinKey(path12.resolve(resolvedPath)));
10686
10714
  if (pinned === void 0) {
@@ -10747,6 +10775,7 @@ function resolveBody(entry) {
10747
10775
  return indexedSourceText(entry.filePath, source).split(/\r?\n/).slice(Math.max(0, entry.lineStart - 1), entry.lineEnd).join("\n");
10748
10776
  }
10749
10777
  var STALE_WARNING = "\u26A0 STALE: index is older than the file on disk (worker hasn't reindexed yet \u2014 retry shortly, or read the file directly)";
10778
+ var STALE_READ_ONLY_WARNING = "\u26A0 STALE: index is older than the file on disk and cannot be updated this run (the index is read-only here), so read the file directly";
10750
10779
  var DELETED_WARNING = "\u26A0 DELETED: this file is no longer on disk \u2014 what follows is what the index last saw of it";
10751
10780
  var DELETED_TAG = "\u26A0 DELETED: file no longer on disk";
10752
10781
  var STALE_TAG = "\u26A0 STALE: file changed on disk and could not be reindexed";
@@ -10764,11 +10793,12 @@ function staleWarning(resolvedPath) {
10764
10793
  ` : "";
10765
10794
  }
10766
10795
  if (diskSha === entry.sha) return "";
10767
- return `${STALE_WARNING}
10796
+ return `${isReadOnlyDb(globalDbPath()) ? STALE_READ_ONLY_WARNING : STALE_WARNING}
10768
10797
  `;
10769
10798
  }
10770
10799
  function healStaleIndex(resolvedPath) {
10771
10800
  const entry = getFileEntry(resolvedPath);
10801
+ if (isReadOnlyDb(globalDbPath())) return;
10772
10802
  if (entry === null || entry.sha === "") {
10773
10803
  if (fingerprintFile(resolvedPath) === null) return;
10774
10804
  try {
@@ -10816,9 +10846,8 @@ function warnIfFilesStale(filePaths) {
10816
10846
  healStaleIndex(raw);
10817
10847
  }
10818
10848
  if (staleCount > 0) {
10819
- console.warn(
10820
- `token-goat: ${countNoun(staleCount, "file")} behind these results changed on disk since the index last saw ${staleCount === 1 ? "it" : "them"} -- a reindex just ran, so a repeat of this command will reflect the current version.`
10821
- );
10849
+ const after = isReadOnlyDb(globalDbPath()) ? "the index is read-only this run, so these results are from the older version." : "a reindex just ran, so a repeat of this command will reflect the current version.";
10850
+ console.warn(`token-goat: ${countNoun(staleCount, "file")} behind these results changed on disk since the index last saw ${staleCount === 1 ? "it" : "them"} -- ${after}`);
10822
10851
  }
10823
10852
  }
10824
10853
  function emitGuarded(text, command) {
@@ -10851,11 +10880,21 @@ function sumFileSizes(filePaths) {
10851
10880
  }
10852
10881
  return total;
10853
10882
  }
10883
+ function largestFileSize(filePaths) {
10884
+ let largest = 0;
10885
+ for (const fp of new Set(filePaths)) {
10886
+ try {
10887
+ largest = Math.max(largest, Math.min(fs12.statSync(fp).size, PER_FILE_COUNTERFACTUAL_CEILING));
10888
+ } catch {
10889
+ }
10890
+ }
10891
+ return largest;
10892
+ }
10854
10893
  function refsSearchBaselineBytes(rows) {
10855
10894
  let total = 0;
10856
10895
  for (const ref of rows) total += Buffer.byteLength(`${refsDisplayPath(ref.filePath)}:${ref.line}: ${ref.context}
10857
10896
  `, "utf8");
10858
- return total;
10897
+ return deliveredOutputBytes(total);
10859
10898
  }
10860
10899
  function recordReadStat(kind, fullSourceBytes, emittedText, detail) {
10861
10900
  const emittedBytes = Buffer.byteLength(emittedText, "utf8");
@@ -11008,7 +11047,7 @@ ${emptyIndexMessage(emptyIndexRoot)}`;
11008
11047
  }
11009
11048
  return { text: text2, code: 1 };
11010
11049
  }
11011
- const fullSourceBytes = sumFileSizes(results.map((s) => s.filePath));
11050
+ const fullSourceBytes = largestFileSize(results.map((s) => s.filePath));
11012
11051
  const symbolDisplayRoot = getDisplayRoot(opts.projectRoot);
11013
11052
  const refCounts = opts.stats === true ? queryRefCounts(
11014
11053
  results.map((s) => s.name),
@@ -11029,8 +11068,7 @@ ${emptyIndexMessage(emptyIndexRoot)}`;
11029
11068
  const items = capped.items.map((s) => ({
11030
11069
  ...s,
11031
11070
  filePath: toDisplayPath(symbolDisplayRoot, s.filePath),
11032
- // Only present when true, so a result set of live files stays byte-identical to what this
11033
- // command has always emitted and only the genuinely-gone rows grow a field.
11071
+ // Only present when true, so a result set of live files stays byte-identical to what this command has always emitted and only the genuinely-gone rows grow a field.
11034
11072
  ...fileIsGone(s.filePath) ? { deleted: true } : {},
11035
11073
  ...stillStale.has(s.filePath) ? { stale: true } : {},
11036
11074
  ...refCounts !== void 0 ? { refCount: refCounts.get(s.name) ?? 0, hasDoc: hasRealDocstring(s.docstring) } : {}
@@ -11413,8 +11451,7 @@ function runRefsCrossFile(pairs, opts) {
11413
11451
  return renderRefsTargets(
11414
11452
  pairs.map((p) => ({ file: p.file, symbol: p.symbol, key: keyFor(p) })),
11415
11453
  opts,
11416
- // Not annotated today; renderRefsTargets's own option doc explains why that is a preserved
11417
- // divergence rather than a decision.
11454
+ // Not annotated today; renderRefsTargets's own option doc explains why that is a preserved divergence rather than a decision.
11418
11455
  { annotateHiddenByGrep: false }
11419
11456
  );
11420
11457
  }
@@ -11935,6 +11972,7 @@ function runGrep(opts) {
11935
11972
  return 0;
11936
11973
  }
11937
11974
  var RRF_K = 60;
11975
+ var WEAK_MATCH_DISTANCE = 0.85;
11938
11976
  function applyRelevanceFloor(hits, floor) {
11939
11977
  const kept = [];
11940
11978
  let nearestRejected = null;
@@ -12047,6 +12085,8 @@ async function runSemantic(query, opts) {
12047
12085
  }
12048
12086
  rawHits = kept;
12049
12087
  }
12088
+ const closestDense = rawHits.reduce((best, h) => best === null || h.distance < best ? h.distance : best, null);
12089
+ const weakClosestDistance = closestDense !== null && closestDense > WEAK_MATCH_DISTANCE ? closestDense : null;
12050
12090
  if (rawHits.length === 0 && floorNearestRejected === null && isAvailable() && preflight.status === "ready" && !searchSemanticError) {
12051
12091
  try {
12052
12092
  const enabled = loadConfig().indexing.embeddings_enabled;
@@ -12140,6 +12180,7 @@ async function runSemantic(query, opts) {
12140
12180
  truncated: capped.truncated || limitTruncated,
12141
12181
  totalCount: eligibleCount,
12142
12182
  ...candidatesClipped ? { totalCountIsFloor: true } : {},
12183
+ ...weakClosestDistance !== null ? { lowConfidence: { closestDistance: weakClosestDistance, threshold: WEAK_MATCH_DISTANCE } } : {},
12143
12184
  ...preflight.status !== "ready" ? {
12144
12185
  preflightStatus: preflight.status,
12145
12186
  warning: preflight.summary,
@@ -12149,7 +12190,7 @@ async function runSemantic(query, opts) {
12149
12190
  warning: `Matching on meaning failed (${searchSemanticError}); results come from keyword search alone.`
12150
12191
  } : {}
12151
12192
  });
12152
- recordReadStat("semantic_search", sumFileSizes(hits.map((h) => h.filePath)), text3, query);
12193
+ recordReadStat("semantic_search", largestFileSize(hits.map((h) => h.filePath)), text3, query);
12153
12194
  return { text: text3, code: 0 };
12154
12195
  }
12155
12196
  const blocks = hits.map((h, i) => {
@@ -12166,7 +12207,12 @@ ${previewLines(h.previewText, 3)}`;
12166
12207
  if (hits.length < eligibleCount) {
12167
12208
  emitErr(`Showing ${hits.length} of ${candidatesClipped ? "at least " : ""}${countNoun(eligibleCount, "match", "matches")} (raise --limit to see the rest).`);
12168
12209
  }
12169
- recordReadStat("semantic_search", sumFileSizes(hits.map((h) => h.filePath)), text2, query);
12210
+ if (weakClosestDistance !== null) {
12211
+ console.warn(
12212
+ `Matching on meaning found nothing close for '${query}' (closest was ${weakClosestDistance.toFixed(3)}, weak above ${WEAK_MATCH_DISTANCE}); these results may be unrelated. For a known name try token-goat symbol --grep <pattern> or rg, or rephrase the query.`
12213
+ );
12214
+ }
12215
+ recordReadStat("semantic_search", largestFileSize(hits.map((h) => h.filePath)), text2, query);
12170
12216
  return { text: text2, code: 0 };
12171
12217
  }
12172
12218
  if (matchesGrep !== void 0 && preFilterCount > 0) {
@@ -12188,7 +12234,7 @@ ${previewLines(h.previewText, 3)}`;
12188
12234
  if (!anyFilter) {
12189
12235
  const evidenceHits = await searchEvidenceSemantically(rootDir, query, n);
12190
12236
  if (evidenceHits.length > 0) {
12191
- const evidenceFullBytes = evidenceHits.reduce((sum, entry) => sum + Buffer.byteLength(entry.text, "utf8"), 0);
12237
+ const evidenceFullBytes = evidenceHits.reduce((sum, entry) => sum + deliveredOutputBytes(Buffer.byteLength(entry.text, "utf8")), 0);
12192
12238
  if (opts.json === true) {
12193
12239
  const items = evidenceHits.map((entry) => ({
12194
12240
  source: toDisplayPath(rootDir, entry.source),
@@ -12212,6 +12258,18 @@ ${previewLines(entry.text, 3)}`).join("\n\n"),
12212
12258
  }
12213
12259
  const indexEmpty = isIndexEmptyForProject(globalDbPath(), rootDir);
12214
12260
  if (opts.json === true) {
12261
+ let symFound = false;
12262
+ const trimmedQuery2 = query.trim();
12263
+ const isIdentifier2 = /^[A-Za-z0-9_.:-]+$/.test(trimmedQuery2);
12264
+ if (!indexEmpty && isIdentifier2) {
12265
+ try {
12266
+ const symMatches = querySymbols({ name: trimmedQuery2, rootDir, limit: 1 });
12267
+ if (symMatches.length > 0) {
12268
+ symFound = true;
12269
+ }
12270
+ } catch {
12271
+ }
12272
+ }
12215
12273
  const payload = indexEmpty ? {
12216
12274
  source: "fts",
12217
12275
  items: [],
@@ -12239,6 +12297,10 @@ ${previewLines(entry.text, 3)}`).join("\n\n"),
12239
12297
  } : searchSemanticError !== null ? {
12240
12298
  preflightStatus: "degraded",
12241
12299
  warning: `Matching on meaning failed (${searchSemanticError}); results come from keyword search alone.`
12300
+ } : {},
12301
+ ...!indexEmpty && isIdentifier2 ? {
12302
+ symbolSuggestion: `token-goat symbol "${trimmedQuery2}"`,
12303
+ ...symFound ? { indexedSymbolFound: true } : {}
12242
12304
  } : {}
12243
12305
  };
12244
12306
  const text2 = displaySafeJson(payload);
@@ -12246,6 +12308,25 @@ ${previewLines(entry.text, 3)}`).join("\n\n"),
12246
12308
  }
12247
12309
  let text = indexEmpty ? `token-goat: no matches for '${query}'
12248
12310
  ${emptyIndexMessage(rootDir)}` : `token-goat: no matches for '${query}'`;
12311
+ const trimmedQuery = query.trim();
12312
+ const isIdentifier = /^[A-Za-z0-9_.:-]+$/.test(trimmedQuery);
12313
+ if (!indexEmpty && isIdentifier) {
12314
+ let symFound = false;
12315
+ try {
12316
+ const symMatches = querySymbols({ name: trimmedQuery, rootDir, limit: 1 });
12317
+ if (symMatches.length > 0) {
12318
+ symFound = true;
12319
+ }
12320
+ } catch {
12321
+ }
12322
+ if (symFound) {
12323
+ text += `
12324
+ (note: '${trimmedQuery}' is an indexed symbol name; use: token-goat symbol "${trimmedQuery}")`;
12325
+ } else {
12326
+ text += `
12327
+ Try: token-goat symbol "${trimmedQuery}"`;
12328
+ }
12329
+ }
12249
12330
  if (preflight.status !== "ready") {
12250
12331
  text += `
12251
12332
  (note: semantic indexing is degraded [${preflight.status}]: ${preflight.summary}${preflight.actionRequired ? ` \u2014 ${preflight.actionRequired}` : ""})`;
@@ -12255,6 +12336,24 @@ ${emptyIndexMessage(rootDir)}` : `token-goat: no matches for '${query}'`;
12255
12336
  }
12256
12337
  return { text, code: 1 };
12257
12338
  }
12339
+ async function runSemanticMulti(queries, opts) {
12340
+ const laterOpts = { ...opts };
12341
+ delete laterOpts.warm;
12342
+ const blocks = [];
12343
+ const entries = [];
12344
+ let anyOk = false;
12345
+ for (const [i, query] of queries.entries()) {
12346
+ const sub = await runSemantic(query, i === 0 ? opts : laterOpts);
12347
+ if (sub.code === 0) anyOk = true;
12348
+ if (opts.json === true) {
12349
+ entries.push({ query, ...JSON.parse(sub.text) });
12350
+ continue;
12351
+ }
12352
+ blocks.push(`'${query}':
12353
+ ${sub.text}`);
12354
+ }
12355
+ return { text: opts.json === true ? displaySafeJson(entries) : blocks.join("\n\n"), code: anyOk ? 0 : 1 };
12356
+ }
12258
12357
 
12259
12358
  // src/read_spec.ts
12260
12359
  function fileExists3(p) {
@@ -12628,6 +12727,19 @@ function resolveSymbolSpecOrEmitError(commandName, spec, projectRoot) {
12628
12727
  return resolution.entry;
12629
12728
  }
12630
12729
 
12730
+ // src/handle_stat.ts
12731
+ init_define_import_meta_env();
12732
+ import * as fs14 from "node:fs";
12733
+ var OPEN_FOR_STAT = process.platform === "win32" ? fs14.constants.O_RDONLY : fs14.constants.O_RDONLY | fs14.constants.O_NONBLOCK;
12734
+ function statThroughHandle(p) {
12735
+ const fd = fs14.openSync(p, OPEN_FOR_STAT);
12736
+ try {
12737
+ return fs14.fstatSync(fd, { bigint: true });
12738
+ } finally {
12739
+ fs14.closeSync(fd);
12740
+ }
12741
+ }
12742
+
12631
12743
  // src/content_store.ts
12632
12744
  init_define_import_meta_env();
12633
12745
  import { deflateRawSync } from "node:zlib";
@@ -12790,7 +12902,7 @@ export {
12790
12902
  runOpenApiOp,
12791
12903
  rankSimilarNames,
12792
12904
  filterSimilarHeadings,
12793
- didYouMean,
12905
+ didYouMeanLines,
12794
12906
  extraFileArgsNote,
12795
12907
  parseLineRange,
12796
12908
  parseColonLineSpec,
@@ -12848,6 +12960,8 @@ export {
12848
12960
  runScreenshot,
12849
12961
  runGrep,
12850
12962
  runSemantic,
12963
+ runSemanticMulti,
12964
+ statThroughHandle,
12851
12965
  CONTENT_MAX_INPUT_CHARS,
12852
12966
  compressText,
12853
12967
  retrieveText,