token-goat 2.9.2 → 2.9.4

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 (26) hide show
  1. package/README.md +22 -50
  2. package/dist/{token-goat-chunk-UZ2NFOOZ.mjs → token-goat-chunk-3ZR4NLB3.mjs} +165 -8
  3. package/dist/{token-goat-chunk-NY4HYRSK.mjs → token-goat-chunk-5BHXZEOI.mjs} +10 -12
  4. package/dist/{token-goat-chunk-Q4LOQY44.mjs → token-goat-chunk-63XEQMNU.mjs} +137 -12
  5. package/dist/{token-goat-chunk-KKIB7O3Z.mjs → token-goat-chunk-6MU6FHE3.mjs} +463 -106
  6. package/dist/token-goat-chunk-A37V4PBF.mjs +56 -0
  7. package/dist/{token-goat-chunk-LJ3CHCTT.mjs → token-goat-chunk-CBO45DYZ.mjs} +3728 -61
  8. package/dist/{token-goat-chunk-G6XLWJWI.mjs → token-goat-chunk-E3K3BTEQ.mjs} +5 -2
  9. package/dist/{token-goat-chunk-AO2QD2AG.mjs → token-goat-chunk-EEIDFMEM.mjs} +4 -0
  10. package/dist/{token-goat-chunk-CGWACYYZ.mjs → token-goat-chunk-EPX5DWGM.mjs} +6 -1
  11. package/dist/token-goat-chunk-EQKNR7CN.mjs +23 -0
  12. package/dist/{token-goat-chunk-324QOJYZ.mjs → token-goat-chunk-EVC4TOLE.mjs} +4 -1
  13. package/dist/{token-goat-chunk-WN5T5EW5.mjs → token-goat-chunk-FQD3OB5W.mjs} +98 -2
  14. package/dist/{token-goat-chunk-VCNW7BGU.mjs → token-goat-chunk-FSC44QOH.mjs} +20 -3
  15. package/dist/{token-goat-chunk-JMUBXBG7.mjs → token-goat-chunk-GEXHIIKM.mjs} +7 -7
  16. package/dist/{token-goat-chunk-5CVKO3DA.mjs → token-goat-chunk-LYWIRYCF.mjs} +5 -2
  17. package/dist/{token-goat-chunk-LEBYARO3.mjs → token-goat-chunk-OZAEJQ7L.mjs} +9 -6
  18. package/dist/{token-goat-chunk-R4SR7MQY.mjs → token-goat-chunk-PXWBHSFB.mjs} +2 -2
  19. package/dist/{token-goat-chunk-FXAPKVRG.mjs → token-goat-chunk-US57I7GN.mjs} +26 -5
  20. package/dist/token-goat-hook.mjs +12 -7
  21. package/dist/token-goat.core.mjs +10 -7
  22. package/docs/cli.md +68 -8
  23. package/docs/security.md +6 -2
  24. package/package.json +8 -2
  25. package/dist/token-goat-chunk-AEX54RUZ.mjs +0 -11
  26. package/dist/token-goat-chunk-ZVN5WHTO.mjs +0 -23
