token-goat 2.9.1 → 2.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/SECURITY.md CHANGED
@@ -49,7 +49,7 @@ The following are not treated as security issues unless paired with a working pr
49
49
  | an install without optional packages | `npm install --omit=optional token-goat` then `npm audit --omit=dev --omit=optional` | clean, 2 packages |
50
50
  | a default install | `npm install token-goat` then `npm audit --omit=dev` | clean, 70 packages |
51
51
 
52
- The repository carries an `overrides` block in [`package.json`](package.json) that pins six transitive packages to patched versions, and **npm applies `overrides` only in the root project**, so those pins do not travel to anyone who installs Token-Goat as a dependency. That distinction used to matter a great deal, because a clean repository scan was standing in for an install that was not clean. It decides one thing now, and the section on the embedding runtime below says which. Otherwise the packages those pins were protecting against are not in a consumer's tree at all, whether or not the pins travel; the block stays because the development tree still resolves them.
52
+ The repository carries an `overrides` block in [`package.json`](package.json) that pins six packages to patched versions, and **npm applies `overrides` only in the root project**, so those pins do not travel to anyone who installs Token-Goat as a dependency. That distinction used to matter a great deal, because a clean repository scan was standing in for an install that was not clean. It decides one thing now, and the section on the embedding runtime below says which. Otherwise the packages those pins were protecting against are not in a consumer's tree at all, whether or not the pins travel; the block stays because the development tree still resolves them.
53
53
 
54
54
  There is no table of reaching advisories here any more, and the last entry in it is worth recording rather than deleting. `@xenova/transformers` was an optional dependency, which in npm means everyone got it unless they asked not to, and it carried [`protobufjs`](https://github.com/advisories/GHSA-xq3m-2v4x-88gg) through `onnx-proto` and `onnxruntime-web` -- one critical advisory and four more -- plus its own nested, older `sharp` carrying [four inherited libvips CVEs](https://github.com/advisories/GHSA-f88m-g3jw-g9cj). None of the six was fixable from here: every one sits in a transitive package with no patched version, and the pins that would have solved it do not travel to consumers.
55
55
 
@@ -2,7 +2,7 @@ import { createRequire as __cjsRequire } from 'node:module';
2
2
  const require = __cjsRequire(import.meta.url);
3
3
  import {
4
4
  detectHarness
5
- } from "./token-goat-chunk-4ZDRTNGV.mjs";
5
+ } from "./token-goat-chunk-UZ2NFOOZ.mjs";
6
6
 
7
7
  // src/delivery_cap.ts
8
8
  var CLAUDE_CODE_BASH_OUTPUT_CAP_BYTES = 2e4;
@@ -43,6 +43,7 @@ import {
43
43
  mergeNearbyHits,
44
44
  ocrImage,
45
45
  ocrIntegrityFailed,
46
+ parseIpv6Groups,
46
47
  parseWhereSpecs,
47
48
  pathEqClause,
48
49
  probeImageMeta,
@@ -67,7 +68,7 @@ import {
67
68
  walkProject,
68
69
  yamlLineClosesQuote,
69
70
  yamlOpenQuoteAfter
70
- } from "./token-goat-chunk-FDXINYK4.mjs";
71
+ } from "./token-goat-chunk-LJ3CHCTT.mjs";
71
72
  import {
72
73
  Database,
73
74
  PER_FILE_COUNTERFACTUAL_CEILING,
@@ -121,7 +122,7 @@ import {
121
122
  unsupportedLanguageName,
122
123
  windowsCmdQuoteArg,
123
124
  withExtension
124
- } from "./token-goat-chunk-4ZDRTNGV.mjs";
125
+ } from "./token-goat-chunk-UZ2NFOOZ.mjs";
125
126
  import {
126
127
  registerReset
127
128
  } from "./token-goat-chunk-AO2QD2AG.mjs";
