token-goat 2.9.1 → 2.9.3
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.
- package/README.md +38 -765
- package/SECURITY.md +1 -1
- package/dist/{token-goat-chunk-RRNRPCLX.mjs → token-goat-chunk-2VVXTAGD.mjs} +192 -16
- package/dist/{token-goat-chunk-CD6U5OD6.mjs → token-goat-chunk-3UBORD6Z.mjs} +9 -6
- package/dist/{token-goat-chunk-FDXINYK4.mjs → token-goat-chunk-3XVGPLDS.mjs} +3592 -63
- package/dist/{token-goat-chunk-SQSB5P5P.mjs → token-goat-chunk-6FQMEMWX.mjs} +583 -107
- package/dist/{token-goat-chunk-SXSWQMNP.mjs → token-goat-chunk-7A7SBE6R.mjs} +166 -72
- package/dist/token-goat-chunk-A37V4PBF.mjs +56 -0
- package/dist/{token-goat-chunk-MR7MNSDR.mjs → token-goat-chunk-A4VBNWSL.mjs} +20 -3
- package/dist/{token-goat-chunk-G6XLWJWI.mjs → token-goat-chunk-E3K3BTEQ.mjs} +5 -2
- package/dist/{token-goat-chunk-AO2QD2AG.mjs → token-goat-chunk-EEIDFMEM.mjs} +4 -0
- package/dist/{token-goat-chunk-324QOJYZ.mjs → token-goat-chunk-EVC4TOLE.mjs} +4 -1
- package/dist/{token-goat-chunk-WN5T5EW5.mjs → token-goat-chunk-FQD3OB5W.mjs} +98 -2
- package/dist/token-goat-chunk-HC5NMGPD.mjs +23 -0
- package/dist/{token-goat-chunk-4ZDRTNGV.mjs → token-goat-chunk-KKHKXUVS.mjs} +317 -32
- package/dist/{token-goat-chunk-4KD2N46D.mjs → token-goat-chunk-LLNA42NI.mjs} +10 -12
- package/dist/{token-goat-chunk-5CVKO3DA.mjs → token-goat-chunk-LYWIRYCF.mjs} +5 -2
- package/dist/{token-goat-chunk-LHMC5ENL.mjs → token-goat-chunk-OKJX2JWW.mjs} +6 -1
- package/dist/{token-goat-chunk-R4SR7MQY.mjs → token-goat-chunk-PXWBHSFB.mjs} +2 -2
- package/dist/{token-goat-chunk-V5T3YNYR.mjs → token-goat-chunk-XSSQFI4C.mjs} +7 -7
- package/dist/token-goat-hook.mjs +12 -7
- package/dist/token-goat.core.mjs +10 -7
- package/docs/C4_RUNTIME_ARCHITECTURE.md +303 -0
- package/docs/cli.md +392 -0
- package/docs/install.md +331 -0
- package/docs/security.md +106 -0
- package/package.json +14 -3
- package/dist/token-goat-chunk-AEX54RUZ.mjs +0 -11
- package/dist/token-goat-chunk-AUM22UQ2.mjs +0 -23
|
@@ -86,7 +86,7 @@ import {
|
|
|
86
86
|
runZipRead,
|
|
87
87
|
symbolNamesInFile,
|
|
88
88
|
upsertNote
|
|
89
|
-
} from "./token-goat-chunk-
|
|
89
|
+
} from "./token-goat-chunk-7A7SBE6R.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-
|
|
111
|
+
} from "./token-goat-chunk-A4VBNWSL.mjs";
|
|
112
112
|
import {
|
|
113
113
|
AGENT_SALT_MARKER,
|
|
114
114
|
BASH_OUTPUT_SUBDIR,
|
|
@@ -238,15 +238,20 @@ import {
|
|
|
238
238
|
visionTokensSavedByText,
|
|
239
239
|
walkProject,
|
|
240
240
|
writeCompact
|
|
241
|
-
} from "./token-goat-chunk-
|
|
241
|
+
} from "./token-goat-chunk-3XVGPLDS.mjs";
|
|
242
242
|
import {
|
|
243
243
|
C,
|
|
244
244
|
CONFIG_KEY_ENV_OVERRIDES,
|
|
245
|
+
CompressedOutput,
|
|
245
246
|
ENV_KEYS,
|
|
246
247
|
FILTERS,
|
|
247
248
|
LOCK_WAIT_MS_HARDENED,
|
|
248
249
|
MATERIALIZE_SHRUNK_IMAGE_JS,
|
|
250
|
+
PROJECT_LOCKED_KEYS,
|
|
251
|
+
PROJECT_LOCKED_SECTIONS,
|
|
249
252
|
RESET,
|
|
253
|
+
TOOL_FILTERS,
|
|
254
|
+
ToolFilter,
|
|
250
255
|
VERSION,
|
|
251
256
|
_useRichStats,
|
|
252
257
|
anchoredMarkerPattern,
|
|
@@ -255,6 +260,8 @@ import {
|
|
|
255
260
|
canonicalize,
|
|
256
261
|
cappedSourceBytesSaved,
|
|
257
262
|
colorStdout,
|
|
263
|
+
combineStreams,
|
|
264
|
+
compileCustomPatterns,
|
|
258
265
|
configPath,
|
|
259
266
|
copilotCliConfigPath,
|
|
260
267
|
copilotCliMcpToolsDir,
|
|
@@ -264,11 +271,14 @@ import {
|
|
|
264
271
|
dataDir,
|
|
265
272
|
decodeSource,
|
|
266
273
|
defaultConfig,
|
|
274
|
+
deliverCompressed,
|
|
275
|
+
detectFromCommand,
|
|
267
276
|
detectLanguage,
|
|
268
277
|
detectSourceEncoding,
|
|
269
278
|
encodeSource,
|
|
270
279
|
ensureDirSync,
|
|
271
280
|
ensureNewline,
|
|
281
|
+
envBool,
|
|
272
282
|
escapeRegExp,
|
|
273
283
|
extractErrorMessage,
|
|
274
284
|
fg,
|
|
@@ -354,15 +364,24 @@ import {
|
|
|
354
364
|
withFileLock,
|
|
355
365
|
withRetryOnLock,
|
|
356
366
|
writeJsonSettings
|
|
357
|
-
} from "./token-goat-chunk-
|
|
367
|
+
} from "./token-goat-chunk-KKHKXUVS.mjs";
|
|
358
368
|
import {
|
|
359
|
-
__export
|
|
360
|
-
|
|
369
|
+
__export,
|
|
370
|
+
init_define_import_meta_env
|
|
371
|
+
} from "./token-goat-chunk-A37V4PBF.mjs";
|
|
361
372
|
|
|
362
373
|
// src/cli.ts
|
|
374
|
+
init_define_import_meta_env();
|
|
363
375
|
import { randomBytes } from "node:crypto";
|
|
364
376
|
|
|
377
|
+
// node_modules/commander/index.js
|
|
378
|
+
init_define_import_meta_env();
|
|
379
|
+
|
|
380
|
+
// node_modules/commander/lib/argument.js
|
|
381
|
+
init_define_import_meta_env();
|
|
382
|
+
|
|
365
383
|
// node_modules/commander/lib/error.js
|
|
384
|
+
init_define_import_meta_env();
|
|
366
385
|
var CommanderError = class extends Error {
|
|
367
386
|
/**
|
|
368
387
|
* Constructs the CommanderError class
|
|
@@ -513,6 +532,7 @@ function humanReadableArgName(arg) {
|
|
|
513
532
|
}
|
|
514
533
|
|
|
515
534
|
// node_modules/commander/lib/command.js
|
|
535
|
+
init_define_import_meta_env();
|
|
516
536
|
import { EventEmitter } from "node:events";
|
|
517
537
|
import childProcess from "node:child_process";
|
|
518
538
|
import path from "node:path";
|
|
@@ -521,6 +541,7 @@ import process2 from "node:process";
|
|
|
521
541
|
import { stripVTControlCharacters as stripVTControlCharacters2 } from "node:util";
|
|
522
542
|
|
|
523
543
|
// node_modules/commander/lib/help.js
|
|
544
|
+
init_define_import_meta_env();
|
|
524
545
|
import { stripVTControlCharacters } from "node:util";
|
|
525
546
|
var Help = class {
|
|
526
547
|
constructor() {
|
|
@@ -1113,6 +1134,7 @@ ${itemIndentStr}`);
|
|
|
1113
1134
|
};
|
|
1114
1135
|
|
|
1115
1136
|
// node_modules/commander/lib/option.js
|
|
1137
|
+
init_define_import_meta_env();
|
|
1116
1138
|
var Option = class {
|
|
1117
1139
|
/**
|
|
1118
1140
|
* Initialize a new `Option` with the given `flags` and `description`.
|
|
@@ -1419,6 +1441,7 @@ function splitOptionFlags(flags) {
|
|
|
1419
1441
|
}
|
|
1420
1442
|
|
|
1421
1443
|
// node_modules/commander/lib/suggestSimilar.js
|
|
1444
|
+
init_define_import_meta_env();
|
|
1422
1445
|
var maxDistance = 3;
|
|
1423
1446
|
function editDistance(a, b) {
|
|
1424
1447
|
if (Math.abs(a.length - b.length) > maxDistance)
|
|
@@ -3473,9 +3496,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3473
3496
|
* @param {string} [path]
|
|
3474
3497
|
* @return {(string|null|Command)}
|
|
3475
3498
|
*/
|
|
3476
|
-
executableDir(
|
|
3477
|
-
if (
|
|
3478
|
-
this._executableDir =
|
|
3499
|
+
executableDir(path31) {
|
|
3500
|
+
if (path31 === void 0) return this._executableDir;
|
|
3501
|
+
this._executableDir = path31;
|
|
3479
3502
|
return this;
|
|
3480
3503
|
}
|
|
3481
3504
|
/**
|
|
@@ -3731,6 +3754,7 @@ function useColor() {
|
|
|
3731
3754
|
var program = new Command();
|
|
3732
3755
|
|
|
3733
3756
|
// src/command_intent.ts
|
|
3757
|
+
init_define_import_meta_env();
|
|
3734
3758
|
var INTENT_SUGGESTIONS = [
|
|
3735
3759
|
[
|
|
3736
3760
|
["search", "lookup", "query"],
|
|
@@ -3774,11 +3798,12 @@ function attemptedCommandName(argv) {
|
|
|
3774
3798
|
}
|
|
3775
3799
|
|
|
3776
3800
|
// src/cli.ts
|
|
3777
|
-
import * as
|
|
3778
|
-
import * as
|
|
3801
|
+
import * as fs29 from "fs";
|
|
3802
|
+
import * as path30 from "path";
|
|
3779
3803
|
import { homedir as homedir13 } from "os";
|
|
3780
3804
|
|
|
3781
3805
|
// src/walk_index.ts
|
|
3806
|
+
init_define_import_meta_env();
|
|
3782
3807
|
import * as fs2 from "node:fs";
|
|
3783
3808
|
import * as os from "node:os";
|
|
3784
3809
|
import * as path2 from "node:path";
|
|
@@ -3827,6 +3852,7 @@ function collectWalkIndexFiles(root, opts = {}) {
|
|
|
3827
3852
|
}
|
|
3828
3853
|
|
|
3829
3854
|
// src/bridges/gemini_install.ts
|
|
3855
|
+
init_define_import_meta_env();
|
|
3830
3856
|
import * as fs3 from "node:fs";
|
|
3831
3857
|
import * as os2 from "node:os";
|
|
3832
3858
|
import * as path3 from "node:path";
|
|
@@ -3970,6 +3996,7 @@ function isGeminiInstalled() {
|
|
|
3970
3996
|
}
|
|
3971
3997
|
|
|
3972
3998
|
// src/bridges/qwen_install.ts
|
|
3999
|
+
init_define_import_meta_env();
|
|
3973
4000
|
import * as fs4 from "node:fs";
|
|
3974
4001
|
import * as os3 from "node:os";
|
|
3975
4002
|
import * as path4 from "node:path";
|
|
@@ -4094,11 +4121,13 @@ function isQwenInstalled() {
|
|
|
4094
4121
|
}
|
|
4095
4122
|
|
|
4096
4123
|
// src/bridges/pi_install.ts
|
|
4124
|
+
init_define_import_meta_env();
|
|
4097
4125
|
import * as fs5 from "node:fs";
|
|
4098
4126
|
import * as os4 from "node:os";
|
|
4099
4127
|
import * as path5 from "node:path";
|
|
4100
4128
|
|
|
4101
4129
|
// src/bridges/pi.ts
|
|
4130
|
+
init_define_import_meta_env();
|
|
4102
4131
|
var PI_EXTENSION_SCRIPT = `// token-goat bridge extension for pi (pi-coding-agent)
|
|
4103
4132
|
// Bridges pi's extension events to token-goat's subprocess hook protocol.
|
|
4104
4133
|
// https://github.com/DFKHelper/token-goat
|
|
@@ -4317,7 +4346,7 @@ function materializeShrunkImage(context: string | undefined): string | undefined
|
|
|
4317
4346
|
try {
|
|
4318
4347
|
pruneMaterializedShrinks();
|
|
4319
4348
|
const buf = Buffer.from(match[2], "base64");
|
|
4320
|
-
const name = \`token-goat-shrink-\${process.pid}-\${Date.now()}-\${
|
|
4349
|
+
const name = \`token-goat-shrink-\${process.pid}-\${Date.now()}-\${globalThis.crypto.randomUUID()}.\${match[1]}\`;
|
|
4321
4350
|
const file = path.join(os.tmpdir(), name);
|
|
4322
4351
|
fs.writeFileSync(file, buf);
|
|
4323
4352
|
return file;
|
|
@@ -4489,11 +4518,16 @@ function isPiInstalled(opts = {}) {
|
|
|
4489
4518
|
}
|
|
4490
4519
|
|
|
4491
4520
|
// src/bridges/opencode_install.ts
|
|
4521
|
+
init_define_import_meta_env();
|
|
4492
4522
|
import * as fs6 from "node:fs";
|
|
4493
4523
|
import * as os5 from "node:os";
|
|
4494
4524
|
import * as path6 from "node:path";
|
|
4495
4525
|
|
|
4526
|
+
// src/bridges/opencode.ts
|
|
4527
|
+
init_define_import_meta_env();
|
|
4528
|
+
|
|
4496
4529
|
// src/bridges/relay_block.ts
|
|
4530
|
+
init_define_import_meta_env();
|
|
4497
4531
|
var BRIDGE_RELAY_JS = `// resolveEntryPath reads a sidecar JSON file (token-goat-entry.json, written by
|
|
4498
4532
|
// the install step next to this plugin file) containing the absolute path to
|
|
4499
4533
|
// the token-goat CLI entry that was running at install time. Unlike
|
|
@@ -4783,11 +4817,13 @@ function isOpencodeInstalled() {
|
|
|
4783
4817
|
}
|
|
4784
4818
|
|
|
4785
4819
|
// src/bridges/openclaw_install.ts
|
|
4820
|
+
init_define_import_meta_env();
|
|
4786
4821
|
import * as fs7 from "node:fs";
|
|
4787
4822
|
import * as os6 from "node:os";
|
|
4788
4823
|
import * as path7 from "node:path";
|
|
4789
4824
|
|
|
4790
4825
|
// src/bridges/openclaw.ts
|
|
4826
|
+
init_define_import_meta_env();
|
|
4791
4827
|
var OPENCLAW_PLUGIN_SCRIPT = `// token-goat bridge plugin for OpenClaw
|
|
4792
4828
|
// Bridges OpenClaw's tool-call and session hooks to token-goat's subprocess
|
|
4793
4829
|
// hook protocol. https://github.com/DFKHelper/token-goat
|
|
@@ -5094,6 +5130,7 @@ function isOpenclawInstalled() {
|
|
|
5094
5130
|
}
|
|
5095
5131
|
|
|
5096
5132
|
// src/bridges_status.ts
|
|
5133
|
+
init_define_import_meta_env();
|
|
5097
5134
|
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";
|
|
5098
5135
|
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";
|
|
5099
5136
|
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";
|
|
@@ -5397,6 +5434,7 @@ function installVerificationNotice(harness) {
|
|
|
5397
5434
|
}
|
|
5398
5435
|
|
|
5399
5436
|
// src/sharepoint_resolve.ts
|
|
5437
|
+
init_define_import_meta_env();
|
|
5400
5438
|
import * as fs8 from "node:fs";
|
|
5401
5439
|
import * as os7 from "node:os";
|
|
5402
5440
|
import * as path8 from "node:path";
|
|
@@ -5504,6 +5542,7 @@ function resolveLocalPath(parsed, env = process.env, home = os7.homedir()) {
|
|
|
5504
5542
|
}
|
|
5505
5543
|
|
|
5506
5544
|
// src/video_chapters.ts
|
|
5545
|
+
init_define_import_meta_env();
|
|
5507
5546
|
import { spawnSync } from "node:child_process";
|
|
5508
5547
|
var _ffprobeAvailable;
|
|
5509
5548
|
function isFfprobeAvailable() {
|
|
@@ -5551,6 +5590,7 @@ function extractVideoChapters(file) {
|
|
|
5551
5590
|
}
|
|
5552
5591
|
|
|
5553
5592
|
// src/transcript_extract.ts
|
|
5593
|
+
init_define_import_meta_env();
|
|
5554
5594
|
import * as fs9 from "node:fs";
|
|
5555
5595
|
var TIMESTAMP_RE = /(\d{1,2}:)?(\d{2}):(\d{2})[.,](\d{1,3})/;
|
|
5556
5596
|
var CUE_LINE_RE = new RegExp(`^\\s*${TIMESTAMP_RE.source}\\s*-->\\s*${TIMESTAMP_RE.source}`);
|
|
@@ -5664,6 +5704,7 @@ function formatCues(cues) {
|
|
|
5664
5704
|
}
|
|
5665
5705
|
|
|
5666
5706
|
// src/affected.ts
|
|
5707
|
+
init_define_import_meta_env();
|
|
5667
5708
|
import * as path9 from "node:path";
|
|
5668
5709
|
var DEFAULT_AFFECTED_DEPTH = 5;
|
|
5669
5710
|
function emit(text) {
|
|
@@ -5765,6 +5806,7 @@ function runAffected(opts) {
|
|
|
5765
5806
|
}
|
|
5766
5807
|
|
|
5767
5808
|
// src/purge.ts
|
|
5809
|
+
init_define_import_meta_env();
|
|
5768
5810
|
import * as fs10 from "node:fs";
|
|
5769
5811
|
import * as path10 from "node:path";
|
|
5770
5812
|
function directorySize(root) {
|
|
@@ -5818,6 +5860,7 @@ function formatBytes2(bytes) {
|
|
|
5818
5860
|
}
|
|
5819
5861
|
|
|
5820
5862
|
// src/cli_stats.ts
|
|
5863
|
+
init_define_import_meta_env();
|
|
5821
5864
|
import * as fs11 from "node:fs";
|
|
5822
5865
|
import * as path11 from "node:path";
|
|
5823
5866
|
function writeRaw(text) {
|
|
@@ -5940,6 +5983,7 @@ function runStats(opts = {}) {
|
|
|
5940
5983
|
}
|
|
5941
5984
|
|
|
5942
5985
|
// src/cli_doctor.ts
|
|
5986
|
+
init_define_import_meta_env();
|
|
5943
5987
|
import * as fs12 from "fs";
|
|
5944
5988
|
import * as os8 from "os";
|
|
5945
5989
|
import * as path12 from "path";
|
|
@@ -6153,19 +6197,19 @@ function checkEmbeddingCoverage(dbPath, rootDir) {
|
|
|
6153
6197
|
if (indexedFiles === 0) {
|
|
6154
6198
|
return { name: "Embedding coverage", status: "ok", message: "no indexed files yet" };
|
|
6155
6199
|
}
|
|
6156
|
-
const
|
|
6200
|
+
const pct3 = Math.round(embeddedFiles / indexedFiles * 100);
|
|
6157
6201
|
const sizeKb = cfg.indexing.large_file_symbol_only_kb;
|
|
6158
6202
|
if (embeddedFiles / indexedFiles < EMBED_COVERAGE_WARN_FRACTION) {
|
|
6159
6203
|
return {
|
|
6160
6204
|
name: "Embedding coverage",
|
|
6161
6205
|
status: "warn",
|
|
6162
|
-
message: `only ${embeddedFiles} of ${indexedFiles} indexed file(s) (${
|
|
6206
|
+
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`
|
|
6163
6207
|
};
|
|
6164
6208
|
}
|
|
6165
6209
|
return {
|
|
6166
6210
|
name: "Embedding coverage",
|
|
6167
6211
|
status: "ok",
|
|
6168
|
-
message: `${embeddedFiles} of ${indexedFiles} indexed file(s) (${
|
|
6212
|
+
message: `${embeddedFiles} of ${indexedFiles} indexed file(s) (${pct3}%) have embeddings`
|
|
6169
6213
|
};
|
|
6170
6214
|
} catch (err2) {
|
|
6171
6215
|
return {
|
|
@@ -6402,6 +6446,40 @@ function checkStrayClaudeMdBlocks(searchRoot) {
|
|
|
6402
6446
|
message: `${strays.length} stray cop${strays.length === 1 ? "y" : "ies"} outside CLAUDE.md (never refreshed by install, never removed by uninstall, will go stale): ${strays.join(", ")}`
|
|
6403
6447
|
};
|
|
6404
6448
|
}
|
|
6449
|
+
var LOCKED_BOOLEAN_SAFE_VALUE = {
|
|
6450
|
+
"gdrive.enabled": false,
|
|
6451
|
+
"injection.enabled": true,
|
|
6452
|
+
"redaction.strict": true,
|
|
6453
|
+
"mcp.confine_reads_to_project_root": true,
|
|
6454
|
+
"screenshot.block_private_targets": true,
|
|
6455
|
+
"network.offline": true,
|
|
6456
|
+
"indexing.cross_project_symbols": false,
|
|
6457
|
+
"webfetch.compress_bodies": true
|
|
6458
|
+
};
|
|
6459
|
+
function lockedEnvOverridableKeys() {
|
|
6460
|
+
const out2 = [];
|
|
6461
|
+
for (const key of Object.keys(CONFIG_KEY_ENV_OVERRIDES)) {
|
|
6462
|
+
const section = key.split(".")[0] ?? "";
|
|
6463
|
+
const locked = PROJECT_LOCKED_SECTIONS.includes(section) || PROJECT_LOCKED_KEYS.includes(key);
|
|
6464
|
+
if (locked && (CONFIG_KEY_ENV_OVERRIDES[key] ?? []).length > 0) out2.push(key);
|
|
6465
|
+
}
|
|
6466
|
+
return out2.sort();
|
|
6467
|
+
}
|
|
6468
|
+
function envOverriddenSecuritySettings() {
|
|
6469
|
+
const out2 = [];
|
|
6470
|
+
for (const setting of lockedEnvOverridableKeys()) {
|
|
6471
|
+
const safe = LOCKED_BOOLEAN_SAFE_VALUE[setting];
|
|
6472
|
+
for (const envVar of CONFIG_KEY_ENV_OVERRIDES[setting] ?? []) {
|
|
6473
|
+
if (safe === void 0) {
|
|
6474
|
+
const raw = process.env[envVar];
|
|
6475
|
+
if (raw !== void 0 && raw.trim() !== "") out2.push({ setting, envVar, kind: "replaced" });
|
|
6476
|
+
} else if (envBool(envVar, safe) !== safe) {
|
|
6477
|
+
out2.push({ setting, envVar, kind: "weakened" });
|
|
6478
|
+
}
|
|
6479
|
+
}
|
|
6480
|
+
}
|
|
6481
|
+
return out2;
|
|
6482
|
+
}
|
|
6405
6483
|
function checkSecurityPosture(cfg, dataDirPath) {
|
|
6406
6484
|
const results = [];
|
|
6407
6485
|
results.push({
|
|
@@ -6424,6 +6502,19 @@ function checkSecurityPosture(cfg, dataDirPath) {
|
|
|
6424
6502
|
status: "ok",
|
|
6425
6503
|
message: allow > 0 ? `${allow} allowed host pattern${allow === 1 ? "" : "s"}, ${deny} denied: nothing outside the allow list is fetched` : `no allow list, ${deny} denied pattern${deny === 1 ? "" : "s"}: any host not denied can be fetched`
|
|
6426
6504
|
});
|
|
6505
|
+
const custom = compileCustomPatterns(cfg.redaction.custom_patterns);
|
|
6506
|
+
const strictNote = cfg.redaction.strict ? "strict mode on" : "strict mode off (redaction.strict)";
|
|
6507
|
+
const patternNote = custom.patterns.length === 0 ? "built-in patterns only" : `${custom.patterns.length} custom pattern${custom.patterns.length === 1 ? "" : "s"} plus the built-in ones`;
|
|
6508
|
+
results.push(
|
|
6509
|
+
custom.problems.length > 0 ? {
|
|
6510
|
+
name: "Security redaction",
|
|
6511
|
+
// A pattern the operator believes is redacting, but which never compiled, is the one
|
|
6512
|
+
// failure here that is invisible from the output itself -- so it warns rather than
|
|
6513
|
+
// being reported as a healthy count that happens to be short.
|
|
6514
|
+
status: "warn",
|
|
6515
|
+
message: `${custom.problems.length} custom redaction pattern${custom.problems.length === 1 ? "" : "s"} could not be used and ${custom.problems.length === 1 ? "is" : "are"} not redacting anything: ` + custom.problems.map((p) => `${p.pattern} (${p.reason})`).join("; ")
|
|
6516
|
+
} : { name: "Security redaction", status: "ok", message: `${patternNote}, ${strictNote}` }
|
|
6517
|
+
);
|
|
6427
6518
|
const extraRoots = cfg.mcp.allowed_roots.length;
|
|
6428
6519
|
results.push(
|
|
6429
6520
|
cfg.mcp.confine_reads_to_project_root ? {
|
|
@@ -6432,6 +6523,27 @@ function checkSecurityPosture(cfg, dataDirPath) {
|
|
|
6432
6523
|
message: extraRoots === 0 ? "reads are confined to the project root" : `reads are confined to the project root plus ${extraRoots} configured root${extraRoots === 1 ? "" : "s"}`
|
|
6433
6524
|
} : { name: "Security mcp roots", status: "warn", message: "confinement is off (mcp.confine_reads_to_project_root): a read can leave the project" }
|
|
6434
6525
|
);
|
|
6526
|
+
const overridden = envOverriddenSecuritySettings();
|
|
6527
|
+
const weakened = overridden.filter((o) => o.kind === "weakened");
|
|
6528
|
+
const replaced = overridden.filter((o) => o.kind === "replaced");
|
|
6529
|
+
const describe = (o) => `${o.setting} (${o.envVar})`;
|
|
6530
|
+
const parts = [];
|
|
6531
|
+
if (weakened.length > 0) parts.push(`held open: ${weakened.map(describe).join(", ")}`);
|
|
6532
|
+
if (replaced.length > 0) parts.push(`set from the environment: ${replaced.map(describe).join(", ")}`);
|
|
6533
|
+
results.push(
|
|
6534
|
+
overridden.length === 0 ? {
|
|
6535
|
+
name: "Security config overrides",
|
|
6536
|
+
status: "ok",
|
|
6537
|
+
// Naming the count keeps this from reading as a guarantee about settings it never looked
|
|
6538
|
+
// at, which is what the first version of this line did while nine locked keys went
|
|
6539
|
+
// unchecked behind it.
|
|
6540
|
+
message: `no environment variable is overriding any of the ${lockedEnvOverridableKeys().length} project-locked settings`
|
|
6541
|
+
} : {
|
|
6542
|
+
name: "Security config overrides",
|
|
6543
|
+
status: "warn",
|
|
6544
|
+
message: `the environment, not the config file, is deciding ${overridden.length === 1 ? "a" : "these"} project-locked setting${overridden.length === 1 ? "" : "s"}. ${parts.join("; ")}. A project config cannot change these; an environment variable can, and one can be set by a file in a cloned repository.`
|
|
6545
|
+
}
|
|
6546
|
+
);
|
|
6435
6547
|
results.push(dataDirPermissionResult(dataDirPath));
|
|
6436
6548
|
return results;
|
|
6437
6549
|
}
|
|
@@ -6616,7 +6728,96 @@ async function runDoctorAndExit(opts) {
|
|
|
6616
6728
|
return results.some((r) => r.status === "fail") ? 1 : 0;
|
|
6617
6729
|
}
|
|
6618
6730
|
|
|
6731
|
+
// src/capabilities.ts
|
|
6732
|
+
init_define_import_meta_env();
|
|
6733
|
+
function collectCapabilities(config = loadConfig()) {
|
|
6734
|
+
const online = !config.network.offline;
|
|
6735
|
+
return [
|
|
6736
|
+
{
|
|
6737
|
+
id: "network.http_fetch",
|
|
6738
|
+
kind: "egress",
|
|
6739
|
+
what: "Fetches a URL when a command asks for one, including page text and remote images.",
|
|
6740
|
+
enabled: online,
|
|
6741
|
+
controlledBy: "network.offline",
|
|
6742
|
+
enforcedAt: "src/webfetch.ts::performHttpFetch"
|
|
6743
|
+
},
|
|
6744
|
+
{
|
|
6745
|
+
id: "network.google_drive",
|
|
6746
|
+
kind: "egress",
|
|
6747
|
+
what: "Exports a Google Doc so a section of it can be read.",
|
|
6748
|
+
// Two independent gates, so this reports the conjunction: turning either one off is enough.
|
|
6749
|
+
enabled: online && config.gdrive.enabled,
|
|
6750
|
+
controlledBy: "gdrive.enabled, network.offline",
|
|
6751
|
+
enforcedAt: "src/gdrive.ts::fetchDoc (network gate in src/webfetch.ts::performHttpFetch)"
|
|
6752
|
+
},
|
|
6753
|
+
{
|
|
6754
|
+
id: "network.embedding_model_download",
|
|
6755
|
+
kind: "egress",
|
|
6756
|
+
what: "Downloads the local embedding model once, so semantic search can run without a server.",
|
|
6757
|
+
enabled: online,
|
|
6758
|
+
controlledBy: "network.offline",
|
|
6759
|
+
enforcedAt: "src/embed_model.ts"
|
|
6760
|
+
},
|
|
6761
|
+
{
|
|
6762
|
+
id: "network.ocr_data_download",
|
|
6763
|
+
kind: "egress",
|
|
6764
|
+
what: "Downloads OCR language data once, so text can be read out of an image.",
|
|
6765
|
+
enabled: online,
|
|
6766
|
+
controlledBy: "network.offline",
|
|
6767
|
+
enforcedAt: "src/image_ocr.ts"
|
|
6768
|
+
},
|
|
6769
|
+
{
|
|
6770
|
+
id: "network.screenshot",
|
|
6771
|
+
kind: "egress",
|
|
6772
|
+
what: "Loads a page in a browser to capture it.",
|
|
6773
|
+
enabled: online,
|
|
6774
|
+
controlledBy: "network.offline",
|
|
6775
|
+
enforcedAt: "src/screenshot.ts"
|
|
6776
|
+
},
|
|
6777
|
+
{
|
|
6778
|
+
id: "at_rest.symbol_index",
|
|
6779
|
+
kind: "at-rest",
|
|
6780
|
+
what: "Stores the text of indexed source files in a local database, so a symbol can be returned without re-reading the file.",
|
|
6781
|
+
// Always on: it is the product. Reported anyway, because a reviewer deciding about data at
|
|
6782
|
+
// rest needs the always-on items more than the optional ones.
|
|
6783
|
+
enabled: true,
|
|
6784
|
+
controlledBy: "always on (this is what the tool does)",
|
|
6785
|
+
enforcedAt: "src/db.ts"
|
|
6786
|
+
},
|
|
6787
|
+
{
|
|
6788
|
+
id: "at_rest.command_output_cache",
|
|
6789
|
+
kind: "at-rest",
|
|
6790
|
+
what: "Keeps recent command and web output on disk so it can be recalled instead of re-run. Expires after 24 hours.",
|
|
6791
|
+
enabled: true,
|
|
6792
|
+
controlledBy: "always on, 24-hour expiry",
|
|
6793
|
+
enforcedAt: "src/disk_cache.ts"
|
|
6794
|
+
}
|
|
6795
|
+
];
|
|
6796
|
+
}
|
|
6797
|
+
function renderCapabilities(caps) {
|
|
6798
|
+
const lines = [];
|
|
6799
|
+
for (const kind of ["egress", "at-rest"]) {
|
|
6800
|
+
const group = caps.filter((c) => c.kind === kind);
|
|
6801
|
+
if (group.length === 0) continue;
|
|
6802
|
+
lines.push(kind === "egress" ? "Can send data off this machine:" : "Leaves data on this machine:");
|
|
6803
|
+
for (const c of group) {
|
|
6804
|
+
lines.push(` [${c.enabled ? "ON " : "OFF"}] ${c.id}`);
|
|
6805
|
+
lines.push(` ${c.what}`);
|
|
6806
|
+
lines.push(` controlled by: ${c.controlledBy}`);
|
|
6807
|
+
lines.push(` enforced at: ${c.enforcedAt}`);
|
|
6808
|
+
}
|
|
6809
|
+
lines.push("");
|
|
6810
|
+
}
|
|
6811
|
+
lines.push("Verify rather than trust: `token-goat capabilities --json` reports the state of the");
|
|
6812
|
+
lines.push('binary you have installed, and each "enforced at" names the code that decides it.');
|
|
6813
|
+
return lines.join("\n");
|
|
6814
|
+
}
|
|
6815
|
+
|
|
6816
|
+
// src/gdrive.ts
|
|
6817
|
+
init_define_import_meta_env();
|
|
6818
|
+
|
|
6619
6819
|
// src/webfetch.ts
|
|
6820
|
+
init_define_import_meta_env();
|
|
6620
6821
|
import { existsSync as existsSync7, readdirSync as readdirSync5, statSync as statSync4, unlinkSync as unlinkSync2 } from "fs";
|
|
6621
6822
|
import * as http from "http";
|
|
6622
6823
|
import * as https from "https";
|
|
@@ -7075,6 +7276,7 @@ async function getSectionContent(fileId, heading, opts = {}) {
|
|
|
7075
7276
|
}
|
|
7076
7277
|
|
|
7077
7278
|
// src/pack.ts
|
|
7279
|
+
init_define_import_meta_env();
|
|
7078
7280
|
import * as fs13 from "node:fs";
|
|
7079
7281
|
import * as path14 from "node:path";
|
|
7080
7282
|
|
|
@@ -7094,8 +7296,13 @@ __export(esm_exports, {
|
|
|
7094
7296
|
sep: () => sep2,
|
|
7095
7297
|
unescape: () => unescape
|
|
7096
7298
|
});
|
|
7299
|
+
init_define_import_meta_env();
|
|
7300
|
+
|
|
7301
|
+
// node_modules/brace-expansion/dist/esm/index.js
|
|
7302
|
+
init_define_import_meta_env();
|
|
7097
7303
|
|
|
7098
7304
|
// node_modules/balanced-match/dist/esm/index.js
|
|
7305
|
+
init_define_import_meta_env();
|
|
7099
7306
|
var balanced = (a, b, str) => {
|
|
7100
7307
|
const ma = a instanceof RegExp ? maybeMatch(a, str) : a;
|
|
7101
7308
|
const mb2 = b instanceof RegExp ? maybeMatch(b, str) : b;
|
|
@@ -7362,6 +7569,7 @@ function expand_(str, max, maxLength, isTop) {
|
|
|
7362
7569
|
}
|
|
7363
7570
|
|
|
7364
7571
|
// node_modules/minimatch/dist/esm/assert-valid-pattern.js
|
|
7572
|
+
init_define_import_meta_env();
|
|
7365
7573
|
var MAX_PATTERN_LENGTH = 1024 * 64;
|
|
7366
7574
|
var assertValidPattern = (pattern) => {
|
|
7367
7575
|
if (typeof pattern !== "string") {
|
|
@@ -7372,7 +7580,11 @@ var assertValidPattern = (pattern) => {
|
|
|
7372
7580
|
}
|
|
7373
7581
|
};
|
|
7374
7582
|
|
|
7583
|
+
// node_modules/minimatch/dist/esm/ast.js
|
|
7584
|
+
init_define_import_meta_env();
|
|
7585
|
+
|
|
7375
7586
|
// node_modules/minimatch/dist/esm/brace-expressions.js
|
|
7587
|
+
init_define_import_meta_env();
|
|
7376
7588
|
var posixClasses = {
|
|
7377
7589
|
"[:alnum:]": ["\\p{L}\\p{Nl}\\p{Nd}", true],
|
|
7378
7590
|
"[:alpha:]": ["\\p{L}\\p{Nl}", true],
|
|
@@ -7482,6 +7694,7 @@ var parseClass = (glob, position) => {
|
|
|
7482
7694
|
};
|
|
7483
7695
|
|
|
7484
7696
|
// node_modules/minimatch/dist/esm/unescape.js
|
|
7697
|
+
init_define_import_meta_env();
|
|
7485
7698
|
var unescape = (s, { windowsPathsNoEscape = false, magicalBraces = true } = {}) => {
|
|
7486
7699
|
if (magicalBraces) {
|
|
7487
7700
|
return windowsPathsNoEscape ? s.replace(/\[([^/\\])\]/g, "$1") : s.replace(/((?!\\).|^)\[([^/\\])\]/g, "$1$2").replace(/\\([^/])/g, "$1");
|
|
@@ -8134,6 +8347,7 @@ var AST = class {
|
|
|
8134
8347
|
_a = AST;
|
|
8135
8348
|
|
|
8136
8349
|
// node_modules/minimatch/dist/esm/escape.js
|
|
8350
|
+
init_define_import_meta_env();
|
|
8137
8351
|
var escape = (s, { windowsPathsNoEscape = false, magicalBraces = false } = {}) => {
|
|
8138
8352
|
if (magicalBraces) {
|
|
8139
8353
|
return windowsPathsNoEscape ? s.replace(/[?*()[\]{}]/g, "[$&]") : s.replace(/[?*()[\]\\{}]/g, "\\$&");
|
|
@@ -9409,12 +9623,12 @@ function formatBudgetText(result, contextK) {
|
|
|
9409
9623
|
lines.push(` ${e.rel_path.padEnd(colW, " ")} ${String(e.lines).padStart(6, " ")} ${String(e.tokens).padStart(8, " ")}`);
|
|
9410
9624
|
}
|
|
9411
9625
|
lines.push(` ${"-".repeat(colW)} ${"-".repeat(6)} ${"-".repeat(8)}`);
|
|
9412
|
-
let
|
|
9626
|
+
let pct3 = "";
|
|
9413
9627
|
if (contextK) {
|
|
9414
|
-
|
|
9628
|
+
pct3 = ` (${Math.round(result.total_tokens / (contextK * 1e3) * 100)}% of ${contextK}K)`;
|
|
9415
9629
|
}
|
|
9416
9630
|
lines.push(
|
|
9417
|
-
` ${"Total".padEnd(colW, " ")} ${String(result.total_lines).padStart(6, " ")} ${String(result.total_tokens).padStart(8, " ")}${
|
|
9631
|
+
` ${"Total".padEnd(colW, " ")} ${String(result.total_lines).padStart(6, " ")} ${String(result.total_tokens).padStart(8, " ")}${pct3}`
|
|
9418
9632
|
);
|
|
9419
9633
|
if (result.skipped.length > 0) {
|
|
9420
9634
|
const skipped = result.skipped.slice(0, 5).join(", ");
|
|
@@ -9426,6 +9640,7 @@ function formatBudgetText(result, contextK) {
|
|
|
9426
9640
|
}
|
|
9427
9641
|
|
|
9428
9642
|
// src/failures.ts
|
|
9643
|
+
init_define_import_meta_env();
|
|
9429
9644
|
function getFailureCount(result) {
|
|
9430
9645
|
return result.blocks.length || result.summaryLines.length;
|
|
9431
9646
|
}
|
|
@@ -9850,6 +10065,7 @@ function formatFailureDeltaJson(delta, runner) {
|
|
|
9850
10065
|
}
|
|
9851
10066
|
|
|
9852
10067
|
// src/failures_state.ts
|
|
10068
|
+
init_define_import_meta_env();
|
|
9853
10069
|
import * as fs14 from "node:fs";
|
|
9854
10070
|
import * as path15 from "node:path";
|
|
9855
10071
|
var KEY_RE = /^[A-Za-z0-9_-]{1,80}$/;
|
|
@@ -9895,10 +10111,12 @@ function saveFailureSnapshot(projectHash, key, snapshot) {
|
|
|
9895
10111
|
}
|
|
9896
10112
|
|
|
9897
10113
|
// src/text_commands.ts
|
|
10114
|
+
init_define_import_meta_env();
|
|
9898
10115
|
import * as fs16 from "fs";
|
|
9899
10116
|
import * as path17 from "path";
|
|
9900
10117
|
|
|
9901
10118
|
// src/project_memory.ts
|
|
10119
|
+
init_define_import_meta_env();
|
|
9902
10120
|
import * as fs15 from "node:fs";
|
|
9903
10121
|
import * as path16 from "node:path";
|
|
9904
10122
|
var MAX_ENTRIES = 30;
|
|
@@ -11122,6 +11340,7 @@ function countPackIgnorePatterns(root) {
|
|
|
11122
11340
|
}
|
|
11123
11341
|
|
|
11124
11342
|
// src/dep_docs.ts
|
|
11343
|
+
init_define_import_meta_env();
|
|
11125
11344
|
import { createRequire } from "node:module";
|
|
11126
11345
|
import * as fs17 from "node:fs";
|
|
11127
11346
|
import * as path18 from "node:path";
|
|
@@ -11409,7 +11628,11 @@ function runDepDocs(opts) {
|
|
|
11409
11628
|
return { text, code: 0 };
|
|
11410
11629
|
}
|
|
11411
11630
|
|
|
11631
|
+
// src/cache_session_commands.ts
|
|
11632
|
+
init_define_import_meta_env();
|
|
11633
|
+
|
|
11412
11634
|
// src/resume.ts
|
|
11635
|
+
init_define_import_meta_env();
|
|
11413
11636
|
import { readFile } from "node:fs/promises";
|
|
11414
11637
|
var MAX_RESUME_TOKENS = 2e3;
|
|
11415
11638
|
var MAX_RESUME_CHARS = MAX_RESUME_TOKENS * 4;
|
|
@@ -11749,15 +11972,15 @@ function cmdCompactHint(opts) {
|
|
|
11749
11972
|
const pressure = getContextPressure(cache ?? void 0);
|
|
11750
11973
|
const [manifest, eventCount] = sessionId !== null ? buildManifestWithCount(sessionId) : ["", 0];
|
|
11751
11974
|
const manifestTokens = estimateTokens(manifest);
|
|
11752
|
-
const
|
|
11975
|
+
const pct3 = (pressure.fillFraction * 100).toFixed(1);
|
|
11753
11976
|
if (opts.json === true) {
|
|
11754
|
-
const out2 = { tier: pressure.tier, fillFraction: pressure.fillFraction, pct: Number(
|
|
11977
|
+
const out2 = { tier: pressure.tier, fillFraction: pressure.fillFraction, pct: Number(pct3), manifestTokens, eventCount };
|
|
11755
11978
|
if (sessionId !== null) out2["sessionId"] = sessionId;
|
|
11756
11979
|
if (opts.trigger !== void 0) out2["trigger"] = opts.trigger;
|
|
11757
11980
|
process.stdout.write(JSON.stringify(out2, null, 2) + "\n");
|
|
11758
11981
|
return;
|
|
11759
11982
|
}
|
|
11760
|
-
process.stdout.write(`Compact hint \u2014 context: ${pressure.tier} (${
|
|
11983
|
+
process.stdout.write(`Compact hint \u2014 context: ${pressure.tier} (${pct3}% full)
|
|
11761
11984
|
`);
|
|
11762
11985
|
if (sessionId !== null) process.stdout.write(`Session: ${sessionId}
|
|
11763
11986
|
`);
|
|
@@ -11844,6 +12067,7 @@ function cmdBaseline(opts) {
|
|
|
11844
12067
|
}
|
|
11845
12068
|
|
|
11846
12069
|
// src/index_reclaim.ts
|
|
12070
|
+
init_define_import_meta_env();
|
|
11847
12071
|
import * as fs18 from "node:fs";
|
|
11848
12072
|
import * as path19 from "node:path";
|
|
11849
12073
|
var DERIVED_TABLES = ["chunk_vectors", "chunks", "refs", "symbols", "files"];
|
|
@@ -11970,6 +12194,7 @@ function cmdReclaimIndex(opts) {
|
|
|
11970
12194
|
}
|
|
11971
12195
|
|
|
11972
12196
|
// src/config_commands.ts
|
|
12197
|
+
init_define_import_meta_env();
|
|
11973
12198
|
import * as fs19 from "node:fs";
|
|
11974
12199
|
import * as os9 from "node:os";
|
|
11975
12200
|
import * as path20 from "node:path";
|
|
@@ -12639,6 +12864,7 @@ function cmdHistory(opts) {
|
|
|
12639
12864
|
}
|
|
12640
12865
|
|
|
12641
12866
|
// src/cli_bootstrap_audit.ts
|
|
12867
|
+
init_define_import_meta_env();
|
|
12642
12868
|
import * as fs20 from "node:fs";
|
|
12643
12869
|
import * as os10 from "node:os";
|
|
12644
12870
|
import * as path21 from "node:path";
|
|
@@ -12855,6 +13081,7 @@ async function runBootstrapAudit(opts = {}) {
|
|
|
12855
13081
|
}
|
|
12856
13082
|
|
|
12857
13083
|
// src/cli_memory.ts
|
|
13084
|
+
init_define_import_meta_env();
|
|
12858
13085
|
import * as fs21 from "node:fs";
|
|
12859
13086
|
import * as path22 from "node:path";
|
|
12860
13087
|
function removeExactDupLines(text, report) {
|
|
@@ -12974,10 +13201,12 @@ async function runMemoryCommand(opts = {}) {
|
|
|
12974
13201
|
}
|
|
12975
13202
|
|
|
12976
13203
|
// src/cli_waste.ts
|
|
13204
|
+
init_define_import_meta_env();
|
|
12977
13205
|
import * as fs24 from "node:fs";
|
|
12978
13206
|
import * as path25 from "node:path";
|
|
12979
13207
|
|
|
12980
13208
|
// src/waste.ts
|
|
13209
|
+
init_define_import_meta_env();
|
|
12981
13210
|
import * as fs22 from "node:fs";
|
|
12982
13211
|
import * as os11 from "node:os";
|
|
12983
13212
|
import * as path23 from "node:path";
|
|
@@ -13225,6 +13454,7 @@ async function buildWasteReport(transcriptPath, opts = {}) {
|
|
|
13225
13454
|
}
|
|
13226
13455
|
|
|
13227
13456
|
// src/copilot_waste.ts
|
|
13457
|
+
init_define_import_meta_env();
|
|
13228
13458
|
import * as fs23 from "node:fs";
|
|
13229
13459
|
import * as path24 from "node:path";
|
|
13230
13460
|
var HOOK_RECORD_TYPES = /* @__PURE__ */ new Set(["hook.start", "hook.end"]);
|
|
@@ -13379,10 +13609,10 @@ function printCopilotReport(report) {
|
|
|
13379
13609
|
w(` Conversation: ${conversationTokens.toLocaleString()} tok
|
|
13380
13610
|
`);
|
|
13381
13611
|
if (total > 0) {
|
|
13382
|
-
const
|
|
13612
|
+
const pct3 = (fixed / total * 100).toFixed(1);
|
|
13383
13613
|
w(` ${fixed.toLocaleString()} tok of system prompt and tool definitions ships with every
|
|
13384
13614
|
`);
|
|
13385
|
-
w(` request; at shutdown that was ${
|
|
13615
|
+
w(` request; at shutdown that was ${pct3}% of the context. No hook can reach it: Copilot
|
|
13386
13616
|
`);
|
|
13387
13617
|
w(" assembles both natively, with nothing between assembly and send. The levers are all\n");
|
|
13388
13618
|
w(" config: fewer MCP servers and custom tools, and --excluded-tools / --available-tools /\n");
|
|
@@ -13442,9 +13672,9 @@ function printCopilotReport(report) {
|
|
|
13442
13672
|
`);
|
|
13443
13673
|
} else {
|
|
13444
13674
|
for (const block of report.blocks) {
|
|
13445
|
-
const
|
|
13675
|
+
const pct3 = block.bytes > 0 ? (block.repeatBytes / block.bytes * 100).toFixed(1) : "0.0";
|
|
13446
13676
|
w(` ${block.kind}: ${countNoun(block.count, "injection")}, ${formatBytes(block.bytes)}`);
|
|
13447
|
-
w(block.repeatBytes > 0 ? `, ${formatBytes(block.repeatBytes)} re-sent verbatim (${
|
|
13677
|
+
w(block.repeatBytes > 0 ? `, ${formatBytes(block.repeatBytes)} re-sent verbatim (${pct3}%)
|
|
13448
13678
|
` : "\n");
|
|
13449
13679
|
}
|
|
13450
13680
|
}
|
|
@@ -13609,6 +13839,7 @@ async function runWasteCommand(opts = {}) {
|
|
|
13609
13839
|
}
|
|
13610
13840
|
|
|
13611
13841
|
// src/session_read.ts
|
|
13842
|
+
init_define_import_meta_env();
|
|
13612
13843
|
import * as fs25 from "node:fs";
|
|
13613
13844
|
import * as path26 from "node:path";
|
|
13614
13845
|
import * as readline2 from "node:readline";
|
|
@@ -13775,6 +14006,7 @@ function formatSessionSlice(turns) {
|
|
|
13775
14006
|
}
|
|
13776
14007
|
|
|
13777
14008
|
// src/session_audit.ts
|
|
14009
|
+
init_define_import_meta_env();
|
|
13778
14010
|
import * as fs26 from "node:fs";
|
|
13779
14011
|
import * as os12 from "node:os";
|
|
13780
14012
|
import * as path27 from "node:path";
|
|
@@ -14132,13 +14364,13 @@ async function auditOneFile(filePath, s, toolMap, attachmentMap, hookMap, laneOb
|
|
|
14132
14364
|
s.readInterception.readResults += 1;
|
|
14133
14365
|
const denyTemplate = DENY_TEMPLATES.find((t) => t.re.test(text));
|
|
14134
14366
|
if (denyTemplate !== void 0) {
|
|
14135
|
-
const
|
|
14136
|
-
const lastSlash =
|
|
14367
|
+
const path31 = readPathById.get(id) ?? "";
|
|
14368
|
+
const lastSlash = path31.lastIndexOf("/");
|
|
14137
14369
|
openDenies.push({
|
|
14138
14370
|
kind: denyTemplate.kind,
|
|
14139
14371
|
withheldBytes: parseWithheldBytes(denyTemplate.kind, text),
|
|
14140
|
-
path:
|
|
14141
|
-
basename: lastSlash === -1 ?
|
|
14372
|
+
path: path31,
|
|
14373
|
+
basename: lastSlash === -1 ? path31 : path31.slice(lastSlash + 1),
|
|
14142
14374
|
callIndexAtDeny: perCall.length,
|
|
14143
14375
|
compactEpochAtOpen: compactEpoch,
|
|
14144
14376
|
compactEpochAtWindow: null,
|
|
@@ -14606,6 +14838,7 @@ function formatSessionAudit(s) {
|
|
|
14606
14838
|
}
|
|
14607
14839
|
|
|
14608
14840
|
// src/cli_mcp_audit.ts
|
|
14841
|
+
init_define_import_meta_env();
|
|
14609
14842
|
import * as fs27 from "node:fs";
|
|
14610
14843
|
import * as os13 from "node:os";
|
|
14611
14844
|
import * as path28 from "node:path";
|
|
@@ -14759,6 +14992,7 @@ async function runMcpAuditCommand(opts = {}) {
|
|
|
14759
14992
|
}
|
|
14760
14993
|
|
|
14761
14994
|
// src/cli_recall.ts
|
|
14995
|
+
init_define_import_meta_env();
|
|
14762
14996
|
var RECALL_COMMAND = {
|
|
14763
14997
|
bash: "bash-output",
|
|
14764
14998
|
web: "web-output",
|
|
@@ -14818,7 +15052,231 @@ function runRecallCommand(query, opts = {}) {
|
|
|
14818
15052
|
printHits(browse ? void 0 : query, hits);
|
|
14819
15053
|
}
|
|
14820
15054
|
|
|
15055
|
+
// src/cli_bench.ts
|
|
15056
|
+
init_define_import_meta_env();
|
|
15057
|
+
import * as fs28 from "node:fs";
|
|
15058
|
+
import * as path29 from "node:path";
|
|
15059
|
+
var ControlFilter = class extends ToolFilter {
|
|
15060
|
+
constructor(name, transform) {
|
|
15061
|
+
super();
|
|
15062
|
+
this.name = name;
|
|
15063
|
+
this.transform = transform;
|
|
15064
|
+
}
|
|
15065
|
+
name;
|
|
15066
|
+
transform;
|
|
15067
|
+
apply(stdout, stderr, exitCode) {
|
|
15068
|
+
const originalBytes = Buffer.byteLength(stdout, "utf8") + Buffer.byteLength(stderr, "utf8");
|
|
15069
|
+
const text = this.transform(combineStreams(stdout, stderr));
|
|
15070
|
+
return new CompressedOutput(text, originalBytes, Buffer.byteLength(text, "utf8"), this.name, exitCode);
|
|
15071
|
+
}
|
|
15072
|
+
};
|
|
15073
|
+
var CONTROL_FILTERS = {
|
|
15074
|
+
identity: new ControlFilter("control:identity", (s) => s),
|
|
15075
|
+
destroy: new ControlFilter("control:destroy", () => "")
|
|
15076
|
+
};
|
|
15077
|
+
var MAX_BENCH_FILE_BYTES = 5 * 1024 * 1024;
|
|
15078
|
+
function readCaseFile(id, filePath, what) {
|
|
15079
|
+
const bytes = fs28.statSync(filePath).size;
|
|
15080
|
+
if (bytes > MAX_BENCH_FILE_BYTES) {
|
|
15081
|
+
throw new Error(
|
|
15082
|
+
`bench case ${id}: ${what} is ${bytes} bytes, over the ${MAX_BENCH_FILE_BYTES}-byte limit for a corpus file (${filePath})`
|
|
15083
|
+
);
|
|
15084
|
+
}
|
|
15085
|
+
return fs28.readFileSync(filePath, "utf8");
|
|
15086
|
+
}
|
|
15087
|
+
function parseCase(id, metaPath, outputPath) {
|
|
15088
|
+
const metaText = readCaseFile(id, metaPath, "metadata");
|
|
15089
|
+
let raw;
|
|
15090
|
+
try {
|
|
15091
|
+
raw = JSON.parse(metaText);
|
|
15092
|
+
} catch (e) {
|
|
15093
|
+
throw new Error(`bench case ${id}: ${metaPath} is not valid JSON (${e instanceof Error ? e.message : String(e)})`, { cause: e });
|
|
15094
|
+
}
|
|
15095
|
+
if (typeof raw !== "object" || raw === null) throw new Error(`bench case ${id}: expected a JSON object`);
|
|
15096
|
+
const meta = raw;
|
|
15097
|
+
const str = (key) => {
|
|
15098
|
+
const v = meta[key];
|
|
15099
|
+
if (typeof v !== "string" || v.trim() === "") throw new Error(`bench case ${id}: "${key}" must be a non-empty string`);
|
|
15100
|
+
return v;
|
|
15101
|
+
};
|
|
15102
|
+
const mustKeep = meta["mustKeep"];
|
|
15103
|
+
if (!Array.isArray(mustKeep) || mustKeep.some((s) => typeof s !== "string" || s === "")) {
|
|
15104
|
+
throw new Error(`bench case ${id}: "mustKeep" must be an array of non-empty strings`);
|
|
15105
|
+
}
|
|
15106
|
+
const exitCode = meta["exitCode"];
|
|
15107
|
+
if (exitCode !== void 0 && typeof exitCode !== "number") throw new Error(`bench case ${id}: "exitCode" must be a number`);
|
|
15108
|
+
return {
|
|
15109
|
+
id,
|
|
15110
|
+
provenance: str("provenance"),
|
|
15111
|
+
command: str("command"),
|
|
15112
|
+
exitCode: typeof exitCode === "number" ? exitCode : 0,
|
|
15113
|
+
mustKeep,
|
|
15114
|
+
output: readCaseFile(id, outputPath, "output")
|
|
15115
|
+
};
|
|
15116
|
+
}
|
|
15117
|
+
function loadCorpus(dir) {
|
|
15118
|
+
let entries;
|
|
15119
|
+
try {
|
|
15120
|
+
entries = fs28.readdirSync(dir);
|
|
15121
|
+
} catch {
|
|
15122
|
+
throw new Error(`bench corpus not found: ${dir}`);
|
|
15123
|
+
}
|
|
15124
|
+
const cases = [];
|
|
15125
|
+
for (const entry of entries.sort()) {
|
|
15126
|
+
if (!entry.endsWith(".json")) continue;
|
|
15127
|
+
const id = entry.slice(0, -".json".length);
|
|
15128
|
+
const outputPath = path29.join(dir, `${id}.txt`);
|
|
15129
|
+
if (!fs28.existsSync(outputPath)) throw new Error(`bench case ${id}: missing output file ${outputPath}`);
|
|
15130
|
+
cases.push(parseCase(id, path29.join(dir, entry), outputPath));
|
|
15131
|
+
}
|
|
15132
|
+
if (cases.length === 0) throw new Error(`bench corpus is empty: ${dir}`);
|
|
15133
|
+
return cases;
|
|
15134
|
+
}
|
|
15135
|
+
function runCase(c, control = "none") {
|
|
15136
|
+
const detected = detectFromCommand(c.command);
|
|
15137
|
+
const filter2 = control === "none" ? detected?.filter : CONTROL_FILTERS[control];
|
|
15138
|
+
const argv = detected?.argv ?? [];
|
|
15139
|
+
const delivery = filter2 ? deliverCompressed(filter2, c.output, "", c.exitCode, argv) : null;
|
|
15140
|
+
const body = delivery ? delivery.text + delivery.marker : c.output;
|
|
15141
|
+
const originalBytes = Buffer.byteLength(c.output, "utf8");
|
|
15142
|
+
const deliveredBytes = Buffer.byteLength(body, "utf8");
|
|
15143
|
+
const missing = c.mustKeep.filter((needle) => !body.includes(needle));
|
|
15144
|
+
return {
|
|
15145
|
+
id: c.id,
|
|
15146
|
+
command: c.command,
|
|
15147
|
+
filter: filter2?.name ?? null,
|
|
15148
|
+
applied: delivery?.applied ?? false,
|
|
15149
|
+
originalBytes,
|
|
15150
|
+
deliveredBytes,
|
|
15151
|
+
savedPercent: originalBytes > 0 ? 100 * Math.max(0, originalBytes - deliveredBytes) / originalBytes : 0,
|
|
15152
|
+
kept: c.mustKeep.length - missing.length,
|
|
15153
|
+
mustKeepTotal: c.mustKeep.length,
|
|
15154
|
+
missing
|
|
15155
|
+
};
|
|
15156
|
+
}
|
|
15157
|
+
function runCorpus(cases, control = "none") {
|
|
15158
|
+
const results = cases.map((c) => runCase(c, control));
|
|
15159
|
+
const sum = (pick) => results.reduce((n, r) => n + pick(r), 0);
|
|
15160
|
+
const originalBytes = sum((r) => r.originalBytes);
|
|
15161
|
+
const deliveredBytes = sum((r) => r.deliveredBytes);
|
|
15162
|
+
const kept = sum((r) => r.kept);
|
|
15163
|
+
const mustKeepTotal = sum((r) => r.mustKeepTotal);
|
|
15164
|
+
return {
|
|
15165
|
+
cases: results,
|
|
15166
|
+
originalBytes,
|
|
15167
|
+
deliveredBytes,
|
|
15168
|
+
ratioPercent: originalBytes > 0 ? 100 * Math.max(0, originalBytes - deliveredBytes) / originalBytes : 0,
|
|
15169
|
+
kept,
|
|
15170
|
+
mustKeepTotal,
|
|
15171
|
+
appliedCases: results.filter((r) => r.applied).length,
|
|
15172
|
+
coveredFilters: new Set(results.map((r) => r.filter).filter((n) => n !== null)).size,
|
|
15173
|
+
registeredFilters: TOOL_FILTERS.length,
|
|
15174
|
+
fidelityIntact: kept === mustKeepTotal
|
|
15175
|
+
};
|
|
15176
|
+
}
|
|
15177
|
+
var pct2 = (n) => `${n.toFixed(1)}%`;
|
|
15178
|
+
function renderTable(report, floorPercent) {
|
|
15179
|
+
const rows = [...report.cases].sort((a, b) => b.originalBytes - a.originalBytes);
|
|
15180
|
+
const idWidth = Math.max(4, ...rows.map((r) => r.id.length));
|
|
15181
|
+
const filterWidth = Math.max(6, ...rows.map((r) => (r.filter ?? "-").length));
|
|
15182
|
+
const lines = [];
|
|
15183
|
+
const header = `${"case".padEnd(idWidth)} ${"filter".padEnd(filterWidth)} ${"in".padStart(9)} ${"out".padStart(9)} ${"saved".padStart(7)} fidelity`;
|
|
15184
|
+
lines.push(header, "-".repeat(header.length));
|
|
15185
|
+
for (const r of rows) {
|
|
15186
|
+
const saved = r.applied ? pct2(r.savedPercent) : "-";
|
|
15187
|
+
const fidelity = `${r.kept}/${r.mustKeepTotal}${r.missing.length ? " FAIL" : ""}`;
|
|
15188
|
+
lines.push(
|
|
15189
|
+
`${r.id.padEnd(idWidth)} ${(r.filter ?? "-").padEnd(filterWidth)} ${String(r.originalBytes).padStart(9)} ${String(r.deliveredBytes).padStart(9)} ${saved.padStart(7)} ${fidelity}`
|
|
15190
|
+
);
|
|
15191
|
+
}
|
|
15192
|
+
lines.push("-".repeat(header.length));
|
|
15193
|
+
lines.push(
|
|
15194
|
+
`${"TOTAL".padEnd(idWidth)} ${"".padEnd(filterWidth)} ${String(report.originalBytes).padStart(9)} ${String(report.deliveredBytes).padStart(9)} ${pct2(report.ratioPercent).padStart(7)} ${report.kept}/${report.mustKeepTotal}`
|
|
15195
|
+
);
|
|
15196
|
+
lines.push("");
|
|
15197
|
+
lines.push(`ratio ${pct2(report.ratioPercent)} saved (PRIMARY -- must improve; measured floor ${pct2(floorPercent)}, headroom ${pct2(100 - report.ratioPercent)})`);
|
|
15198
|
+
lines.push(`fidelity ${report.kept}/${report.mustKeepTotal} kept (GUARD -- must not regress; any miss exits 1)`);
|
|
15199
|
+
lines.push(`coverage ${report.coveredFilters}/${report.registeredFilters} filters exercised, ${report.appliedCases}/${report.cases.length} cases compressed`);
|
|
15200
|
+
for (const r of report.cases) {
|
|
15201
|
+
for (const needle of r.missing) lines.push(` DROPPED ${r.id}: ${JSON.stringify(needle)}`);
|
|
15202
|
+
}
|
|
15203
|
+
return lines.join("\n");
|
|
15204
|
+
}
|
|
15205
|
+
function renderValidation(cases) {
|
|
15206
|
+
const identity = runCorpus(cases, "identity");
|
|
15207
|
+
const destroy = runCorpus(cases, "destroy");
|
|
15208
|
+
const checks = [
|
|
15209
|
+
{
|
|
15210
|
+
// Not "scores exactly 0%": the unapplied path delivers the streams recombined, which can
|
|
15211
|
+
// differ from the captured bytes by a trailing newline. That is a real property of delivery,
|
|
15212
|
+
// so the floor is measured and reported rather than assumed -- what must hold is that the
|
|
15213
|
+
// net-benefit gate REFUSED every no-op rewrite, which is what makes the floor a floor.
|
|
15214
|
+
label: "floor: the net-benefit gate refuses a no-op filter on every case",
|
|
15215
|
+
ok: identity.appliedCases === 0,
|
|
15216
|
+
detail: `identity control applied to ${identity.appliedCases}/${identity.cases.length} cases, measured floor ${pct2(identity.ratioPercent)}`
|
|
15217
|
+
},
|
|
15218
|
+
{
|
|
15219
|
+
label: "floor: a no-op filter keeps every must-keep line",
|
|
15220
|
+
ok: identity.fidelityIntact,
|
|
15221
|
+
detail: `identity control kept ${identity.kept}/${identity.mustKeepTotal}`
|
|
15222
|
+
},
|
|
15223
|
+
{
|
|
15224
|
+
label: "guard: deleting everything is caught",
|
|
15225
|
+
ok: !destroy.fidelityIntact,
|
|
15226
|
+
detail: `destroy control kept ${destroy.kept}/${destroy.mustKeepTotal} at ${pct2(destroy.ratioPercent)} saved`
|
|
15227
|
+
}
|
|
15228
|
+
];
|
|
15229
|
+
const failed = checks.filter((c) => !c.ok);
|
|
15230
|
+
const lines = checks.map((c) => `${c.ok ? "ok " : "FAIL"} ${c.label} -- ${c.detail}`);
|
|
15231
|
+
lines.push("");
|
|
15232
|
+
lines.push(
|
|
15233
|
+
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.`
|
|
15234
|
+
);
|
|
15235
|
+
return { text: lines.join("\n"), code: failed.length === 0 ? 0 : 1 };
|
|
15236
|
+
}
|
|
15237
|
+
var TSV_HEADER = "timestamp commit cases original_bytes delivered_bytes ratio_percent fidelity_kept fidelity_total covered_filters\n";
|
|
15238
|
+
function appendTsv(file, report, commit) {
|
|
15239
|
+
const row = [
|
|
15240
|
+
(/* @__PURE__ */ new Date()).toISOString(),
|
|
15241
|
+
commit,
|
|
15242
|
+
report.cases.length,
|
|
15243
|
+
report.originalBytes,
|
|
15244
|
+
report.deliveredBytes,
|
|
15245
|
+
report.ratioPercent.toFixed(2),
|
|
15246
|
+
report.kept,
|
|
15247
|
+
report.mustKeepTotal,
|
|
15248
|
+
report.coveredFilters
|
|
15249
|
+
].join(" ");
|
|
15250
|
+
const dir = path29.dirname(path29.resolve(file));
|
|
15251
|
+
fs28.mkdirSync(dir, { recursive: true });
|
|
15252
|
+
const header = fs28.existsSync(file) ? "" : TSV_HEADER;
|
|
15253
|
+
fs28.appendFileSync(file, header + row + "\n", "utf8");
|
|
15254
|
+
}
|
|
15255
|
+
function currentCommit(cwd) {
|
|
15256
|
+
const opts = cwd === void 0 ? {} : { cwd };
|
|
15257
|
+
try {
|
|
15258
|
+
const r = runGit(["rev-parse", "--short", "HEAD"], opts);
|
|
15259
|
+
const sha = r.stdout.trim();
|
|
15260
|
+
if (r.exitCode !== 0 || sha === "") return "unknown";
|
|
15261
|
+
const st = runGit(["status", "--porcelain"], opts);
|
|
15262
|
+
return st.exitCode === 0 && st.stdout.trim() !== "" ? `${sha}-dirty` : sha;
|
|
15263
|
+
} catch {
|
|
15264
|
+
return "unknown";
|
|
15265
|
+
}
|
|
15266
|
+
}
|
|
15267
|
+
function runBenchCommand(opts) {
|
|
15268
|
+
const cases = loadCorpus(opts.corpus);
|
|
15269
|
+
if (opts.validate === true) return renderValidation(cases);
|
|
15270
|
+
const report = runCorpus(cases);
|
|
15271
|
+
if (opts.tsv !== void 0) appendTsv(opts.tsv, report, currentCommit());
|
|
15272
|
+
const code = report.fidelityIntact ? 0 : 1;
|
|
15273
|
+
const floorPercent = runCorpus(cases, "identity").ratioPercent;
|
|
15274
|
+
if (opts.json === true) return { text: JSON.stringify({ ...report, floorPercent }, null, 2), code };
|
|
15275
|
+
return { text: renderTable(report, floorPercent), code };
|
|
15276
|
+
}
|
|
15277
|
+
|
|
14821
15278
|
// src/cli_hint_stats.ts
|
|
15279
|
+
init_define_import_meta_env();
|
|
14822
15280
|
function formatSpentCell(row) {
|
|
14823
15281
|
if (row.emitted === 0) return "n/a";
|
|
14824
15282
|
if (row.bytesEmitted === null) return "n/a (legacy)";
|
|
@@ -14834,9 +15292,9 @@ function printSummary(rows) {
|
|
|
14834
15292
|
};
|
|
14835
15293
|
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");
|
|
14836
15294
|
for (const row of rows) {
|
|
14837
|
-
const
|
|
15295
|
+
const pct3 = row.efficacyPct === null ? "n/a" : `${row.efficacyPct}%`;
|
|
14838
15296
|
w(
|
|
14839
|
-
pad(row.category, 22) + pad(String(row.emitted), 9) + pad(String(row.actedOn), 10) + pad(
|
|
15297
|
+
pad(row.category, 22) + pad(String(row.emitted), 9) + pad(String(row.actedOn), 10) + pad(pct3, 10) + pad(suppressedCell(row), 17) + pad(String(row.manualEffective), 9) + pad(String(row.manualIneffective), 9) + formatSpentCell(row) + "\n"
|
|
14840
15298
|
);
|
|
14841
15299
|
}
|
|
14842
15300
|
}
|
|
@@ -14888,6 +15346,7 @@ hints.backoff_thresholds is empty, so suppression here is permanent rather than
|
|
|
14888
15346
|
}
|
|
14889
15347
|
|
|
14890
15348
|
// src/cli_statusline.ts
|
|
15349
|
+
init_define_import_meta_env();
|
|
14891
15350
|
var STDIN_TIMEOUT_MS = 1500;
|
|
14892
15351
|
function isPlainObject(v) {
|
|
14893
15352
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
@@ -14981,10 +15440,10 @@ function readBoundedText(text, file) {
|
|
|
14981
15440
|
if (text === void 0 && file === void 0) throw new CliError("provide text or --file");
|
|
14982
15441
|
let value;
|
|
14983
15442
|
if (file !== void 0) {
|
|
14984
|
-
if (
|
|
15443
|
+
if (fs29.statSync(file).size > CONTENT_MAX_INPUT_CHARS) {
|
|
14985
15444
|
throw new CliError(`file exceeds the ${CONTENT_MAX_INPUT_CHARS}-byte safety limit`);
|
|
14986
15445
|
}
|
|
14987
|
-
value =
|
|
15446
|
+
value = fs29.readFileSync(file, "utf8");
|
|
14988
15447
|
} else {
|
|
14989
15448
|
if (text === void 0) throw new CliError("provide text or --file");
|
|
14990
15449
|
value = text;
|
|
@@ -15122,7 +15581,7 @@ async function cmdIndex(pathArg, opts = {}) {
|
|
|
15122
15581
|
continue;
|
|
15123
15582
|
}
|
|
15124
15583
|
const sha = fingerprintFile(key);
|
|
15125
|
-
if (sha === null && !
|
|
15584
|
+
if (sha === null && !fs29.existsSync(key)) continue;
|
|
15126
15585
|
const entry = sha !== null ? getFileEntry(key, dbPath) : null;
|
|
15127
15586
|
const spellingStale = entry !== null && indexedPathSpellingIsStale(entry.filePath, key);
|
|
15128
15587
|
const parseUnchanged = !force && !spellingStale && sha !== null && entry?.sha === sha && entry.parserSha === PARSER_FINGERPRINT;
|
|
@@ -15148,7 +15607,7 @@ async function cmdIndex(pathArg, opts = {}) {
|
|
|
15148
15607
|
}
|
|
15149
15608
|
continue;
|
|
15150
15609
|
}
|
|
15151
|
-
if (!
|
|
15610
|
+
if (!fs29.existsSync(key)) continue;
|
|
15152
15611
|
}
|
|
15153
15612
|
if (!embedUnchanged) {
|
|
15154
15613
|
paintProgress("embedding");
|
|
@@ -15208,8 +15667,8 @@ async function cmdMcpServe() {
|
|
|
15208
15667
|
let StdioServerTransport;
|
|
15209
15668
|
try {
|
|
15210
15669
|
;
|
|
15211
|
-
({ createMcpServer } = await import("./token-goat-chunk-
|
|
15212
|
-
({ StdioServerTransport } = await import("./token-goat-chunk-
|
|
15670
|
+
({ createMcpServer } = await import("./token-goat-chunk-3UBORD6Z.mjs"));
|
|
15671
|
+
({ StdioServerTransport } = await import("./token-goat-chunk-EVC4TOLE.mjs"));
|
|
15213
15672
|
} catch (err2) {
|
|
15214
15673
|
process.stderr.write(
|
|
15215
15674
|
`token-goat: mcp-server unavailable (could not load the MCP server modules): ${String(err2)}
|
|
@@ -15221,8 +15680,8 @@ async function cmdMcpServe() {
|
|
|
15221
15680
|
const server = await createMcpServer();
|
|
15222
15681
|
const transport = new StdioServerTransport();
|
|
15223
15682
|
await server.connect(transport);
|
|
15224
|
-
await new Promise((
|
|
15225
|
-
server.onclose =
|
|
15683
|
+
await new Promise((resolve15) => {
|
|
15684
|
+
server.onclose = resolve15;
|
|
15226
15685
|
});
|
|
15227
15686
|
}
|
|
15228
15687
|
function printBridgeVerificationNotice(harness) {
|
|
@@ -15233,7 +15692,7 @@ async function cmdHook(event, opts) {
|
|
|
15233
15692
|
if (typeof opts.harness === "string" && opts.harness.length > 0) {
|
|
15234
15693
|
process.env[ENV_KEYS.HARNESS_OVERRIDE] = opts.harness;
|
|
15235
15694
|
}
|
|
15236
|
-
const { relay } = await import("./token-goat-chunk-
|
|
15695
|
+
const { relay } = await import("./token-goat-chunk-HC5NMGPD.mjs");
|
|
15237
15696
|
await relay(event);
|
|
15238
15697
|
}
|
|
15239
15698
|
async function cmdInstall(opts) {
|
|
@@ -15346,16 +15805,16 @@ async function cmdInstall(opts) {
|
|
|
15346
15805
|
);
|
|
15347
15806
|
}
|
|
15348
15807
|
try {
|
|
15349
|
-
const skillDir =
|
|
15350
|
-
if (
|
|
15351
|
-
const entries =
|
|
15808
|
+
const skillDir = path30.join(homedir13(), ".claude", "skills");
|
|
15809
|
+
if (fs29.existsSync(skillDir)) {
|
|
15810
|
+
const entries = fs29.readdirSync(skillDir, { withFileTypes: true });
|
|
15352
15811
|
const skillNames = [];
|
|
15353
15812
|
const sessionId = getSessionId();
|
|
15354
15813
|
for (const entry of entries) {
|
|
15355
15814
|
if (!entry.isDirectory()) continue;
|
|
15356
|
-
const skillFile =
|
|
15357
|
-
if (
|
|
15358
|
-
const body =
|
|
15815
|
+
const skillFile = path30.join(skillDir, entry.name, "SKILL.md");
|
|
15816
|
+
if (fs29.existsSync(skillFile)) {
|
|
15817
|
+
const body = fs29.readFileSync(skillFile, "utf-8");
|
|
15359
15818
|
const compact = extractCompactFromMarker(body);
|
|
15360
15819
|
if (compact === null) continue;
|
|
15361
15820
|
const sourceSha = contentHash(body);
|
|
@@ -15365,10 +15824,10 @@ async function cmdInstall(opts) {
|
|
|
15365
15824
|
}
|
|
15366
15825
|
if (skillNames.length > 0) {
|
|
15367
15826
|
const dir = skillOutputsDir();
|
|
15368
|
-
await
|
|
15369
|
-
const pregenPath =
|
|
15827
|
+
await fs29.promises.mkdir(dir, { recursive: true });
|
|
15828
|
+
const pregenPath = path30.join(dir, "pregen.json");
|
|
15370
15829
|
const pregenData = { ts: Date.now(), names: skillNames };
|
|
15371
|
-
await
|
|
15830
|
+
await fs29.promises.writeFile(pregenPath, JSON.stringify(pregenData, null, 2));
|
|
15372
15831
|
out(`Pre-generated ${skillNames.length} skill compacts.`);
|
|
15373
15832
|
}
|
|
15374
15833
|
}
|
|
@@ -15572,7 +16031,7 @@ ${formatSessionOutline(turns)}`;
|
|
|
15572
16031
|
}
|
|
15573
16032
|
function sessionTranscriptSize(transcriptPath) {
|
|
15574
16033
|
try {
|
|
15575
|
-
return
|
|
16034
|
+
return fs29.statSync(transcriptPath).size;
|
|
15576
16035
|
} catch {
|
|
15577
16036
|
return 0;
|
|
15578
16037
|
}
|
|
@@ -15702,7 +16161,7 @@ function fenceFileFieldIfMatched(text) {
|
|
|
15702
16161
|
}
|
|
15703
16162
|
function fileSizeOrZero(filePath) {
|
|
15704
16163
|
try {
|
|
15705
|
-
return
|
|
16164
|
+
return fs29.statSync(filePath).size;
|
|
15706
16165
|
} catch {
|
|
15707
16166
|
return 0;
|
|
15708
16167
|
}
|
|
@@ -15717,11 +16176,11 @@ function cmdBashOutput(id, opts) {
|
|
|
15717
16176
|
}
|
|
15718
16177
|
let content;
|
|
15719
16178
|
try {
|
|
15720
|
-
const st =
|
|
16179
|
+
const st = fs29.statSync(opts.file);
|
|
15721
16180
|
if (st.isFIFO() || st.isSocket()) {
|
|
15722
16181
|
throw new CliError(`--file '${opts.file}' is a special file (FIFO or socket) \u2014 only regular files are supported`);
|
|
15723
16182
|
}
|
|
15724
|
-
content = redactIfDotenv(opts.file, decodeSource(
|
|
16183
|
+
content = redactIfDotenv(opts.file, decodeSource(fs29.readFileSync(opts.file)));
|
|
15725
16184
|
} catch (e) {
|
|
15726
16185
|
if (e instanceof CliError) throw e;
|
|
15727
16186
|
throw new CliError(`cannot read file: ${opts.file}`);
|
|
@@ -15830,9 +16289,9 @@ async function cmdPdfMeta(file, opts = {}) {
|
|
|
15830
16289
|
}
|
|
15831
16290
|
async function cmdImageMeta(file, opts = {}) {
|
|
15832
16291
|
const meta = await runImageMeta(file);
|
|
15833
|
-
if (!meta.
|
|
15834
|
-
const msg = "image-meta unavailable (
|
|
15835
|
-
const text2 = opts.json === true ? JSON.stringify({ bytes: meta.bytes,
|
|
16292
|
+
if (!meta.decodable) {
|
|
16293
|
+
const msg = "image-meta unavailable (not a format token-goat can read)";
|
|
16294
|
+
const text2 = opts.json === true ? JSON.stringify({ bytes: meta.bytes, decodable: false, error: msg }, null, 2) : `Size: ${meta.bytes} bytes
|
|
15836
16295
|
${msg}`;
|
|
15837
16296
|
out(text2);
|
|
15838
16297
|
return;
|
|
@@ -16131,7 +16590,7 @@ function readStdinPaths() {
|
|
|
16131
16590
|
}
|
|
16132
16591
|
let raw;
|
|
16133
16592
|
try {
|
|
16134
|
-
raw =
|
|
16593
|
+
raw = fs29.readFileSync(0, "utf8");
|
|
16135
16594
|
} catch (e) {
|
|
16136
16595
|
throw new CliError(`could not read the file list from stdin: ${extractErrorMessage(e)}`);
|
|
16137
16596
|
}
|
|
@@ -16167,7 +16626,7 @@ function emitExtraFileArgsNote(command, first, extras, opts = {}) {
|
|
|
16167
16626
|
}
|
|
16168
16627
|
async function cmdCompress(opts) {
|
|
16169
16628
|
try {
|
|
16170
|
-
const bashRunner = await import("./token-goat-chunk-
|
|
16629
|
+
const bashRunner = await import("./token-goat-chunk-LLNA42NI.mjs");
|
|
16171
16630
|
if (opts.compress === false) {
|
|
16172
16631
|
process.exitCode = bashRunner.runRaw(opts.cmd, parseTimeout(opts.timeout, bashRunner.DEFAULT_TIMEOUT_SECONDS));
|
|
16173
16632
|
return;
|
|
@@ -16193,7 +16652,7 @@ async function cmdSkillBody(name, opts) {
|
|
|
16193
16652
|
if (filePath === null) {
|
|
16194
16653
|
throw new CliError(`skill '${name}' not found`);
|
|
16195
16654
|
}
|
|
16196
|
-
const body = decodeSource(
|
|
16655
|
+
const body = decodeSource(fs29.readFileSync(filePath));
|
|
16197
16656
|
if (opts.compact === true) {
|
|
16198
16657
|
const emitted = extractCompactFromMarker(body) ?? body;
|
|
16199
16658
|
out(emitted);
|
|
@@ -16220,7 +16679,7 @@ async function cmdSkillCompact(name, opts) {
|
|
|
16220
16679
|
}
|
|
16221
16680
|
let body2;
|
|
16222
16681
|
try {
|
|
16223
|
-
body2 = decodeSource(
|
|
16682
|
+
body2 = decodeSource(fs29.readFileSync(filePath));
|
|
16224
16683
|
} catch {
|
|
16225
16684
|
unresolvable++;
|
|
16226
16685
|
continue;
|
|
@@ -16254,19 +16713,19 @@ async function cmdSkillCompact(name, opts) {
|
|
|
16254
16713
|
if (!opts.path.trim()) {
|
|
16255
16714
|
throw new CliError("--path cannot be empty");
|
|
16256
16715
|
}
|
|
16257
|
-
if (!
|
|
16716
|
+
if (!fs29.existsSync(opts.path)) {
|
|
16258
16717
|
throw new CliError(`skill file not found: ${opts.path}`);
|
|
16259
16718
|
}
|
|
16260
16719
|
try {
|
|
16261
|
-
body =
|
|
16720
|
+
body = fs29.readFileSync(opts.path, "utf-8");
|
|
16262
16721
|
} catch (e) {
|
|
16263
16722
|
if (e.code === "ENOENT") {
|
|
16264
16723
|
throw new CliError(`skill file not found: ${opts.path}`);
|
|
16265
16724
|
}
|
|
16266
16725
|
throw new CliError(`failed to read skill file '${opts.path}': ${extractErrorMessage(e)}`);
|
|
16267
16726
|
}
|
|
16268
|
-
cacheName = name ??
|
|
16269
|
-
sourcePath =
|
|
16727
|
+
cacheName = name ?? path30.basename(path30.dirname(path30.resolve(opts.path)));
|
|
16728
|
+
sourcePath = path30.resolve(opts.path);
|
|
16270
16729
|
} else {
|
|
16271
16730
|
if (name === void 0 || !name.trim()) {
|
|
16272
16731
|
throw new CliError("skill-compact requires a <name> or --path <file>");
|
|
@@ -16275,7 +16734,7 @@ async function cmdSkillCompact(name, opts) {
|
|
|
16275
16734
|
if (filePath === null) {
|
|
16276
16735
|
throw new CliError(`skill '${name}' not found`);
|
|
16277
16736
|
}
|
|
16278
|
-
body =
|
|
16737
|
+
body = fs29.readFileSync(filePath, "utf-8");
|
|
16279
16738
|
cacheName = name;
|
|
16280
16739
|
sourcePath = filePath;
|
|
16281
16740
|
}
|
|
@@ -16407,8 +16866,8 @@ async function cmdSkillDiff(name) {
|
|
|
16407
16866
|
}
|
|
16408
16867
|
const newer = versions[0];
|
|
16409
16868
|
const older = versions[1];
|
|
16410
|
-
const newerBody = await
|
|
16411
|
-
const olderBody = await
|
|
16869
|
+
const newerBody = await fs29.promises.readFile(path30.resolve(dir, `${newer.outputId}.txt`), "utf-8").catch(() => null);
|
|
16870
|
+
const olderBody = await fs29.promises.readFile(path30.resolve(dir, `${older.outputId}.txt`), "utf-8").catch(() => null);
|
|
16412
16871
|
if (newerBody === null || olderBody === null) {
|
|
16413
16872
|
out(`a cached version of '${name}' was evicted while diffing -- try again`);
|
|
16414
16873
|
return;
|
|
@@ -16437,7 +16896,7 @@ async function cmdSkillSection(nameHeading, headingArg) {
|
|
|
16437
16896
|
if (!filePath) {
|
|
16438
16897
|
throw new CliError(`skill '${skillName}' not found`);
|
|
16439
16898
|
}
|
|
16440
|
-
const body = decodeSource(
|
|
16899
|
+
const body = decodeSource(fs29.readFileSync(filePath));
|
|
16441
16900
|
const extracted = extractNamedSection(body, heading);
|
|
16442
16901
|
if (!extracted) {
|
|
16443
16902
|
const messages = [`Section '${heading}' not found in skill '${skillName}'`];
|
|
@@ -16452,7 +16911,7 @@ async function cmdSkillSection(nameHeading, headingArg) {
|
|
|
16452
16911
|
}
|
|
16453
16912
|
function atomicWriteBuffer(dest, data) {
|
|
16454
16913
|
try {
|
|
16455
|
-
if (
|
|
16914
|
+
if (fs29.statSync(dest).isDirectory()) {
|
|
16456
16915
|
const e = Object.assign(new Error(`EISDIR: illegal operation on a directory, open '${dest}'`), { code: "EISDIR", path: dest });
|
|
16457
16916
|
throw e;
|
|
16458
16917
|
}
|
|
@@ -16460,23 +16919,23 @@ function atomicWriteBuffer(dest, data) {
|
|
|
16460
16919
|
if (e.code !== "ENOENT") throw e;
|
|
16461
16920
|
}
|
|
16462
16921
|
const rnd = randomBytes(4).toString("hex");
|
|
16463
|
-
const tmp =
|
|
16922
|
+
const tmp = path30.join(path30.dirname(path30.resolve(dest)), `.tmp.${process.pid}.${rnd}`);
|
|
16464
16923
|
try {
|
|
16465
|
-
|
|
16924
|
+
fs29.writeFileSync(tmp, data, { mode: 384 });
|
|
16466
16925
|
try {
|
|
16467
|
-
const destMode =
|
|
16468
|
-
|
|
16926
|
+
const destMode = fs29.statSync(dest).mode;
|
|
16927
|
+
fs29.chmodSync(tmp, destMode);
|
|
16469
16928
|
} catch (e) {
|
|
16470
16929
|
if (e.code !== "ENOENT") throw e;
|
|
16471
16930
|
}
|
|
16472
16931
|
withRetryOnLock(() => {
|
|
16473
16932
|
try {
|
|
16474
|
-
|
|
16933
|
+
fs29.renameSync(tmp, dest);
|
|
16475
16934
|
} catch (e) {
|
|
16476
16935
|
if (e.code === "EXDEV") {
|
|
16477
|
-
|
|
16936
|
+
fs29.copyFileSync(tmp, dest);
|
|
16478
16937
|
try {
|
|
16479
|
-
|
|
16938
|
+
fs29.unlinkSync(tmp);
|
|
16480
16939
|
} catch (ue) {
|
|
16481
16940
|
process.stderr.write(`token-goat write-file: warning: could not remove temp file ${tmp}: ${ue.message}
|
|
16482
16941
|
`);
|
|
@@ -16488,7 +16947,7 @@ function atomicWriteBuffer(dest, data) {
|
|
|
16488
16947
|
});
|
|
16489
16948
|
} catch (e) {
|
|
16490
16949
|
try {
|
|
16491
|
-
|
|
16950
|
+
fs29.unlinkSync(tmp);
|
|
16492
16951
|
} catch {
|
|
16493
16952
|
}
|
|
16494
16953
|
throw e;
|
|
@@ -16498,9 +16957,9 @@ function mapFsError(e, src, dest, srcLabel = "source") {
|
|
|
16498
16957
|
const fe = e;
|
|
16499
16958
|
if (fe.code === "ENOENT") {
|
|
16500
16959
|
const errPath = fe.path ?? "";
|
|
16501
|
-
const isSource = src !== void 0 &&
|
|
16960
|
+
const isSource = src !== void 0 && path30.resolve(errPath) === path30.resolve(src);
|
|
16502
16961
|
if (isSource) throw new CliError(`${/\bfile$/i.test(srcLabel) ? srcLabel : `${srcLabel} file`} not found: ${src}`);
|
|
16503
|
-
const destDir = dest ?
|
|
16962
|
+
const destDir = dest ? path30.dirname(path30.resolve(dest)) : path30.dirname(path30.resolve(errPath || "."));
|
|
16504
16963
|
throw new CliError(`destination directory does not exist: ${destDir}`);
|
|
16505
16964
|
}
|
|
16506
16965
|
if (fe.code === "ENOTDIR") {
|
|
@@ -16511,7 +16970,7 @@ function mapFsError(e, src, dest, srcLabel = "source") {
|
|
|
16511
16970
|
}
|
|
16512
16971
|
if (fe.code === "EISDIR") {
|
|
16513
16972
|
const errPath = fe.path ?? "";
|
|
16514
|
-
const isSource = src !== void 0 && (errPath === "" ||
|
|
16973
|
+
const isSource = src !== void 0 && (errPath === "" || path30.resolve(errPath) === path30.resolve(src));
|
|
16515
16974
|
if (isSource) throw new CliError(`source is a directory, not a file: ${src}`);
|
|
16516
16975
|
throw new CliError(`destination is a directory, not a file: ${dest ?? (errPath || "(unknown)")}`);
|
|
16517
16976
|
}
|
|
@@ -16580,7 +17039,7 @@ function validateWritablePath(dest, label) {
|
|
|
16580
17039
|
throw new CliError(`${label} path contains a null byte`);
|
|
16581
17040
|
}
|
|
16582
17041
|
if (isWindows()) {
|
|
16583
|
-
const base =
|
|
17042
|
+
const base = path30.basename(dest);
|
|
16584
17043
|
const stem = base.replace(/\.[^.]*$/, "").toUpperCase();
|
|
16585
17044
|
if (WIN_RESERVED.has(stem)) {
|
|
16586
17045
|
throw new CliError(`${label} '${base}' is a reserved Windows device name`);
|
|
@@ -16610,7 +17069,7 @@ function readFileBoundedRaw(filePath, label, allowStdIn = false) {
|
|
|
16610
17069
|
throw new CliError(`${label} ${filePath} requires piped input; use ${altLabel} for interactive use`);
|
|
16611
17070
|
}
|
|
16612
17071
|
try {
|
|
16613
|
-
const st =
|
|
17072
|
+
const st = fs29.statSync(filePath);
|
|
16614
17073
|
if (st.isFIFO() || st.isSocket()) {
|
|
16615
17074
|
throw new CliError(`${label} '${filePath}' is a special file (FIFO or socket) \u2014 only regular files are supported`);
|
|
16616
17075
|
}
|
|
@@ -16618,7 +17077,7 @@ function readFileBoundedRaw(filePath, label, allowStdIn = false) {
|
|
|
16618
17077
|
if (st.size > maxBytes) {
|
|
16619
17078
|
throw new CliError(`${label} '${filePath}' exceeds size limit (${Math.round(st.size / 1024 / 1024)} MB); set TOKEN_GOAT_MAX_STDIN_MB to override`);
|
|
16620
17079
|
}
|
|
16621
|
-
return
|
|
17080
|
+
return fs29.readFileSync(filePath);
|
|
16622
17081
|
} catch (e) {
|
|
16623
17082
|
if (e instanceof CliError) throw e;
|
|
16624
17083
|
mapFsError(e, filePath, void 0, label);
|
|
@@ -16662,7 +17121,7 @@ function cmdNoteAdd(file, opts) {
|
|
|
16662
17121
|
throw new CliError("note content must be valid UTF-8 text");
|
|
16663
17122
|
}
|
|
16664
17123
|
const resolvedPath = resolveIndexPath(file);
|
|
16665
|
-
if (!
|
|
17124
|
+
if (!fs29.existsSync(resolvedPath)) {
|
|
16666
17125
|
throw new CliError(`File not found: '${resolvedPath}'`);
|
|
16667
17126
|
}
|
|
16668
17127
|
healStaleIndex(resolvedPath);
|
|
@@ -16721,7 +17180,7 @@ function cmdWriteFile(dest, opts) {
|
|
|
16721
17180
|
throw new CliError(`TOKEN_GOAT_MAX_STDIN_MB must be a positive integer; got '${process.env["TOKEN_GOAT_MAX_STDIN_MB"] ?? ""}'`);
|
|
16722
17181
|
}
|
|
16723
17182
|
const maxBytes = maxMB * 1024 * 1024;
|
|
16724
|
-
return new Promise((
|
|
17183
|
+
return new Promise((resolve15, reject) => {
|
|
16725
17184
|
const chunks = [];
|
|
16726
17185
|
let totalBytes = 0;
|
|
16727
17186
|
let settled = false;
|
|
@@ -16745,7 +17204,7 @@ function cmdWriteFile(dest, opts) {
|
|
|
16745
17204
|
try {
|
|
16746
17205
|
atomicWriteBuffer(dest, Buffer.concat(chunks));
|
|
16747
17206
|
enqueueDirtyPathSafe(dest);
|
|
16748
|
-
|
|
17207
|
+
resolve15();
|
|
16749
17208
|
} catch (e) {
|
|
16750
17209
|
try {
|
|
16751
17210
|
mapFsError(e, void 0, dest);
|
|
@@ -16876,14 +17335,14 @@ function writeReplacedBuffer(file, replacedBuf, preWriteStat) {
|
|
|
16876
17335
|
const until = process.env["TOKEN_GOAT_TEST_REPLACE_DELAY_UNTIL"];
|
|
16877
17336
|
const deadline = Date.now() + testDelayMs;
|
|
16878
17337
|
if (until !== void 0 && until !== "") {
|
|
16879
|
-
while (Date.now() < deadline && !
|
|
17338
|
+
while (Date.now() < deadline && !fs29.existsSync(until)) sleepSync(5);
|
|
16880
17339
|
} else {
|
|
16881
17340
|
sleepSync(testDelayMs);
|
|
16882
17341
|
}
|
|
16883
17342
|
}
|
|
16884
17343
|
let preRenameStat;
|
|
16885
17344
|
try {
|
|
16886
|
-
preRenameStat =
|
|
17345
|
+
preRenameStat = fs29.statSync(file);
|
|
16887
17346
|
} catch {
|
|
16888
17347
|
}
|
|
16889
17348
|
if (preRenameStat !== void 0 && (preRenameStat.mtimeMs !== preWriteStat.mtimeMs || preRenameStat.size !== preWriteStat.size)) {
|
|
@@ -16924,7 +17383,7 @@ function cmdReplace(file, opts) {
|
|
|
16924
17383
|
const targetBuf = readFileBoundedRaw(file, "target file", true);
|
|
16925
17384
|
let preWriteStat;
|
|
16926
17385
|
try {
|
|
16927
|
-
preWriteStat =
|
|
17386
|
+
preWriteStat = fs29.statSync(file);
|
|
16928
17387
|
} catch {
|
|
16929
17388
|
}
|
|
16930
17389
|
const usingFrom = opts.oldFrom !== void 0 || opts.newFrom !== void 0;
|
|
@@ -17018,7 +17477,7 @@ function cmdInsertSection(file, opts) {
|
|
|
17018
17477
|
}
|
|
17019
17478
|
let preWriteStat;
|
|
17020
17479
|
try {
|
|
17021
|
-
preWriteStat =
|
|
17480
|
+
preWriteStat = fs29.statSync(file);
|
|
17022
17481
|
} catch {
|
|
17023
17482
|
}
|
|
17024
17483
|
const result = readSection(file, opts.after);
|
|
@@ -17044,7 +17503,7 @@ function cmdInsertSection(file, opts) {
|
|
|
17044
17503
|
}
|
|
17045
17504
|
let rawBytes;
|
|
17046
17505
|
try {
|
|
17047
|
-
rawBytes =
|
|
17506
|
+
rawBytes = fs29.readFileSync(file);
|
|
17048
17507
|
} catch (e) {
|
|
17049
17508
|
mapFsError(e, void 0, file);
|
|
17050
17509
|
}
|
|
@@ -17060,7 +17519,7 @@ function cmdInsertSection(file, opts) {
|
|
|
17060
17519
|
if (preWriteStat !== void 0) {
|
|
17061
17520
|
let preRenameStat;
|
|
17062
17521
|
try {
|
|
17063
|
-
preRenameStat =
|
|
17522
|
+
preRenameStat = fs29.statSync(file);
|
|
17064
17523
|
} catch {
|
|
17065
17524
|
}
|
|
17066
17525
|
if (preRenameStat !== void 0 && (preRenameStat.mtimeMs !== preWriteStat.mtimeMs || preRenameStat.size !== preWriteStat.size)) {
|
|
@@ -17102,25 +17561,25 @@ ${content}`;
|
|
|
17102
17561
|
}
|
|
17103
17562
|
function expandGlobs(root, patterns, globFnOverride) {
|
|
17104
17563
|
const out2 = [];
|
|
17105
|
-
const globFn = globFnOverride ??
|
|
17564
|
+
const globFn = globFnOverride ?? fs29["globSync"];
|
|
17106
17565
|
for (const p of patterns) {
|
|
17107
17566
|
if (globFn !== void 0 && (p.includes("*") || p.includes("?") || p.includes("{"))) {
|
|
17108
17567
|
try {
|
|
17109
17568
|
const hits = globFn(p, { cwd: root });
|
|
17110
|
-
for (const h of hits) out2.push(
|
|
17569
|
+
for (const h of hits) out2.push(path30.isAbsolute(h) ? h : path30.join(root, h));
|
|
17111
17570
|
continue;
|
|
17112
17571
|
} catch {
|
|
17113
17572
|
}
|
|
17114
17573
|
}
|
|
17115
|
-
out2.push(
|
|
17574
|
+
out2.push(path30.isAbsolute(p) ? p : path30.join(root, p));
|
|
17116
17575
|
}
|
|
17117
17576
|
return out2;
|
|
17118
17577
|
}
|
|
17119
17578
|
function readIgnoreFile(root) {
|
|
17120
|
-
const ignorePath =
|
|
17579
|
+
const ignorePath = path30.join(root, ".tokengoatignore");
|
|
17121
17580
|
let raw;
|
|
17122
17581
|
try {
|
|
17123
|
-
raw =
|
|
17582
|
+
raw = fs29.readFileSync(ignorePath, "utf8");
|
|
17124
17583
|
} catch {
|
|
17125
17584
|
return void 0;
|
|
17126
17585
|
}
|
|
@@ -17161,14 +17620,14 @@ function cmdPack(patterns, opts) {
|
|
|
17161
17620
|
}
|
|
17162
17621
|
let instruction;
|
|
17163
17622
|
if (opts.instructionFile !== void 0) {
|
|
17164
|
-
instruction =
|
|
17623
|
+
instruction = fs29.readFileSync(opts.instructionFile, "utf8");
|
|
17165
17624
|
}
|
|
17166
17625
|
const formatted = formatPack(result, style, {
|
|
17167
17626
|
...opts.lineNumbers === true ? { line_numbers: true } : {},
|
|
17168
17627
|
...instruction !== void 0 ? { instruction } : {}
|
|
17169
17628
|
});
|
|
17170
17629
|
if (opts.output !== void 0) {
|
|
17171
|
-
|
|
17630
|
+
fs29.writeFileSync(opts.output, formatted, "utf8");
|
|
17172
17631
|
} else {
|
|
17173
17632
|
out(formatted);
|
|
17174
17633
|
}
|
|
@@ -17188,17 +17647,17 @@ function cmdTokens(patterns, opts) {
|
|
|
17188
17647
|
if (opts.tree === true) {
|
|
17189
17648
|
const dirs = /* @__PURE__ */ new Map();
|
|
17190
17649
|
for (const e of entries) {
|
|
17191
|
-
const dir =
|
|
17650
|
+
const dir = path30.dirname(e.rel_path);
|
|
17192
17651
|
if (!dirs.has(dir)) dirs.set(dir, []);
|
|
17193
17652
|
dirs.get(dir).push(e);
|
|
17194
17653
|
}
|
|
17195
17654
|
const lines2 = [];
|
|
17196
17655
|
for (const [dir, dirEntries] of dirs) {
|
|
17197
17656
|
const dirTokens = dirEntries.reduce((s, e) => s + e.tokens, 0);
|
|
17198
|
-
const
|
|
17199
|
-
lines2.push(`${dir}/ (${dirTokens} tokens, ${
|
|
17657
|
+
const pct3 = result.total_tokens > 0 ? Math.round(dirTokens / result.total_tokens * 100) : 0;
|
|
17658
|
+
lines2.push(`${dir}/ (${dirTokens} tokens, ${pct3}%)`);
|
|
17200
17659
|
for (const e of dirEntries) {
|
|
17201
|
-
lines2.push(` ${
|
|
17660
|
+
lines2.push(` ${path30.basename(e.rel_path).padEnd(30)} ${String(e.tokens).padStart(8)} tokens`);
|
|
17202
17661
|
}
|
|
17203
17662
|
}
|
|
17204
17663
|
out(lines2.join("\n"));
|
|
@@ -17232,7 +17691,7 @@ function cmdBudget(patterns, opts) {
|
|
|
17232
17691
|
}
|
|
17233
17692
|
}
|
|
17234
17693
|
function cmdFailures(src, opts) {
|
|
17235
|
-
const text = src !== void 0 ?
|
|
17694
|
+
const text = src !== void 0 ? fs29.readFileSync(src, "utf8") : fs29.readFileSync(0, "utf8");
|
|
17236
17695
|
const result = extractFailures(text, opts.runner !== void 0 ? { runner: opts.runner } : {});
|
|
17237
17696
|
if (opts.delta !== true) {
|
|
17238
17697
|
out(opts.json === true ? formatFailuresJson(result) : formatFailuresText(result));
|
|
@@ -17286,10 +17745,11 @@ function generateCompactHelp() {
|
|
|
17286
17745
|
"",
|
|
17287
17746
|
"Compression: compress-text, retrieve, handoff-create, handoff-resolve,",
|
|
17288
17747
|
" compress, recall, bash-output, web-output, mcp-output, compress-text,",
|
|
17289
|
-
" compress",
|
|
17748
|
+
" compress, bench",
|
|
17290
17749
|
"",
|
|
17291
17750
|
"Config & Integration: install, uninstall, mcp-serve, mcp-status, hook,",
|
|
17292
|
-
" bridges-status, worker, statusline, version, config, config-get,
|
|
17751
|
+
" bridges-status, worker, statusline, version, config, config-get,",
|
|
17752
|
+
" capabilities, help",
|
|
17293
17753
|
"",
|
|
17294
17754
|
"Data: note, note-add, note-get, note-list, sqlite-query, sqlite-schema,",
|
|
17295
17755
|
" csv-profile, csv-query",
|
|
@@ -17471,6 +17931,16 @@ function buildProgram() {
|
|
|
17471
17931
|
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));
|
|
17472
17932
|
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));
|
|
17473
17933
|
program2.command("mcp-serve").description("run token-goat as an MCP stdio server exposing surgical reads and local compression/handoff tools").action(guard(cmdMcpServe));
|
|
17934
|
+
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(
|
|
17935
|
+
(opts) => runExitText(
|
|
17936
|
+
() => runBenchCommand({
|
|
17937
|
+
corpus: opts.corpus ?? path30.join("tests", "fixtures", "bench"),
|
|
17938
|
+
...opts.tsv !== void 0 ? { tsv: opts.tsv } : {},
|
|
17939
|
+
...opts.validate === true ? { validate: true } : {},
|
|
17940
|
+
...opts.json === true ? { json: true } : {}
|
|
17941
|
+
})
|
|
17942
|
+
)
|
|
17943
|
+
);
|
|
17474
17944
|
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));
|
|
17475
17945
|
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));
|
|
17476
17946
|
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));
|
|
@@ -17493,6 +17963,12 @@ function buildProgram() {
|
|
|
17493
17963
|
})
|
|
17494
17964
|
)
|
|
17495
17965
|
);
|
|
17966
|
+
program2.command("capabilities").description("report every capability that can send data off this machine, and its current state").option("-j, --json", "emit as JSON, for asserting on in a pipeline").action(
|
|
17967
|
+
guard((opts) => {
|
|
17968
|
+
const caps = collectCapabilities();
|
|
17969
|
+
console.log(opts.json ? JSON.stringify({ version: VERSION, capabilities: caps }, null, 2) : renderCapabilities(caps));
|
|
17970
|
+
})
|
|
17971
|
+
);
|
|
17496
17972
|
program2.command("doctor").description("diagnose token-goat health").option("--context", "include context footprint analysis").option("--json", "emit check results as JSON instead of text").action(guard(cmdDoctor));
|
|
17497
17973
|
program2.command("context-stats").description("show context statistics").option("--project <path>", "project root to analyze").option("-j, --json", "output as JSON").option("--fix", "apply automatic fixes (confirm-gated; shows a diff before writing)").option("-y, --yes", "with --fix, apply without prompting (non-interactive / scripted use)").action(guard(cmdContextStats));
|
|
17498
17974
|
program2.command("bootstrap-audit").description("audit Claude Code startup-context contributors without reading prompt bodies").option("--project <path>", "project root to analyze").option("--home <path>", "home directory override (for CI/testing)").option("--follow-links", "follow external symlink/junction roots and direct children").option("-j, --json", "output as JSON").option("--top <n>", "largest metadata entries to show (default 10)", "10").option("--warn-tokens <n>", "warn when total estimated startup tokens exceed n").option("--fail-tokens <n>", "fail when total estimated startup tokens exceed n").option("--warn-bytes <n>", "warn when agent/skill metadata bytes exceed n").option("--fail-bytes <n>", "fail when agent/skill metadata bytes exceed n").action(guard(cmdBootstrapAudit));
|
|
@@ -17913,7 +18389,7 @@ async function run(argv = process.argv) {
|
|
|
17913
18389
|
return;
|
|
17914
18390
|
}
|
|
17915
18391
|
if (argv[2] === "--batch-serve" && typeof argv[3] === "string") {
|
|
17916
|
-
const { serveBatch } = await import("./token-goat-chunk-
|
|
18392
|
+
const { serveBatch } = await import("./token-goat-chunk-E3K3BTEQ.mjs");
|
|
17917
18393
|
serveBatch(argv[3], (a) => run(a));
|
|
17918
18394
|
return;
|
|
17919
18395
|
}
|