@@ -86,7 +86,7 @@ import {
86
86
  runZipRead,
87
87
  symbolNamesInFile,
88
88
  upsertNote
89
- } from "./token-goat-chunk-FXAPKVRG.mjs";
89
+ } from "./token-goat-chunk-US57I7GN.mjs";
90
90
  import {
91
91
  DEFAULT_RECONCILE_BUDGET_MS,
92
92
  GEMINI_TOOL_NAME_MAP,
@@ -108,7 +108,7 @@ import {
108
108
  runReconcile,
109
109
  storeWebOutput,
110
110
  summarizeResidentContext
111
- } from "./token-goat-chunk-VCNW7BGU.mjs";
111
+ } from "./token-goat-chunk-FSC44QOH.mjs";
112
112
  import {
113
113
  AGENT_SALT_MARKER,
114
114
  BASH_OUTPUT_SUBDIR,
@@ -175,6 +175,7 @@ import {
175
175
  getFileEntry,
176
176
  getHintStatsSummary,
177
177
  getHintStatsTotals,
178
+ getParserFreshness,
178
179
  getProjectIndexCounts,
179
180
  getSessionFiles,
180
181
  getSessionId,
@@ -193,6 +194,7 @@ import {
193
194
  isHintCategory,
194
195
  isParseSkipEligible,
195
196
  isRecallCacheType,
197
+ isSuppressionCategory,
196
198
  isWorkerRunning,
197
199
  listBlobs,
198
200
  listOutputs,
@@ -238,10 +240,11 @@ import {
238
240
  visionTokensSavedByText,
239
241
  walkProject,
240
242
  writeCompact
241
- } from "./token-goat-chunk-LJ3CHCTT.mjs";
243
+ } from "./token-goat-chunk-CBO45DYZ.mjs";
242
244
  import {
243
245
  C,
244
246
  CONFIG_KEY_ENV_OVERRIDES,
247
+ CompressedOutput,
245
248
  ENV_KEYS,
246
249
  FILTERS,
247
250
  LOCK_WAIT_MS_HARDENED,
@@ -249,6 +252,8 @@ import {
249
252
  PROJECT_LOCKED_KEYS,
250
253
  PROJECT_LOCKED_SECTIONS,
251
254
  RESET,
255
+ TOOL_FILTERS,
256
+ ToolFilter,
252
257
  VERSION,
253
258
  _useRichStats,
254
259
  anchoredMarkerPattern,
@@ -257,6 +262,7 @@ import {
257
262
  canonicalize,
258
263
  cappedSourceBytesSaved,
259
264
  colorStdout,
265
+ combineStreams,
260
266
  compileCustomPatterns,
261
267
  configPath,
262
268
  copilotCliConfigPath,
@@ -267,6 +273,8 @@ import {
267
273
  dataDir,
268
274
  decodeSource,
269
275
  defaultConfig,
276
+ deliverCompressed,
277
+ detectFromCommand,
270
278
  detectLanguage,
271
279
  detectSourceEncoding,
272
280
  encodeSource,
@@ -358,15 +366,24 @@ import {
358
366
  withFileLock,
359
367
  withRetryOnLock,
360
368
  writeJsonSettings
361
- } from "./token-goat-chunk-UZ2NFOOZ.mjs";
369
+ } from "./token-goat-chunk-3ZR4NLB3.mjs";
362
370
  import {
363
- __export
364
- } from "./token-goat-chunk-AEX54RUZ.mjs";
371
+ __export,
372
+ init_define_import_meta_env
373
+ } from "./token-goat-chunk-A37V4PBF.mjs";
365
374
 
366
375
  // src/cli.ts
376
+ init_define_import_meta_env();
367
377
  import { randomBytes } from "node:crypto";
368
378
 
379
+ // node_modules/commander/index.js
380
+ init_define_import_meta_env();
381
+
382
+ // node_modules/commander/lib/argument.js
383
+ init_define_import_meta_env();
384
+
369
385
  // node_modules/commander/lib/error.js
386
+ init_define_import_meta_env();
370
387
  var CommanderError = class extends Error {
371
388
  /**
372
389
  * Constructs the CommanderError class
@@ -517,6 +534,7 @@ function humanReadableArgName(arg) {
517
534
  }
518
535
 
519
536
  // node_modules/commander/lib/command.js
537
+ init_define_import_meta_env();
520
538
  import { EventEmitter } from "node:events";
521
539
  import childProcess from "node:child_process";
522
540
  import path from "node:path";
@@ -525,6 +543,7 @@ import process2 from "node:process";
525
543
  import { stripVTControlCharacters as stripVTControlCharacters2 } from "node:util";
526
544
 
527
545
  // node_modules/commander/lib/help.js
546
+ init_define_import_meta_env();
528
547
  import { stripVTControlCharacters } from "node:util";
529
548
  var Help = class {
530
549
  constructor() {
@@ -1117,6 +1136,7 @@ ${itemIndentStr}`);
1117
1136
  };
1118
1137
 
1119
1138
  // node_modules/commander/lib/option.js
1139
+ init_define_import_meta_env();
1120
1140
  var Option = class {
1121
1141
  /**
1122
1142
  * Initialize a new `Option` with the given `flags` and `description`.
@@ -1423,6 +1443,7 @@ function splitOptionFlags(flags) {
1423
1443
  }
1424
1444
 
1425
1445
  // node_modules/commander/lib/suggestSimilar.js
1446
+ init_define_import_meta_env();
1426
1447
  var maxDistance = 3;
1427
1448
  function editDistance(a, b) {
1428
1449
  if (Math.abs(a.length - b.length) > maxDistance)
@@ -3477,9 +3498,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
3477
3498
  * @param {string} [path]
3478
3499
  * @return {(string|null|Command)}
3479
3500
  */
3480
- executableDir(path30) {
3481
- if (path30 === void 0) return this._executableDir;
3482
- this._executableDir = path30;
3501
+ executableDir(path31) {
3502
+ if (path31 === void 0) return this._executableDir;
3503
+ this._executableDir = path31;
3483
3504
  return this;
3484
3505
  }
3485
3506
  /**
@@ -3735,6 +3756,7 @@ function useColor() {
3735
3756
  var program = new Command();
3736
3757
 
3737
3758
  // src/command_intent.ts
3759
+ init_define_import_meta_env();
3738
3760
  var INTENT_SUGGESTIONS = [
3739
3761
  [
3740
3762
  ["search", "lookup", "query"],
@@ -3778,11 +3800,12 @@ function attemptedCommandName(argv) {
3778
3800
  }
3779
3801
 
3780
3802
  // src/cli.ts
3781
- import * as fs28 from "fs";
3782
- import * as path29 from "path";
3803
+ import * as fs29 from "fs";
3804
+ import * as path30 from "path";
3783
3805
  import { homedir as homedir13 } from "os";
3784
3806
 
3785
3807
  // src/walk_index.ts
3808
+ init_define_import_meta_env();
3786
3809
  import * as fs2 from "node:fs";
3787
3810
  import * as os from "node:os";
3788
3811
  import * as path2 from "node:path";
@@ -3831,6 +3854,7 @@ function collectWalkIndexFiles(root, opts = {}) {
3831
3854
  }
3832
3855
 
3833
3856
  // src/bridges/gemini_install.ts
3857
+ init_define_import_meta_env();
3834
3858
  import * as fs3 from "node:fs";
3835
3859
  import * as os2 from "node:os";
3836
3860
  import * as path3 from "node:path";
@@ -3974,6 +3998,7 @@ function isGeminiInstalled() {
3974
3998
  }
3975
3999
 
3976
4000
  // src/bridges/qwen_install.ts
4001
+ init_define_import_meta_env();
3977
4002
  import * as fs4 from "node:fs";
3978
4003
  import * as os3 from "node:os";
3979
4004
  import * as path4 from "node:path";
@@ -4098,11 +4123,13 @@ function isQwenInstalled() {
4098
4123
  }
4099
4124
 
4100
4125
  // src/bridges/pi_install.ts
4126
+ init_define_import_meta_env();
4101
4127
  import * as fs5 from "node:fs";
4102
4128
  import * as os4 from "node:os";
4103
4129
  import * as path5 from "node:path";
4104
4130
 
4105
4131
  // src/bridges/pi.ts
4132
+ init_define_import_meta_env();
4106
4133
  var PI_EXTENSION_SCRIPT = `// token-goat bridge extension for pi (pi-coding-agent)
4107
4134
  // Bridges pi's extension events to token-goat's subprocess hook protocol.
4108
4135
  // https://github.com/DFKHelper/token-goat
@@ -4493,11 +4520,16 @@ function isPiInstalled(opts = {}) {
4493
4520
  }
4494
4521
 
4495
4522
  // src/bridges/opencode_install.ts
4523
+ init_define_import_meta_env();
4496
4524
  import * as fs6 from "node:fs";
4497
4525
  import * as os5 from "node:os";
4498
4526
  import * as path6 from "node:path";
4499
4527
 
4528
+ // src/bridges/opencode.ts
4529
+ init_define_import_meta_env();
4530
+
4500
4531
  // src/bridges/relay_block.ts
4532
+ init_define_import_meta_env();
4501
4533
  var BRIDGE_RELAY_JS = `// resolveEntryPath reads a sidecar JSON file (token-goat-entry.json, written by
4502
4534
  // the install step next to this plugin file) containing the absolute path to
4503
4535
  // the token-goat CLI entry that was running at install time. Unlike
@@ -4787,11 +4819,13 @@ function isOpencodeInstalled() {
4787
4819
  }
4788
4820
 
4789
4821
  // src/bridges/openclaw_install.ts
4822
+ init_define_import_meta_env();
4790
4823
  import * as fs7 from "node:fs";
4791
4824
  import * as os6 from "node:os";
4792
4825
  import * as path7 from "node:path";
4793
4826
 
4794
4827
  // src/bridges/openclaw.ts
4828
+ init_define_import_meta_env();
4795
4829
  var OPENCLAW_PLUGIN_SCRIPT = `// token-goat bridge plugin for OpenClaw
4796
4830
  // Bridges OpenClaw's tool-call and session hooks to token-goat's subprocess
4797
4831
  // hook protocol. https://github.com/DFKHelper/token-goat
@@ -5098,6 +5132,7 @@ function isOpenclawInstalled() {
5098
5132
  }
5099
5133
 
5100
5134
  // src/bridges_status.ts
5135
+ init_define_import_meta_env();
5101
5136
  var NO_SERVER_HANDLER_REASON = "token-goat has no registered server-side handler for this event (zero registerHook('notification'|'stop', ...) call sites in src/) -- wiring it client-side would currently be a no-op";
5102
5137
  var NO_POST_COMPACT_EVENT_REASON = "post_compact is a Claude Code event (hook_event_name PostCompact, carrying compact_summary); no equivalent has been confirmed for this harness, so it is left unwired rather than guessed at";
5103
5138
  var NO_SEPARATE_FAILURE_EVENT_REASON = "post_tool_use_failure exists because Copilot CLI routes a failed tool result to a separate postToolUseFailure event instead of postToolUse. No separate failure event is wired for this harness, so a failed tool call either arrives on post_tool_use like any other result or is not seen; which of the two has not been checked here";
@@ -5401,6 +5436,7 @@ function installVerificationNotice(harness) {
5401
5436
  }
5402
5437
 
5403
5438
  // src/sharepoint_resolve.ts
5439
+ init_define_import_meta_env();
5404
5440
  import * as fs8 from "node:fs";
5405
5441
  import * as os7 from "node:os";
5406
5442
  import * as path8 from "node:path";
@@ -5508,6 +5544,7 @@ function resolveLocalPath(parsed, env = process.env, home = os7.homedir()) {
5508
5544
  }
5509
5545
 
5510
5546
  // src/video_chapters.ts
5547
+ init_define_import_meta_env();
5511
5548
  import { spawnSync } from "node:child_process";
5512
5549
  var _ffprobeAvailable;
5513
5550
  function isFfprobeAvailable() {
@@ -5555,6 +5592,7 @@ function extractVideoChapters(file) {
5555
5592
  }
5556
5593
 
5557
5594
  // src/transcript_extract.ts
5595
+ init_define_import_meta_env();
5558
5596
  import * as fs9 from "node:fs";
5559
5597
  var TIMESTAMP_RE = /(\d{1,2}:)?(\d{2}):(\d{2})[.,](\d{1,3})/;
5560
5598
  var CUE_LINE_RE = new RegExp(`^\\s*${TIMESTAMP_RE.source}\\s*-->\\s*${TIMESTAMP_RE.source}`);
@@ -5668,6 +5706,7 @@ function formatCues(cues) {
5668
5706
  }
5669
5707
 
5670
5708
  // src/affected.ts
5709
+ init_define_import_meta_env();
5671
5710
  import * as path9 from "node:path";
5672
5711
  var DEFAULT_AFFECTED_DEPTH = 5;
5673
5712
  function emit(text) {
@@ -5769,6 +5808,7 @@ function runAffected(opts) {
5769
5808
  }
5770
5809
 
5771
5810
  // src/purge.ts
5811
+ init_define_import_meta_env();
5772
5812
  import * as fs10 from "node:fs";
5773
5813
  import * as path10 from "node:path";
5774
5814
  function directorySize(root) {
@@ -5822,6 +5862,7 @@ function formatBytes2(bytes) {
5822
5862
  }
5823
5863
 
5824
5864
  // src/cli_stats.ts
5865
+ init_define_import_meta_env();
5825
5866
  import * as fs11 from "node:fs";
5826
5867
  import * as path11 from "node:path";
5827
5868
  function writeRaw(text) {
@@ -5944,6 +5985,7 @@ function runStats(opts = {}) {
5944
5985
  }
5945
5986
 
5946
5987
  // src/cli_doctor.ts
5988
+ init_define_import_meta_env();
5947
5989
  import * as fs12 from "fs";
5948
5990
  import * as os8 from "os";
5949
5991
  import * as path12 from "path";
@@ -6157,19 +6199,19 @@ function checkEmbeddingCoverage(dbPath, rootDir) {
6157
6199
  if (indexedFiles === 0) {
6158
6200
  return { name: "Embedding coverage", status: "ok", message: "no indexed files yet" };
6159
6201
  }
6160
- const pct2 = Math.round(embeddedFiles / indexedFiles * 100);
6202
+ const pct3 = Math.round(embeddedFiles / indexedFiles * 100);
6161
6203
  const sizeKb = cfg.indexing.large_file_symbol_only_kb;
6162
6204
  if (embeddedFiles / indexedFiles < EMBED_COVERAGE_WARN_FRACTION) {
6163
6205
  return {
6164
6206
  name: "Embedding coverage",
6165
6207
  status: "warn",
6166
- message: `only ${embeddedFiles} of ${indexedFiles} indexed file(s) (${pct2}%) have embeddings \u2014 'semantic' searches those files only, and reports finding nothing in the same words it uses after searching everything. Files over indexing.large_file_symbol_only_kb (currently ${sizeKb} KB) are indexed for symbols only and are the usual reason; raise it with 'token-goat config set indexing.large_file_symbol_only_kb <KB>' and re-embed with 'token-goat index --force' to widen coverage. Exact symbol lookups are unaffected`
6208
+ message: `only ${embeddedFiles} of ${indexedFiles} indexed file(s) (${pct3}%) have embeddings \u2014 'semantic' searches those files only, and reports finding nothing in the same words it uses after searching everything. Files over indexing.large_file_symbol_only_kb (currently ${sizeKb} KB) are indexed for symbols only and are the usual reason; raise it with 'token-goat config set indexing.large_file_symbol_only_kb <KB>' and re-embed with 'token-goat index --force' to widen coverage. Exact symbol lookups are unaffected`
6167
6209
  };
6168
6210
  }
6169
6211
  return {
6170
6212
  name: "Embedding coverage",
6171
6213
  status: "ok",
6172
- message: `${embeddedFiles} of ${indexedFiles} indexed file(s) (${pct2}%) have embeddings`
6214
+ message: `${embeddedFiles} of ${indexedFiles} indexed file(s) (${pct3}%) have embeddings`
6173
6215
  };
6174
6216
  } catch (err2) {
6175
6217
  return {
@@ -6179,6 +6221,38 @@ function checkEmbeddingCoverage(dbPath, rootDir) {
6179
6221
  };
6180
6222
  }
6181
6223
  }
6224
+ var PARSER_FRESHNESS_WARN_FRACTION = 0.25;
6225
+ function checkParserFreshness(dbPath, rootDir) {
6226
+ if (!fs12.existsSync(dbPath)) {
6227
+ return { name: "Parser freshness", status: "ok", message: "no database yet" };
6228
+ }
6229
+ try {
6230
+ const { indexedFiles, currentFiles } = getParserFreshness(dbPath, PARSER_FINGERPRINT, rootDir);
6231
+ if (indexedFiles === 0) {
6232
+ return { name: "Parser freshness", status: "ok", message: "no indexed files yet" };
6233
+ }
6234
+ const stale = indexedFiles - currentFiles;
6235
+ const pct3 = Math.round(stale / indexedFiles * 100);
6236
+ if (currentFiles / indexedFiles < 1 - PARSER_FRESHNESS_WARN_FRACTION) {
6237
+ return {
6238
+ name: "Parser freshness",
6239
+ status: "warn",
6240
+ message: `${stale} of ${indexedFiles} indexed file(s) (${pct3}%) were parsed by a different build of the extraction logic, so their symbols are whatever that build extracted \u2014 'symbol', 'read', 'outline' and 'skeleton' answer from those rows, and the read-hook body fold declines on them. Run 'token-goat index' in this project to reparse them; --force is not needed, a parser mismatch reindexes on its own`
6241
+ };
6242
+ }
6243
+ return {
6244
+ name: "Parser freshness",
6245
+ status: "ok",
6246
+ message: `${currentFiles} of ${indexedFiles} indexed file(s) match the running parser`
6247
+ };
6248
+ } catch (err2) {
6249
+ return {
6250
+ name: "Parser freshness",
6251
+ status: "warn",
6252
+ message: `could not query parser freshness: ${extractErrorMessage(err2)}`
6253
+ };
6254
+ }
6255
+ }
6182
6256
  var DIRTY_QUEUE_BACKLOG_WARN_THRESHOLD = 500;
6183
6257
  function checkDirtyQueueHealth(dataDir2) {
6184
6258
  let pendingCount = 0;
@@ -6414,6 +6488,7 @@ var LOCKED_BOOLEAN_SAFE_VALUE = {
6414
6488
  "screenshot.block_private_targets": true,
6415
6489
  "network.offline": true,
6416
6490
  "indexing.cross_project_symbols": false,
6491
+ "hints.fold_code_bodies": false,
6417
6492
  "webfetch.compress_bodies": true
6418
6493
  };
6419
6494
  function lockedEnvOverridableKeys() {
@@ -6616,6 +6691,7 @@ function runDoctor(dataDir2, configPath2, rootDir, processes) {
6616
6691
  results.push(checkConfigValid(actualConfigPath));
6617
6692
  results.push(checkEmbeddings(loadConfig(rootDir)));
6618
6693
  results.push(checkEmbeddingCoverage(path12.join(actualDataDir, "global.db"), rootDir));
6694
+ results.push(checkParserFreshness(path12.join(actualDataDir, "global.db"), rootDir));
6619
6695
  for (const result of checkSecurityPosture(loadConfig(rootDir), actualDataDir)) results.push(result);
6620
6696
  results.push(checkDiskSpace(actualDataDir));
6621
6697
  const copilotResult = checkCopilotCli(copilotCliConfigPath(), copilotCliScriptPath());
@@ -6689,6 +6765,7 @@ async function runDoctorAndExit(opts) {
6689
6765
  }
6690
6766
 
6691
6767
  // src/capabilities.ts
6768
+ init_define_import_meta_env();
6692
6769
  function collectCapabilities(config = loadConfig()) {
6693
6770
  const online = !config.network.offline;
6694
6771
  return [
@@ -6772,7 +6849,11 @@ function renderCapabilities(caps) {
6772
6849
  return lines.join("\n");
6773
6850
  }
6774
6851
 
6852
+ // src/gdrive.ts
6853
+ init_define_import_meta_env();
6854
+
6775
6855
  // src/webfetch.ts
6856
+ init_define_import_meta_env();
6776
6857
  import { existsSync as existsSync7, readdirSync as readdirSync5, statSync as statSync4, unlinkSync as unlinkSync2 } from "fs";
6777
6858
  import * as http from "http";
6778
6859
  import * as https from "https";
@@ -7231,6 +7312,7 @@ async function getSectionContent(fileId, heading, opts = {}) {
7231
7312
  }
7232
7313
 
7233
7314
  // src/pack.ts
7315
+ init_define_import_meta_env();
7234
7316
  import * as fs13 from "node:fs";
7235
7317
  import * as path14 from "node:path";
7236
7318
 
@@ -7250,8 +7332,13 @@ __export(esm_exports, {
7250
7332
  sep: () => sep2,
7251
7333
  unescape: () => unescape
7252
7334
  });
7335
+ init_define_import_meta_env();
7336
+
7337
+ // node_modules/brace-expansion/dist/esm/index.js
7338
+ init_define_import_meta_env();
7253
7339
 
7254
7340
  // node_modules/balanced-match/dist/esm/index.js
7341
+ init_define_import_meta_env();
7255
7342
  var balanced = (a, b, str) => {
7256
7343
  const ma = a instanceof RegExp ? maybeMatch(a, str) : a;
7257
7344
  const mb2 = b instanceof RegExp ? maybeMatch(b, str) : b;
@@ -7518,6 +7605,7 @@ function expand_(str, max, maxLength, isTop) {
7518
7605
  }
7519
7606
 
7520
7607
  // node_modules/minimatch/dist/esm/assert-valid-pattern.js
7608
+ init_define_import_meta_env();
7521
7609
  var MAX_PATTERN_LENGTH = 1024 * 64;
7522
7610
  var assertValidPattern = (pattern) => {
7523
7611
  if (typeof pattern !== "string") {
@@ -7528,7 +7616,11 @@ var assertValidPattern = (pattern) => {
7528
7616
  }
7529
7617
  };
7530
7618
 
7619
+ // node_modules/minimatch/dist/esm/ast.js
7620
+ init_define_import_meta_env();
7621
+
7531
7622
  // node_modules/minimatch/dist/esm/brace-expressions.js
7623
+ init_define_import_meta_env();
7532
7624
  var posixClasses = {
7533
7625
  "[:alnum:]": ["\\p{L}\\p{Nl}\\p{Nd}", true],
7534
7626
  "[:alpha:]": ["\\p{L}\\p{Nl}", true],
@@ -7638,6 +7730,7 @@ var parseClass = (glob, position) => {
7638
7730
  };
7639
7731
 
7640
7732
  // node_modules/minimatch/dist/esm/unescape.js
7733
+ init_define_import_meta_env();
7641
7734
  var unescape = (s, { windowsPathsNoEscape = false, magicalBraces = true } = {}) => {
7642
7735
  if (magicalBraces) {
7643
7736
  return windowsPathsNoEscape ? s.replace(/\[([^/\\])\]/g, "$1") : s.replace(/((?!\\).|^)\[([^/\\])\]/g, "$1$2").replace(/\\([^/])/g, "$1");
@@ -8290,6 +8383,7 @@ var AST = class {
8290
8383
  _a = AST;
8291
8384
 
8292
8385
  // node_modules/minimatch/dist/esm/escape.js
8386
+ init_define_import_meta_env();
8293
8387
  var escape = (s, { windowsPathsNoEscape = false, magicalBraces = false } = {}) => {
8294
8388
  if (magicalBraces) {
8295
8389
  return windowsPathsNoEscape ? s.replace(/[?*()[\]{}]/g, "[$&]") : s.replace(/[?*()[\]\\{}]/g, "\\$&");
@@ -9565,12 +9659,12 @@ function formatBudgetText(result, contextK) {
9565
9659
  lines.push(` ${e.rel_path.padEnd(colW, " ")} ${String(e.lines).padStart(6, " ")} ${String(e.tokens).padStart(8, " ")}`);
9566
9660
  }
9567
9661
  lines.push(` ${"-".repeat(colW)} ${"-".repeat(6)} ${"-".repeat(8)}`);
9568
- let pct2 = "";
9662
+ let pct3 = "";
9569
9663
  if (contextK) {
9570
- pct2 = ` (${Math.round(result.total_tokens / (contextK * 1e3) * 100)}% of ${contextK}K)`;
9664
+ pct3 = ` (${Math.round(result.total_tokens / (contextK * 1e3) * 100)}% of ${contextK}K)`;
9571
9665
  }
9572
9666
  lines.push(
9573
- ` ${"Total".padEnd(colW, " ")} ${String(result.total_lines).padStart(6, " ")} ${String(result.total_tokens).padStart(8, " ")}${pct2}`
9667
+ ` ${"Total".padEnd(colW, " ")} ${String(result.total_lines).padStart(6, " ")} ${String(result.total_tokens).padStart(8, " ")}${pct3}`
9574
9668
  );
9575
9669
  if (result.skipped.length > 0) {
9576
9670
  const skipped = result.skipped.slice(0, 5).join(", ");
@@ -9582,6 +9676,7 @@ function formatBudgetText(result, contextK) {
9582
9676
  }
9583
9677
 
9584
9678
  // src/failures.ts
9679
+ init_define_import_meta_env();
9585
9680
  function getFailureCount(result) {
9586
9681
  return result.blocks.length || result.summaryLines.length;
9587
9682
  }
@@ -10006,6 +10101,7 @@ function formatFailureDeltaJson(delta, runner) {
10006
10101
  }
10007
10102
 
10008
10103
  // src/failures_state.ts
10104
+ init_define_import_meta_env();
10009
10105
  import * as fs14 from "node:fs";
10010
10106
  import * as path15 from "node:path";
10011
10107
  var KEY_RE = /^[A-Za-z0-9_-]{1,80}$/;
@@ -10051,10 +10147,12 @@ function saveFailureSnapshot(projectHash, key, snapshot) {
10051
10147
  }
10052
10148
 
10053
10149
  // src/text_commands.ts
10150
+ init_define_import_meta_env();
10054
10151
  import * as fs16 from "fs";
10055
10152
  import * as path17 from "path";
10056
10153
 
10057
10154
  // src/project_memory.ts
10155
+ init_define_import_meta_env();
10058
10156
  import * as fs15 from "node:fs";
10059
10157
  import * as path16 from "node:path";
10060
10158
  var MAX_ENTRIES = 30;
@@ -11278,6 +11376,7 @@ function countPackIgnorePatterns(root) {
11278
11376
  }
11279
11377
 
11280
11378
  // src/dep_docs.ts
11379
+ init_define_import_meta_env();
11281
11380
  import { createRequire } from "node:module";
11282
11381
  import * as fs17 from "node:fs";
11283
11382
  import * as path18 from "node:path";
@@ -11565,7 +11664,11 @@ function runDepDocs(opts) {
11565
11664
  return { text, code: 0 };
11566
11665
  }
11567
11666
 
11667
+ // src/cache_session_commands.ts
11668
+ init_define_import_meta_env();
11669
+
11568
11670
  // src/resume.ts
11671
+ init_define_import_meta_env();
11569
11672
  import { readFile } from "node:fs/promises";
11570
11673
  var MAX_RESUME_TOKENS = 2e3;
11571
11674
  var MAX_RESUME_CHARS = MAX_RESUME_TOKENS * 4;
@@ -11905,15 +12008,15 @@ function cmdCompactHint(opts) {
11905
12008
  const pressure = getContextPressure(cache ?? void 0);
11906
12009
  const [manifest, eventCount] = sessionId !== null ? buildManifestWithCount(sessionId) : ["", 0];
11907
12010
  const manifestTokens = estimateTokens(manifest);
11908
- const pct2 = (pressure.fillFraction * 100).toFixed(1);
12011
+ const pct3 = (pressure.fillFraction * 100).toFixed(1);
11909
12012
  if (opts.json === true) {
11910
- const out2 = { tier: pressure.tier, fillFraction: pressure.fillFraction, pct: Number(pct2), manifestTokens, eventCount };
12013
+ const out2 = { tier: pressure.tier, fillFraction: pressure.fillFraction, pct: Number(pct3), manifestTokens, eventCount };
11911
12014
  if (sessionId !== null) out2["sessionId"] = sessionId;
11912
12015
  if (opts.trigger !== void 0) out2["trigger"] = opts.trigger;
11913
12016
  process.stdout.write(JSON.stringify(out2, null, 2) + "\n");
11914
12017
  return;
11915
12018
  }
11916
- process.stdout.write(`Compact hint \u2014 context: ${pressure.tier} (${pct2}% full)
12019
+ process.stdout.write(`Compact hint \u2014 context: ${pressure.tier} (${pct3}% full)
11917
12020
  `);
11918
12021
  if (sessionId !== null) process.stdout.write(`Session: ${sessionId}
11919
12022
  `);
@@ -12000,6 +12103,7 @@ function cmdBaseline(opts) {
12000
12103
  }
12001
12104
 
12002
12105
  // src/index_reclaim.ts
12106
+ init_define_import_meta_env();
12003
12107
  import * as fs18 from "node:fs";
12004
12108
  import * as path19 from "node:path";
12005
12109
  var DERIVED_TABLES = ["chunk_vectors", "chunks", "refs", "symbols", "files"];
@@ -12126,6 +12230,7 @@ function cmdReclaimIndex(opts) {
12126
12230
  }
12127
12231
 
12128
12232
  // src/config_commands.ts
12233
+ init_define_import_meta_env();
12129
12234
  import * as fs19 from "node:fs";
12130
12235
  import * as os9 from "node:os";
12131
12236
  import * as path20 from "node:path";
@@ -12795,6 +12900,7 @@ function cmdHistory(opts) {
12795
12900
  }
12796
12901
 
12797
12902
  // src/cli_bootstrap_audit.ts
12903
+ init_define_import_meta_env();
12798
12904
  import * as fs20 from "node:fs";
12799
12905
  import * as os10 from "node:os";
12800
12906
  import * as path21 from "node:path";
@@ -13011,6 +13117,7 @@ async function runBootstrapAudit(opts = {}) {
13011
13117
  }
13012
13118
 
13013
13119
  // src/cli_memory.ts
13120
+ init_define_import_meta_env();
13014
13121
  import * as fs21 from "node:fs";
13015
13122
  import * as path22 from "node:path";
13016
13123
  function removeExactDupLines(text, report) {
@@ -13130,10 +13237,12 @@ async function runMemoryCommand(opts = {}) {
13130
13237
  }
13131
13238
 
13132
13239
  // src/cli_waste.ts
13240
+ init_define_import_meta_env();
13133
13241
  import * as fs24 from "node:fs";
13134
13242
  import * as path25 from "node:path";
13135
13243
 
13136
13244
  // src/waste.ts
13245
+ init_define_import_meta_env();
13137
13246
  import * as fs22 from "node:fs";
13138
13247
  import * as os11 from "node:os";
13139
13248
  import * as path23 from "node:path";
@@ -13381,6 +13490,7 @@ async function buildWasteReport(transcriptPath, opts = {}) {
13381
13490
  }
13382
13491
 
13383
13492
  // src/copilot_waste.ts
13493
+ init_define_import_meta_env();
13384
13494
  import * as fs23 from "node:fs";
13385
13495
  import * as path24 from "node:path";
13386
13496
  var HOOK_RECORD_TYPES = /* @__PURE__ */ new Set(["hook.start", "hook.end"]);
@@ -13535,10 +13645,10 @@ function printCopilotReport(report) {
13535
13645
  w(` Conversation: ${conversationTokens.toLocaleString()} tok
13536
13646
  `);
13537
13647
  if (total > 0) {
13538
- const pct2 = (fixed / total * 100).toFixed(1);
13648
+ const pct3 = (fixed / total * 100).toFixed(1);
13539
13649
  w(` ${fixed.toLocaleString()} tok of system prompt and tool definitions ships with every
13540
13650
  `);
13541
- w(` request; at shutdown that was ${pct2}% of the context. No hook can reach it: Copilot
13651
+ w(` request; at shutdown that was ${pct3}% of the context. No hook can reach it: Copilot
13542
13652
  `);
13543
13653
  w(" assembles both natively, with nothing between assembly and send. The levers are all\n");
13544
13654
  w(" config: fewer MCP servers and custom tools, and --excluded-tools / --available-tools /\n");
@@ -13598,9 +13708,9 @@ function printCopilotReport(report) {
13598
13708
  `);
13599
13709
  } else {
13600
13710
  for (const block of report.blocks) {
13601
- const pct2 = block.bytes > 0 ? (block.repeatBytes / block.bytes * 100).toFixed(1) : "0.0";
13711
+ const pct3 = block.bytes > 0 ? (block.repeatBytes / block.bytes * 100).toFixed(1) : "0.0";
13602
13712
  w(` ${block.kind}: ${countNoun(block.count, "injection")}, ${formatBytes(block.bytes)}`);
13603
- w(block.repeatBytes > 0 ? `, ${formatBytes(block.repeatBytes)} re-sent verbatim (${pct2}%)
13713
+ w(block.repeatBytes > 0 ? `, ${formatBytes(block.repeatBytes)} re-sent verbatim (${pct3}%)
13604
13714
  ` : "\n");
13605
13715
  }
13606
13716
  }
@@ -13765,6 +13875,7 @@ async function runWasteCommand(opts = {}) {
13765
13875
  }
13766
13876
 
13767
13877
  // src/session_read.ts
13878
+ init_define_import_meta_env();
13768
13879
  import * as fs25 from "node:fs";
13769
13880
  import * as path26 from "node:path";
13770
13881
  import * as readline2 from "node:readline";
@@ -13931,6 +14042,7 @@ function formatSessionSlice(turns) {
13931
14042
  }
13932
14043
 
13933
14044
  // src/session_audit.ts
14045
+ init_define_import_meta_env();
13934
14046
  import * as fs26 from "node:fs";
13935
14047
  import * as os12 from "node:os";
13936
14048
  import * as path27 from "node:path";
@@ -14288,13 +14400,13 @@ async function auditOneFile(filePath, s, toolMap, attachmentMap, hookMap, laneOb
14288
14400
  s.readInterception.readResults += 1;
14289
14401
  const denyTemplate = DENY_TEMPLATES.find((t) => t.re.test(text));
14290
14402
  if (denyTemplate !== void 0) {
14291
- const path30 = readPathById.get(id) ?? "";
14292
- const lastSlash = path30.lastIndexOf("/");
14403
+ const path31 = readPathById.get(id) ?? "";
14404
+ const lastSlash = path31.lastIndexOf("/");
14293
14405
  openDenies.push({
14294
14406
  kind: denyTemplate.kind,
14295
14407
  withheldBytes: parseWithheldBytes(denyTemplate.kind, text),
14296
- path: path30,
14297
- basename: lastSlash === -1 ? path30 : path30.slice(lastSlash + 1),
14408
+ path: path31,
14409
+ basename: lastSlash === -1 ? path31 : path31.slice(lastSlash + 1),
14298
14410
  callIndexAtDeny: perCall.length,
14299
14411
  compactEpochAtOpen: compactEpoch,
14300
14412
  compactEpochAtWindow: null,
@@ -14762,6 +14874,7 @@ function formatSessionAudit(s) {
14762
14874
  }
14763
14875
 
14764
14876
  // src/cli_mcp_audit.ts
14877
+ init_define_import_meta_env();
14765
14878
  import * as fs27 from "node:fs";
14766
14879
  import * as os13 from "node:os";
14767
14880
  import * as path28 from "node:path";
@@ -14915,6 +15028,7 @@ async function runMcpAuditCommand(opts = {}) {
14915
15028
  }
14916
15029
 
14917
15030
  // src/cli_recall.ts
15031
+ init_define_import_meta_env();
14918
15032
  var RECALL_COMMAND = {
14919
15033
  bash: "bash-output",
14920
15034
  web: "web-output",
@@ -14974,7 +15088,231 @@ function runRecallCommand(query, opts = {}) {
14974
15088
  printHits(browse ? void 0 : query, hits);
14975
15089
  }
14976
15090
 
15091
+ // src/cli_bench.ts
15092
+ init_define_import_meta_env();
15093
+ import * as fs28 from "node:fs";
15094
+ import * as path29 from "node:path";
15095
+ var ControlFilter = class extends ToolFilter {
15096
+ constructor(name, transform) {
15097
+ super();
15098
+ this.name = name;
15099
+ this.transform = transform;
15100
+ }
15101
+ name;
15102
+ transform;
15103
+ apply(stdout, stderr, exitCode) {
15104
+ const originalBytes = Buffer.byteLength(stdout, "utf8") + Buffer.byteLength(stderr, "utf8");
15105
+ const text = this.transform(combineStreams(stdout, stderr));
15106
+ return new CompressedOutput(text, originalBytes, Buffer.byteLength(text, "utf8"), this.name, exitCode);
15107
+ }
15108
+ };
15109
+ var CONTROL_FILTERS = {
15110
+ identity: new ControlFilter("control:identity", (s) => s),
15111
+ destroy: new ControlFilter("control:destroy", () => "")
15112
+ };
15113
+ var MAX_BENCH_FILE_BYTES = 5 * 1024 * 1024;
15114
+ function readCaseFile(id, filePath, what) {
15115
+ const bytes = fs28.statSync(filePath).size;
15116
+ if (bytes > MAX_BENCH_FILE_BYTES) {
15117
+ throw new Error(
15118
+ `bench case ${id}: ${what} is ${bytes} bytes, over the ${MAX_BENCH_FILE_BYTES}-byte limit for a corpus file (${filePath})`
15119
+ );
15120
+ }
15121
+ return fs28.readFileSync(filePath, "utf8");
15122
+ }
15123
+ function parseCase(id, metaPath, outputPath) {
15124
+ const metaText = readCaseFile(id, metaPath, "metadata");
15125
+ let raw;
15126
+ try {
15127
+ raw = JSON.parse(metaText);
15128
+ } catch (e) {
15129
+ throw new Error(`bench case ${id}: ${metaPath} is not valid JSON (${e instanceof Error ? e.message : String(e)})`, { cause: e });
15130
+ }
15131
+ if (typeof raw !== "object" || raw === null) throw new Error(`bench case ${id}: expected a JSON object`);
15132
+ const meta = raw;
15133
+ const str = (key) => {
15134
+ const v = meta[key];
15135
+ if (typeof v !== "string" || v.trim() === "") throw new Error(`bench case ${id}: "${key}" must be a non-empty string`);
15136
+ return v;
15137
+ };
15138
+ const mustKeep = meta["mustKeep"];
15139
+ if (!Array.isArray(mustKeep) || mustKeep.some((s) => typeof s !== "string" || s === "")) {
15140
+ throw new Error(`bench case ${id}: "mustKeep" must be an array of non-empty strings`);
15141
+ }
15142
+ const exitCode = meta["exitCode"];
15143
+ if (exitCode !== void 0 && typeof exitCode !== "number") throw new Error(`bench case ${id}: "exitCode" must be a number`);
15144
+ return {
15145
+ id,
15146
+ provenance: str("provenance"),
15147
+ command: str("command"),
15148
+ exitCode: typeof exitCode === "number" ? exitCode : 0,
15149
+ mustKeep,
15150
+ output: readCaseFile(id, outputPath, "output")
15151
+ };
15152
+ }
15153
+ function loadCorpus(dir) {
15154
+ let entries;
15155
+ try {
15156
+ entries = fs28.readdirSync(dir);
15157
+ } catch {
15158
+ throw new Error(`bench corpus not found: ${dir}`);
15159
+ }
15160
+ const cases = [];
15161
+ for (const entry of entries.sort()) {
15162
+ if (!entry.endsWith(".json")) continue;
15163
+ const id = entry.slice(0, -".json".length);
15164
+ const outputPath = path29.join(dir, `${id}.txt`);
15165
+ if (!fs28.existsSync(outputPath)) throw new Error(`bench case ${id}: missing output file ${outputPath}`);
15166
+ cases.push(parseCase(id, path29.join(dir, entry), outputPath));
15167
+ }
15168
+ if (cases.length === 0) throw new Error(`bench corpus is empty: ${dir}`);
15169
+ return cases;
15170
+ }
15171
+ function runCase(c, control = "none") {
15172
+ const detected = detectFromCommand(c.command);
15173
+ const filter2 = control === "none" ? detected?.filter : CONTROL_FILTERS[control];
15174
+ const argv = detected?.argv ?? [];
15175
+ const delivery = filter2 ? deliverCompressed(filter2, c.output, "", c.exitCode, argv) : null;
15176
+ const body = delivery ? delivery.text + delivery.marker : c.output;
15177
+ const originalBytes = Buffer.byteLength(c.output, "utf8");
15178
+ const deliveredBytes = Buffer.byteLength(body, "utf8");
15179
+ const missing = c.mustKeep.filter((needle) => !body.includes(needle));
15180
+ return {
15181
+ id: c.id,
15182
+ command: c.command,
15183
+ filter: filter2?.name ?? null,
15184
+ applied: delivery?.applied ?? false,
15185
+ originalBytes,
15186
+ deliveredBytes,
15187
+ savedPercent: originalBytes > 0 ? 100 * Math.max(0, originalBytes - deliveredBytes) / originalBytes : 0,
15188
+ kept: c.mustKeep.length - missing.length,
15189
+ mustKeepTotal: c.mustKeep.length,
15190
+ missing
15191
+ };
15192
+ }
15193
+ function runCorpus(cases, control = "none") {
15194
+ const results = cases.map((c) => runCase(c, control));
15195
+ const sum = (pick) => results.reduce((n, r) => n + pick(r), 0);
15196
+ const originalBytes = sum((r) => r.originalBytes);
15197
+ const deliveredBytes = sum((r) => r.deliveredBytes);
15198
+ const kept = sum((r) => r.kept);
15199
+ const mustKeepTotal = sum((r) => r.mustKeepTotal);
15200
+ return {
15201
+ cases: results,
15202
+ originalBytes,
15203
+ deliveredBytes,
15204
+ ratioPercent: originalBytes > 0 ? 100 * Math.max(0, originalBytes - deliveredBytes) / originalBytes : 0,
15205
+ kept,
15206
+ mustKeepTotal,
15207
+ appliedCases: results.filter((r) => r.applied).length,
15208
+ coveredFilters: new Set(results.map((r) => r.filter).filter((n) => n !== null)).size,
15209
+ registeredFilters: TOOL_FILTERS.length,
15210
+ fidelityIntact: kept === mustKeepTotal
15211
+ };
15212
+ }
15213
+ var pct2 = (n) => `${n.toFixed(1)}%`;
15214
+ function renderTable(report, floorPercent) {
15215
+ const rows = [...report.cases].sort((a, b) => b.originalBytes - a.originalBytes);
15216
+ const idWidth = Math.max(4, ...rows.map((r) => r.id.length));
15217
+ const filterWidth = Math.max(6, ...rows.map((r) => (r.filter ?? "-").length));
15218
+ const lines = [];
15219
+ const header = `${"case".padEnd(idWidth)} ${"filter".padEnd(filterWidth)} ${"in".padStart(9)} ${"out".padStart(9)} ${"saved".padStart(7)} fidelity`;
15220
+ lines.push(header, "-".repeat(header.length));
15221
+ for (const r of rows) {
15222
+ const saved = r.applied ? pct2(r.savedPercent) : "-";
15223
+ const fidelity = `${r.kept}/${r.mustKeepTotal}${r.missing.length ? " FAIL" : ""}`;
15224
+ lines.push(
15225
+ `${r.id.padEnd(idWidth)} ${(r.filter ?? "-").padEnd(filterWidth)} ${String(r.originalBytes).padStart(9)} ${String(r.deliveredBytes).padStart(9)} ${saved.padStart(7)} ${fidelity}`
15226
+ );
15227
+ }
15228
+ lines.push("-".repeat(header.length));
15229
+ lines.push(
15230
+ `${"TOTAL".padEnd(idWidth)} ${"".padEnd(filterWidth)} ${String(report.originalBytes).padStart(9)} ${String(report.deliveredBytes).padStart(9)} ${pct2(report.ratioPercent).padStart(7)} ${report.kept}/${report.mustKeepTotal}`
15231
+ );
15232
+ lines.push("");
15233
+ lines.push(`ratio ${pct2(report.ratioPercent)} saved (PRIMARY -- must improve; measured floor ${pct2(floorPercent)}, headroom ${pct2(100 - report.ratioPercent)})`);
15234
+ lines.push(`fidelity ${report.kept}/${report.mustKeepTotal} kept (GUARD -- must not regress; any miss exits 1)`);
15235
+ lines.push(`coverage ${report.coveredFilters}/${report.registeredFilters} filters exercised, ${report.appliedCases}/${report.cases.length} cases compressed`);
15236
+ for (const r of report.cases) {
15237
+ for (const needle of r.missing) lines.push(` DROPPED ${r.id}: ${JSON.stringify(needle)}`);
15238
+ }
15239
+ return lines.join("\n");
15240
+ }
15241
+ function renderValidation(cases) {
15242
+ const identity = runCorpus(cases, "identity");
15243
+ const destroy = runCorpus(cases, "destroy");
15244
+ const checks = [
15245
+ {
15246
+ // Not "scores exactly 0%": the unapplied path delivers the streams recombined, which can
15247
+ // differ from the captured bytes by a trailing newline. That is a real property of delivery,
15248
+ // so the floor is measured and reported rather than assumed -- what must hold is that the
15249
+ // net-benefit gate REFUSED every no-op rewrite, which is what makes the floor a floor.
15250
+ label: "floor: the net-benefit gate refuses a no-op filter on every case",
15251
+ ok: identity.appliedCases === 0,
15252
+ detail: `identity control applied to ${identity.appliedCases}/${identity.cases.length} cases, measured floor ${pct2(identity.ratioPercent)}`
15253
+ },
15254
+ {
15255
+ label: "floor: a no-op filter keeps every must-keep line",
15256
+ ok: identity.fidelityIntact,
15257
+ detail: `identity control kept ${identity.kept}/${identity.mustKeepTotal}`
15258
+ },
15259
+ {
15260
+ label: "guard: deleting everything is caught",
15261
+ ok: !destroy.fidelityIntact,
15262
+ detail: `destroy control kept ${destroy.kept}/${destroy.mustKeepTotal} at ${pct2(destroy.ratioPercent)} saved`
15263
+ }
15264
+ ];
15265
+ const failed = checks.filter((c) => !c.ok);
15266
+ const lines = checks.map((c) => `${c.ok ? "ok " : "FAIL"} ${c.label} -- ${c.detail}`);
15267
+ lines.push("");
15268
+ lines.push(
15269
+ failed.length === 0 ? "The corpus discriminates: a ratio measured against it cannot be raised by deleting content." : `${failed.length} control check(s) failed. Do not optimise against this corpus until they pass.`
15270
+ );
15271
+ return { text: lines.join("\n"), code: failed.length === 0 ? 0 : 1 };
15272
+ }
15273
+ var TSV_HEADER = "timestamp commit cases original_bytes delivered_bytes ratio_percent fidelity_kept fidelity_total covered_filters\n";
15274
+ function appendTsv(file, report, commit) {
15275
+ const row = [
15276
+ (/* @__PURE__ */ new Date()).toISOString(),
15277
+ commit,
15278
+ report.cases.length,
15279
+ report.originalBytes,
15280
+ report.deliveredBytes,
15281
+ report.ratioPercent.toFixed(2),
15282
+ report.kept,
15283
+ report.mustKeepTotal,
15284
+ report.coveredFilters
15285
+ ].join(" ");
15286
+ const dir = path29.dirname(path29.resolve(file));
15287
+ fs28.mkdirSync(dir, { recursive: true });
15288
+ const header = fs28.existsSync(file) ? "" : TSV_HEADER;
15289
+ fs28.appendFileSync(file, header + row + "\n", "utf8");
15290
+ }
15291
+ function currentCommit(cwd) {
15292
+ const opts = cwd === void 0 ? {} : { cwd };
15293
+ try {
15294
+ const r = runGit(["rev-parse", "--short", "HEAD"], opts);
15295
+ const sha = r.stdout.trim();
15296
+ if (r.exitCode !== 0 || sha === "") return "unknown";
15297
+ const st = runGit(["status", "--porcelain"], opts);
15298
+ return st.exitCode === 0 && st.stdout.trim() !== "" ? `${sha}-dirty` : sha;
15299
+ } catch {
15300
+ return "unknown";
15301
+ }
15302
+ }
15303
+ function runBenchCommand(opts) {
15304
+ const cases = loadCorpus(opts.corpus);
15305
+ if (opts.validate === true) return renderValidation(cases);
15306
+ const report = runCorpus(cases);
15307
+ if (opts.tsv !== void 0) appendTsv(opts.tsv, report, currentCommit());
15308
+ const code = report.fidelityIntact ? 0 : 1;
15309
+ const floorPercent = runCorpus(cases, "identity").ratioPercent;
15310
+ if (opts.json === true) return { text: JSON.stringify({ ...report, floorPercent }, null, 2), code };
15311
+ return { text: renderTable(report, floorPercent), code };
15312
+ }
15313
+
14977
15314
  // src/cli_hint_stats.ts
15315
+ init_define_import_meta_env();
14978
15316
  function formatSpentCell(row) {
14979
15317
  if (row.emitted === 0) return "n/a";
14980
15318
  if (row.bytesEmitted === null) return "n/a (legacy)";
@@ -14984,15 +15322,18 @@ function suppressedCell(row) {
14984
15322
  if (!row.suppressed) return "no";
14985
15323
  return row.suppressionPermanent ? "yes (permanent)" : "yes";
14986
15324
  }
15325
+ function efficacyCell(row) {
15326
+ const pct3 = row.efficacyPct === null ? "n/a" : `${row.efficacyPct}%`;
15327
+ return isSuppressionCategory(row.category) ? `${pct3} *` : pct3;
15328
+ }
14987
15329
  function printSummary(rows) {
14988
15330
  const w = (text) => {
14989
15331
  process.stdout.write(text);
14990
15332
  };
14991
- w(pad("category", 22) + pad("emitted", 9) + pad("acted-on", 10) + pad("efficacy", 10) + pad("suppressed", 17) + pad("manual+", 9) + pad("manual-", 9) + "spent\n");
15333
+ w(pad("category", 22) + pad("emitted", 9) + pad("acted-on", 10) + pad("efficacy", 12) + pad("suppressed", 17) + pad("manual+", 9) + pad("manual-", 9) + "spent\n");
14992
15334
  for (const row of rows) {
14993
- const pct2 = row.efficacyPct === null ? "n/a" : `${row.efficacyPct}%`;
14994
15335
  w(
14995
- pad(row.category, 22) + pad(String(row.emitted), 9) + pad(String(row.actedOn), 10) + pad(pct2, 10) + pad(suppressedCell(row), 17) + pad(String(row.manualEffective), 9) + pad(String(row.manualIneffective), 9) + formatSpentCell(row) + "\n"
15336
+ pad(row.category, 22) + pad(String(row.emitted), 9) + pad(String(row.actedOn), 10) + pad(efficacyCell(row), 12) + pad(suppressedCell(row), 17) + pad(String(row.manualEffective), 9) + pad(String(row.manualIneffective), 9) + formatSpentCell(row) + "\n"
14996
15337
  );
14997
15338
  }
14998
15339
  }
@@ -15033,6 +15374,11 @@ function runHintStatsCommand(opts = {}) {
15033
15374
  process.stdout.write("No hint emissions recorded yet \u2014 the zeros below are absence of data, not measured ineffectiveness.\n");
15034
15375
  }
15035
15376
  printSummary(rows);
15377
+ if (rows.some((r) => isSuppressionCategory(r.category) && r.emitted > 0)) {
15378
+ process.stdout.write(
15379
+ '\n* Scored on an absence: these hints ask the agent NOT to do something, so a window that expires with no re-read counts as compliance. Their percentage is not comparable with the unmarked rows, which only count when the agent runs the command the hint named. A high starred figure means "the warned-against read was not seen", not "this hint persuaded anyone".\n'
15380
+ );
15381
+ }
15036
15382
  const permanent = rows.filter((r) => r.suppressionPermanent);
15037
15383
  if (permanent.length > 0) {
15038
15384
  const names = permanent.map((r) => r.category).join(", ");
@@ -15044,6 +15390,7 @@ hints.backoff_thresholds is empty, so suppression here is permanent rather than
15044
15390
  }
15045
15391
 
15046
15392
  // src/cli_statusline.ts
15393
+ init_define_import_meta_env();
15047
15394
  var STDIN_TIMEOUT_MS = 1500;
15048
15395
  function isPlainObject(v) {
15049
15396
  return typeof v === "object" && v !== null && !Array.isArray(v);
@@ -15137,10 +15484,10 @@ function readBoundedText(text, file) {
15137
15484
  if (text === void 0 && file === void 0) throw new CliError("provide text or --file");
15138
15485
  let value;
15139
15486
  if (file !== void 0) {
15140
- if (fs28.statSync(file).size > CONTENT_MAX_INPUT_CHARS) {
15487
+ if (fs29.statSync(file).size > CONTENT_MAX_INPUT_CHARS) {
15141
15488
  throw new CliError(`file exceeds the ${CONTENT_MAX_INPUT_CHARS}-byte safety limit`);
15142
15489
  }
15143
- value = fs28.readFileSync(file, "utf8");
15490
+ value = fs29.readFileSync(file, "utf8");
15144
15491
  } else {
15145
15492
  if (text === void 0) throw new CliError("provide text or --file");
15146
15493
  value = text;
@@ -15278,7 +15625,7 @@ async function cmdIndex(pathArg, opts = {}) {
15278
15625
  continue;
15279
15626
  }
15280
15627
  const sha = fingerprintFile(key);
15281
- if (sha === null && !fs28.existsSync(key)) continue;
15628
+ if (sha === null && !fs29.existsSync(key)) continue;
15282
15629
  const entry = sha !== null ? getFileEntry(key, dbPath) : null;
15283
15630
  const spellingStale = entry !== null && indexedPathSpellingIsStale(entry.filePath, key);
15284
15631
  const parseUnchanged = !force && !spellingStale && sha !== null && entry?.sha === sha && entry.parserSha === PARSER_FINGERPRINT;
@@ -15304,7 +15651,7 @@ async function cmdIndex(pathArg, opts = {}) {
15304
15651
  }
15305
15652
  continue;
15306
15653
  }
15307
- if (!fs28.existsSync(key)) continue;
15654
+ if (!fs29.existsSync(key)) continue;
15308
15655
  }
15309
15656
  if (!embedUnchanged) {
15310
15657
  paintProgress("embedding");
@@ -15364,8 +15711,8 @@ async function cmdMcpServe() {
15364
15711
  let StdioServerTransport;
15365
15712
  try {
15366
15713
  ;
15367
- ({ createMcpServer } = await import("./token-goat-chunk-LEBYARO3.mjs"));
15368
- ({ StdioServerTransport } = await import("./token-goat-chunk-324QOJYZ.mjs"));
15714
+ ({ createMcpServer } = await import("./token-goat-chunk-OZAEJQ7L.mjs"));
15715
+ ({ StdioServerTransport } = await import("./token-goat-chunk-EVC4TOLE.mjs"));
15369
15716
  } catch (err2) {
15370
15717
  process.stderr.write(
15371
15718
  `token-goat: mcp-server unavailable (could not load the MCP server modules): ${String(err2)}
@@ -15377,8 +15724,8 @@ async function cmdMcpServe() {
15377
15724
  const server = await createMcpServer();
15378
15725
  const transport = new StdioServerTransport();
15379
15726
  await server.connect(transport);
15380
- await new Promise((resolve14) => {
15381
- server.onclose = resolve14;
15727
+ await new Promise((resolve15) => {
15728
+ server.onclose = resolve15;
15382
15729
  });
15383
15730
  }
15384
15731
  function printBridgeVerificationNotice(harness) {
@@ -15389,7 +15736,7 @@ async function cmdHook(event, opts) {
15389
15736
  if (typeof opts.harness === "string" && opts.harness.length > 0) {
15390
15737
  process.env[ENV_KEYS.HARNESS_OVERRIDE] = opts.harness;
15391
15738
  }
15392
- const { relay } = await import("./token-goat-chunk-ZVN5WHTO.mjs");
15739
+ const { relay } = await import("./token-goat-chunk-EQKNR7CN.mjs");
15393
15740
  await relay(event);
15394
15741
  }
15395
15742
  async function cmdInstall(opts) {
@@ -15502,16 +15849,16 @@ async function cmdInstall(opts) {
15502
15849
  );
15503
15850
  }
15504
15851
  try {
15505
- const skillDir = path29.join(homedir13(), ".claude", "skills");
15506
- if (fs28.existsSync(skillDir)) {
15507
- const entries = fs28.readdirSync(skillDir, { withFileTypes: true });
15852
+ const skillDir = path30.join(homedir13(), ".claude", "skills");
15853
+ if (fs29.existsSync(skillDir)) {
15854
+ const entries = fs29.readdirSync(skillDir, { withFileTypes: true });
15508
15855
  const skillNames = [];
15509
15856
  const sessionId = getSessionId();
15510
15857
  for (const entry of entries) {
15511
15858
  if (!entry.isDirectory()) continue;
15512
- const skillFile = path29.join(skillDir, entry.name, "SKILL.md");
15513
- if (fs28.existsSync(skillFile)) {
15514
- const body = fs28.readFileSync(skillFile, "utf-8");
15859
+ const skillFile = path30.join(skillDir, entry.name, "SKILL.md");
15860
+ if (fs29.existsSync(skillFile)) {
15861
+ const body = fs29.readFileSync(skillFile, "utf-8");
15515
15862
  const compact = extractCompactFromMarker(body);
15516
15863
  if (compact === null) continue;
15517
15864
  const sourceSha = contentHash(body);
@@ -15521,10 +15868,10 @@ async function cmdInstall(opts) {
15521
15868
  }
15522
15869
  if (skillNames.length > 0) {
15523
15870
  const dir = skillOutputsDir();
15524
- await fs28.promises.mkdir(dir, { recursive: true });
15525
- const pregenPath = path29.join(dir, "pregen.json");
15871
+ await fs29.promises.mkdir(dir, { recursive: true });
15872
+ const pregenPath = path30.join(dir, "pregen.json");
15526
15873
  const pregenData = { ts: Date.now(), names: skillNames };
15527
- await fs28.promises.writeFile(pregenPath, JSON.stringify(pregenData, null, 2));
15874
+ await fs29.promises.writeFile(pregenPath, JSON.stringify(pregenData, null, 2));
15528
15875
  out(`Pre-generated ${skillNames.length} skill compacts.`);
15529
15876
  }
15530
15877
  }
@@ -15728,7 +16075,7 @@ ${formatSessionOutline(turns)}`;
15728
16075
  }
15729
16076
  function sessionTranscriptSize(transcriptPath) {
15730
16077
  try {
15731
- return fs28.statSync(transcriptPath).size;
16078
+ return fs29.statSync(transcriptPath).size;
15732
16079
  } catch {
15733
16080
  return 0;
15734
16081
  }
@@ -15858,7 +16205,7 @@ function fenceFileFieldIfMatched(text) {
15858
16205
  }
15859
16206
  function fileSizeOrZero(filePath) {
15860
16207
  try {
15861
- return fs28.statSync(filePath).size;
16208
+ return fs29.statSync(filePath).size;
15862
16209
  } catch {
15863
16210
  return 0;
15864
16211
  }
@@ -15873,11 +16220,11 @@ function cmdBashOutput(id, opts) {
15873
16220
  }
15874
16221
  let content;
15875
16222
  try {
15876
- const st = fs28.statSync(opts.file);
16223
+ const st = fs29.statSync(opts.file);
15877
16224
  if (st.isFIFO() || st.isSocket()) {
15878
16225
  throw new CliError(`--file '${opts.file}' is a special file (FIFO or socket) \u2014 only regular files are supported`);
15879
16226
  }
15880
- content = redactIfDotenv(opts.file, decodeSource(fs28.readFileSync(opts.file)));
16227
+ content = redactIfDotenv(opts.file, decodeSource(fs29.readFileSync(opts.file)));
15881
16228
  } catch (e) {
15882
16229
  if (e instanceof CliError) throw e;
15883
16230
  throw new CliError(`cannot read file: ${opts.file}`);
@@ -15986,9 +16333,9 @@ async function cmdPdfMeta(file, opts = {}) {
15986
16333
  }
15987
16334
  async function cmdImageMeta(file, opts = {}) {
15988
16335
  const meta = await runImageMeta(file);
15989
- if (!meta.sharpAvailable) {
15990
- const msg = "image-meta unavailable (install sharp to use this feature)";
15991
- const text2 = opts.json === true ? JSON.stringify({ bytes: meta.bytes, sharpAvailable: false, error: msg }, null, 2) : `Size: ${meta.bytes} bytes
16336
+ if (!meta.decodable) {
16337
+ const msg = "image-meta unavailable (not a format token-goat can read)";
16338
+ const text2 = opts.json === true ? JSON.stringify({ bytes: meta.bytes, decodable: false, error: msg }, null, 2) : `Size: ${meta.bytes} bytes
15992
16339
  ${msg}`;
15993
16340
  out(text2);
15994
16341
  return;
@@ -16287,7 +16634,7 @@ function readStdinPaths() {
16287
16634
  }
16288
16635
  let raw;
16289
16636
  try {
16290
- raw = fs28.readFileSync(0, "utf8");
16637
+ raw = fs29.readFileSync(0, "utf8");
16291
16638
  } catch (e) {
16292
16639
  throw new CliError(`could not read the file list from stdin: ${extractErrorMessage(e)}`);
16293
16640
  }
@@ -16323,7 +16670,7 @@ function emitExtraFileArgsNote(command, first, extras, opts = {}) {
16323
16670
  }
16324
16671
  async function cmdCompress(opts) {
16325
16672
  try {
16326
- const bashRunner = await import("./token-goat-chunk-NY4HYRSK.mjs");
16673
+ const bashRunner = await import("./token-goat-chunk-5BHXZEOI.mjs");
16327
16674
  if (opts.compress === false) {
16328
16675
  process.exitCode = bashRunner.runRaw(opts.cmd, parseTimeout(opts.timeout, bashRunner.DEFAULT_TIMEOUT_SECONDS));
16329
16676
  return;
@@ -16349,7 +16696,7 @@ async function cmdSkillBody(name, opts) {
16349
16696
  if (filePath === null) {
16350
16697
  throw new CliError(`skill '${name}' not found`);
16351
16698
  }
16352
- const body = decodeSource(fs28.readFileSync(filePath));
16699
+ const body = decodeSource(fs29.readFileSync(filePath));
16353
16700
  if (opts.compact === true) {
16354
16701
  const emitted = extractCompactFromMarker(body) ?? body;
16355
16702
  out(emitted);
@@ -16376,7 +16723,7 @@ async function cmdSkillCompact(name, opts) {
16376
16723
  }
16377
16724
  let body2;
16378
16725
  try {
16379
- body2 = decodeSource(fs28.readFileSync(filePath));
16726
+ body2 = decodeSource(fs29.readFileSync(filePath));
16380
16727
  } catch {
16381
16728
  unresolvable++;
16382
16729
  continue;
@@ -16410,19 +16757,19 @@ async function cmdSkillCompact(name, opts) {
16410
16757
  if (!opts.path.trim()) {
16411
16758
  throw new CliError("--path cannot be empty");
16412
16759
  }
16413
- if (!fs28.existsSync(opts.path)) {
16760
+ if (!fs29.existsSync(opts.path)) {
16414
16761
  throw new CliError(`skill file not found: ${opts.path}`);
16415
16762
  }
16416
16763
  try {
16417
- body = fs28.readFileSync(opts.path, "utf-8");
16764
+ body = fs29.readFileSync(opts.path, "utf-8");
16418
16765
  } catch (e) {
16419
16766
  if (e.code === "ENOENT") {
16420
16767
  throw new CliError(`skill file not found: ${opts.path}`);
16421
16768
  }
16422
16769
  throw new CliError(`failed to read skill file '${opts.path}': ${extractErrorMessage(e)}`);
16423
16770
  }
16424
- cacheName = name ?? path29.basename(path29.dirname(path29.resolve(opts.path)));
16425
- sourcePath = path29.resolve(opts.path);
16771
+ cacheName = name ?? path30.basename(path30.dirname(path30.resolve(opts.path)));
16772
+ sourcePath = path30.resolve(opts.path);
16426
16773
  } else {
16427
16774
  if (name === void 0 || !name.trim()) {
16428
16775
  throw new CliError("skill-compact requires a <name> or --path <file>");
@@ -16431,7 +16778,7 @@ async function cmdSkillCompact(name, opts) {
16431
16778
  if (filePath === null) {
16432
16779
  throw new CliError(`skill '${name}' not found`);
16433
16780
  }
16434
- body = fs28.readFileSync(filePath, "utf-8");
16781
+ body = fs29.readFileSync(filePath, "utf-8");
16435
16782
  cacheName = name;
16436
16783
  sourcePath = filePath;
16437
16784
  }
@@ -16563,8 +16910,8 @@ async function cmdSkillDiff(name) {
16563
16910
  }
16564
16911
  const newer = versions[0];
16565
16912
  const older = versions[1];
16566
- const newerBody = await fs28.promises.readFile(path29.resolve(dir, `${newer.outputId}.txt`), "utf-8").catch(() => null);
16567
- const olderBody = await fs28.promises.readFile(path29.resolve(dir, `${older.outputId}.txt`), "utf-8").catch(() => null);
16913
+ const newerBody = await fs29.promises.readFile(path30.resolve(dir, `${newer.outputId}.txt`), "utf-8").catch(() => null);
16914
+ const olderBody = await fs29.promises.readFile(path30.resolve(dir, `${older.outputId}.txt`), "utf-8").catch(() => null);
16568
16915
  if (newerBody === null || olderBody === null) {
16569
16916
  out(`a cached version of '${name}' was evicted while diffing -- try again`);
16570
16917
  return;
@@ -16593,7 +16940,7 @@ async function cmdSkillSection(nameHeading, headingArg) {
16593
16940
  if (!filePath) {
16594
16941
  throw new CliError(`skill '${skillName}' not found`);
16595
16942
  }
16596
- const body = decodeSource(fs28.readFileSync(filePath));
16943
+ const body = decodeSource(fs29.readFileSync(filePath));
16597
16944
  const extracted = extractNamedSection(body, heading);
16598
16945
  if (!extracted) {
16599
16946
  const messages = [`Section '${heading}' not found in skill '${skillName}'`];
@@ -16608,7 +16955,7 @@ async function cmdSkillSection(nameHeading, headingArg) {
16608
16955
  }
16609
16956
  function atomicWriteBuffer(dest, data) {
16610
16957
  try {
16611
- if (fs28.statSync(dest).isDirectory()) {
16958
+ if (fs29.statSync(dest).isDirectory()) {
16612
16959
  const e = Object.assign(new Error(`EISDIR: illegal operation on a directory, open '${dest}'`), { code: "EISDIR", path: dest });
16613
16960
  throw e;
16614
16961
  }
@@ -16616,23 +16963,23 @@ function atomicWriteBuffer(dest, data) {
16616
16963
  if (e.code !== "ENOENT") throw e;
16617
16964
  }
16618
16965
  const rnd = randomBytes(4).toString("hex");
16619
- const tmp = path29.join(path29.dirname(path29.resolve(dest)), `.tmp.${process.pid}.${rnd}`);
16966
+ const tmp = path30.join(path30.dirname(path30.resolve(dest)), `.tmp.${process.pid}.${rnd}`);
16620
16967
  try {
16621
- fs28.writeFileSync(tmp, data, { mode: 384 });
16968
+ fs29.writeFileSync(tmp, data, { mode: 384 });
16622
16969
  try {
16623
- const destMode = fs28.statSync(dest).mode;
16624
- fs28.chmodSync(tmp, destMode);
16970
+ const destMode = fs29.statSync(dest).mode;
16971
+ fs29.chmodSync(tmp, destMode);
16625
16972
  } catch (e) {
16626
16973
  if (e.code !== "ENOENT") throw e;
16627
16974
  }
16628
16975
  withRetryOnLock(() => {
16629
16976
  try {
16630
- fs28.renameSync(tmp, dest);
16977
+ fs29.renameSync(tmp, dest);
16631
16978
  } catch (e) {
16632
16979
  if (e.code === "EXDEV") {
16633
- fs28.copyFileSync(tmp, dest);
16980
+ fs29.copyFileSync(tmp, dest);
16634
16981
  try {
16635
- fs28.unlinkSync(tmp);
16982
+ fs29.unlinkSync(tmp);
16636
16983
  } catch (ue) {
16637
16984
  process.stderr.write(`token-goat write-file: warning: could not remove temp file ${tmp}: ${ue.message}
16638
16985
  `);
@@ -16644,7 +16991,7 @@ function atomicWriteBuffer(dest, data) {
16644
16991
  });
16645
16992
  } catch (e) {
16646
16993
  try {
16647
- fs28.unlinkSync(tmp);
16994
+ fs29.unlinkSync(tmp);
16648
16995
  } catch {
16649
16996
  }
16650
16997
  throw e;
@@ -16654,9 +17001,9 @@ function mapFsError(e, src, dest, srcLabel = "source") {
16654
17001
  const fe = e;
16655
17002
  if (fe.code === "ENOENT") {
16656
17003
  const errPath = fe.path ?? "";
16657
- const isSource = src !== void 0 && path29.resolve(errPath) === path29.resolve(src);
17004
+ const isSource = src !== void 0 && path30.resolve(errPath) === path30.resolve(src);
16658
17005
  if (isSource) throw new CliError(`${/\bfile$/i.test(srcLabel) ? srcLabel : `${srcLabel} file`} not found: ${src}`);
16659
- const destDir = dest ? path29.dirname(path29.resolve(dest)) : path29.dirname(path29.resolve(errPath || "."));
17006
+ const destDir = dest ? path30.dirname(path30.resolve(dest)) : path30.dirname(path30.resolve(errPath || "."));
16660
17007
  throw new CliError(`destination directory does not exist: ${destDir}`);
16661
17008
  }
16662
17009
  if (fe.code === "ENOTDIR") {
@@ -16667,7 +17014,7 @@ function mapFsError(e, src, dest, srcLabel = "source") {
16667
17014
  }
16668
17015
  if (fe.code === "EISDIR") {
16669
17016
  const errPath = fe.path ?? "";
16670
- const isSource = src !== void 0 && (errPath === "" || path29.resolve(errPath) === path29.resolve(src));
17017
+ const isSource = src !== void 0 && (errPath === "" || path30.resolve(errPath) === path30.resolve(src));
16671
17018
  if (isSource) throw new CliError(`source is a directory, not a file: ${src}`);
16672
17019
  throw new CliError(`destination is a directory, not a file: ${dest ?? (errPath || "(unknown)")}`);
16673
17020
  }
@@ -16736,7 +17083,7 @@ function validateWritablePath(dest, label) {
16736
17083
  throw new CliError(`${label} path contains a null byte`);
16737
17084
  }
16738
17085
  if (isWindows()) {
16739
- const base = path29.basename(dest);
17086
+ const base = path30.basename(dest);
16740
17087
  const stem = base.replace(/\.[^.]*$/, "").toUpperCase();
16741
17088
  if (WIN_RESERVED.has(stem)) {
16742
17089
  throw new CliError(`${label} '${base}' is a reserved Windows device name`);
@@ -16766,7 +17113,7 @@ function readFileBoundedRaw(filePath, label, allowStdIn = false) {
16766
17113
  throw new CliError(`${label} ${filePath} requires piped input; use ${altLabel} for interactive use`);
16767
17114
  }
16768
17115
  try {
16769
- const st = fs28.statSync(filePath);
17116
+ const st = fs29.statSync(filePath);
16770
17117
  if (st.isFIFO() || st.isSocket()) {
16771
17118
  throw new CliError(`${label} '${filePath}' is a special file (FIFO or socket) \u2014 only regular files are supported`);
16772
17119
  }
@@ -16774,7 +17121,7 @@ function readFileBoundedRaw(filePath, label, allowStdIn = false) {
16774
17121
  if (st.size > maxBytes) {
16775
17122
  throw new CliError(`${label} '${filePath}' exceeds size limit (${Math.round(st.size / 1024 / 1024)} MB); set TOKEN_GOAT_MAX_STDIN_MB to override`);
16776
17123
  }
16777
- return fs28.readFileSync(filePath);
17124
+ return fs29.readFileSync(filePath);
16778
17125
  } catch (e) {
16779
17126
  if (e instanceof CliError) throw e;
16780
17127
  mapFsError(e, filePath, void 0, label);
@@ -16818,7 +17165,7 @@ function cmdNoteAdd(file, opts) {
16818
17165
  throw new CliError("note content must be valid UTF-8 text");
16819
17166
  }
16820
17167
  const resolvedPath = resolveIndexPath(file);
16821
- if (!fs28.existsSync(resolvedPath)) {
17168
+ if (!fs29.existsSync(resolvedPath)) {
16822
17169
  throw new CliError(`File not found: '${resolvedPath}'`);
16823
17170
  }
16824
17171
  healStaleIndex(resolvedPath);
@@ -16877,7 +17224,7 @@ function cmdWriteFile(dest, opts) {
16877
17224
  throw new CliError(`TOKEN_GOAT_MAX_STDIN_MB must be a positive integer; got '${process.env["TOKEN_GOAT_MAX_STDIN_MB"] ?? ""}'`);
16878
17225
  }
16879
17226
  const maxBytes = maxMB * 1024 * 1024;
16880
- return new Promise((resolve14, reject) => {
17227
+ return new Promise((resolve15, reject) => {
16881
17228
  const chunks = [];
16882
17229
  let totalBytes = 0;
16883
17230
  let settled = false;
@@ -16901,7 +17248,7 @@ function cmdWriteFile(dest, opts) {
16901
17248
  try {
16902
17249
  atomicWriteBuffer(dest, Buffer.concat(chunks));
16903
17250
  enqueueDirtyPathSafe(dest);
16904
- resolve14();
17251
+ resolve15();
16905
17252
  } catch (e) {
16906
17253
  try {
16907
17254
  mapFsError(e, void 0, dest);
@@ -17032,14 +17379,14 @@ function writeReplacedBuffer(file, replacedBuf, preWriteStat) {
17032
17379
  const until = process.env["TOKEN_GOAT_TEST_REPLACE_DELAY_UNTIL"];
17033
17380
  const deadline = Date.now() + testDelayMs;
17034
17381
  if (until !== void 0 && until !== "") {
17035
- while (Date.now() < deadline && !fs28.existsSync(until)) sleepSync(5);
17382
+ while (Date.now() < deadline && !fs29.existsSync(until)) sleepSync(5);
17036
17383
  } else {
17037
17384
  sleepSync(testDelayMs);
17038
17385
  }
17039
17386
  }
17040
17387
  let preRenameStat;
17041
17388
  try {
17042
- preRenameStat = fs28.statSync(file);
17389
+ preRenameStat = fs29.statSync(file);
17043
17390
  } catch {
17044
17391
  }
17045
17392
  if (preRenameStat !== void 0 && (preRenameStat.mtimeMs !== preWriteStat.mtimeMs || preRenameStat.size !== preWriteStat.size)) {
@@ -17080,7 +17427,7 @@ function cmdReplace(file, opts) {
17080
17427
  const targetBuf = readFileBoundedRaw(file, "target file", true);
17081
17428
  let preWriteStat;
17082
17429
  try {
17083
- preWriteStat = fs28.statSync(file);
17430
+ preWriteStat = fs29.statSync(file);
17084
17431
  } catch {
17085
17432
  }
17086
17433
  const usingFrom = opts.oldFrom !== void 0 || opts.newFrom !== void 0;
@@ -17174,7 +17521,7 @@ function cmdInsertSection(file, opts) {
17174
17521
  }
17175
17522
  let preWriteStat;
17176
17523
  try {
17177
- preWriteStat = fs28.statSync(file);
17524
+ preWriteStat = fs29.statSync(file);
17178
17525
  } catch {
17179
17526
  }
17180
17527
  const result = readSection(file, opts.after);
@@ -17200,7 +17547,7 @@ function cmdInsertSection(file, opts) {
17200
17547
  }
17201
17548
  let rawBytes;
17202
17549
  try {
17203
- rawBytes = fs28.readFileSync(file);
17550
+ rawBytes = fs29.readFileSync(file);
17204
17551
  } catch (e) {
17205
17552
  mapFsError(e, void 0, file);
17206
17553
  }
@@ -17216,7 +17563,7 @@ function cmdInsertSection(file, opts) {
17216
17563
  if (preWriteStat !== void 0) {
17217
17564
  let preRenameStat;
17218
17565
  try {
17219
- preRenameStat = fs28.statSync(file);
17566
+ preRenameStat = fs29.statSync(file);
17220
17567
  } catch {
17221
17568
  }
17222
17569
  if (preRenameStat !== void 0 && (preRenameStat.mtimeMs !== preWriteStat.mtimeMs || preRenameStat.size !== preWriteStat.size)) {
@@ -17258,25 +17605,25 @@ ${content}`;
17258
17605
  }
17259
17606
  function expandGlobs(root, patterns, globFnOverride) {
17260
17607
  const out2 = [];
17261
- const globFn = globFnOverride ?? fs28["globSync"];
17608
+ const globFn = globFnOverride ?? fs29["globSync"];
17262
17609
  for (const p of patterns) {
17263
17610
  if (globFn !== void 0 && (p.includes("*") || p.includes("?") || p.includes("{"))) {
17264
17611
  try {
17265
17612
  const hits = globFn(p, { cwd: root });
17266
- for (const h of hits) out2.push(path29.isAbsolute(h) ? h : path29.join(root, h));
17613
+ for (const h of hits) out2.push(path30.isAbsolute(h) ? h : path30.join(root, h));
17267
17614
  continue;
17268
17615
  } catch {
17269
17616
  }
17270
17617
  }
17271
- out2.push(path29.isAbsolute(p) ? p : path29.join(root, p));
17618
+ out2.push(path30.isAbsolute(p) ? p : path30.join(root, p));
17272
17619
  }
17273
17620
  return out2;
17274
17621
  }
17275
17622
  function readIgnoreFile(root) {
17276
- const ignorePath = path29.join(root, ".tokengoatignore");
17623
+ const ignorePath = path30.join(root, ".tokengoatignore");
17277
17624
  let raw;
17278
17625
  try {
17279
- raw = fs28.readFileSync(ignorePath, "utf8");
17626
+ raw = fs29.readFileSync(ignorePath, "utf8");
17280
17627
  } catch {
17281
17628
  return void 0;
17282
17629
  }
@@ -17317,14 +17664,14 @@ function cmdPack(patterns, opts) {
17317
17664
  }
17318
17665
  let instruction;
17319
17666
  if (opts.instructionFile !== void 0) {
17320
- instruction = fs28.readFileSync(opts.instructionFile, "utf8");
17667
+ instruction = fs29.readFileSync(opts.instructionFile, "utf8");
17321
17668
  }
17322
17669
  const formatted = formatPack(result, style, {
17323
17670
  ...opts.lineNumbers === true ? { line_numbers: true } : {},
17324
17671
  ...instruction !== void 0 ? { instruction } : {}
17325
17672
  });
17326
17673
  if (opts.output !== void 0) {
17327
- fs28.writeFileSync(opts.output, formatted, "utf8");
17674
+ fs29.writeFileSync(opts.output, formatted, "utf8");
17328
17675
  } else {
17329
17676
  out(formatted);
17330
17677
  }
@@ -17344,17 +17691,17 @@ function cmdTokens(patterns, opts) {
17344
17691
  if (opts.tree === true) {
17345
17692
  const dirs = /* @__PURE__ */ new Map();
17346
17693
  for (const e of entries) {
17347
- const dir = path29.dirname(e.rel_path);
17694
+ const dir = path30.dirname(e.rel_path);
17348
17695
  if (!dirs.has(dir)) dirs.set(dir, []);
17349
17696
  dirs.get(dir).push(e);
17350
17697
  }
17351
17698
  const lines2 = [];
17352
17699
  for (const [dir, dirEntries] of dirs) {
17353
17700
  const dirTokens = dirEntries.reduce((s, e) => s + e.tokens, 0);
17354
- const pct2 = result.total_tokens > 0 ? Math.round(dirTokens / result.total_tokens * 100) : 0;
17355
- lines2.push(`${dir}/ (${dirTokens} tokens, ${pct2}%)`);
17701
+ const pct3 = result.total_tokens > 0 ? Math.round(dirTokens / result.total_tokens * 100) : 0;
17702
+ lines2.push(`${dir}/ (${dirTokens} tokens, ${pct3}%)`);
17356
17703
  for (const e of dirEntries) {
17357
- lines2.push(` ${path29.basename(e.rel_path).padEnd(30)} ${String(e.tokens).padStart(8)} tokens`);
17704
+ lines2.push(` ${path30.basename(e.rel_path).padEnd(30)} ${String(e.tokens).padStart(8)} tokens`);
17358
17705
  }
17359
17706
  }
17360
17707
  out(lines2.join("\n"));
@@ -17388,7 +17735,7 @@ function cmdBudget(patterns, opts) {
17388
17735
  }
17389
17736
  }
17390
17737
  function cmdFailures(src, opts) {
17391
- const text = src !== void 0 ? fs28.readFileSync(src, "utf8") : fs28.readFileSync(0, "utf8");
17738
+ const text = src !== void 0 ? fs29.readFileSync(src, "utf8") : fs29.readFileSync(0, "utf8");
17392
17739
  const result = extractFailures(text, opts.runner !== void 0 ? { runner: opts.runner } : {});
17393
17740
  if (opts.delta !== true) {
17394
17741
  out(opts.json === true ? formatFailuresJson(result) : formatFailuresText(result));
@@ -17442,7 +17789,7 @@ function generateCompactHelp() {
17442
17789
  "",
17443
17790
  "Compression: compress-text, retrieve, handoff-create, handoff-resolve,",
17444
17791
  " compress, recall, bash-output, web-output, mcp-output, compress-text,",
17445
- " compress",
17792
+ " compress, bench",
17446
17793
  "",
17447
17794
  "Config & Integration: install, uninstall, mcp-serve, mcp-status, hook,",
17448
17795
  " bridges-status, worker, statusline, version, config, config-get,",
@@ -17628,6 +17975,16 @@ function buildProgram() {
17628
17975
  program2.command("bridges-status").description("hook-event parity matrix across every AI-harness bridge (read-only static analysis, never invokes a real harness binary)").option("--json", "emit the matrix as JSON instead of text").action(guard(cmdBridgesStatus));
17629
17976
  program2.command("commands").description("machine-readable manifest of every registered command, its options, and its arguments").option("--json", "emit the manifest as JSON instead of text").option("--grep <pattern>", "filter to commands whose name, description, or aliases match this regex").action(guard(cmdCommands));
17630
17977
  program2.command("mcp-serve").description("run token-goat as an MCP stdio server exposing surgical reads and local compression/handoff tools").action(guard(cmdMcpServe));
17978
+ program2.command("bench").description("replay a corpus of captured command output through the compressors; prints the byte savings ratio and a fidelity check, and exits 1 when a must-keep line was dropped").option("--corpus <dir>", "corpus directory (default: tests/fixtures/bench, relative to the working directory)").option("--tsv <path>", "append one result row, keyed by the current commit, creating the file and its header if absent").option("--validate", "score the corpus with control filters instead: proves the ratio has a floor and the fidelity guard can actually fail").option("-j, --json", "output as JSON").action(
17979
+ (opts) => runExitText(
17980
+ () => runBenchCommand({
17981
+ corpus: opts.corpus ?? path30.join("tests", "fixtures", "bench"),
17982
+ ...opts.tsv !== void 0 ? { tsv: opts.tsv } : {},
17983
+ ...opts.validate === true ? { validate: true } : {},
17984
+ ...opts.json === true ? { json: true } : {}
17985
+ })
17986
+ )
17987
+ );
17631
17988
  program2.command("compress-text [text]").description("compress arbitrary local text and print an opaque recovery ID plus compact payload").option("--file <path>", "read text from a local file instead of the argument").option("--payload", "always print the compact payload, even when inlining it costs more tokens than the original text").action(guard(cmdContentCompress));
17632
17989
  program2.command("retrieve <id>").description("retrieve original text previously stored by token-goat compress").option("--head <n>", "show first N lines").option("--tail <n>", "show last N lines").option("--grep <pattern>", "filter lines matching regex").option("--max-matches <n>", "cap --grep output to the first N matching lines").option("--section <heading>", "extract a specific section from the retrieved text").option("--full", "print the entire retrieved text with no head/tail elision (default behaviour when no other flag is given)").action(guard(cmdRetrieve));
17633
17990
  program2.command("handoff-create <name> [text]").description("create a project-local named compressed handoff").option("--file <path>", "read handoff text from a local file instead of the argument").action(guard(cmdHandoffCreate));
@@ -18076,7 +18433,7 @@ async function run(argv = process.argv) {
18076
18433
  return;
18077
18434
  }
18078
18435
  if (argv[2] === "--batch-serve" && typeof argv[3] === "string") {
18079
- const { serveBatch } = await import("./token-goat-chunk-G6XLWJWI.mjs");
18436
+ const { serveBatch } = await import("./token-goat-chunk-E3K3BTEQ.mjs");
18080
18437
  serveBatch(argv[3], (a) => run(a));
18081
18438
  return;
18082
18439
  }