@wrongstack/tools 1.0.1 → 1.0.2

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 (63) hide show
  1. package/dist/builtin.js +13 -13
  2. package/dist/{chunk-VVZPQPTY.js → chunk-3AU6CZWL.js} +4 -2
  3. package/dist/{chunk-N3K2SFEI.js → chunk-52UXXQMP.js} +1408 -200
  4. package/dist/{chunk-DK4J2WMH.js → chunk-7XUEPBNT.js} +2 -2
  5. package/dist/{chunk-IYH4OHBP.js → chunk-DKHMPKDG.js} +2 -2
  6. package/dist/{chunk-NU2IZ72J.js → chunk-DL2ARI4S.js} +7 -5
  7. package/dist/{chunk-E7JE3UEX.js → chunk-EL2NJXSK.js} +2 -2
  8. package/dist/{chunk-YEISRT4S.js → chunk-HWXIRVKH.js} +1408 -235
  9. package/dist/{chunk-GKSG5CPH.js → chunk-KVTEIUND.js} +2 -2
  10. package/dist/{chunk-GDDXX27P.js → chunk-MBR5VAB5.js} +2 -2
  11. package/dist/{chunk-7LQCT3LT.js → chunk-NFX2IUQA.js} +3 -3
  12. package/dist/{chunk-ZTCJCYLN.js → chunk-TI5COGLY.js} +49 -6
  13. package/dist/{chunk-CGXTR34H.js → chunk-TU5MTW2S.js} +2 -2
  14. package/dist/{chunk-IAYMTTR2.js → chunk-UCXFTCAI.js} +12 -8
  15. package/dist/{chunk-MK2JK35J.js → chunk-UOYRAS4J.js} +3 -3
  16. package/dist/{chunk-UCYQTZ7F.js → chunk-ZKC5UNGD.js} +56 -2
  17. package/dist/codebase-index/atlas-brief.d.ts +90 -0
  18. package/dist/codebase-index/atlas-export.d.ts +38 -0
  19. package/dist/codebase-index/atlas-projection.d.ts +114 -0
  20. package/dist/codebase-index/atlas-types.d.ts +90 -0
  21. package/dist/codebase-index/background-indexer.d.ts +15 -4
  22. package/dist/codebase-index/codebase-context-tool.d.ts +54 -0
  23. package/dist/codebase-index/concept-enrichment.d.ts +154 -0
  24. package/dist/codebase-index/context-retrieval.d.ts +91 -0
  25. package/dist/codebase-index/embedding-pass.d.ts +95 -0
  26. package/dist/codebase-index/graph-adjacency-cache.d.ts +36 -0
  27. package/dist/codebase-index/graph-rank-pass.d.ts +46 -0
  28. package/dist/codebase-index/graph-rank.d.ts +198 -0
  29. package/dist/codebase-index/index-service.d.ts +15 -1
  30. package/dist/codebase-index/index.d.ts +34 -19
  31. package/dist/codebase-index/index.js +126 -9
  32. package/dist/codebase-index/parser-worker-script.js +3 -3
  33. package/dist/codebase-index/perf-metrics.d.ts +19 -0
  34. package/dist/codebase-index/project-server-protocol.d.ts +2 -0
  35. package/dist/codebase-index/project-server-query-cache.d.ts +4 -0
  36. package/dist/codebase-index/project-server.js +54 -7
  37. package/dist/codebase-index/repo-map-fallback.d.ts +18 -0
  38. package/dist/codebase-index/repo-map-render.d.ts +42 -0
  39. package/dist/codebase-index/repo-map-types.d.ts +21 -0
  40. package/dist/codebase-index/repo-map.d.ts +28 -16
  41. package/dist/codebase-index/schema.d.ts +20 -0
  42. package/dist/codebase-index/worker-protocol.d.ts +47 -1
  43. package/dist/codebase-index/worker.js +11 -5
  44. package/dist/codebase-index/writer-concepts.d.ts +84 -0
  45. package/dist/codebase-index/writer-graph-decorate.d.ts +30 -0
  46. package/dist/codebase-index/writer-graph-reader.d.ts +22 -0
  47. package/dist/codebase-index/writer-rank.d.ts +78 -0
  48. package/dist/codebase-index/writer-schema.d.ts +51 -0
  49. package/dist/codebase-index/writer-vectors.d.ts +53 -0
  50. package/dist/codebase-index/writer.d.ts +59 -0
  51. package/dist/edit.js +7 -7
  52. package/dist/{go-parser-D7ELWQ7F.js → go-parser-QIEXU3P2.js} +4 -2
  53. package/dist/index.d.ts +48 -48
  54. package/dist/index.js +40 -16
  55. package/dist/pack.js +14 -14
  56. package/dist/{parser-dispatch-BDVCJXTV.js → parser-dispatch-37FT3EXQ.js} +4 -4
  57. package/dist/patch.js +7 -7
  58. package/dist/{py-parser-QC6MR4GB.js → py-parser-6GJTGUXK.js} +3 -3
  59. package/dist/read.js +7 -7
  60. package/dist/replace.js +7 -7
  61. package/dist/tool-tier.js +15 -15
  62. package/dist/write.js +7 -7
  63. package/package.json +5 -5
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-MSOAX3GC.js";
4
4
  import {
5
5
  enqueueReindex
6
- } from "./chunk-ZTCJCYLN.js";
6
+ } from "./chunk-TI5COGLY.js";
7
7
  import {
8
8
  safeResolveReal,
9
9
  sha256hex,
@@ -179,4 +179,4 @@ async function finishWrite(input, ctx, prepared, signal) {
179
179
  export {
180
180
  writeTool
181
181
  };
182
- //# sourceMappingURL=chunk-GKSG5CPH.js.map
182
+ //# sourceMappingURL=chunk-KVTEIUND.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  resolveIndexDir
3
- } from "./chunk-N3K2SFEI.js";
3
+ } from "./chunk-52UXXQMP.js";
4
4
 