@@ -2347,24 +2348,32 @@ function collectionTagName(state, event, defaultTagName) {
2347
2348
  function isMappingTag(tag) {
2348
2349
  return tag.nodeKind === "mapping";
2349
2350
  }
2351
+ function chargeMergeWork(state) {
2352
+ state.totalMergeKeys++;
2353
+ if (state.maxTotalMergeKeys !== -1 && state.totalMergeKeys > state.maxTotalMergeKeys) throwError$1(state, `merge keys exceeded maxTotalMergeKeys (${state.maxTotalMergeKeys})`);
2354
+ }
2350
2355
  function mergeKeys(state, frame, source, sourceTag) {
2356
+ chargeMergeWork(state);
2351
2357
  for (const sourceKey of sourceTag.keys(source)) {
2352
- if (state.maxTotalMergeKeys !== -1 && ++state.totalMergeKeys > state.maxTotalMergeKeys) throwError$1(state, `merge keys exceeded maxTotalMergeKeys (${state.maxTotalMergeKeys})`);
2358
+ chargeMergeWork(state);
2353
2359
  if (frame.tag.has(frame.value, sourceKey)) continue;
2354
2360
  const err = frame.tag.addPair(frame.value, sourceKey, sourceTag.get(source, sourceKey));
2355
2361
  if (err) throwError$1(state, err);
2356
- (frame.overridable ??= /* @__PURE__ */ new Set()).add(sourceKey);
2362
+ frame.overridable ??= /* @__PURE__ */ new Set();
2363
+ frame.overridable.add(sourceKey);
2357
2364
  }
2358
2365
  }
2359
2366
  function mergeSource(state, frame, source, sourceTag) {
2360
2367
  state.position = frame.keyPosition;
2361
2368
  if (isMappingTag(sourceTag)) mergeKeys(state, frame, source, sourceTag);
2362
- else if (sourceTag.nodeKind === "sequence" && Array.isArray(source)) for (const element of source) {
2363
- const elementTag = state.nodeTags.get(element);
2364
- if (!elementTag) throwError$1(state, "cannot merge mappings; the provided source object is unacceptable");
2365
- mergeKeys(state, frame, element, elementTag);
2366
- }
2367
- else throwError$1(state, "cannot merge mappings; the provided source object is unacceptable");
2369
+ else if (sourceTag.nodeKind === "sequence" && Array.isArray(source)) {
2370
+ if (source.length > 100) throwError$1(state, "abnormal merge sequence size");
2371
+ for (const element of source) {
2372
+ const elementTag = state.nodeTags.get(element);
2373
+ if (!elementTag) throwError$1(state, "cannot merge mappings; the provided source object is unacceptable");
2374
+ mergeKeys(state, frame, element, elementTag);
2375
+ }
2376
+ } else throwError$1(state, "cannot merge mappings; the provided source object is unacceptable");
2368
2377
  }
2369
2378
  function addMappingValue(state, frame, key, value, tag) {
2370
2379
  state.position = frame.keyPosition;
@@ -2707,6 +2716,24 @@ function testDocumentSeparator(state, position = state.position) {
2707
2716
  }
2708
2717
  return false;
2709
2718
  }
2719
+ function skipByteOrderMark(state) {
2720
+ if (state.position === state.lineStart && state.input.charCodeAt(state.position) === 65279) {
2721
+ state.position++;
2722
+ state.lineStart = state.position;
2723
+ }
2724
+ }
2725
+ function testDocumentBoundary(state) {
2726
+ if (state.position !== state.lineStart) return false;
2727
+ if (testDocumentSeparator(state)) return true;
2728
+ if (state.input.charCodeAt(state.position) !== 65279) return false;
2729
+ const snapshot = snapshotState(state);
2730
+ skipByteOrderMark(state);
2731
+ skipSeparationSpace(state, true);
2732
+ const ch = state.input.charCodeAt(state.position);
2733
+ const result = state.position === state.lineStart && (ch === 37 || ch === 45 && testDocumentSeparator(state));
2734
+ restoreState(state, snapshot);
2735
+ return result;
2736
+ }
2710
2737
  function skipUntilLineEnd(state) {
2711
2738
  let ch = state.input.charCodeAt(state.position);
2712
2739
  while (ch !== 0 && !isEol(ch)) ch = state.input.charCodeAt(++state.position);
@@ -2890,7 +2917,7 @@ function readBlockScalar(state, parentIndent, props) {
2890
2917
  } else if (column > 0) valueEnd = linePosition + column;
2891
2918
  break;
2892
2919
  }
2893
- if (linePosition === state.lineStart && testDocumentSeparator(state, linePosition)) break;
2920
+ if (testDocumentBoundary(state)) break;
2894
2921
  if (!detectedIndent && contentIndent === -1 && isEol(first)) maxLeadingIndent = Math.max(maxLeadingIndent, column);
2895
2922
  if (!detectedIndent && contentIndent === -1 && !isEol(first)) {
2896
2923
  if (first === 9 && column < parentIndent) {
@@ -2943,7 +2970,7 @@ function readPlainScalar(state, nodeIndent, nodeContext, props) {
2943
2970
  const inFlow = nodeContext === CONTEXT_FLOW_IN;
2944
2971
  let multiline = false;
2945
2972
  while (ch !== 0) {
2946
- if (state.position === state.lineStart && testDocumentSeparator(state)) break;
2973
+ if (testDocumentBoundary(state)) break;
2947
2974
  if (ch === 58) {
2948
2975
  const following = state.input.charCodeAt(state.position + 1);
2949
2976
  if (isWsOrEolOrEnd(following) || inFlow && isFlowIndicator(following)) break;
@@ -3300,7 +3327,7 @@ function readDocument(state) {
3300
3327
  const documentEvent = state.events[documentEventIndex];
3301
3328
  if (documentEvent?.type === EVENT_ID.DOCUMENT) documentEvent.explicitEnd = explicitEnd;
3302
3329
  addPopEvent(state);
3303
- if (!explicitEnd && state.position < state.length && !(state.position === state.lineStart && testDocumentSeparator(state))) throwError(state, "end of the stream or a document separator is expected");
3330
+ if (!explicitEnd && state.position < state.length && !testDocumentBoundary(state)) throwError(state, "end of the stream or a document separator is expected");
3304
3331
  }
3305
3332
  function parseEvents(input, options) {
3306
3333
  const length = input.length;
@@ -3321,8 +3348,8 @@ function parseEvents(input, options) {
3321
3348
  };
3322
3349
  const nullpos = input.indexOf("\0");
3323
3350
  if (nullpos !== -1) YAMLException.throwAt(input, nullpos, "null byte is not allowed in input", state.filename);
3324
- if (state.input.charCodeAt(state.position) === 65279) state.position++;
3325
3351
  while (state.position < state.length) {
3352
+ skipByteOrderMark(state);
3326
3353
  skipSeparationSpace(state, true);
3327
3354
  if (state.position >= state.length) break;
3328
3355
  const documentStart = state.position;
@@ -3363,27 +3390,108 @@ function load(input, options) {
3363
3390
  if (documents.length === 1) return documents[0];
3364
3391
  throw new YAMLException("expected a single document in the stream, but found more");
3365
3392
  }
3366
- var ESCAPE_SEQUENCES = {};
3367
- ESCAPE_SEQUENCES[0] = "\\0";
3368
- ESCAPE_SEQUENCES[7] = "\\a";
3369
- ESCAPE_SEQUENCES[8] = "\\b";
3370
- ESCAPE_SEQUENCES[9] = "\\t";
3371
- ESCAPE_SEQUENCES[10] = "\\n";
3372
- ESCAPE_SEQUENCES[11] = "\\v";
3373
- ESCAPE_SEQUENCES[12] = "\\f";
3374
- ESCAPE_SEQUENCES[13] = "\\r";
3375
- ESCAPE_SEQUENCES[27] = "\\e";
3376
- ESCAPE_SEQUENCES[34] = '\\"';
3377
- ESCAPE_SEQUENCES[92] = "\\\\";
3378
- ESCAPE_SEQUENCES[133] = "\\N";
3379
- ESCAPE_SEQUENCES[160] = "\\_";
3380
- ESCAPE_SEQUENCES[8232] = "\\L";
3381
- ESCAPE_SEQUENCES[8233] = "\\P";
3393
+ function hasBit(mask, bit) {
3394
+ return (mask & 1 << bit) !== 0;
3395
+ }
3396
+ var DEFAULT_SCALAR_STYLE_RULES = {
3397
+ applyQuoteFlowKeysOption,
3398
+ doubleQuoteForInvisibles,
3399
+ doubleQuoteWhitespaceOnly,
3400
+ applyForceQuotesOption,
3401
+ tryLongOrMultilineAsBlock,
3402
+ quoteInvalidPlain,
3403
+ fallbackToDoubleQuoted
3404
+ };
3405
+ function _preferredQuotedStyle(layout) {
3406
+ if (layout.presenterOptions.quoteStyle === "single" && hasBit(layout.allowedStylesMask, SCALAR_STYLE.SINGLE_QUOTED)) return SCALAR_STYLE.SINGLE_QUOTED;
3407
+ return SCALAR_STYLE.DOUBLE_QUOTED;
3408
+ }
3409
+ function applyQuoteFlowKeysOption(layout) {
3410
+ if (!layout.presenterOptions.quoteFlowKeys) return;
3411
+ if (!layout.isKey || !layout.flowOnly || layout.style !== SCALAR_STYLE.PLAIN) return;
3412
+ layout.style = SCALAR_STYLE.DOUBLE_QUOTED;
3413
+ }
3414
+ function doubleQuoteForInvisibles(layout) {
3415
+ if (layout.style === SCALAR_STYLE.PLAIN && /[\t\x7F-\xA0\u2028\u2029\uFEFF\uFFFE\uFFFF]/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED;
3416
+ }
3417
+ function doubleQuoteWhitespaceOnly(layout) {
3418
+ if (layout.style === SCALAR_STYLE.PLAIN && /^\s+$/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED;
3419
+ }
3420
+ function applyForceQuotesOption(layout) {
3421
+ if (!layout.presenterOptions.forceQuotes) return;
3422
+ if (layout.isKey || layout.style !== SCALAR_STYLE.PLAIN) return;
3423
+ layout.style = layout.node.value.includes("\n") ? SCALAR_STYLE.DOUBLE_QUOTED : _preferredQuotedStyle(layout);
3424
+ }
3425
+ function tryLongOrMultilineAsBlock(layout) {
3426
+ if (layout.style !== SCALAR_STYLE.PLAIN || layout.isKey) return;
3427
+ const value = layout.node.value;
3428
+ const multiline = value.indexOf("\n") !== -1;
3429
+ if (!hasBit(layout.allowedStylesMask, SCALAR_STYLE.LITERAL_BLOCK)) {
3430
+ if (multiline) layout.style = SCALAR_STYLE.DOUBLE_QUOTED;
3431
+ return;
3432
+ }
3433
+ const w = layout.presenterOptions.lineWidth;
3434
+ if (w === -1) {
3435
+ if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK;
3436
+ return;
3437
+ }
3438
+ const availableWidth = Math.max(Math.min(w, 40), w - layout.shiftOfContent);
3439
+ let position = 0;
3440
+ let shouldFold = false;
3441
+ while (position <= value.length) {
3442
+ let lineEnd = value.length;
3443
+ const nextLineBreak = value.indexOf("\n", position);
3444
+ if (nextLineBreak !== -1) lineEnd = nextLineBreak;
3445
+ const line = value.slice(position, lineEnd);
3446
+ if (line.length > availableWidth && line[0] !== " " && / [^ \t]/.test(line)) shouldFold = true;
3447
+ if (nextLineBreak === -1) break;
3448
+ position = nextLineBreak + 1;
3449
+ }
3450
+ if (shouldFold) layout.style = SCALAR_STYLE.FOLDED_BLOCK;
3451
+ else if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK;
3452
+ }
3453
+ function quoteInvalidPlain(layout) {
3454
+ if (layout.style === SCALAR_STYLE.PLAIN && !hasBit(layout.allowedStylesMask, SCALAR_STYLE.PLAIN)) layout.style = _preferredQuotedStyle(layout);
3455
+ }
3456
+ function fallbackToDoubleQuoted(layout) {
3457
+ if (!hasBit(layout.allowedStylesMask, layout.style)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED;
3458
+ }
3459
+ var SRC_C_PRINTABLE = "[\\x09\\x0A\\x0D\\x20-\\x7E\\x85\\xA0-\\uD7FF\\uE000-\\uFFFD\\u{10000}-\\u{10FFFF}]";
3460
+ var SRC_B_CHAR = "[\\n\\r]";
3461
+ var SRC_C_BYTE_ORDER_MARK = "\\uFEFF";
3462
+ var SRC_S_WHITE = "[ \\t]";
3463
+ var SRC_NB_CHAR = `(?:(?!(?:${SRC_B_CHAR}|${SRC_C_BYTE_ORDER_MARK}))${SRC_C_PRINTABLE})`;
3464
+ var SRC_NS_CHAR = `(?:(?!${SRC_S_WHITE})${SRC_NB_CHAR})`;
3465
+ var SRC_NB_JSON = "[\\x09\\x20-\\uD7FF\\uE000-\\uFFFF\\u{10000}-\\u{10FFFF}]";
3466
+ var SRC_C_INDICATOR = "[-?:,\\[\\]{}#&*!|>'\"%@`]";
3467
+ var SRC_C_FLOW_INDICATOR = "[,\\[\\]{}]";
3468
+ var SRC_NS_PLAIN_SAFE_FLOW_OUT = SRC_NS_CHAR;
3469
+ var SRC_NS_PLAIN_SAFE_FLOW_IN = `(?:(?!${SRC_C_FLOW_INDICATOR})${SRC_NS_CHAR})`;
3470
+ var SRC_NS_PLAIN_FIRST_FLOW_OUT = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))`;
3471
+ var SRC_NS_PLAIN_FIRST_FLOW_IN = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))`;
3472
+ var SRC_NS_PLAIN_CHAR_FLOW_OUT = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_OUT})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))#*`;
3473
+ var SRC_NS_PLAIN_CHAR_FLOW_IN = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_IN})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))#*`;
3474
+ var SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_OUT})*`;
3475
+ var SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_IN})*`;
3476
+ var SRC_NS_PLAIN_ONE_LINE_FLOW_OUT = `${SRC_NS_PLAIN_FIRST_FLOW_OUT}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`;
3477
+ var SRC_NS_PLAIN_ONE_LINE_FLOW_IN = `${SRC_NS_PLAIN_FIRST_FLOW_IN}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`;
3478
+ var SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_OUT;
3479
+ var SRC_NS_PLAIN_ONE_LINE_FLOW_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_IN;
3480
+ var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_OUT}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`;
3481
+ var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_IN}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`;
3482
+ var SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT = `${SRC_NS_PLAIN_ONE_LINE_FLOW_OUT}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT})*`;
3483
+ var SRC_NS_PLAIN_MULTI_LINE_FLOW_IN = `${SRC_NS_PLAIN_ONE_LINE_FLOW_IN}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN})*`;
3484
+ var NS_PLAIN_FLOW_OUT = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT})$`, "u");
3485
+ var NS_PLAIN_FLOW_IN = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_IN})$`, "u");
3486
+ var NS_PLAIN_BLOCK_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY})$`, "u");
3487
+ var NS_PLAIN_FLOW_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_FLOW_KEY})$`, "u");
3488
+ var NB_SINGLE_ONE_LINE = new RegExp(`^(?:${SRC_NB_JSON})*$`, "u");
3489
+ var NB_SINGLE_MULTI_LINE = new RegExp(`^(?:${SRC_NB_JSON}|\\n)*$`, "u");
3490
+ var BLOCK_SCALAR_CONTENT = new RegExp(`^(?:${SRC_NB_CHAR}|\\n)*$`, "u");
3382
3491
  var DEFAULT_PRESENTER_OPTIONS = {
3383
3492
  indent: 2,
3384
3493
  seqNoIndent: false,
3385
3494
  seqInlineFirst: true,
3386
- sortKeys: false,
3387
3495
  lineWidth: 80,
3388
3496
  flowBracketPadding: false,
3389
3497
  flowSkipCommaSpace: false,
@@ -3391,6 +3499,7 @@ var DEFAULT_PRESENTER_OPTIONS = {
3391
3499
  quoteFlowKeys: false,
3392
3500
  quoteStyle: "single",
3393
3501
  forceQuotes: false,
3502
+ scalarStyleRules: Object.keys(DEFAULT_SCALAR_STYLE_RULES).map((name) => Reflect.get(DEFAULT_SCALAR_STYLE_RULES, name)),
3394
3503
  tagBeforeAnchor: false
3395
3504
  };
3396
3505
  var DEFAULT_DUMP_OPTIONS = {
@@ -3399,6 +3508,7 @@ var DEFAULT_DUMP_OPTIONS = {
3399
3508
  skipInvalid: false,
3400
3509
  noRefs: false,
3401
3510
  flowLevel: -1,
3511
+ sortKeys: false,
3402
3512
  transform: () => {
3403
3513
  }
3404
3514
  };
@@ -4574,43 +4684,6 @@ function isBlockedIpv4Octets(a, b) {
4574
4684
  if (a === 0) return true;
4575
4685
  return false;
4576
4686
  }
4577
- function parseIpv6Groups(text) {
4578
- let rest = text;
4579
- const zoneAt = rest.indexOf("%");
4580
- if (zoneAt !== -1) rest = rest.slice(0, zoneAt);
4581
- if (!/^[0-9a-f:.]+$/i.test(rest) || !rest.includes(":")) return null;
4582
- const lastColon = rest.lastIndexOf(":");
4583
- const tail = rest.slice(lastColon + 1);
4584
- if (tail.includes(".")) {
4585
- const quad = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(tail);
4586
- if (!quad) return null;
4587
- const octets = [Number(quad[1]), Number(quad[2]), Number(quad[3]), Number(quad[4])];
4588
- if (octets.some((n) => n > 255)) return null;
4589
- const hi = octets[0] << 8 | octets[1];
4590
- const lo = octets[2] << 8 | octets[3];
4591
- rest = `${rest.slice(0, lastColon + 1)}${hi.toString(16)}:${lo.toString(16)}`;
4592
- }
4593
- const parseGroup = (g) => /^[0-9a-f]{1,4}$/i.test(g) ? parseInt(g, 16) : null;
4594
- const halves = rest.split("::");
4595
- if (halves.length > 2) return null;
4596
- let parts;
4597
- if (halves.length === 2) {
4598
- const left = halves[0].length > 0 ? halves[0].split(":") : [];
4599
- const right = halves[1].length > 0 ? halves[1].split(":") : [];
4600
- if (left.length + right.length > 7) return null;
4601
- parts = [...left, ...Array(8 - left.length - right.length).fill("0"), ...right];
4602
- } else {
4603
- parts = rest.split(":");
4604
- if (parts.length !== 8) return null;
4605
- }
4606
- const groups = [];
4607
- for (const part of parts) {
4608
- const value = parseGroup(part);
4609
- if (value === null) return null;
4610
- groups.push(value);
4611
- }
4612
- return groups;
4613
- }
4614
4687
  function isBlockedIpv6(groups) {
4615
4688
  if (groups.every((g) => g === 0)) return true;
4616
4689
  if (groups.slice(0, 7).every((g) => g === 0) && groups[7] === 1) return true;
@@ -10906,5 +10979,5 @@ export {
10906
10979
  /*! Bundled license information:
10907
10980
 
10908
10981
  js-yaml/dist/js-yaml.mjs:
10909
- (*! js-yaml 5.3.0 https://github.com/nodeca/js-yaml @license MIT *)
10982
+ (*! js-yaml 5.4.1 https://github.com/nodeca/js-yaml @license MIT *)
10910
10983
  */
@@ -7,11 +7,11 @@ import {
7
7
  expandGlobs,
8
8
  leftoverIntegrations,
9
9
  run
10
- } from "./token-goat-chunk-SQSB5P5P.mjs";
11
- import "./token-goat-chunk-SXSWQMNP.mjs";
12
- import "./token-goat-chunk-MR7MNSDR.mjs";
13
- import "./token-goat-chunk-FDXINYK4.mjs";
14
- import "./token-goat-chunk-4ZDRTNGV.mjs";
10
+ } from "./token-goat-chunk-KKIB7O3Z.mjs";
11
+ import "./token-goat-chunk-FXAPKVRG.mjs";
12
+ import "./token-goat-chunk-VCNW7BGU.mjs";
13
+ import "./token-goat-chunk-LJ3CHCTT.mjs";
14
+ import "./token-goat-chunk-UZ2NFOOZ.mjs";
15
15
  import "./token-goat-chunk-AO2QD2AG.mjs";
16
16
  import "./token-goat-chunk-AEX54RUZ.mjs";
17
17
  export {
@@ -86,7 +86,7 @@ import {
86
86
  runZipRead,
87
87
  symbolNamesInFile,
88
88
  upsertNote
89
- } from "./token-goat-chunk-SXSWQMNP.mjs";
89
+ } from "./token-goat-chunk-FXAPKVRG.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-MR7MNSDR.mjs";
111
+ } from "./token-goat-chunk-VCNW7BGU.mjs";
112
112
  import {
113
113
  AGENT_SALT_MARKER,
114
114
  BASH_OUTPUT_SUBDIR,
@@ -238,7 +238,7 @@ import {
238
238
  visionTokensSavedByText,
239
239
  walkProject,
240
240
  writeCompact
241
- } from "./token-goat-chunk-FDXINYK4.mjs";
241
+ } from "./token-goat-chunk-LJ3CHCTT.mjs";
242
242
  import {
243
243
  C,
244
244
  CONFIG_KEY_ENV_OVERRIDES,
@@ -246,6 +246,8 @@ import {
246
246
  FILTERS,
247
247
  LOCK_WAIT_MS_HARDENED,
248
248
  MATERIALIZE_SHRUNK_IMAGE_JS,
249
+ PROJECT_LOCKED_KEYS,
250
+ PROJECT_LOCKED_SECTIONS,
249
251
  RESET,
250
252
  VERSION,
251
253
  _useRichStats,
@@ -255,6 +257,7 @@ import {
255
257
  canonicalize,
256
258
  cappedSourceBytesSaved,
257
259
  colorStdout,
260
+ compileCustomPatterns,
258
261
  configPath,
259
262
  copilotCliConfigPath,
260
263
  copilotCliMcpToolsDir,
@@ -269,6 +272,7 @@ import {
269
272
  encodeSource,
270
273
  ensureDirSync,
271
274
  ensureNewline,
275
+ envBool,
272
276
  escapeRegExp,
273
277
  extractErrorMessage,
274
278
  fg,
@@ -354,7 +358,7 @@ import {
354
358
  withFileLock,
355
359
  withRetryOnLock,
356
360
  writeJsonSettings
357
- } from "./token-goat-chunk-4ZDRTNGV.mjs";
361
+ } from "./token-goat-chunk-UZ2NFOOZ.mjs";
358
362
  import {
359
363
  __export
360
364
  } from "./token-goat-chunk-AEX54RUZ.mjs";
@@ -4317,7 +4321,7 @@ function materializeShrunkImage(context: string | undefined): string | undefined
4317
4321
  try {
4318
4322
  pruneMaterializedShrinks();
4319
4323
  const buf = Buffer.from(match[2], "base64");
4320
- const name = \`token-goat-shrink-\${process.pid}-\${Date.now()}-\${Math.random().toString(36).slice(2)}.\${match[1]}\`;
4324
+ const name = \`token-goat-shrink-\${process.pid}-\${Date.now()}-\${globalThis.crypto.randomUUID()}.\${match[1]}\`;
4321
4325
  const file = path.join(os.tmpdir(), name);
4322
4326
  fs.writeFileSync(file, buf);
4323
4327
  return file;
@@ -6402,6 +6406,40 @@ function checkStrayClaudeMdBlocks(searchRoot) {
6402
6406
  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
6407
  };
6404
6408
  }
6409
+ var LOCKED_BOOLEAN_SAFE_VALUE = {
6410
+ "gdrive.enabled": false,
6411
+ "injection.enabled": true,
6412
+ "redaction.strict": true,
6413
+ "mcp.confine_reads_to_project_root": true,
6414
+ "screenshot.block_private_targets": true,
6415
+ "network.offline": true,
6416
+ "indexing.cross_project_symbols": false,
6417
+ "webfetch.compress_bodies": true
6418
+ };
6419
+ function lockedEnvOverridableKeys() {
6420
+ const out2 = [];
6421
+ for (const key of Object.keys(CONFIG_KEY_ENV_OVERRIDES)) {
6422
+ const section = key.split(".")[0] ?? "";
6423
+ const locked = PROJECT_LOCKED_SECTIONS.includes(section) || PROJECT_LOCKED_KEYS.includes(key);
6424
+ if (locked && (CONFIG_KEY_ENV_OVERRIDES[key] ?? []).length > 0) out2.push(key);
6425
+ }
6426
+ return out2.sort();
6427
+ }
6428
+ function envOverriddenSecuritySettings() {
6429
+ const out2 = [];
6430
+ for (const setting of lockedEnvOverridableKeys()) {
6431
+ const safe = LOCKED_BOOLEAN_SAFE_VALUE[setting];
6432
+ for (const envVar of CONFIG_KEY_ENV_OVERRIDES[setting] ?? []) {
6433
+ if (safe === void 0) {
6434
+ const raw = process.env[envVar];
6435
+ if (raw !== void 0 && raw.trim() !== "") out2.push({ setting, envVar, kind: "replaced" });
6436
+ } else if (envBool(envVar, safe) !== safe) {
6437
+ out2.push({ setting, envVar, kind: "weakened" });
6438
+ }
6439
+ }
6440
+ }
6441
+ return out2;
6442
+ }
6405
6443
  function checkSecurityPosture(cfg, dataDirPath) {
6406
6444
  const results = [];
6407
6445
  results.push({
@@ -6424,6 +6462,19 @@ function checkSecurityPosture(cfg, dataDirPath) {
6424
6462
  status: "ok",
6425
6463
  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
6464
  });
6465
+ const custom = compileCustomPatterns(cfg.redaction.custom_patterns);
6466
+ const strictNote = cfg.redaction.strict ? "strict mode on" : "strict mode off (redaction.strict)";
6467
+ 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`;
6468
+ results.push(
6469
+ custom.problems.length > 0 ? {
6470
+ name: "Security redaction",
6471
+ // A pattern the operator believes is redacting, but which never compiled, is the one
6472
+ // failure here that is invisible from the output itself -- so it warns rather than
6473
+ // being reported as a healthy count that happens to be short.
6474
+ status: "warn",
6475
+ 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("; ")
6476
+ } : { name: "Security redaction", status: "ok", message: `${patternNote}, ${strictNote}` }
6477
+ );
6427
6478
  const extraRoots = cfg.mcp.allowed_roots.length;
6428
6479
  results.push(
6429
6480
  cfg.mcp.confine_reads_to_project_root ? {
@@ -6432,6 +6483,27 @@ function checkSecurityPosture(cfg, dataDirPath) {
6432
6483
  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
6484
  } : { name: "Security mcp roots", status: "warn", message: "confinement is off (mcp.confine_reads_to_project_root): a read can leave the project" }
6434
6485
  );
6486
+ const overridden = envOverriddenSecuritySettings();
6487
+ const weakened = overridden.filter((o) => o.kind === "weakened");
6488
+ const replaced = overridden.filter((o) => o.kind === "replaced");
6489
+ const describe = (o) => `${o.setting} (${o.envVar})`;
6490
+ const parts = [];
6491
+ if (weakened.length > 0) parts.push(`held open: ${weakened.map(describe).join(", ")}`);
6492
+ if (replaced.length > 0) parts.push(`set from the environment: ${replaced.map(describe).join(", ")}`);
6493
+ results.push(
6494
+ overridden.length === 0 ? {
6495
+ name: "Security config overrides",
6496
+ status: "ok",
6497
+ // Naming the count keeps this from reading as a guarantee about settings it never looked
6498
+ // at, which is what the first version of this line did while nine locked keys went
6499
+ // unchecked behind it.
6500
+ message: `no environment variable is overriding any of the ${lockedEnvOverridableKeys().length} project-locked settings`
6501
+ } : {
6502
+ name: "Security config overrides",
6503
+ status: "warn",
6504
+ 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.`
6505
+ }
6506
+ );
6435
6507
  results.push(dataDirPermissionResult(dataDirPath));
6436
6508
  return results;
6437
6509
  }
@@ -6616,6 +6688,90 @@ async function runDoctorAndExit(opts) {
6616
6688
  return results.some((r) => r.status === "fail") ? 1 : 0;
6617
6689
  }
6618
6690
 
6691
+ // src/capabilities.ts
6692
+ function collectCapabilities(config = loadConfig()) {
6693
+ const online = !config.network.offline;
6694
+ return [
6695
+ {
6696
+ id: "network.http_fetch",
6697
+ kind: "egress",
6698
+ what: "Fetches a URL when a command asks for one, including page text and remote images.",
6699
+ enabled: online,
6700
+ controlledBy: "network.offline",
6701
+ enforcedAt: "src/webfetch.ts::performHttpFetch"
6702
+ },
6703
+ {
6704
+ id: "network.google_drive",
6705
+ kind: "egress",
6706
+ what: "Exports a Google Doc so a section of it can be read.",
6707
+ // Two independent gates, so this reports the conjunction: turning either one off is enough.
6708
+ enabled: online && config.gdrive.enabled,
6709
+ controlledBy: "gdrive.enabled, network.offline",
6710
+ enforcedAt: "src/gdrive.ts::fetchDoc (network gate in src/webfetch.ts::performHttpFetch)"
6711
+ },
6712
+ {
6713
+ id: "network.embedding_model_download",
6714
+ kind: "egress",
6715
+ what: "Downloads the local embedding model once, so semantic search can run without a server.",
6716
+ enabled: online,
6717
+ controlledBy: "network.offline",
6718
+ enforcedAt: "src/embed_model.ts"
6719
+ },
6720
+ {
6721
+ id: "network.ocr_data_download",
6722
+ kind: "egress",
6723
+ what: "Downloads OCR language data once, so text can be read out of an image.",
6724
+ enabled: online,
6725
+ controlledBy: "network.offline",
6726
+ enforcedAt: "src/image_ocr.ts"
6727
+ },
6728
+ {
6729
+ id: "network.screenshot",
6730
+ kind: "egress",
6731
+ what: "Loads a page in a browser to capture it.",
6732
+ enabled: online,
6733
+ controlledBy: "network.offline",
6734
+ enforcedAt: "src/screenshot.ts"
6735
+ },
6736
+ {
6737
+ id: "at_rest.symbol_index",
6738
+ kind: "at-rest",
6739
+ what: "Stores the text of indexed source files in a local database, so a symbol can be returned without re-reading the file.",
6740
+ // Always on: it is the product. Reported anyway, because a reviewer deciding about data at
6741
+ // rest needs the always-on items more than the optional ones.
6742
+ enabled: true,
6743
+ controlledBy: "always on (this is what the tool does)",
6744
+ enforcedAt: "src/db.ts"
6745
+ },
6746
+ {
6747
+ id: "at_rest.command_output_cache",
6748
+ kind: "at-rest",
6749
+ what: "Keeps recent command and web output on disk so it can be recalled instead of re-run. Expires after 24 hours.",
6750
+ enabled: true,
6751
+ controlledBy: "always on, 24-hour expiry",
6752
+ enforcedAt: "src/disk_cache.ts"
6753
+ }
6754
+ ];
6755
+ }
6756
+ function renderCapabilities(caps) {
6757
+ const lines = [];
6758
+ for (const kind of ["egress", "at-rest"]) {
6759
+ const group = caps.filter((c) => c.kind === kind);
6760
+ if (group.length === 0) continue;
6761
+ lines.push(kind === "egress" ? "Can send data off this machine:" : "Leaves data on this machine:");
6762
+ for (const c of group) {
6763
+ lines.push(` [${c.enabled ? "ON " : "OFF"}] ${c.id}`);
6764
+ lines.push(` ${c.what}`);
6765
+ lines.push(` controlled by: ${c.controlledBy}`);
6766
+ lines.push(` enforced at: ${c.enforcedAt}`);
6767
+ }
6768
+ lines.push("");
6769
+ }
6770
+ lines.push("Verify rather than trust: `token-goat capabilities --json` reports the state of the");
6771
+ lines.push('binary you have installed, and each "enforced at" names the code that decides it.');
6772
+ return lines.join("\n");
6773
+ }
6774
+
6619
6775
  // src/webfetch.ts
6620
6776
  import { existsSync as existsSync7, readdirSync as readdirSync5, statSync as statSync4, unlinkSync as unlinkSync2 } from "fs";
6621
6777
  import * as http from "http";
@@ -15208,7 +15364,7 @@ async function cmdMcpServe() {
15208
15364
  let StdioServerTransport;
15209
15365
  try {
15210
15366
  ;
15211
- ({ createMcpServer } = await import("./token-goat-chunk-CD6U5OD6.mjs"));
15367
+ ({ createMcpServer } = await import("./token-goat-chunk-LEBYARO3.mjs"));
15212
15368
  ({ StdioServerTransport } = await import("./token-goat-chunk-324QOJYZ.mjs"));
15213
15369
  } catch (err2) {
15214
15370
  process.stderr.write(
@@ -15233,7 +15389,7 @@ async function cmdHook(event, opts) {
15233
15389
  if (typeof opts.harness === "string" && opts.harness.length > 0) {
15234
15390
  process.env[ENV_KEYS.HARNESS_OVERRIDE] = opts.harness;
15235
15391
  }
15236
- const { relay } = await import("./token-goat-chunk-AUM22UQ2.mjs");
15392
+ const { relay } = await import("./token-goat-chunk-ZVN5WHTO.mjs");
15237
15393
  await relay(event);
15238
15394
  }
15239
15395
  async function cmdInstall(opts) {
@@ -16167,7 +16323,7 @@ function emitExtraFileArgsNote(command, first, extras, opts = {}) {
16167
16323
  }
16168
16324
  async function cmdCompress(opts) {
16169
16325
  try {
16170
- const bashRunner = await import("./token-goat-chunk-4KD2N46D.mjs");
16326
+ const bashRunner = await import("./token-goat-chunk-NY4HYRSK.mjs");
16171
16327
  if (opts.compress === false) {
16172
16328
  process.exitCode = bashRunner.runRaw(opts.cmd, parseTimeout(opts.timeout, bashRunner.DEFAULT_TIMEOUT_SECONDS));
16173
16329
  return;
@@ -17289,7 +17445,8 @@ function generateCompactHelp() {
17289
17445
  " compress",
17290
17446
  "",
17291
17447
  "Config & Integration: install, uninstall, mcp-serve, mcp-status, hook,",
17292
- " bridges-status, worker, statusline, version, config, config-get, help",
17448
+ " bridges-status, worker, statusline, version, config, config-get,",
17449
+ " capabilities, help",
17293
17450
  "",
17294
17451
  "Data: note, note-add, note-get, note-list, sqlite-query, sqlite-schema,",
17295
17452
  " csv-profile, csv-query",
@@ -17493,6 +17650,12 @@ function buildProgram() {
17493
17650
  })
17494
17651
  )
17495
17652
  );
17653
+ 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(
17654
+ guard((opts) => {
17655
+ const caps = collectCapabilities();
17656
+ console.log(opts.json ? JSON.stringify({ version: VERSION, capabilities: caps }, null, 2) : renderCapabilities(caps));
17657
+ })
17658
+ );
17496
17659
  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
17660
  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
17661
  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));