@wrongstack/tools 0.298.3 → 0.300.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 (42) hide show
  1. package/dist/audit.js +6 -2
  2. package/dist/bash.js +20 -2
  3. package/dist/builtin.js +1901 -327
  4. package/dist/codebase-index/background-indexer.d.ts +6 -1
  5. package/dist/codebase-index/codebase-incoming-calls-tool.d.ts +34 -0
  6. package/dist/codebase-index/codebase-outgoing-calls-tool.d.ts +34 -0
  7. package/dist/codebase-index/import-extractor.d.ts +39 -0
  8. package/dist/codebase-index/index-service.d.ts +24 -2
  9. package/dist/codebase-index/index.d.ts +4 -2
  10. package/dist/codebase-index/index.js +1779 -256
  11. package/dist/codebase-index/languages.d.ts +24 -0
  12. package/dist/codebase-index/module-resolver.d.ts +78 -0
  13. package/dist/codebase-index/module-roots.d.ts +81 -0
  14. package/dist/codebase-index/parser-output.d.ts +29 -0
  15. package/dist/codebase-index/project-server.js +1556 -237
  16. package/dist/codebase-index/rs-parser.d.ts +22 -0
  17. package/dist/codebase-index/schema.d.ts +47 -1
  18. package/dist/codebase-index/worker-protocol.d.ts +14 -0
  19. package/dist/codebase-index/worker.js +1545 -238
  20. package/dist/codebase-index/writer-graph-helpers.d.ts +17 -5
  21. package/dist/codebase-index/writer-graph-reader.d.ts +24 -1
  22. package/dist/codebase-index/writer-ref-mapper.d.ts +3 -0
  23. package/dist/codebase-index/writer-schema.d.ts +15 -3
  24. package/dist/codebase-index/writer.d.ts +97 -4
  25. package/dist/exec.js +39 -2
  26. package/dist/format.js +6 -2
  27. package/dist/index.js +1901 -327
  28. package/dist/install.js +6 -2
  29. package/dist/json.js +51 -2
  30. package/dist/languages/index.js +6 -2
  31. package/dist/lint.js +6 -2
  32. package/dist/outdated.js +6 -2
  33. package/dist/pack.js +1899 -327
  34. package/dist/process-registry.d.ts +6 -0
  35. package/dist/process-registry.js +6 -2
  36. package/dist/ps-slash.js +10 -2
  37. package/dist/read.js +1551 -244
  38. package/dist/test.js +6 -2
  39. package/dist/tool-tier.js +1901 -327
  40. package/dist/typecheck.js +6 -2
  41. package/package.json +3 -3
  42. package/dist/codebase-index/refs-extractor.d.ts +0 -11
@@ -2,15 +2,28 @@ import type { GraphEdge, GraphNode, SymbolLang } from './schema.js';
2
2
  /**
3
3
  * Derive a monorepo package name from an absolute file path.
4
4
  * Handles both `packages/<name>/...` and `apps/<name>/...` layouts.
5
+ *
6
+ * This is the fallback only. The authoritative grouping is computed at index
7
+ * time from each ecosystem's own manifests and stored on `files.package` —
8
+ * see {@link createPackageLabeller}. A path-shape guess is all that is left
9
+ * for a repo with no manifest at all.
5
10
  */
6
11
  export declare function derivePackage(filePath: string): string | undefined;
7
- export declare function packageFromImport(moduleName: string): string | undefined;
12
+ /**
13
+ * Build the `file → package` lookup the graph readers group by.
14
+ *
15
+ * `stored` comes from `files.package`, which the indexer filled from `go.mod`,
16
+ * `Cargo.toml`, `package.json`, `pom.xml` and friends. Files missing a stored
17
+ * label (indexed by an older run, or outside any manifest) fall back to the
18
+ * path-shape heuristic and finally to `(root)`.
19
+ */
20
+ export declare function createPackageLabeller(stored: ReadonlyMap<string, string>): (file: string) => string;
8
21
  export declare function buildPackageGraphNodes(fileCounts: Array<{
9
22
  file: string;
10
23
  n: number;
11
24
  }>, files: Array<{
12
25
  file: string;
13
- }>): {
26
+ }>, packageOf: (file: string) => string): {
14
27
  pkgNodes: Map<string, GraphNode>;
15
28
  fileToPkg: Map<string, string>;
16
29
  };