5
5
  // src/codebase-index/project-server-endpoint.ts
6
6
  import { createHash } from "node:crypto";
@@ -120,4 +120,4 @@ export {
120
120
  PROJECT_INDEX_SERVER_MAX_FRAME_CHARS,
121
121
  encodeProjectServerMessage
122
122
  };
123
- //# sourceMappingURL=chunk-GDDXX27P.js.map
123
+ //# sourceMappingURL=chunk-MBR5VAB5.js.map
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  builtinToolsPack
3
- } from "./chunk-E7JE3UEX.js";
3
+ } from "./chunk-EL2NJXSK.js";
4
4
  import {
5
5
  TIER1_TOOLS,
6
6
  TIER2_TOOLS
7
- } from "./chunk-IAYMTTR2.js";
7
+ } from "./chunk-UCXFTCAI.js";
8
8
 
9
9
  // src/tool-tier.ts
10
10
  function toolNameSet(tools) {
@@ -54,4 +54,4 @@ export {
54
54
  selectBuiltinToolsForTier,
55
55
  registerBuiltinToolTier
56
56
  };
57
- //# sourceMappingURL=chunk-7LQCT3LT.js.map
57
+ //# sourceMappingURL=chunk-NFX2IUQA.js.map
@@ -9,7 +9,7 @@ import {
9
9
  projectIndexServerBuildId,
10
10
  projectIndexServerEndpoint,
11
11
  projectIndexServerMetadataPath
12
- } from "./chunk-GDDXX27P.js";
12
+ } from "./chunk-MBR5VAB5.js";
13
13
  import {
14
14
  CircuitOpenError,
15
15
  IndexTimeoutError,
@@ -24,7 +24,10 @@ import {
24
24
  searchService,
25
25
  statsService,
26
26
  symbolGraphService
27
- } from "./chunk-N3K2SFEI.js";
27
+ } from "./chunk-52UXXQMP.js";
28
+ import {
29
+ recordIpcPending
30
+ } from "./chunk-ZKC5UNGD.js";
28
31
  import {
29
32
  isIndexablePath
30
33
  } from "./chunk-YOHO4DVT.js";
@@ -385,6 +388,7 @@ var ProjectServerConnection = class {
385
388
  onAbort,
386
389
  onProgress: options.onProgress
387
390
  });
