@wrongstack/tools 0.309.1 → 0.310.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/_regex.d.ts +6 -34
  2. package/dist/bash.js +3 -3
  3. package/dist/builtin.js +3011 -1677
  4. package/dist/codebase-index/binary-frame.d.ts +57 -8
  5. package/dist/codebase-index/codebase-incoming-calls-tool.d.ts +6 -0
  6. package/dist/codebase-index/codebase-outgoing-calls-tool.d.ts +6 -0
  7. package/dist/codebase-index/codebase-search-tool.d.ts +15 -5
  8. package/dist/codebase-index/index-service.d.ts +3 -19
  9. package/dist/codebase-index/index.js +2735 -1415
  10. package/dist/codebase-index/indexer.d.ts +3 -0
  11. package/dist/codebase-index/parser-batch.d.ts +53 -0
  12. package/dist/codebase-index/parser-dispatch.d.ts +32 -0
  13. package/dist/codebase-index/parser-output.d.ts +14 -0
  14. package/dist/codebase-index/parser-worker-pool.d.ts +57 -4
  15. package/dist/codebase-index/parser-worker-script.d.ts +5 -2
  16. package/dist/codebase-index/parser-worker-script.js +4042 -0
  17. package/dist/codebase-index/project-server-cache.d.ts +16 -0
  18. package/dist/codebase-index/project-server-client.d.ts +2 -2
  19. package/dist/codebase-index/project-server-query-cache.d.ts +88 -0
  20. package/dist/codebase-index/project-server.js +2846 -1308
  21. package/dist/codebase-index/py-parser.d.ts +5 -0
  22. package/dist/codebase-index/schema.d.ts +14 -1
  23. package/dist/codebase-index/sqlite-runtime.d.ts +2 -2
  24. package/dist/codebase-index/tree-sitter/queries.d.ts +30 -3
  25. package/dist/codebase-index/tree-sitter/visitor.d.ts +2 -1
  26. package/dist/codebase-index/vector-search.d.ts +12 -0
  27. package/dist/codebase-index/wal-maintenance.d.ts +58 -0
  28. package/dist/codebase-index/worker-protocol/contracts.d.ts +44 -0
  29. package/dist/codebase-index/worker-protocol.d.ts +17 -1
  30. package/dist/codebase-index/worker.js +2300 -1020
  31. package/dist/codebase-index/writer-admin.d.ts +11 -0
  32. package/dist/codebase-index/writer-helpers.d.ts +31 -1
  33. package/dist/codebase-index/writer-mutations.d.ts +0 -6
  34. package/dist/codebase-index/writer-schema.d.ts +2 -2
  35. package/dist/codebase-index/writer.d.ts +15 -0
  36. package/dist/edit.js +2511 -1203
  37. package/dist/exec.js +5 -3
  38. package/dist/grep.js +5 -124
  39. package/dist/index.js +3007 -1736
  40. package/dist/json.js +5 -124
  41. package/dist/kanban.js +130 -0
  42. package/dist/logs.js +5 -121
  43. package/dist/pack.js +3011 -1677
  44. package/dist/patch.js +2524 -1216
  45. package/dist/plan.js +106 -0
  46. package/dist/read.js +2506 -1198
  47. package/dist/replace.js +2487 -1295
  48. package/dist/search.js +6 -2
  49. package/dist/session-kanban.js +24 -16
  50. package/dist/task.js +106 -0
  51. package/dist/todo.js +106 -0
  52. package/dist/tool-tier.d.ts +11 -0
  53. package/dist/tool-tier.js +3019 -1677
  54. package/dist/tree.js +14 -3
  55. package/dist/win32.js +3 -3
  56. package/dist/write.js +2513 -1205
  57. package/package.json +5 -4
@@ -10,6 +10,9 @@ export declare function resolveParallelBatch(): number;
10
10
  * Pool startup is amortized across the complete index run, not one outer
11
11
  * batch. Balanced batches are capped at 40 files, so comparing the per-batch
12
12
  * parse count with the 500-file threshold made the worker path unreachable.