@@ -22,7 +35,7 @@ export type WriterFileGraphSymbolRow = {
22
35
  lang: string;
23
36
  line: number;
24
37
  };
25
- export declare function buildFileGraphNodeState(pkgSyms: WriterFileGraphSymbolRow[], localFiles: Set<string>): {
38
+ export declare function buildFileGraphNodeState(pkgSyms: WriterFileGraphSymbolRow[], localFiles: Set<string>, packageOf: (file: string) => string): {
26
39
  fileNodes: Map<string, GraphNode>;
27
40
  symToFile: Map<number, string>;
28
41
  fileStats: Map<string, {
@@ -41,8 +54,7 @@ export type WriterSymbolGraphRow = {
41
54
  signature: string;
42
55
  scope: string;
43
56
  };
44
- export declare function buildSymbolGraphNodes(symById: Map<number, WriterSymbolGraphRow>, relatedIds: Set<number>, fileFilter: string): GraphNode[];
45
- export declare function resolveRelativeImport(fromFile: string, moduleName: string, indexedFiles: Set<string>): string | undefined;
57
+ export declare function buildSymbolGraphNodes(symById: Map<number, WriterSymbolGraphRow>, relatedIds: Set<number>, fileFilter: string, packageOf: (file: string) => string): GraphNode[];
46
58
  export type WeightedEdgeAccumulator = {
47
59
  weight: number;
48
60
  types: Map<string, number>;
@@ -1,7 +1,30 @@
1
1
  import type { DatabaseSync } from 'node:sqlite';
2
- import type { CodeMapGraph, Ref } from './schema.js';
2
+ import type { CallSite, CodeMapGraph, Ref } from './schema.js';
3
3
  type Statement = ReturnType<DatabaseSync['prepare']>;
4
4
  type PrepareStatement = (sql: string) => Statement;
5
+ /**
6
+ * Find all symbols that CALL/USE the named target symbol (incoming callers).
7
+ *
8
+ * Returns one `CallSite` per ref edge, with the caller's full metadata so the
9
+ * agent sees file, line, kind, and signature without a second lookup.
10
+ */
11
+ export declare function findIncomingCallsByName(stmt: PrepareStatement, symbolName: string, file: string | undefined, limit: number): {
12
+ calls: CallSite[];
13
+ symbolFound: boolean;
14
+ ambiguous: boolean;
15
+ totalMatches: number;
16
+ };
17
+ /**
18
+ * Find all symbols that the named source symbol CALLS/USES (outgoing callees).
19
+ *
20
+ * Returns one `CallSite` per ref edge, with the callee's full metadata.
21
+ */
22
+ export declare function findOutgoingCallsByName(stmt: PrepareStatement, symbolName: string, file: string | undefined, limit: number): {
23
+ calls: CallSite[];
24
+ symbolFound: boolean;
25
+ unresolvedCount: number;
26
+ totalMatches: number;
27
+ };
5
28
  export declare function findRefsToWithStatement(stmt: PrepareStatement, symbolId: number): Ref[];
6
29
  export declare function findRefsFromWithStatement(stmt: PrepareStatement, symbolId: number): Ref[];
7
30
  export declare function getPackageGraphWithStatement(stmt: PrepareStatement): CodeMapGraph;
@@ -6,6 +6,9 @@ export type WriterRefRow = {
6
6
  to_id: number | null;
7
7
  call_type: string;
8
8
  line: number;
9
+ lang?: string | null;
10
+ module?: string | null;
11
+ to_file?: string | null;
9
12
  };
10
13
  export declare function mapWriterRefRow(row: WriterRefRow): Ref;
11
14
  //# sourceMappingURL=writer-ref-mapper.d.ts.map
@@ -1,7 +1,19 @@
1
1
  export declare const METADATA_TABLE_SQL = "\n CREATE TABLE IF NOT EXISTS metadata (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n );\n";
2
- export declare const CORE_TABLES_SQL = "\n CREATE TABLE IF NOT EXISTS files (\n file TEXT PRIMARY KEY,\n lang TEXT NOT NULL,\n mtime_ms INTEGER NOT NULL,\n symbol_count INTEGER NOT NULL DEFAULT 0,\n last_indexed INTEGER NOT NULL\n );\n CREATE TABLE IF NOT EXISTS symbols (\n id INTEGER PRIMARY KEY,\n lang TEXT NOT NULL,\n kind TEXT NOT NULL,\n name TEXT NOT NULL,\n file TEXT NOT NULL,\n line INTEGER NOT NULL,\n col INTEGER NOT NULL,\n signature TEXT NOT NULL DEFAULT '',\n doc_comment TEXT NOT NULL DEFAULT '',\n scope TEXT NOT NULL DEFAULT '',\n text TEXT NOT NULL DEFAULT '',\n file_fk TEXT NOT NULL\n );\n";
2
+ export declare const CORE_TABLES_SQL = "\n CREATE TABLE IF NOT EXISTS files (\n file TEXT PRIMARY KEY,\n lang TEXT NOT NULL,\n mtime_ms INTEGER NOT NULL,\n symbol_count INTEGER NOT NULL DEFAULT 0,\n last_indexed INTEGER NOT NULL,\n -- Code Atlas grouping label, computed at index time from the ecosystem's\n -- own manifests (package.json, go.mod, Cargo.toml, \u2026). Stored rather than\n -- re-derived per query because the evidence lives on disk, not in the DB.\n package TEXT NOT NULL DEFAULT ''\n );\n CREATE TABLE IF NOT EXISTS symbols (\n id INTEGER PRIMARY KEY,\n lang TEXT NOT NULL,\n kind TEXT NOT NULL,\n name TEXT NOT NULL,\n file TEXT NOT NULL,\n line INTEGER NOT NULL,\n col INTEGER NOT NULL,\n signature TEXT NOT NULL DEFAULT '',\n doc_comment TEXT NOT NULL DEFAULT '',\n scope TEXT NOT NULL DEFAULT '',\n text TEXT NOT NULL DEFAULT '',\n file_fk TEXT NOT NULL\n );\n";
3
+ export declare const FILE_INDEX_SQL: readonly ['CREATE INDEX IF NOT EXISTS idx_f_package ON files(package)'];
3
4
  export declare const SYMBOL_INDEX_SQL: readonly ['CREATE INDEX IF NOT EXISTS idx_s_name ON symbols(name)', 'CREATE INDEX IF NOT EXISTS idx_s_kind ON symbols(kind)', 'CREATE INDEX IF NOT EXISTS idx_s_lang ON symbols(lang)', 'CREATE INDEX IF NOT EXISTS idx_s_file ON symbols(file)', 'CREATE INDEX IF NOT EXISTS idx_s_lang_kind ON symbols(lang, kind)', 'CREATE INDEX IF NOT EXISTS idx_s_file_fk ON symbols(file_fk)', 'CREATE INDEX IF NOT EXISTS idx_s_name_id ON symbols(name, id)'];
4
- export declare const REFS_TABLE_SQL = "\n CREATE TABLE IF NOT EXISTS refs (\n id INTEGER PRIMARY KEY,\n from_id INTEGER NOT NULL,\n to_name TEXT NOT NULL,\n to_id INTEGER,\n call_type TEXT NOT NULL,\n line INTEGER NOT NULL\n );\n";
5
- export declare const REFS_INDEX_SQL: readonly ['CREATE INDEX IF NOT EXISTS idx_r_from ON refs(from_id)', 'CREATE INDEX IF NOT EXISTS idx_r_to_id ON refs(to_id)', 'CREATE INDEX IF NOT EXISTS idx_r_to_name ON refs(to_name)', 'CREATE INDEX IF NOT EXISTS idx_r_call_type ON refs(call_type)'];
5
+ export declare const REFS_TABLE_SQL = "\n CREATE TABLE IF NOT EXISTS refs (\n id INTEGER PRIMARY KEY,\n from_id INTEGER NOT NULL,\n to_name TEXT NOT NULL,\n to_id INTEGER,\n call_type TEXT NOT NULL,\n line INTEGER NOT NULL,\n lang TEXT NOT NULL DEFAULT '',\n module TEXT,\n to_file TEXT\n );\n";
6
+ export declare const REFS_INDEX_SQL: readonly ['CREATE INDEX IF NOT EXISTS idx_r_from ON refs(from_id)', 'CREATE INDEX IF NOT EXISTS idx_r_to_id ON refs(to_id)', 'CREATE INDEX IF NOT EXISTS idx_r_to_name ON refs(to_name)', 'CREATE INDEX IF NOT EXISTS idx_r_call_type ON refs(call_type)', 'CREATE INDEX IF NOT EXISTS idx_r_to_name_lang ON refs(to_name, lang)', 'CREATE INDEX IF NOT EXISTS idx_r_module ON refs(module)', 'CREATE INDEX IF NOT EXISTS idx_r_to_file ON refs(to_file)'];
7
+ /**
8
+ * Static `lang → family` mirror of {@link LANG_FAMILY_ENTRIES}, so ref
9
+ * resolution can scope a match to one language family with a join rather than
10
+ * binding a per-family IN-list into every statement.
11
+ *
12
+ * Row `('', '*')` is the wildcard for refs written without a language (older
13
+ * rows, and tests that construct refs by hand): they keep resolving globally.
14
+ */
15
+ export declare const LANG_FAMILY_TABLE_SQL = "\n CREATE TABLE IF NOT EXISTS lang_family (\n lang TEXT PRIMARY KEY,\n family TEXT NOT NULL\n );\n";
16
+ /** Family value that matches every symbol family, used by language-less refs. */
17
+ export declare const LANG_FAMILY_WILDCARD = "*";
6
18
  export declare const SYMBOLS_FTS_SQL = "CREATE VIRTUAL TABLE IF NOT EXISTS symbols_fts USING fts5(text, tokenize = 'unicode61')";
7
19
  //# sourceMappingURL=writer-schema.d.ts.map
@@ -1,4 +1,4 @@
1
- import type { CodeMapGraph, FileMeta, IndexStats, Symbol as IndexSymbol, Ref, SearchResult, SymbolKind, SymbolLang } from './schema.js';
1
+ import type { CallSite, CodeMapGraph, FileMeta, IndexStats, Symbol as IndexSymbol, Ref, SearchResult, SymbolKind, SymbolLang } from './schema.js';
2
2
  import { type WriterSearchFilter } from './writer-search-helpers.js';
3
3
  import { StorePool } from './writer-store-pool.js';
4
4
  export { codebaseIndexDirOverride, resolveIndexDir } from './writer-helpers.js';
@@ -56,10 +56,44 @@ export declare class IndexStore {
56
56
  indexDir?: string | undefined;
57
57
  });
58
58
  runWithRetry<T>(fn: () => T): T;
59
+ /**
60
+ * Mirror the in-process language→family map into SQLite.
61
+ *
62
+ * Rewritten on every open rather than only on schema bumps: the mapping is
63
+ * static lookup data, so a code-side change (a new language, a language
64
+ * moving families) must take effect without forcing a full reindex.
65
+ */
66
+ private seedLangFamilies;
67
+ /**
68
+ * Add any column the current schema expects but the on-disk table lacks.
69
+ *
70
+ * `CREATE TABLE IF NOT EXISTS` silently keeps an existing table's old shape,
71
+ * and the version check above only rebuilds on a version *mismatch*. That
72
+ * leaves a real gap: several wstack processes share this database, and while
73
+ * a version upgrade is rolling out one of them may still be running the
74
+ * previous build. That older process sees the newer version number, drops the
75
+ * tables, and recreates them from *its* DDL — without the newer columns —
76
+ * while the metadata row still reads the new version. Every later query for
77
+ * one of those columns then fails with `no such column`, and no amount of
78
+ * reindexing fixes it, because the version numbers already agree.
79
+ *
80
+ * Repairing column-by-column makes the schema self-healing from any of those
81
+ * states. Table and column names are compile-time literals from this module,
82
+ * never user input.
83
+ */
84
+ private repairMissingColumns;
59
85
  private initSchema;
60
86
  private static readonly NEXT_SYMBOL_ID_KEY;
61
87
  /** Stay under typical SQLite SQLITE_MAX_VARIABLE_NUMBER (often 999). */
62
88
  private static readonly MAX_SQL_VARS;
89
+ /**
90
+ * Correlated predicate: the ref in `refs` and the candidate symbol aliased
91
+ * `sym` belong to the same language family — or the ref carries no language,
92
+ * in which case the wildcard bind matches everything.
93
+ *
94
+ * Each textual occurrence consumes one `?` bind of {@link LANG_FAMILY_WILDCARD}.
95
+ */
96
+ private static readonly FAMILY_MATCH_SQL;
63
97
  /**
64
98
  * Ensure `metadata.next_symbol_id` exists. Safe to call outside a write
65
99
  * transaction on open; the first concurrent writer under BEGIN IMMEDIATE
@@ -101,6 +135,42 @@ export declare class IndexStore {
101
135
  upsertFile(meta: FileMeta): void;
102
136
  getFileMeta(file: string): FileMeta | null;
103
137
  getAllFileMetas(): FileMeta[];
138
+ /** Store the Code Atlas grouping label for each indexed file. */
139
+ setFilePackages(entries: ReadonlyMap<string, string>): void;
140
+ /**
141
+ * Every indexed `namespace`/`module` declaration, for ecosystems whose import
142
+ * specifiers name a namespace rather than a path (C#, PHP, Elixir, Haskell).
143
+ * Ordered so the resolver's choice among duplicate declarations is stable.
144
+ */
145
+ getNamespaceDeclarations(): Array<{
146
+ name: string;
147
+ file: string;
148
+ }>;
149
+ /** `file → package` for every indexed file that has a label. */
150
+ getFilePackages(): Map<string, string>;
151
+ /**
152
+ * Distinct `(fromFile, lang, module)` triples needing module resolution.
153
+ *
154
+ * Distinct rather than per-ref because resolution depends only on these three
155
+ * values: a file importing the same module twenty times resolves it once.
156
+ */
157
+ getUnresolvedImports(onlyFiles?: readonly string[]): Array<{
158
+ fromFile: string;
159
+ lang: string;
160
+ module: string;
161
+ }>;
162
+ /**
163
+ * Write resolved import targets back onto `refs.to_file`.
164
+ *
165
+ * Applied through a temp table and a single UPDATE: one statement per
166
+ * resolution would mean thousands of round-trips on a first index.
167
+ */
168
+ applyImportResolutions(resolutions: ReadonlyArray<{
169
+ fromFile: string;
170
+ lang: string;
171
+ module: string;
172
+ toFile: string;
173
+ }>): number;
104
174
  search(query: string, filter?: WriterSearchFilter, opts?: {
105
175
  limit?: number | undefined;
106
176
  }): SearchResult[];
@@ -228,9 +298,12 @@ export declare class IndexStore {
228
298
  * Resolve `to_name` → `to_id` for all refs that have a name but no id.
229
299
  * Call this after all symbols have been inserted to fill in cross-references.
230
300
  *
231
- * Single statement: the `to_name IN (SELECT name FROM symbols)` guard restricts
232
- * the UPDATE to refs that will actually resolve, so `.changes` counts only refs
233
- * that found a targetmatching the previous per-row loop's return value.
301
+ * A match additionally requires the referencing ref and the target symbol to
302
+ * be in the same {@link LangFamily}. Without that guard a name match is a
303
+ * cross-language accident waiting to happen `main`, `New`, `Parse` and
304
+ * `Config` are declared in most languages at once, and each collision draws a
305
+ * Code Atlas edge between files that never reference each other. Refs stored
306
+ * without a language keep the old global behaviour via the `'*'` wildcard row.
234
307
  */
235
308
  resolveRefs(): number;
236
309
  resolveRefsForNames(names: Iterable<string>): number;
@@ -252,6 +325,26 @@ export declare class IndexStore {
252
325
  minBytes?: number;
253
326
  minFreeRatio?: number;
254
327
  }): boolean;
328
+ /**
329
+ * Find all symbols that reference the named target symbol (incoming callers).
330
+ * Accepts a name instead of an id so the agent doesn't need a prior lookup.
331
+ */
332
+ findIncomingCallsByName(symbolName: string, file?: string, limit?: number): {
333
+ calls: CallSite[];
334
+ symbolFound: boolean;
335
+ ambiguous: boolean;
336
+ totalMatches: number;
337
+ };
338
+ /**
339
+ * Find all symbols that the named source symbol references (outgoing callees).
340
+ * Accepts a name instead of an id so the agent doesn't need a prior lookup.
341
+ */
342
+ findOutgoingCallsByName(symbolName: string, file?: string, limit?: number): {
343
+ calls: CallSite[];
344
+ symbolFound: boolean;
345
+ unresolvedCount: number;
346
+ totalMatches: number;
347
+ };
255
348
  /**
256
349
  * Find all references TO a given symbol (who calls / uses this symbol?).
257
350
  */
package/dist/exec.js CHANGED
@@ -1131,7 +1131,7 @@ var ProcessRegistryImpl = class {
1131
1131
  const p = this.processes.get(pid);
1132
1132
  if (!p) return false;
1133
1133
  if (p.killed) return true;
1134
- if (p.protected) return false;
1134
+ if (p.protected && opts.includeProtected !== true) return false;
1135
1135
  if (opts.preserveBackground && p.background) return false;
1136
1136
  const { force = false, graceMs = DEFAULT_GRACE_MS } = opts;
1137
1137
  const isWin3 = os.platform() === "win32";
@@ -1182,9 +1182,13 @@ var ProcessRegistryImpl = class {
1182
1182
  killAll(opts = {}) {
1183
1183
  const pids = Array.from(this.processes.keys());
1184
1184
  const killed = [];
1185
+ const includeProtected = opts.includeProtected === true;
1185
1186
  for (const pid of pids) {
1186
1187
  const p = this.processes.get(pid);
1187
- if (p && !p.protected && this.kill(pid, opts)) killed.push(pid);
1188
+ if (!p) continue;
1189
+ if (p.protected && !includeProtected) continue;
1190
+ if (opts.preserveBackground && p.background) continue;
1191
+ if (this.kill(pid, opts)) killed.push(pid);
1188
1192
  }
1189
1193
  return killed;
1190
1194
  }
@@ -1284,6 +1288,10 @@ async function acquireLock(lockfilePath, timeoutMs = 5e3) {
1284
1288
  const start = Date.now();
1285
1289
  const pidStr = String(process.pid);
1286
1290
  const hostStr = os2.hostname();
1291
+ try {
1292
+ await fs2.mkdir(path4.dirname(lockfilePath), { recursive: true });
1293
+ } catch {
1294
+ }
1287
1295
  while (Date.now() - start < timeoutMs) {
1288
1296
  try {
1289
1297
  await fs2.writeFile(lockfilePath, `${pidStr}:${hostStr}:${Date.now()}`, { flag: "wx" });
@@ -2638,6 +2646,26 @@ var BLOCKED_ARG_PATTERNS = {
2638
2646
  pnpm: [],
2639
2647
  npx: []
2640
2648
  };
2649
+ var BLOCKED_OPTION_NAMES = {
2650
+ git: /* @__PURE__ */ new Set([
2651
+ "--exec",
2652
+ "--upload-pack",
2653
+ "--receive-pack",
2654
+ "--exec-path",
2655
+ "--git-dir",
2656
+ "--work-tree",
2657
+ "--namespace",
2658
+ "-c",
2659
+ "--config",
2660
+ "--config-env",
2661
+ "-C"
2662
+ ]),
2663
+ find: /* @__PURE__ */ new Set(["-exec", "-ok", "-execdir"])
2664
+ };
2665
+ function optionName(arg) {
2666
+ const eq = arg.indexOf("=");
2667
+ return eq > 0 ? arg.slice(0, eq) : arg;
2668
+ }
2641
2669
  var BLOCKED_SUBCOMMANDS = {
2642
2670
  docker: /* @__PURE__ */ new Set(["push"]),
2643
2671
  podman: /* @__PURE__ */ new Set(["push"]),
@@ -2675,6 +2703,15 @@ function validateArgs(cmd, args) {
2675
2703
  const blocked2 = blockedSequences.find((seq) => seq.every((part, idx) => actual[idx] === part));
2676
2704
  if (blocked2) return `Blocked subcommand "${blocked2.join(" ")}" for command "${cmd}"`;
2677
2705
  }
2706
+ const blockedOptions = BLOCKED_OPTION_NAMES[cmd];
2707
+ if (blockedOptions) {
2708
+ for (const arg of args) {
2709
+ if (arg === "--") break;
2710
+ if (blockedOptions.has(optionName(arg))) {
2711
+ return `Blocked option "${optionName(arg)}" for command "${cmd}"`;
2712
+ }
2713
+ }
2714
+ }
2678
2715
  const blocked = BLOCKED_ARG_PATTERNS[cmd];
2679
2716
  if (!blocked) return null;
2680
2717
  for (const arg of args) {
package/dist/format.js CHANGED
@@ -666,7 +666,7 @@ var ProcessRegistryImpl = class {
666
666
  const p = this.processes.get(pid);
667
667
  if (!p) return false;
668
668
  if (p.killed) return true;
669
- if (p.protected) return false;
669
+ if (p.protected && opts.includeProtected !== true) return false;
670
670
  if (opts.preserveBackground && p.background) return false;
671
671
  const { force = false, graceMs = DEFAULT_GRACE_MS } = opts;
672
672
  const isWin2 = os.platform() === "win32";
@@ -717,9 +717,13 @@ var ProcessRegistryImpl = class {
717
717
  killAll(opts = {}) {
718
718
  const pids = Array.from(this.processes.keys());
719
719
  const killed = [];
720
+ const includeProtected = opts.includeProtected === true;
720
721
  for (const pid of pids) {
721
722
  const p = this.processes.get(pid);
722
- if (p && !p.protected && this.kill(pid, opts)) killed.push(pid);
723
+ if (!p) continue;
724
+ if (p.protected && !includeProtected) continue;
725
+ if (opts.preserveBackground && p.background) continue;
726
+ if (this.kill(pid, opts)) killed.push(pid);
723
727
  }
724
728
  return killed;
725
729
  }