391
+ recordIpcPending(this.pending.size);
388
392
  if (signal && onAbort) {
389
393
  signal.addEventListener("abort", onAbort, { once: true });
390
394
  if (signal.aborted) {
@@ -1032,6 +1036,7 @@ async function callInline(op, args, opts) {
1032
1036
  }
1033
1037
  var chain = Promise.resolve();
1034
1038
  function withMutex(job) {
1039
+ if (process.env["WRONGSTACK_INDEX_BENCH_NO_HOST_MUTEX"] === "1") return job();
1035
1040
  const run = chain.then(job, job);
1036
1041
  chain = run.then(
1037
1042
  () => void 0,
@@ -1048,6 +1053,7 @@ function circuitOpenError() {
1048
1053
  var DEFAULT_DEBOUNCE_MS = 400;
1049
1054
  var DEFAULT_COALESCE_WINDOW_MS = 50;
1050
1055
  var debounceTimers = /* @__PURE__ */ new Map();
1056
+ var pendingReindexCompletions = /* @__PURE__ */ new Map();
1051
1057
  var readyReindexBatches = /* @__PURE__ */ new Map();
1052
1058
  function debounceKey(projectRoot, indexDir, file) {
1053
1059
  return JSON.stringify([projectRoot, indexDir ?? "", file]);
@@ -1055,6 +1061,11 @@ function debounceKey(projectRoot, indexDir, file) {
1055
1061
  function reindexBatchKey(projectRoot, indexDir) {
1056
1062
  return JSON.stringify([projectRoot, indexDir ?? ""]);
1057
1063
  }
1064
+ function settleReindexCompletions(completions, _error) {
1065
+ for (const completion of completions) {
1066
+ completion.resolve();
1067
+ }
1068
+ }
1058
1069
  function flushReadyReindexBatch(key) {
1059
1070
  const batch = readyReindexBatches.get(key);
1060
1071
  if (!batch) return;
@@ -1062,6 +1073,7 @@ function flushReadyReindexBatch(key) {
1062
1073
  if (!indexCircuitBreaker.allowRequest()) {
1063
1074
  const error = circuitOpenError();
1064
1075
  for (const onError of batch.onErrors) onError(error);
1076
+ settleReindexCompletions(batch.completions, error);
1065
1077
  return;
1066
1078
  }
1067
1079
  void withMutex(
@@ -1075,21 +1087,28 @@ function flushReadyReindexBatch(key) {
1075
1087
  { timeoutMs: batch.timeoutMs }
1076
1088
  )
1077
1089
  ).then(
1078
- () => indexCircuitBreaker.recordSuccess(),
1090
+ () => {
1091
+ indexCircuitBreaker.recordSuccess();
1092
+ settleReindexCompletions(batch.completions);
1093
+ },
1079
1094
  (err) => {
1080
1095
  indexCircuitBreaker.recordFailure(err);
1081
1096
  for (const onError of batch.onErrors) onError(err);
1097
+ settleReindexCompletions(batch.completions, err);
1082
1098
  }
1083
1099
  );
1084
1100
  }
1085
1101
  function addReadyReindex(opts) {
1086
1102
  const key = reindexBatchKey(opts.projectRoot, opts.indexDir);
1087
1103
  const windowMs = opts.coalesceWindowMs ?? DEFAULT_COALESCE_WINDOW_MS;
1104
+ const pending2 = pendingReindexCompletions.get(key);
1105
+ pendingReindexCompletions.delete(key);
1088
1106
  const existing = readyReindexBatches.get(key);
1089
1107
  if (existing) {
1090
1108
  existing.files.add(opts.file);
1091
1109
  existing.timeoutMs = Math.max(existing.timeoutMs, opts.timeoutMs);
1092
1110
  if (opts.onError) existing.onErrors.add(opts.onError);
1111
+ if (pending2) for (const completion of pending2) existing.completions.add(completion);
1093
1112
  if (windowMs > 0 && existing.flush) {
1094
1113
  clearTimeout(existing.flush);
1095
1114
  existing.flush = setTimeout(() => flushReadyReindexBatch(key), windowMs);
@@ -1102,7 +1121,8 @@ function addReadyReindex(opts) {
1102
1121
  indexDir: opts.indexDir,
1103
1122
  files: /* @__PURE__ */ new Set([opts.file]),
1104
1123
  timeoutMs: opts.timeoutMs,
1105
- onErrors: new Set(opts.onError ? [opts.onError] : [])
1124
+ onErrors: new Set(opts.onError ? [opts.onError] : []),
1125
+ completions: pending2 ?? /* @__PURE__ */ new Set()
1106
1126
  };
1107
1127
  batch.flush = setTimeout(() => flushReadyReindexBatch(key), Math.max(0, windowMs));
1108
1128
  batch.flush.unref?.();
@@ -1170,7 +1190,13 @@ async function runStartupIndex(opts) {
1170
1190
  }
1171
1191
  function enqueueReindex(opts) {
1172
1192
  const files = opts.files.filter(isIndexableFile);
1173
- if (files.length === 0) return;
1193
+ if (files.length === 0) return Promise.resolve();
1194
+ const completion = new Promise((resolve, reject) => {
1195
+ const key = reindexBatchKey(opts.projectRoot, opts.indexDir);
1196
+ const pending2 = pendingReindexCompletions.get(key) ?? /* @__PURE__ */ new Set();
1197
+ pending2.add({ resolve, reject });
1198
+ pendingReindexCompletions.set(key, pending2);
1199
+ });
1174
1200
  const ms = opts.debounceMs ?? DEFAULT_DEBOUNCE_MS;
1175
1201
  for (const file of files) {
1176
1202
  const key = debounceKey(opts.projectRoot, opts.indexDir, file);
@@ -1190,6 +1216,7 @@ function enqueueReindex(opts) {
1190
1216
  timer.unref?.();
1191
1217
  debounceTimers.set(key, timer);
1192
1218
  }
1219
+ return completion;
1193
1220
  }
1194
1221
  function cancelPendingReindexes() {
1195
1222
  for (const t of debounceTimers.values()) clearTimeout(t);
@@ -1197,7 +1224,15 @@ function cancelPendingReindexes() {
1197
1224
  for (const batch of readyReindexBatches.values()) {
1198
1225
  if (batch.flush) clearTimeout(batch.flush);
1199
1226
  }
1227
+ const cancelled = new Error("pending reindex cancelled");
1228
+ for (const batch of readyReindexBatches.values()) {
1229
+ settleReindexCompletions(batch.completions, cancelled);
1230
+ }
1200
1231
  readyReindexBatches.clear();
1232
+ for (const completions of pendingReindexCompletions.values()) {
1233
+ settleReindexCompletions(completions, cancelled);
1234
+ }
1235
+ pendingReindexCompletions.clear();
1201
1236
  }
1202
1237
  async function searchCodebaseIndex(args, opts = {}) {
1203
1238
  return callIndexOp("search", args, {
@@ -1211,6 +1246,12 @@ async function codebaseIndexStats(args, opts = {}) {
1211
1246
  signal: opts.signal
1212
1247
  });
1213
1248
  }
1249
+ async function codebaseContext(args) {
1250
+ return callIndexOp("context", args, { timeoutMs: DEFAULT_QUERY_TIMEOUT_MS });
1251
+ }
1252
+ async function codebaseVectorSearch(args) {
1253
+ return callIndexOp("vectorSearch", args, { timeoutMs: DEFAULT_QUERY_TIMEOUT_MS });
1254
+ }
1214
1255
  async function packageGraphService2(args) {
1215
1256
  return callIndexOp("packageGraph", args, { timeoutMs: DEFAULT_QUERY_TIMEOUT_MS });
1216
1257
  }
@@ -1260,6 +1301,8 @@ export {
1260
1301
  cancelPendingReindexes,
1261
1302
  searchCodebaseIndex,
1262
1303
  codebaseIndexStats,
1304
+ codebaseContext,
1305
+ codebaseVectorSearch,
1263
1306
  packageGraphService2 as packageGraphService,
1264
1307
  fileGraphService2 as fileGraphService,
1265
1308
  symbolGraphService2 as symbolGraphService,
@@ -1269,4 +1312,4 @@ export {
1269
1312
  checkCodebaseIndexServerHealth,
1270
1313
  ensureCodebaseIndexServer
1271
1314
  };
1272
- //# sourceMappingURL=chunk-ZTCJCYLN.js.map
1315
+ //# sourceMappingURL=chunk-TI5COGLY.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  enqueueReindex
3
- } from "./chunk-ZTCJCYLN.js";
3
+ } from "./chunk-TI5COGLY.js";
4
4
  import {
5
5
  resolveRealInsideRoot,
6
6
  safeResolveReal,
@@ -395,4 +395,4 @@ function extractPatchedFiles(output) {
395
395
  export {
396
396
  patchTool
397
397
  };
398
- //# sourceMappingURL=chunk-CGXTR34H.js.map
398
+ //# sourceMappingURL=chunk-TU5MTW2S.js.map
@@ -3,6 +3,7 @@ import {
3
3
  } from "./chunk-RV7BVTDG.js";
4
4
  import {
5
5
  codebaseAstReplaceTool,
6
+ codebaseContextTool,
6
7
  codebaseImpactAnalysisTool,
7
8
  codebaseIncomingCallsTool,
8
9
  codebaseIndexTool,
@@ -14,7 +15,7 @@ import {
14
15
  codebaseStatsTool,
15
16
  codebaseTargetedTestTool,
16
17
  deadCodeScanTool
17
- } from "./chunk-YEISRT4S.js";
18
+ } from "./chunk-HWXIRVKH.js";
18
19
  import {
19
20
  planTool
20
21
  } from "./chunk-5KS24LTS.js";
@@ -62,7 +63,7 @@ import {
62
63
  } from "./chunk-AQ5YBURX.js";
63
64
  import {
64
65
  patchTool
65
- } from "./chunk-CGXTR34H.js";
66
+ } from "./chunk-TU5MTW2S.js";
66
67
  import {
67
68
  jsonTool
68
69
  } from "./chunk-VZGPASGD.js";
@@ -88,7 +89,7 @@ import {
88
89
  } from "./chunk-7N5U2RAU.js";
89
90
  import {
90
91
  replaceTool
91
- } from "./chunk-IYH4OHBP.js";
92
+ } from "./chunk-DKHMPKDG.js";
92
93
  import {
93
94
  globTool
94
95
  } from "./chunk-ASEXQRA7.js";
@@ -133,13 +134,13 @@ import {
133
134
  } from "./chunk-SOR7OCYP.js";
134
135
  import {
135
136
  readTool
136
- } from "./chunk-MK2JK35J.js";
137
+ } from "./chunk-UOYRAS4J.js";
137
138
  import {
138
139
  writeTool
139
- } from "./chunk-GKSG5CPH.js";
140
+ } from "./chunk-KVTEIUND.js";
140
141
  import {
141
142
  editTool
142
- } from "./chunk-DK4J2WMH.js";
143
+ } from "./chunk-7XUEPBNT.js";
143
144
  import {
144
145
  resolvePowerShell
145
146
  } from "./chunk-KE7A76VC.js";
@@ -1233,7 +1234,8 @@ var BUILTIN_TOOL_DESCRIPTIONS = {
1233
1234
  "codebase-stats": "Report codebase-index health, indexed file and symbol counts, languages, and freshness. Use it before relying on indexed discovery results.",
1234
1235
  "codebase-search": "Search indexed symbols, signatures, and documentation with optional language, kind, path, or LSP-kind filters. Use it for semantic discovery before broad text search.",
1235
1236
  "codebase-skeleton": "Extract a compact structural skeleton from a source file or directory, preserving declarations while omitting implementation detail. Use it to understand unfamiliar code quickly.",
1236
- "codebase-repo-map": "Generate a reference-weighted, token-budgeted Repository Map of the codebase within ~1200 tokens by default. Use at the beginning of complex tasks or when navigating unfamiliar repositories to get a bird-eye view of the architecture.",
1237
+ "codebase-context": "Find the files and declarations a task touches from a plain-language description. Ranked symbol search seeds a personalised walk over the reference graph, so results include what the matches are structurally attached to, not just what matched by name. Start here for any task spanning more than one file.",
1238
+ "codebase-repo-map": "Generate a centrality-ranked, token-budgeted Repository Map within ~1200 tokens by default: package clusters with their hub file, the repo-wide hotspots, then the signatures of the most central files. Use at the beginning of complex tasks or when navigating unfamiliar repositories to get a bird-eye view of the architecture.",
1237
1239
  "codebase-impact-analysis": "Find likely callers, dependents, related tests, and change risk for a named symbol. Use it before changing a public or widely used declaration.",
1238
1240
  "codebase-targeted-test": "Discover and run tests that cover a specified symbol, source file, or explicit test files. Use it for focused regression validation after a change.",
1239
1241
  "security-ast-scan": "Statically scan source code for supported security patterns and return findings with locations. Use it as a focused code check, not as a substitute for a full security assessment.",
@@ -1305,6 +1307,7 @@ var TIER1_TOOLS = [
1305
1307
  codebaseSearchTool,
1306
1308
  codebaseSkeletonTool,
1307
1309
  codebaseRepoMapTool,
1310
+ codebaseContextTool,
1308
1311
  codebaseImpactAnalysisTool,
1309
1312
  codebaseTargetedTestTool,
1310
1313
  securityAstScanTool,
@@ -1366,6 +1369,7 @@ var rawBuiltinTools = [
1366
1369
  codebaseSearchTool,
1367
1370
  codebaseSkeletonTool,
1368
1371
  codebaseRepoMapTool,
1372
+ codebaseContextTool,
1369
1373
  codebaseImpactAnalysisTool,
1370
1374
  codebaseTargetedTestTool,
1371
1375
  securityAstScanTool,
@@ -1434,4 +1438,4 @@ export {
1434
1438
  TIER3_TOOLS,
1435
1439
  builtinTools
1436
1440
  };
1437
- //# sourceMappingURL=chunk-IAYMTTR2.js.map
1441
+ //# sourceMappingURL=chunk-UCXFTCAI.js.map
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  getIndexState,
3
3
  searchCodebaseIndex
4
- } from "./chunk-ZTCJCYLN.js";
4
+ } from "./chunk-TI5COGLY.js";
5
5
  import {
6
6
  codebaseIndexDirOverride
7
- } from "./chunk-N3K2SFEI.js";
7
+ } from "./chunk-52UXXQMP.js";
8
8
  import {
9
9
  isBinaryBuffer,
10
10
  safeResolveReal,
@@ -340,4 +340,4 @@ ${interesting.join("\n")}` : "symbols/imports: (none detected)"
340
340
  export {
341
341
  readTool
342
342
  };
343
- //# sourceMappingURL=chunk-MK2JK35J.js.map
343
+ //# sourceMappingURL=chunk-UOYRAS4J.js.map
@@ -94,10 +94,58 @@ function dedupeRefs(refs) {
94
94
  });
95
95
  }
96
96
 
97
+ // src/codebase-index/perf-metrics.ts
98
+ var counters = {
99
+ filesystemBytesRead: 0,
100
+ filesystemReadCount: 0,
101
+ parserGateWaitMs: 0,
102
+ parserGateCalls: 0,
103
+ parserSubprocessCount: 0,
104
+ ipcPendingPeak: 0,
105
+ writeQueueWaitMs: 0,
106
+ writeQueueCalls: 0
107
+ };
108
+ function resetCodebaseIndexPerfMetrics() {
109
+ for (const key of Object.keys(counters)) {
110
+ counters[key] = 0;
111
+ }
112
+ }
113
+ function getCodebaseIndexPerfSnapshot() {
114
+ return { ...counters };
115
+ }
116
+ function recordFilesystemRead(bytes) {
117
+ counters.filesystemBytesRead += Math.max(0, bytes);
118
+ counters.filesystemReadCount++;
119
+ }
120
+ function recordParserGateWait(waitMs) {
121
+ counters.parserGateWaitMs += Math.max(0, waitMs);
122
+ counters.parserGateCalls++;
123
+ }
124
+ function recordParserSubprocess() {
125
+ counters.parserSubprocessCount++;
126
+ }
127
+ function recordIpcPending(depth) {
128
+ counters.ipcPendingPeak = Math.max(counters.ipcPendingPeak, depth);
129
+ }
130
+ function recordWriteQueueWait(waitMs) {
131
+ counters.writeQueueWaitMs += Math.max(0, waitMs);
132
+ counters.writeQueueCalls++;
133
+ }
134
+
97
135
  // src/codebase-index/spawn-gate.ts
98
136
  var chain = Promise.resolve();
99
137
  function withSpawnGate(fn) {
100
- const run = chain.then(fn, fn);
138
+ const queuedAt = performance.now();
139
+ const run = chain.then(
140
+ () => {
141
+ recordParserGateWait(performance.now() - queuedAt);
142
+ return fn();
143
+ },
144
+ () => {
145
+ recordParserGateWait(performance.now() - queuedAt);
146
+ return fn();
147
+ }
148
+ );
101
149
  chain = run.then(
102
150
  () => void 0,
103
151
  () => void 0
@@ -108,6 +156,12 @@ function withSpawnGate(fn) {
108
156
  export {
109
157
  parseParserOutput,
110
158
  parseParserBatchOutput,
159
+ resetCodebaseIndexPerfMetrics,
160
+ getCodebaseIndexPerfSnapshot,
161
+ recordFilesystemRead,
162
+ recordParserSubprocess,
163
+ recordIpcPending,
164
+ recordWriteQueueWait,
111
165
  withSpawnGate
112
166
  };
113
- //# sourceMappingURL=chunk-UCYQTZ7F.js.map
167
+ //# sourceMappingURL=chunk-ZKC5UNGD.js.map
@@ -0,0 +1,90 @@
1
+ /**
2
+ * The Atlas brief — what an agent should already know before it asks anything.
3
+ *
4
+ * Every other part of this subsystem answers a question. This one answers the
5
+ * question nobody asks: *what is this repository?* An agent that has to
6
+ * discover the shape of an 8,000-file monorepo by search costs a dozen tool
7
+ * calls per session and rediscovers the same thing every session. A few
8
+ * hundred tokens of "here are the twenty files everything depends on, here is
9
+ * what each package is for" removes that repeatedly-paid cost.
10
+ *
11
+ * ## Why it is a structure, not a string
12
+ *
13
+ * The renderer lives with the caller because the budget does. The CLI's
14
+ * system-prompt contributor has a hard token ceiling and trims from the
15
+ * bottom; a webui panel or a `--brief` flag would want different cuts of the
16
+ * same data. Building a string here would force one budget on all of them.
17
+ *
18
+ * ## Why it reports staleness rather than hiding it
19
+ *
20
+ * A brief describing code that has since changed is worse than no brief: it
21
+ * is confidently wrong in a way the reader cannot detect. `staleFiles` is
22
+ * carried so the caller can say so out loud.
23
+ */
24
+ import { type IndexStore } from './writer.js';
25
+ /** Hubs named in the brief. Past roughly this many, it stops being a summary. */
26
+ export declare const BRIEF_HUB_LIMIT = 20;
27
+ /** Packages named in the brief. */
28
+ export declare const BRIEF_PACKAGE_LIMIT = 12;
29
+ /** Subsystem one-liners included when the concept layer has run. */
30
+ export declare const BRIEF_SUBSYSTEM_LIMIT = 10;
31
+ export interface AtlasBriefHub {
32
+ path: string;
33
+ /** Rank relative to the most central file in the repository. */
34
+ rank: number;
35
+ /** Concept-layer summary, when the layer has run for this file. */
36
+ concept?: string | undefined;
37
+ }
38
+ export interface AtlasBriefPackage {
39
+ name: string;
40
+ files: number;
41
+ /** The package's most central file. */
42
+ hub: string;
43
+ }
44
+ export interface AtlasBriefSubsystem {
45
+ name: string;
46
+ summary: string;
47
+ }
48
+ export interface AtlasBrief {
49
+ /** True once the rank pass has run; false means only counts are meaningful. */
50
+ ranked: boolean;
51
+ counts: {
52
+ files: number;
53
+ symbols: number;
54
+ packages: number;
55
+ };
56
+ hubs: AtlasBriefHub[];
57
+ packages: AtlasBriefPackage[];
58
+ subsystems: AtlasBriefSubsystem[];
59
+ /**
60
+ * Files whose content changed since the written atlas was generated, or
61
+ * `undefined` when no atlas has been written — a project that never ran
62
+ * `--write` is not stale, it simply has no projection.
63
+ */
64
+ staleFiles?: number | undefined;
65
+ }
66
+ /**
67
+ * Build the brief from an open store.
68
+ *
69
+ * Reads only what it names: the ranked head, not the whole ranking. On an
70
+ * index with no ranks this returns `ranked: false` and empty lists rather
71
+ * than falling back to a filename heuristic — a guess presented as the
72
+ * repository's structure is the failure mode this whole subsystem exists to
73
+ * remove.
74
+ */
75
+ export declare function buildAtlasBrief(store: IndexStore, projectRoot: string): Promise<AtlasBrief>;
76
+ /** Reported when a project has no index to summarise. */
77
+ export type AtlasBriefIndexMissing = {
78
+ indexed: false;
79
+ };
80
+ /**
81
+ * Build a project's brief, owning the store lifetime.
82
+ *
83
+ * Refuses without an index for the same reason every other project-level
84
+ * entry point does: acquiring a store CREATES the database, and a prompt
85
+ * contributor must never be the thing that indexes a repository.
86
+ */
87
+ export declare function buildProjectAtlasBrief(projectRoot: string, opts?: {
88
+ indexDir?: string | undefined;
89
+ }): Promise<AtlasBrief | AtlasBriefIndexMissing>;
90
+ //# sourceMappingURL=atlas-brief.d.ts.map
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Single-file, dependency-free HTML rendering of the atlas.
3
+ *
4
+ * The WebUI's CodeMap is the interactive view, but it needs a running server, a
5
+ * built index and a browser pointed at localhost. This is the other half: one
6
+ * file you can attach to a pull request, publish as a CI artifact, or mail to
7
+ * somebody who will never install the toolchain.
8
+ *
9
+ * ## Why it embeds rather than fetches
10
+ *
11
+ * A page that fetches `atlas.json` beside it does not work from `file://` in
12
+ * any modern browser — the request is a cross-origin one to a null origin. The
13
+ * data is inlined as JSON so a double-click opens a working map.
14
+ *
15
+ * ## Why the layout is computed here, not in the page
16
+ *
17
+ * A force simulation in the page would make the same input produce a slightly
18
+ * different picture on every open. Positions are computed once, deterministic
19
+ * given the document, so two exports of the same index are byte-identical and
20
+ * a committed export diffs meaningfully.
21
+ */
22
+ import type { AtlasDocument } from './atlas-types.js';
23
+ /** Packages drawn on the canvas. Beyond this the picture stops being readable. */
24
+ export declare const EXPORT_PACKAGE_LIMIT = 40;
25
+ /** Files listed in the ranked table. */
26
+ export declare const EXPORT_FILE_LIMIT = 120;
27
+ export interface AtlasExportOptions {
28
+ /** Repository name shown in the header. */
29
+ projectName?: string | undefined;
30
+ }
31
+ /**
32
+ * Render the atlas as one self-contained HTML document.
33
+ *
34
+ * Deterministic: the same {@link AtlasDocument} always produces the same bytes,
35
+ * with no timestamp, no random ids and no measurement of the host.
36
+ */
37
+ export declare function renderAtlasHtml(document: AtlasDocument, options?: AtlasExportOptions): string;
38
+ //# sourceMappingURL=atlas-export.d.ts.map
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Atlas — a committable projection of the codebase index.
3
+ *
4
+ * The index itself is a 180 MB SQLite database under `~/.wrongstack/projects/`:
5
+ * machine-local, binary, and unreviewable. That means every fresh clone, every
6
+ * CI run and every teammate starts cold, and nobody can see in a pull request
7
+ * what the index believes about the code.
8
+ *
9
+ * The atlas is the derived, human-sized answer to that: a small, deterministic
10
+ * set of files written into the repository at `.wrongstack/atlas/`. The
11
+ * database stays canonical — this is strictly a one-way projection, and
12
+ * regenerating it from an unchanged index must produce byte-identical output.
13
+ *
14
+ * ## Determinism is a hard requirement
15
+ *
16
+ * Anything that varies between two runs over the same index turns every
17
+ * indexing run into a merge conflict. So: no timestamps, no host paths, keys
18
+ * emitted in sorted order, floats rounded to a fixed precision, and LF line
19
+ * endings (the pre-commit hook enforces those repo-wide anyway).
20
+ *
21
+ * ## Staleness is reported, never guessed
22
+ *
23
+ * A committed atlas describing code that has since moved is worse than no
24
+ * atlas, because it is confidently wrong. {@link checkAtlasFreshness} compares
25
+ * the recorded per-file content hashes against the live index and says exactly
26
+ * which files drifted.
27
+ */
28
+ import type { AtlasDocument, AtlasEdge, AtlasFile, AtlasManifest, AtlasPackage, AtlasProjection, AtlasSymbol } from './atlas-types.js';
29
+ import type { FileRankRow } from './graph-rank.js';
30
+ import { type IndexStore } from './writer.js';
31
+ /** Directory the projection is written to, relative to the project root. */
32
+ export declare const ATLAS_DIR: string;
33
+ export declare const ATLAS_JSON = "atlas.json";
34
+ export declare const ATLAS_MARKDOWN = "ATLAS.md";
35
+ export declare const ATLAS_MANIFEST = "manifest.json";
36
+ /**
37
+ * Bumped when the emitted shape changes. A reader seeing a different schema
38
+ * reports the atlas as stale rather than misinterpreting its fields.
39
+ */
40
+ export declare const ATLAS_SCHEMA = 2;
41
+ /**
42
+ * Files carried in the projection. Enough to describe the architecture,
43
+ * small enough to read in a diff — the full 8k-file list would be neither.
44
+ */
45
+ export declare const ATLAS_FILE_LIMIT = 300;
46
+ export type { AtlasDocument, AtlasEdge, AtlasFile, AtlasManifest, AtlasPackage, AtlasProjection, AtlasSymbol, };
47
+ /**
48
+ * Build the projection from the index. Pure with respect to the filesystem —
49
+ * {@link writeAtlas} is what touches disk.
50
+ */
51
+ export declare function buildAtlas(store: IndexStore, projectRoot: string): AtlasProjection;
52
+ export interface WrittenAtlas {
53
+ dir: string;
54
+ files: string[];
55
+ fileCount: number;
56
+ packageCount: number;
57
+ }
58
+ /** Write the projection into `<projectRoot>/.wrongstack/atlas/`. */
59
+ export declare function writeAtlas(store: IndexStore, projectRoot: string): Promise<WrittenAtlas>;
60
+ export interface AtlasFreshness {
61
+ fresh: boolean;
62
+ /** Why it is not fresh. Absent when `fresh`. */
63
+ reason?: 'missing' | 'unreadable' | 'schema' | 'drift' | undefined;
64
+ /** Atlas files whose content hash no longer matches the index. */
65
+ changed: string[];
66
+ /** Atlas files the index no longer knows about. */
67
+ removed: string[];
68
+ /** Indexed files absent from the atlas manifest. */
69
+ added: number;
70
+ /** True when the whole-repository digest still matches. */
71
+ digestMatches: boolean;
72
+ }
73
+ /** Files listed in a drift report before it is summarised rather than enumerated. */
74
+ export declare const MAX_REPORTED_DRIFT = 20;
75
+ /**
76
+ * Compare the committed atlas against the live index.
77
+ *
78
+ * Reads only the manifest — the atlas document and markdown are derived from
79
+ * the same data, so a manifest that matches means all three are current.
80
+ */
81
+ export declare function checkAtlasFreshness(store: IndexStore, projectRoot: string): Promise<AtlasFreshness>;
82
+ /**
83
+ * Project-level entry points.
84
+ *
85
+ * These own the store lifetime so callers outside this package never have to
86
+ * touch `indexStorePool`. Both refuse to run when there is no index yet:
87
+ * opening a store CREATES the database, and neither writing an atlas nor
88
+ * checking one should be the thing that indexes a project.
89
+ */
90
+ export type AtlasIndexMissing = {
91
+ indexed: false;
92
+ };
93
+ /** Write the atlas for a project, or report that it has no index yet. */
94
+ export declare function writeProjectAtlas(projectRoot: string, opts?: {
95
+ indexDir?: string | undefined;
96
+ }): Promise<WrittenAtlas | AtlasIndexMissing>;
97
+ /** Check a project's written atlas against its index. */
98
+ export declare function checkProjectAtlasFreshness(projectRoot: string, opts?: {
99
+ indexDir?: string | undefined;
100
+ }): Promise<AtlasFreshness | AtlasIndexMissing>;
101
+ /**
102
+ * Build a project's static HTML atlas, or report that it has no index yet.
103
+ *
104
+ * Returns the markup rather than writing it: where the file belongs is the
105
+ * caller's decision (a CI artifact directory, a temp file the CLI opens, an
106
+ * HTTP response body), and this package should not guess.
107
+ */
108
+ export declare function exportProjectAtlasHtml(projectRoot: string, opts?: {
109
+ indexDir?: string | undefined;
110
+ projectName?: string | undefined;
111
+ }): Promise<string | AtlasIndexMissing>;
112
+ /** Re-exported for callers that render rank rows next to atlas output. */
113
+ export type { FileRankRow };
114
+ //# sourceMappingURL=atlas-projection.d.ts.map