token-goat 2.9.17 → 2.9.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +2 -0
  2. package/dist/{token-goat-chunk-HRUGS6CO.mjs → token-goat-chunk-2GTB5RBZ.mjs} +365 -26
  3. package/dist/{token-goat-chunk-W2GUUQAQ.mjs → token-goat-chunk-3W5P673V.mjs} +1 -1
  4. package/dist/{token-goat-chunk-5WB7GDH4.mjs → token-goat-chunk-62VJ47WN.mjs} +6 -6
  5. package/dist/{token-goat-chunk-C26ZBGBC.mjs → token-goat-chunk-7DGTVBWP.mjs} +58 -44
  6. package/dist/{token-goat-chunk-GPCCYQSS.mjs → token-goat-chunk-AVRD7SBO.mjs} +60 -8
  7. package/dist/{token-goat-chunk-66224KCZ.mjs → token-goat-chunk-BTKDZW7F.mjs} +1 -1
  8. package/dist/{token-goat-chunk-LMFO66YD.mjs → token-goat-chunk-DA43OE7L.mjs} +1 -1
  9. package/dist/{token-goat-chunk-YFGEUIEO.mjs → token-goat-chunk-DA6TIDLI.mjs} +21 -16
  10. package/dist/{token-goat-chunk-CPHVXKNU.mjs → token-goat-chunk-DHIXE6GV.mjs} +2 -2
  11. package/dist/{token-goat-chunk-73GXYYZR.mjs → token-goat-chunk-EP7TCWHM.mjs} +304 -46
  12. package/dist/{token-goat-chunk-EKGVCAES.mjs → token-goat-chunk-EXLLLIC3.mjs} +4 -4
  13. package/dist/{token-goat-chunk-CICJFVIH.mjs → token-goat-chunk-F24NE3FO.mjs} +3 -3
  14. package/dist/{token-goat-chunk-THBLW56G.mjs → token-goat-chunk-FJZ5MZK7.mjs} +3 -3
  15. package/dist/{token-goat-chunk-PKNOHVWP.mjs → token-goat-chunk-FQYMZASI.mjs} +632 -350
  16. package/dist/{token-goat-chunk-RFFUCQK7.mjs → token-goat-chunk-FX5DHKGF.mjs} +5 -5
  17. package/dist/{token-goat-chunk-RB24DBBS.mjs → token-goat-chunk-GYC34EGE.mjs} +7 -8
  18. package/dist/{token-goat-chunk-2M33Q3O4.mjs → token-goat-chunk-HPMMLV37.mjs} +369 -120
  19. package/dist/{token-goat-chunk-BK3RPPTK.mjs → token-goat-chunk-IBTFGZBX.mjs} +19 -14
  20. package/dist/{token-goat-chunk-MWSVUKVV.mjs → token-goat-chunk-JNIFSVWM.mjs} +36 -10
  21. package/dist/{token-goat-chunk-KZPO4DWC.mjs → token-goat-chunk-KWM6KBPA.mjs} +2 -2
  22. package/dist/{token-goat-chunk-G75WIVFM.mjs → token-goat-chunk-L2UOJBV4.mjs} +21 -20
  23. package/dist/{token-goat-chunk-2XA5ZW4T.mjs → token-goat-chunk-LACH3WKS.mjs} +4 -4
  24. package/dist/token-goat-chunk-MU6I4IDI.mjs +337 -0
  25. package/dist/{token-goat-chunk-SWRKVA3J.mjs → token-goat-chunk-NJKNAC37.mjs} +1 -1
  26. package/dist/{token-goat-chunk-ERTXEKB6.mjs → token-goat-chunk-NMTKNYGF.mjs} +2 -0
  27. package/dist/{token-goat-chunk-CKIJWTRQ.mjs → token-goat-chunk-NYFYIRG3.mjs} +12 -12
  28. package/dist/{token-goat-chunk-4EXFN2AW.mjs → token-goat-chunk-OZRSREKR.mjs} +2 -2
  29. package/dist/token-goat-chunk-P46RTOAQ.mjs +27 -0
  30. package/dist/{token-goat-chunk-IDHWKNKZ.mjs → token-goat-chunk-PIAESKVU.mjs} +139 -23
  31. package/dist/{token-goat-chunk-26YUO7MP.mjs → token-goat-chunk-S7RFIX4Y.mjs} +180 -50
  32. package/dist/{token-goat-chunk-2VASS5VR.mjs → token-goat-chunk-SOKAPOOC.mjs} +23 -4
  33. package/dist/token-goat-chunk-VJQBYSXG.mjs +20 -0
  34. package/dist/{token-goat-chunk-7VQMOBPQ.mjs → token-goat-chunk-WKO5TVNA.mjs} +948 -618
  35. package/dist/{token-goat-chunk-UBZCON6N.mjs → token-goat-chunk-ZGQXRYKE.mjs} +29 -5
  36. package/dist/token-goat-hook.mjs +12 -12
  37. package/dist/token-goat.core.mjs +21 -20
  38. package/docs/cli.md +4 -3
  39. package/docs/security.md +1 -1
  40. package/package.json +1 -1
  41. package/dist/token-goat-chunk-7EGKXBWT.mjs +0 -173
  42. package/dist/token-goat-chunk-GLOM5W5C.mjs +0 -93