13
+ *
14
+ * Threshold is env-configurable (audit T-04): `WRONGSTACK_INDEX_WORKER_THRESHOLD`
15
+ * overrides the default, `0` disables the worker path entirely.
13
16
  */
14
17
  export declare function shouldUseParserWorkerPool(candidateFileCount: number, parseBatchCount: number): boolean;
15
18
  interface IndexerOptions {
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Batch parsers for the external toolchain languages (Go, Python) — P3.8.
3
+ *
4
+ * The single-file parsers spawn one `go run` / `python` child process per
5
+ * file. For a 400-file Go project that is 400 process spawns, each paying
6
+ * toolchain startup; the spawn gate serializes them, so parse time scales
7
+ * linearly with spawn cost. This module runs the SAME extraction logic over
8
+ * a batch: one child process per chunk of files, sources in over stdin as a
9
+ * JSON array, one JSON envelope out per file.
10
+ *
11
+ * Fallback contract: a file the batch could not parse (per-file error in the
12
+ * envelope, or the chunk itself failing) is simply ABSENT from the returned
13
+ * map — the caller re-parses those files through the single-file parser,
14
+ * which owns the per-language fallback semantics (Go: regex extractor;
15
+ * Python: generic regex only when the runtime is missing). Parity with the
16
+ * per-file path is therefore by construction, not by reimplementation.
17
+ */
18
+ import type { FileSymbols, SymbolLang } from './schema.js';
19
+ /** Max files per child process. Bounded so one pathological file cannot
20
+ * poison an unbounded chunk and stdin stays a comfortable pipe size. */
21
+ export declare const MAX_BATCH_FILES = 100;
22
+ /** Max cumulative source bytes per child process. */
23
+ export declare const MAX_BATCH_BYTES: number;
24
+ export interface BatchFile {
25
+ file: string;
26
+ content: string;
27
+ lang: SymbolLang;
28
+ }
29
+ /** Split a file list into chunks bounded by both file count and total bytes.
30
+ * Generic so callers' extra per-file fields (e.g. source index) survive. */
31
+ export declare function chunkBatchFiles<T extends BatchFile>(files: readonly T[]): T[][];
32
+ /**
33
+ * Test-only: the cached batch-script paths. The security regression test
34
+ * observes WHERE the scripts were written without needing a toolchain —
35
+ * a missing binary still leaves the (already-created) path cached.
36
+ */
37
+ export declare function __batchScriptPathsForTest(): {
38
+ go: string | null;
39
+ py: string | null;
40
+ };
41
+ /**
42
+ * Parse a chunk of Go files with ONE `go run` invocation.
43
+ * Returns per-file results; files absent from the map failed and the caller
44
+ * falls back to the single-file parser.
45
+ */
46
+ export declare function runGoBatch(files: readonly BatchFile[], goBinary?: string): Promise<Map<string, FileSymbols>>;
47
+ /**
48
+ * Parse a chunk of Python files with ONE interpreter invocation.
49
+ * Same contract as {@link runGoBatch}; `pythonBinary` is the cached resolver
50
+ * from py-parser.ts so both paths agree on which interpreter runs.
51
+ */
52
+ export declare function runPyBatch(files: readonly BatchFile[], pythonBinary: string): Promise<Map<string, FileSymbols>>;
53
+ //# sourceMappingURL=parser-batch.d.ts.map
@@ -5,4 +5,36 @@ import type { FileSymbols, SymbolLang } from './schema.js';
5
5
  * SQLite/IPC owner when TS/JS parsing is delegated to parser workers.
6
6
  */
7
7
  export declare function parseFileContent(file: string, content: string, lang: SymbolLang): Promise<FileSymbols>;
8
+ /**
9
+ * Parse a mixed-language batch of files (P3.8).
10
+ *
11
+ * Go and Python files are grouped and handed to ONE child process per chunk
12
+ * (`runGoBatch` / `runPyBatch`) instead of one spawn per file; every other
13
+ * language goes through `parseFileContent` as before. Files the batch
14
+ * parsers could not produce (per-file error inside the envelope, or the
15
+ * whole chunk failing) fall back to the single-file parser, which owns the
16
+ * per-language fallback semantics — so output is identical to the per-file
17
+ * path in every case, only faster.
18
+ *
19
+ * Results are returned in input order (index-aligned), matching what callers
20
+ * expected from N parallel `parseFileContent` calls.
21
+ *
22
+ * Opt out with `WRONGSTACK_TOOLCHAIN_BATCH=0` to restore per-file spawning
23
+ * everywhere (bisecting a toolchain issue, exotic environments).
24
+ */
25
+ /**
26
+ * One file's parse outcome. `result` is null only when the parser THREW —
27
+ * batch-invalid files still come back with the fallback parser's own
28
+ * zero-symbol semantics. `error` carries the throw's message so callers can
29
+ * record something actionable instead of a bare "no result".
30
+ */
31
+ export interface ParseSlot {
32
+ result: FileSymbols | null;
33
+ error?: string | undefined;
34
+ }
35
+ export declare function parseFilesContent(files: ReadonlyArray<{
36
+ file: string;
37
+ content: string;
38
+ lang: SymbolLang;
39
+ }>): Promise<ParseSlot[]>;
8
40
  //# sourceMappingURL=parser-dispatch.d.ts.map
@@ -26,4 +26,18 @@ export interface ParsedParserOutput {
26
26
  }
27
27
  /** Decode a parser child process's stdout. Never throws. */
28
28
  export declare function parseParserOutput(stdout: string, lang: SymbolLang): ParsedParserOutput;
29
+ /**
30
+ * Decode a BATCH parser child process's stdout (P3.8): one envelope with a
31
+ * per-file results array. Per-file entries carry an optional `error` (the
32
+ * file failed inside the batch; the caller falls back to the single-file
33
+ * parser). Never throws — a malformed envelope yields [].
34
+ */
35
+ export interface BatchFileOutput {
36
+ file: string;
37
+ /** Set when this file failed inside the batch (e.g. syntax error). */
38
+ error?: string | undefined;
39
+ symbols: RawParsedSymbol[];
40
+ refs: Ref[];
41
+ }
42
+ export declare function parseParserBatchOutput(stdout: string, lang: SymbolLang): BatchFileOutput[];
29
43
  //# sourceMappingURL=parser-output.d.ts.map
@@ -3,19 +3,41 @@
3
3
  *
4
4
  * Spawns N worker threads (N = CPU cores - 1, clamped to [1, 4]) that share
5
5
  * the file-parsing load during startup/full reindex passes. Each worker runs
6
- * `parser-worker-script.ts`, reads files from disk, parses them via
7
- * `parseFileContent`, and returns `FileSymbols[]`.
6
+ * `parser-worker-script.ts`, parses file content supplied by the main thread
7
+ * via `parseFileContent`, and returns `FileSymbols[]`.
8
8
  *
9
- * The main thread distributes files in round-robin batches, collects results,
9
+ * The main thread distributes files in round-robin chunks, collects results,
10
10
  * and performs all SQLite writes via `commitBatch`. Workers never touch the
11
11
  * database — single-writer WAL semantics are preserved.
12
12
  *
13
+ * Failover (P3.7): every response carries the responding worker's
14
+ * `workerId` (threadId), so busy-tracking is identity-based and a batch
15
+ * knows exactly which chunk each worker owes. When a worker dies mid-batch,
16
+ * its orphaned chunk is re-parsed inline on this thread instead of waiting
17
+ * for a response that never arrive — a partial pool death previously hung
18
+ * the batch until the outer 60s/240s watchdog. Only when every worker dies
19
+ * does the batch reject, letting the indexer's existing inline fallback
20
+ * take over.
21
+ *
13
22
  * The pool is created lazily on first use and terminated on shutdown. Workers
14
23
  * are `unref()`'d so they don't keep the process alive.
15
24
  */
16
25
  import type { FileSymbols, SymbolLang } from './schema.js';
17
26
  /** Minimum number of files before the pool is worth spawning. */
18
27
  export declare const WORKER_POOL_THRESHOLD = 500;
28
+ /**
29
+ * Effective pool threshold for this run (audit T-04): the documented
30
+ * {@link WORKER_POOL_THRESHOLD} default unless `WRONGSTACK_INDEX_WORKER_THRESHOLD`
31
+ * overrides it. Re-resolved on every call — like `resolveParallelBatch` — so
32
+ * profile changes (and tests) apply per index run without a process restart.
33
+ *
34
+ * - unset / unparsable / negative → the 500 default
35
+ * - `0` → disables the worker path (per the `WRONGSTACK_*=0` opt-out
36
+ * convention, e.g. `WRONGSTACK_TOOLCHAIN_BATCH=0`): no candidate count can
37
+ * satisfy `>= 0 && parseBatchCount > 1` gate semantics with an explicit
38
+ * disable, so the gate checks the disable first.
39
+ */
40
+ export declare function resolveWorkerPoolThreshold(): number;
19
41
  export declare class ParserWorkerPool {
20
42
  private readonly maxWorkers;
21
43
  private workers;
@@ -38,7 +60,7 @@ export declare class ParserWorkerPool {
38
60
  ensureReady(): Promise<boolean>;
39
61
  /**
40
62
  * Parse files in parallel across the worker pool. Returns a flat
41
- * `FileSymbols[]` in completion order (caller sorts if needed).
63
+ * `FileSymbols[]` in completion order (caller matches by file path).
42
64
  *
43
65
  * Content is pre-read by the main thread (for the content-hash check)
44
66
  * and passed to workers to avoid a second disk read. Files are
@@ -52,6 +74,37 @@ export declare class ParserWorkerPool {
52
74
  /** Shut down all workers. Safe to call multiple times. */
53
75
  shutdown(): Promise<void>;
54
76
  private handleMessage;
77
+ /**
78
+ * Remove a worker from the pool and salvage any chunk it still owed.
79
+ *
80
+ * Idempotent by workerId — `error` and `exit` can both fire for one
81
+ * death, and a worker may die while no batch references it. When the
82
+ * dead worker owed files to an in-flight batch and other workers remain,
83
+ * those files are re-parsed inline on this thread (one fewer worker
84
+ * should cost latency, not correctness). When it was the last worker,
85
+ * every remaining batch rejects so the indexer's existing inline
86
+ * fallback takes over the whole batch.
87
+ */
88
+ private retireWorker;
89
+ /**
90
+ * Salvage path: re-parse an orphaned chunk on this thread. Files that
91
+ * fail here stay absent from the results — same contract as a per-file
92
+ * error inside a live worker (see handleMessage).
93
+ */
94
+ private reparseInline;
95
+ /**
96
+ * Terminal tail of a salvage — runs on every exit path. Kept free of
97
+ * control flow inside a `finally` (noUnsafeFinally): releases the
98
+ * pending-marker and resolves the batch if this was its last chunk.
99
+ */
100
+ private finishSalvage;
101
+ /**
102
+ * Retire by worker object rather than threadId. `threadId` is -1 before
103
+ * the worker emits `online`, so a death during script load would make a
104
+ * threadId-keyed lookup silently no-op and leak the entry (with its
105
+ * pending chunk) — reference identity is correct in every case.
106
+ */
107
+ private retireByReference;
55
108
  private handleError;
56
109
  }
57
110
  /**
@@ -13,8 +13,7 @@
13
13
  * The worker terminates cleanly when it receives a `{ type: 'shutdown' }`
14
14
  * message. If the parent port closes unexpectedly, the worker exits.
15
15
  */
16
- import type { FileSymbols } from './schema.js';
17
- import type { SymbolLang } from './schema.js';
16
+ import type { FileSymbols, SymbolLang } from './schema.js';
18
17
  export interface ParserWorkerRequest {
19
18
  type: 'parse';
20
19
  id: number;
@@ -29,6 +28,10 @@ export interface ParserWorkerRequest {
29
28
  export interface ParserWorkerResponse {
30
29
  type: 'result';
31
30
  id: number;
31
+ /** Identity of the responding worker (`threadId`) — lets the pool free
32
+ * exactly the worker that answered, and detect which chunk is orphaned
33
+ * when a worker dies mid-batch. */
34
+ workerId: number;
32
35
  results: FileSymbols[];
33
36
  errors: ReadonlyArray<{
34
37
  file: string;