@@ -9,28 +9,28 @@ import {
9
9
  savedTokensFromBytes,
10
10
  storeBlob,
11
11
  stripAnsiEscapes
12
- } from "./token-goat-chunk-26YUO7MP.mjs";
12
+ } from "./token-goat-chunk-S7RFIX4Y.mjs";
13
13
  import {
14
14
  sanitizeFtsQuery
15
- } from "./token-goat-chunk-BK3RPPTK.mjs";
15
+ } from "./token-goat-chunk-IBTFGZBX.mjs";
16
16
  import {
17
17
  getDb
18
- } from "./token-goat-chunk-MWSVUKVV.mjs";
18
+ } from "./token-goat-chunk-JNIFSVWM.mjs";
19
19
  import {
20
20
  loadConfig,
21
21
  shortFingerprint
22
- } from "./token-goat-chunk-2VASS5VR.mjs";
22
+ } from "./token-goat-chunk-SOKAPOOC.mjs";
23
23
  import {
24
24
  registerReset
25
25
  } from "./token-goat-chunk-EEIDFMEM.mjs";
26
26
  import {
27
27
  globalDbPath,
28
28
  runGit
29
- } from "./token-goat-chunk-UBZCON6N.mjs";
29
+ } from "./token-goat-chunk-ZGQXRYKE.mjs";
30
30
  import {
31
31
  normalizePath,
32
32
  resolveIndexPath
33
- } from "./token-goat-chunk-ERTXEKB6.mjs";
33
+ } from "./token-goat-chunk-NMTKNYGF.mjs";
34
34
  import {
35
35
  init_define_import_meta_env
36
36
  } from "./token-goat-chunk-A37V4PBF.mjs";
@@ -1520,6 +1520,9 @@ function commandHashSync(command, cwd = null) {
1520
1520
  function commandHash(command, cwd = null) {
1521
1521
  return Promise.resolve(commandHashSync(command, cwd));
1522
1522
  }
1523
+ function bashOutputIdSync(command, output, cwd = null) {
1524
+ return shortFingerprint(`${commandHashSync(command, cwd)}\0${output}`);
1525
+ }
1523
1526
  function computeBashFingerprints(command, cwd) {
1524
1527
  const fingerprints = {};
1525
1528
  if (cwd && (isGitMutableCommand(command) || isGitPushCommand(command) || isTestRunnerCommand2(command) || isLintCommand(command) || isBuildCommand(command) || isNpmRunScriptCommand(command))) {
@@ -1630,7 +1633,8 @@ function summarizeOutputDelta(oldOutput, newOutput) {
1630
1633
  return `[token-goat: delta] output changed: ${oldLines.length} -> ${newLines.length} lines`;
1631
1634
  }
1632
1635
  function storeBashOutputSync(command, output, exitCode, cwd = null) {
1633
- const id = commandHashSync(command, cwd);
1636
+ const id = bashOutputIdSync(command, output, cwd);
1637
+ const commandKey = commandHashSync(command, cwd);
1634
1638
  const fingerprints = computeBashFingerprints(command, cwd);
1635
1639
  const redactedOutput = redactSecrets(output).text;
1636
1640
  const redactedCommand = redactSecrets(command).text;
@@ -1644,11 +1648,18 @@ function storeBashOutputSync(command, output, exitCode, cwd = null) {
1644
1648
  ...fingerprints ? { fingerprints } : {}
1645
1649
  };
1646
1650
  _byId.set(id, entry);
1651
+ _byId.set(commandKey, entry);
1647
1652
  storeBlob(BASH_OUTPUT_SUBDIR, id, entry);
1653
+ if (commandKey !== id) storeBlob(BASH_OUTPUT_SUBDIR, commandKey, { latestId: id });
1648
1654
  indexRecallEntry("bash", id, redactedCommand, `${redactedCommand}
1649
1655
  ${redactedOutput}`, entry.storedAt);
1650
1656
  return id;
1651
1657
  }
1658
+ function coerceBashRedirect(raw) {
1659
+ if (raw === null || typeof raw !== "object") return null;
1660
+ const latest = raw["latestId"];
1661
+ return typeof latest === "string" && latest.length > 0 ? latest : null;
1662
+ }
1652
1663
  function storeBashOutput(command, output, exitCode, cwd = null) {
1653
1664
  return Promise.resolve(storeBashOutputSync(command, output, exitCode, cwd));
1654
1665
  }
@@ -1682,7 +1693,17 @@ function getBashOutput(id) {
1682
1693
  const hit = _byId.get(id);
1683
1694
  if (hit !== void 0) return hit;
1684
1695
  if (isBlobStale(BASH_OUTPUT_SUBDIR, id)) return null;
1685
- const entry = coerceBashEntry(loadBlob(BASH_OUTPUT_SUBDIR, id));
1696
+ const raw = loadBlob(BASH_OUTPUT_SUBDIR, id);
1697
+ const target = coerceBashRedirect(raw);
1698
+ if (target !== null) {
1699
+ if (isBlobStale(BASH_OUTPUT_SUBDIR, target)) return null;
1700
+ const latest = coerceBashEntry(loadBlob(BASH_OUTPUT_SUBDIR, target));
1701
+ if (latest === null) return null;
1702
+ _byId.set(target, latest);
1703
+ _byId.set(id, latest);
1704
+ return latest;
1705
+ }
1706
+ const entry = coerceBashEntry(raw);
1686
1707
  if (entry === null) return null;
1687
1708
  _byId.set(id, entry);
1688
1709
  return entry;
@@ -1694,6 +1715,7 @@ registerReset(() => {
1694
1715
  // src/tool_filters/base.ts
1695
1716
  init_define_import_meta_env();
1696
1717
  var DEFAULT_MIN_NET_SAVINGS_BYTES = 100;
1718
+ var EARLY_EXIT_NOTE = "early-exit: normalisation alone sufficient";
1697
1719
  function resolveMinNetSavingsBytes() {
1698
1720
  try {
1699
1721
  return loadConfig().bash_compress.min_net_savings_bytes;
@@ -1744,28 +1766,19 @@ var CompressedOutput = class {
1744
1766
  return 100 * this.bytesSaved / this.originalBytes;
1745
1767
  }
1746
1768
  /**
1747
- * Byte cost of the trailing marker {@link withMarker} would append for this
1748
- * result's filter name and percentage. The marker is not free — a rewrite
1749
- * whose `bytesSaved` doesn't even cover its own marker is strictly worse
1750
- * than doing nothing.
1769
+ * Byte cost of the trailing marker {@link withMarker} would append for this result's filter name and percentage. The marker is not free — a rewrite whose `bytesSaved` doesn't even cover its own marker is strictly worse than doing nothing.
1751
1770
  */
1752
1771
  get markerBytes() {
1753
1772
  return byteLength(compressionMarker(this.filterName, this.percentSaved));
1754
1773
  }
1755
1774
  /**
1756
- * Net savings after subtracting the marker's own byte cost — the true
1757
- * benefit of shipping the rewrite instead of the untouched original.
1775
+ * Net savings after subtracting the marker's own byte cost — the true benefit of shipping the rewrite instead of the untouched original.
1758
1776
  */
1759
1777
  get netSavingsBytes() {
1760
1778
  return this.bytesSaved - this.markerBytes;
1761
1779
  }
1762
1780
  /**
1763
- * Single definition of "is this rewrite worth shipping". `minNetSavingsBytes`
1764
- * is the configured floor (`bash_compress.min_net_savings_bytes`) below
1765
- * which a rewrite is considered too trivial to justify destabilising the
1766
- * bytes (breaks provider prefix caching) for — every consumer that chooses
1767
- * between the compressed body and the original output must go through this,
1768
- * not re-derive its own `bytesSaved > 0` check.
1781
+ * Single definition of "is this rewrite worth shipping". `minNetSavingsBytes` is the configured floor (`bash_compress.min_net_savings_bytes`) below which a rewrite is considered too trivial to justify destabilising the bytes (breaks provider prefix caching) for — every consumer that chooses between the compressed body and the original output must go through this, not re-derive its own `bytesSaved > 0` check.
1769
1782
  */
1770
1783
  worthApplying(minNetSavingsBytes) {
1771
1784
  return isRewriteWorthwhile({
@@ -1776,10 +1789,7 @@ var CompressedOutput = class {
1776
1789
  });
1777
1790
  }
1778
1791
  /**
1779
- * `text` with the trailing compression-summary marker appended. Skipped
1780
- * entirely when the rewrite doesn't clear `minNetSavingsBytes` (default 0,
1781
- * i.e. the marker must at least pay for itself) so raw output never carries
1782
- * a marker for a trivial or net-negative rewrite.
1792
+ * `text` with the trailing compression-summary marker appended. Skipped entirely when the rewrite doesn't clear `minNetSavingsBytes` (default 0, i.e. the marker must at least pay for itself) so raw output never carries a marker for a trivial or net-negative rewrite.
1783
1793
  */
1784
1794
  withMarker(minNetSavingsBytes = 0) {
1785
1795
  if (!this.worthApplying(minNetSavingsBytes)) return this.text;
@@ -1794,10 +1804,7 @@ var ToolFilter = class {
1794
1804
  /** When true, pass raw error output through on non-zero exit. */
1795
1805
  errorPassthrough = false;
1796
1806
  /**
1797
- * Return true when this filter should run for `argv`. Checks `binaries`
1798
- * against the lowercased stem (and full name, for dot-in-name binaries like
1799
- * `py.test`) of `argv[0]`; when `subcommands` is non-empty, requires one in
1800
- * the first three positional args.
1807
+ * Return true when this filter should run for `argv`. Checks `binaries` against the lowercased stem (and full name, for dot-in-name binaries like `py.test`) of `argv[0]`; when `subcommands` is non-empty, requires one in the first three positional args.
1801
1808
  */
1802
1809
  matches(argv) {
1803
1810
  if (argv.length === 0) return false;
@@ -1821,18 +1828,13 @@ var ToolFilter = class {
1821
1828
  return squeezeBlankLines(kept.join("\n"));
1822
1829
  }
1823
1830
  /**
1824
- * Hook applied to each stream right after {@link normalise}. Identity by
1825
- * default; the git filter family overrides it to strip CRLF warnings. Keeps
1826
- * `apply` free of per-family name checks.
1831
+ * Hook applied to each stream right after {@link normalise}. Identity by default; the git filter family overrides it to strip CRLF warnings. Keeps `apply` free of per-family name checks.
1827
1832
  */
1828
1833
  postNormalise(text) {
1829
1834
  return text;
1830
1835
  }
1831
1836
  /**
1832
- * Template: when {@link errorPassthrough} is set, return the raw combined
1833
- * error output on non-zero exit before delegating to {@link compressBody}.
1834
- * Filters that handle errors structurally (pytest, cargo) override this
1835
- * directly and leave `errorPassthrough` false.
1837
+ * Template: when {@link errorPassthrough} is set, return the raw combined error output on non-zero exit before delegating to {@link compressBody}. Filters that handle errors structurally (pytest, cargo) override this directly and leave `errorPassthrough` false.
1836
1838
  */
1837
1839
  compress(stdout, stderr, exitCode, argv, ctx = {}) {
1838
1840
  if (this.errorPassthrough) {
@@ -1842,9 +1844,7 @@ var ToolFilter = class {
1842
1844
  return this.compressBody(stdout, stderr, exitCode, argv, ctx);
1843
1845
  }
1844
1846
  /**
1845
- * Inner compression logic, called after the error-passthrough guard.
1846
- * Default is a passthrough that joins the two streams — useful when the only
1847
- * compression is the ANSI / progress strip `apply` already performed.
1847
+ * Inner compression logic, called after the error-passthrough guard. Default is a passthrough that joins the two streams — useful when the only compression is the ANSI / progress strip `apply` already performed.
1848
1848
  */
1849
1849
  compressBody(stdout, stderr, _exitCode, _argv, _ctx = {}) {
1850
1850
  if (stderr && stdout) return `${stdout.replace(/\s+$/, "")}
@@ -1853,10 +1853,7 @@ ${stderr.replace(/\s+$/, "")}`;
1853
1853
  return stdout || stderr;
1854
1854
  }
1855
1855
  /**
1856
- * Top-level entry: sanitise → input cap → normalise → compress → line/byte
1857
- * cap → wrap in {@link CompressedOutput}. Faithful port of the Python
1858
- * `apply` 10-step pipeline. Errors from {@link compress} fall back to a
1859
- * truncated view so the agent always sees something.
1856
+ * Top-level entry: sanitise → input cap → normalise → compress → line/byte cap → wrap in {@link CompressedOutput}. Faithful port of the Python `apply` 10-step pipeline. Errors from {@link compress} fall back to a truncated view so the agent always sees something.
1860
1857
  */
1861
1858
  apply(stdout, stderr, exitCode, argv, opts = {}) {
1862
1859
  const maxLines = opts.maxLines ?? DEFAULT_MAX_LINES;
@@ -1907,7 +1904,7 @@ ${stderr.replace(/\s+$/, "")}`;
1907
1904
  const normBytes = byteLength(normOut) + byteLength(normErr);
1908
1905
  if (preNormBytes > 0 && normBytes <= preNormBytes * 0.6) {
1909
1906
  body = compressBashOutput(normOut, normErr);
1910
- notes.push("early-exit: normalisation alone sufficient");
1907
+ notes.push(EARLY_EXIT_NOTE);
1911
1908
  } else if (normBytes > MAX_INSPECT_BYTES) {
1912
1909
  notes.push(`input exceeded inspect budget (${Math.floor(MAX_INSPECT_BYTES / 1024)} KiB); fell back to truncation`);
1913
1910
  body = fallbackTruncate(normOut, normErr, maxLines);
@@ -1929,7 +1926,8 @@ ${stderr.replace(/\s+$/, "")}`;
1929
1926
  body = redacted.text;
1930
1927
  redactedCount += redacted.count;
1931
1928
  if (redactedCount > 0) notes.push(`redacted ${redactedCount} secret-shaped value(s)`);
1932
- if (notes.length) body = `[${notes.join("; ")}]
1929
+ const shown = notes.filter((n) => n !== EARLY_EXIT_NOTE);
1930
+ if (shown.length) body = `[${shown.join("; ")}]
1933
1931
  ${body}`;
1934
1932
  return new CompressedOutput(body, originalBytes, byteLength(body), this.name, exitCode, notes);
1935
1933
  }
@@ -6674,6 +6672,8 @@ var GrepFilter = class extends ToolFilter {
6674
6672
  if (nonEmpty.length <= _GREP_COMPRESS_THRESHOLD) return clipGrepLines(text, argv);
6675
6673
  const fileCounts = /* @__PURE__ */ new Map();
6676
6674
  let unattributed = 0;
6675
+ const searchFiles = positionalArgs(argv.slice(1)).slice(1);
6676
+ const singleFile = searchFiles.length === 1 ? searchFiles[0] : void 0;
6677
6677
  for (const line of nonEmpty) {
6678
6678
  if (line.startsWith("Binary file ") && line.includes(" matches")) {
6679
6679
  const fname = line.slice("Binary file ".length).replace(/ matches$/, "");
@@ -6690,6 +6690,10 @@ var GrepFilter = class extends ToolFilter {
6690
6690
  continue;
6691
6691
  }
6692
6692
  }
6693
+ if (singleFile !== void 0 && (/^\d+[:-]/.test(line) || colonIdx <= 0)) {
6694
+ fileCounts.set(singleFile, (fileCounts.get(singleFile) ?? 0) + 1);
6695
+ continue;
6696
+ }
6693
6697
  unattributed++;
6694
6698
  }
6695
6699
  const totalMatches = [...fileCounts.values()].reduce((a, b) => a + b, 0) + unattributed;
@@ -14936,6 +14940,12 @@ var PytestFilter = class extends ToolFilter {
14936
14940
  }
14937
14941
  };
14938
14942
  var pytestFilter = new PytestFilter();
14943
+ function looksLikePytestOutput(text) {
14944
+ const lines = text.split("\n").filter((line) => line.trim() !== "");
14945
+ if (lines.length === 0) return false;
14946
+ const progressLines = lines.filter((line) => DOTS_RE.test(line) || FILE_DOTS_RE.test(line) || HEADER_RE.test(line) || XDIST_PREFIX_RE.test(line));
14947
+ return progressLines.length / lines.length >= 0.5;
14948
+ }
14939
14949
 
14940
14950
  // src/tool_filters/test_runners.ts
14941
14951
  init_define_import_meta_env();
@@ -15117,6 +15127,7 @@ export {
15117
15127
  splitOwnTrailingNotices,
15118
15128
  dedupeConsecutive,
15119
15129
  capTokens,
15130
+ pathStem,
15120
15131
  shlexSplit,
15121
15132
  clipLongMatchLine,
15122
15133
  isLockFile,
@@ -15135,6 +15146,7 @@ export {
15135
15146
  isScopedGitStatusOrDiffStatCommand,
15136
15147
  normalizeCommandForCacheKey,
15137
15148
  commandHash,
15149
+ bashOutputIdSync,
15138
15150
  isBashEntryStale,
15139
15151
  summarizeOutputDelta,
15140
15152
  storeBashOutputSync,
@@ -15145,6 +15157,8 @@ export {
15145
15157
  compressedTokensSaved,
15146
15158
  CompressedOutput,
15147
15159
  ToolFilter,
15160
+ pytestFilter,
15161
+ looksLikePytestOutput,
15148
15162
  TOOL_FILTERS,
15149
15163
  dispatchArgv,
15150
15164
  selectFilter,
@@ -25,11 +25,11 @@ import {
25
25
  extractSwift,
26
26
  extractThrift,
27
27
  extractWgsl
28
- } from "./token-goat-chunk-SWRKVA3J.mjs";
28
+ } from "./token-goat-chunk-NJKNAC37.mjs";
29
29
  import {
30
30
  extractShellBannerHeading
31
- } from "./token-goat-chunk-73GXYYZR.mjs";
32
- import "./token-goat-chunk-BK3RPPTK.mjs";
31
+ } from "./token-goat-chunk-EP7TCWHM.mjs";
32
+ import "./token-goat-chunk-IBTFGZBX.mjs";
33
33
  import {
34
34
  GENERIC_CLAUSE,
35
35
  assignBraceBlockSpans,
@@ -58,16 +58,16 @@ import {
58
58
  stripMultilineStringSpan,
59
59
  stripStringLiterals,
60
60
  stripXmlComments
61
- } from "./token-goat-chunk-MWSVUKVV.mjs";
62
- import "./token-goat-chunk-2VASS5VR.mjs";
61
+ } from "./token-goat-chunk-JNIFSVWM.mjs";
62
+ import "./token-goat-chunk-SOKAPOOC.mjs";
63
63
  import "./token-goat-chunk-EEIDFMEM.mjs";
64
64
  import "./token-goat-chunk-OSUFN2FV.mjs";
65
65
  import {
66
66
  countContentLines,
67
67
  escapeRegExp,
68
68
  pushAll
69
- } from "./token-goat-chunk-UBZCON6N.mjs";
70
- import "./token-goat-chunk-ERTXEKB6.mjs";
69
+ } from "./token-goat-chunk-ZGQXRYKE.mjs";
70
+ import "./token-goat-chunk-NMTKNYGF.mjs";
71
71
  import "./token-goat-chunk-Y4AFKTHK.mjs";
72
72
  import "./token-goat-chunk-GMOUBOX4.mjs";
73
73
  import {
@@ -525,6 +525,54 @@ function isNoise(name) {
525
525
  return NOISE_IDS_CLASSES.has(name.toLowerCase());
526
526
  }
527
527
  var MAX_SYMBOLS = 1e4;
528
+ var VOID_ELEMENTS = /* @__PURE__ */ new Set(["area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", "source", "track", "wbr"]);
529
+ var TAG_RE = /<(\/?)([a-zA-Z][a-zA-Z0-9:-]*)(?:\s(?:"[^"]*"|'[^']*'|[^'">])*)?>/g;
530
+ var ELEMENT_SPAN_SCAN_CAP = 2e6;
531
+ function buildElementSpans(code) {
532
+ const spans = /* @__PURE__ */ new Map();
533
+ const openTagRanges = [];
534
+ const stack = [];
535
+ TAG_RE.lastIndex = 0;
536
+ let m;
537
+ while ((m = TAG_RE.exec(code)) !== null) {
538
+ if (m.index > ELEMENT_SPAN_SCAN_CAP) break;
539
+ const isClose = m[1] === "/";
540
+ const name = (m[2] ?? "").toLowerCase();
541
+ const selfClosing = m[0][m[0].length - 2] === "/";
542
+ const tagEnd = m.index + m[0].length;
543
+ if (isClose) {
544
+ for (let i = stack.length - 1; i >= 0; i--) {
545
+ if (stack[i].name === name) {
546
+ spans.set(stack[i].start, tagEnd);
547
+ stack.length = i;
548
+ break;
549
+ }
550
+ }
551
+ continue;
552
+ }
553
+ openTagRanges.push({ start: m.index, end: tagEnd });
554
+ if (selfClosing || VOID_ELEMENTS.has(name)) continue;
555
+ if (name === "style") {
556
+ const closeMatch = /<\/style\s*>/gi.exec(code.slice(tagEnd));
557
+ if (closeMatch !== null) TAG_RE.lastIndex = tagEnd + closeMatch.index + closeMatch[0].length;
558
+ continue;
559
+ }
560
+ stack.push({ name, start: m.index });
561
+ }
562
+ return { spans, openTagRanges };
563
+ }
564
+ function findEnclosingTagStart(openTagRanges, offset) {
565
+ let lo = 0;
566
+ let hi = openTagRanges.length - 1;
567
+ while (lo <= hi) {
568
+ const mid = lo + hi >> 1;
569
+ const range = openTagRanges[mid];
570
+ if (offset < range.start) hi = mid - 1;
571
+ else if (offset >= range.end) lo = mid + 1;
572
+ else return range.start;
573
+ }
574
+ return null;
575
+ }
528
576
  function extractHtml(content, filePath) {
529
577
  const symbols = [];
530
578
  const imports = [];
@@ -550,6 +598,7 @@ function extractHtml(content, filePath) {
550
598
  assignFlatEndLines(sections, totalLines);
551
599
  const seenId = /* @__PURE__ */ new Set();
552
600
  const seenClass = /* @__PURE__ */ new Set();
601
+ const { spans: elementSpans, openTagRanges } = buildElementSpans(code);
553
602
  for (const m of code.matchAll(ID_RE)) {
554
603
  if (symbols.length >= MAX_SYMBOLS) break;
555
604
  const idVal = m[2] ?? "";
@@ -558,7 +607,10 @@ function extractHtml(content, filePath) {
558
607
  const key = `${idVal}\0${line}`;
559
608
  if (!seenId.has(key)) {
560
609
  seenId.add(key);
561
- symbols.push({ filePath, name: idVal, kind: "html_id", lineStart: line, lineEnd: line, body: "", docstring: "", parent: "" });
610
+ const tagStart = findEnclosingTagStart(openTagRanges, m.index ?? 0);
611
+ const elementEnd = tagStart !== null ? elementSpans.get(tagStart) : void 0;
612
+ const lineEnd = elementEnd !== void 0 ? offsetToLine(lineIndex, elementEnd - 1) : line;
613
+ symbols.push({ filePath, name: idVal, kind: "html_id", lineStart: line, lineEnd, body: "", docstring: "", parent: "" });
562
614
  }
563
615
  }
564
616
  }
@@ -12,7 +12,7 @@ import {
12
12
  } from "./token-goat-chunk-AH6QILZM.mjs";
13
13
  import {
14
14
  pushAll
15
- } from "./token-goat-chunk-UBZCON6N.mjs";
15
+ } from "./token-goat-chunk-ZGQXRYKE.mjs";
16
16
  import {
17
17
  DocumentRefusedError,
18
18
  MAX_DOCUMENT_WORK_MILLIS
@@ -5,7 +5,7 @@ import {
5
5
  } from "./token-goat-chunk-OSUFN2FV.mjs";
6
6
  import {
7
7
  displaySafeText
8
- } from "./token-goat-chunk-ERTXEKB6.mjs";
8
+ } from "./token-goat-chunk-NMTKNYGF.mjs";
9
9
  import {
10
10
  init_define_import_meta_env
11
11
  } from "./token-goat-chunk-A37V4PBF.mjs";
@@ -8,6 +8,7 @@ import {
8
8
  createHandoff,
9
9
  fileIdentity,
10
10
  findSpecSeparator,
11
+ parseColonLineSpec,
11
12
  parseLineRange,
12
13
  pinKey,
13
14
  resolveHandoff,
@@ -25,42 +26,43 @@ import {
25
26
  runSkeleton,
26
27
  runSymbol,
27
28
  withPinnedReads
28
- } from "./token-goat-chunk-IDHWKNKZ.mjs";
29
- import "./token-goat-chunk-CICJFVIH.mjs";
30
- import "./token-goat-chunk-LMFO66YD.mjs";
29
+ } from "./token-goat-chunk-PIAESKVU.mjs";
30
+ import "./token-goat-chunk-F24NE3FO.mjs";
31
+ import "./token-goat-chunk-DA43OE7L.mjs";
31
32
  import {
32
33
  buildProjectMap,
34
+ claudeConfigDir,
33
35
  formatProjectMap,
34
36
  getDirtyPathsFor,
35
37
  getEmbeddingCoverage,
36
38
  getProjectIndexCounts,
37
39
  isWorkerRunning,
38
40
  mapLookupBytesSaved
39
- } from "./token-goat-chunk-PKNOHVWP.mjs";
40
- import "./token-goat-chunk-C26ZBGBC.mjs";
41
+ } from "./token-goat-chunk-FQYMZASI.mjs";
42
+ import "./token-goat-chunk-7DGTVBWP.mjs";
41
43
  import {
42
44
  recordStat,
43
45
  savedTokensFromBytes
44
- } from "./token-goat-chunk-26YUO7MP.mjs";
46
+ } from "./token-goat-chunk-S7RFIX4Y.mjs";
45
47
  import "./token-goat-chunk-LKSXAMJB.mjs";
46
- import "./token-goat-chunk-KZPO4DWC.mjs";
48
+ import "./token-goat-chunk-KWM6KBPA.mjs";
47
49
  import "./token-goat-chunk-3BTK54F3.mjs";
48
50
  import "./token-goat-chunk-XTQAOTSO.mjs";
49
51
  import "./token-goat-chunk-AH6QILZM.mjs";
50
- import "./token-goat-chunk-SWRKVA3J.mjs";
52
+ import "./token-goat-chunk-NJKNAC37.mjs";
51
53
  import {
52
54
  checkEmbeddingPreflight,
53
55
  embeddingsDepsAvailable
54
- } from "./token-goat-chunk-73GXYYZR.mjs";
55
- import "./token-goat-chunk-BK3RPPTK.mjs";
56
+ } from "./token-goat-chunk-EP7TCWHM.mjs";
57
+ import "./token-goat-chunk-IBTFGZBX.mjs";
56
58
  import {
57
59
  getDb
58
- } from "./token-goat-chunk-MWSVUKVV.mjs";
60
+ } from "./token-goat-chunk-JNIFSVWM.mjs";
59
61
  import {
60
62
  envStrList,
61
63
  loadConfig,
62
64
  resolveProjectRoot
63
- } from "./token-goat-chunk-2VASS5VR.mjs";
65
+ } from "./token-goat-chunk-SOKAPOOC.mjs";
64
66
  import "./token-goat-chunk-EEIDFMEM.mjs";
65
67
  import "./token-goat-chunk-OSUFN2FV.mjs";
66
68
  import {
@@ -70,11 +72,11 @@ import {
70
72
  extractErrorMessage,
71
73
  foldCaseForContainment,
72
74
  globalDbPath
73
- } from "./token-goat-chunk-UBZCON6N.mjs";
75
+ } from "./token-goat-chunk-ZGQXRYKE.mjs";
74
76
  import {
75
77
  displaySafeJson,
76
78
  normalizePath
77
- } from "./token-goat-chunk-ERTXEKB6.mjs";
79
+ } from "./token-goat-chunk-NMTKNYGF.mjs";
78
80
  import "./token-goat-chunk-Y4AFKTHK.mjs";
79
81
  import "./token-goat-chunk-GMOUBOX4.mjs";
80
82
  import "./token-goat-chunk-RRNZMM3A.mjs";
@@ -170,10 +172,11 @@ var RootNotAllowedError = class extends Error {
170
172
  };
171
173
  function getStandardAuxiliaryRoots(targetPath) {
172
174
  const home = os.homedir();
175
+ const claudeHome = claudeConfigDir(home);
173
176
  const roots = [
174
- path.join(home, ".claude", "skills"),
177
+ path.join(claudeHome, "skills"),
175
178
  path.join(home, ".copilot", "skills"),
176
- path.join(home, ".claude", "projects"),
179
+ path.join(claudeHome, "projects"),
177
180
  path.join(home, ".copilot", "session-state")
178
181
  ];
179
182
  const appData = process.env["APPDATA"] || path.join(home, "AppData", "Roaming");
@@ -244,6 +247,8 @@ function checkWithinProjectRoot(target, resolvedRoot) {
244
247
  function specFilePart(spec) {
245
248
  const range = parseLineRange(spec);
246
249
  if (range !== null) return range.file;
250
+ const region = parseColonLineSpec(spec);
251
+ if (region !== null) return region.file;
247
252
  const colonIdx = findSpecSeparator(spec);
248
253
  return colonIdx === -1 ? spec : spec.slice(0, colonIdx);
249
254
  }
@@ -11,10 +11,10 @@ import {
11
11
  ooxmlPartBudget,
12
12
  parseOoxmlPart,
13
13
  readOoxmlZip
14
- } from "./token-goat-chunk-66224KCZ.mjs";
14
+ } from "./token-goat-chunk-BTKDZW7F.mjs";
15
15
  import {
16
16
  displaySafeText
17
- } from "./token-goat-chunk-ERTXEKB6.mjs";
17
+ } from "./token-goat-chunk-NMTKNYGF.mjs";
18
18
  import {
19
19
  init_define_import_meta_env
20
20
  } from "./token-goat-chunk-A37V4PBF.mjs";