token-goat 2.9.30 → 2.9.31

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 (172) hide show
  1. package/README.md +24 -7
  2. package/SECURITY.md +10 -2
  3. package/THIRD_PARTY_NOTICES.md +1 -1
  4. package/dist/native/linux-arm64/tg-hook +0 -0
  5. package/dist/native/linux-x64/tg-hook +0 -0
  6. package/dist/native/win32-arm64/tg-hook.exe +0 -0
  7. package/dist/native/win32-x64/tg-hook.exe +0 -0
  8. package/dist/{token-goat-chunk-QSBRTGM2.mjs → token-goat-chunk-25TRAWET.mjs} +17 -7
  9. package/dist/token-goat-chunk-2KXO6V2B.mjs +203 -0
  10. package/dist/{token-goat-chunk-IVKIZWAB.mjs → token-goat-chunk-2M7E4PF7.mjs} +41 -12
  11. package/dist/{token-goat-chunk-SMVRN2HU.mjs → token-goat-chunk-2UPZGKKY.mjs} +2 -2
  12. package/dist/token-goat-chunk-2WLPWKHV.mjs +135 -0
  13. package/dist/token-goat-chunk-2XBMMDBD.mjs +126 -0
  14. package/dist/token-goat-chunk-32ZOY4N5.mjs +23 -0
  15. package/dist/token-goat-chunk-3EZRNKTK.mjs +188 -0
  16. package/dist/token-goat-chunk-4ADZHI7J.mjs +63 -0
  17. package/dist/token-goat-chunk-4GBVPH3D.mjs +242 -0
  18. package/dist/{token-goat-chunk-KWPNJBDH.mjs → token-goat-chunk-4GILLLWY.mjs} +7 -4
  19. package/dist/{token-goat-chunk-67TQJ76B.mjs → token-goat-chunk-4NAPX7BA.mjs} +36 -3
  20. package/dist/{token-goat-chunk-PU7V3FD6.mjs → token-goat-chunk-4SC7UJYV.mjs} +3354 -2553
  21. package/dist/token-goat-chunk-4SMRO4TO.mjs +366 -0
  22. package/dist/{token-goat-chunk-AFLYLHDH.mjs → token-goat-chunk-4ZBFWLXF.mjs} +283 -427
  23. package/dist/{token-goat-chunk-JDWCRD6M.mjs → token-goat-chunk-57BIAXJL.mjs} +73 -40
  24. package/dist/token-goat-chunk-5AC66HNP.mjs +115 -0
  25. package/dist/token-goat-chunk-5IMLKSOP.mjs +145 -0
  26. package/dist/token-goat-chunk-646E6U44.mjs +398 -0
  27. package/dist/token-goat-chunk-65N4RHP4.mjs +33 -0
  28. package/dist/{token-goat-chunk-JN4XMLSD.mjs → token-goat-chunk-6DG6HWP3.mjs} +8 -2
  29. package/dist/token-goat-chunk-6ENQSNRZ.mjs +573 -0
  30. package/dist/token-goat-chunk-6ZY4GNF2.mjs +91 -0
  31. package/dist/{token-goat-chunk-VPBBTSJR.mjs → token-goat-chunk-76FGDLRO.mjs} +262 -255
  32. package/dist/{token-goat-chunk-7IN2MKDS.mjs → token-goat-chunk-7EZTZOMC.mjs} +121 -289
  33. package/dist/{token-goat-chunk-OJBNYTJP.mjs → token-goat-chunk-7MAOA6X4.mjs} +640 -80
  34. package/dist/token-goat-chunk-7R2ZVVAX.mjs +218 -0
  35. package/dist/{token-goat-chunk-PD5VKH46.mjs → token-goat-chunk-AUNGYYQX.mjs} +2 -2
  36. package/dist/{token-goat-chunk-HG45AF2B.mjs → token-goat-chunk-AUQYRMMH.mjs} +794 -37
  37. package/dist/token-goat-chunk-B3PEKBYG.mjs +128 -0
  38. package/dist/{token-goat-chunk-A3CK6N5Z.mjs → token-goat-chunk-BA4HI6BW.mjs} +1309 -110
  39. package/dist/{token-goat-chunk-JB6QN6VF.mjs → token-goat-chunk-BFCWY73P.mjs} +59 -23
  40. package/dist/{token-goat-chunk-B45VMIIH.mjs → token-goat-chunk-BWGFUZZE.mjs} +7 -5
  41. package/dist/{token-goat-chunk-P4QMM4WK.mjs → token-goat-chunk-C75NA7PL.mjs} +50 -23
  42. package/dist/token-goat-chunk-CBIQ7WTD.mjs +87 -0
  43. package/dist/token-goat-chunk-CETM74KC.mjs +307 -0
  44. package/dist/{token-goat-chunk-H2PHHGM5.mjs → token-goat-chunk-CIMQ2BB3.mjs} +57 -12
  45. package/dist/{token-goat-chunk-N2NMER56.mjs → token-goat-chunk-CJLS3CDL.mjs} +46 -4
  46. package/dist/{token-goat-chunk-VES7EL7O.mjs → token-goat-chunk-CO3UYX6G.mjs} +1 -1
  47. package/dist/token-goat-chunk-COPNXRJM.mjs +154 -0
  48. package/dist/token-goat-chunk-CSJ5L3NL.mjs +479 -0
  49. package/dist/{token-goat-chunk-4LCCNRTG.mjs → token-goat-chunk-CVCEVUGK.mjs} +8 -6
  50. package/dist/{token-goat-chunk-B2RZZCSS.mjs → token-goat-chunk-CXHOFN7R.mjs} +37 -20
  51. package/dist/token-goat-chunk-D735C4QM.mjs +603 -0
  52. package/dist/{token-goat-chunk-APGZXSPS.mjs → token-goat-chunk-DGS2LVNA.mjs} +47 -30
  53. package/dist/{token-goat-chunk-54K3EUV3.mjs → token-goat-chunk-DOWRSMWO.mjs} +1 -1
  54. package/dist/token-goat-chunk-E45INMY3.mjs +71 -0
  55. package/dist/token-goat-chunk-EC5F37F4.mjs +244 -0
  56. package/dist/{token-goat-chunk-XTQAOTSO.mjs → token-goat-chunk-EDBDRVH5.mjs} +4 -1
  57. package/dist/{token-goat-chunk-5BCIJXMO.mjs → token-goat-chunk-EELTBKDM.mjs} +14 -10
  58. package/dist/{token-goat-chunk-W3QCJS6G.mjs → token-goat-chunk-F4HYL64R.mjs} +8 -6
  59. package/dist/token-goat-chunk-F6PAUIEK.mjs +624 -0
  60. package/dist/token-goat-chunk-FDSREWLX.mjs +692 -0
  61. package/dist/token-goat-chunk-GGGG7RWB.mjs +236 -0
  62. package/dist/{token-goat-chunk-C63JQV5K.mjs → token-goat-chunk-GL3ETKSC.mjs} +233 -15
  63. package/dist/token-goat-chunk-GVB2MUST.mjs +1298 -0
  64. package/dist/token-goat-chunk-GWFLAUMQ.mjs +307 -0
  65. package/dist/{token-goat-chunk-ZEJVMUQH.mjs → token-goat-chunk-HLPW63A7.mjs} +2 -2
  66. package/dist/{token-goat-chunk-GOLEOXZP.mjs → token-goat-chunk-HU4TORC5.mjs} +44 -26
  67. package/dist/{token-goat-chunk-Z57YODA2.mjs → token-goat-chunk-I7VKZZAW.mjs} +2 -2
  68. package/dist/{token-goat-chunk-NYKZLXMK.mjs → token-goat-chunk-IA6XSPE3.mjs} +6 -6
  69. package/dist/{token-goat-chunk-E3OQX2XT.mjs → token-goat-chunk-IAGXMHIK.mjs} +81 -42
  70. package/dist/{token-goat-chunk-HYBFA5X3.mjs → token-goat-chunk-IK2DRMFX.mjs} +24 -68
  71. package/dist/{token-goat-chunk-COBQGL5S.mjs → token-goat-chunk-INNPTRUX.mjs} +249 -299
  72. package/dist/{token-goat-chunk-7NADEDKJ.mjs → token-goat-chunk-JJ5BX4F4.mjs} +6 -1
  73. package/dist/{token-goat-chunk-PEPTHRFF.mjs → token-goat-chunk-JVFSHVFJ.mjs} +6 -6
  74. package/dist/token-goat-chunk-KGEFFSHD.mjs +50 -0
  75. package/dist/token-goat-chunk-KQBLRPBN.mjs +433 -0
  76. package/dist/{token-goat-chunk-Q5VTGRH7.mjs → token-goat-chunk-LCNQ2CNN.mjs} +55 -319
  77. package/dist/token-goat-chunk-M3LFJDPU.mjs +58 -0
  78. package/dist/token-goat-chunk-M52KPT3C.mjs +87 -0
  79. package/dist/token-goat-chunk-MBEG42H7.mjs +150 -0
  80. package/dist/{token-goat-chunk-EVC4TOLE.mjs → token-goat-chunk-METECDOH.mjs} +3 -12
  81. package/dist/{token-goat-chunk-T4FK7VOV.mjs → token-goat-chunk-MHX7XCC3.mjs} +2 -1
  82. package/dist/token-goat-chunk-N5LSOVSU.mjs +137 -0
  83. package/dist/{token-goat-chunk-LOBGHXPB.mjs → token-goat-chunk-N5MMR2IW.mjs} +1 -1
  84. package/dist/token-goat-chunk-N7B3JQ2C.mjs +160 -0
  85. package/dist/{token-goat-chunk-RHXKCZX3.mjs → token-goat-chunk-NISNMD7T.mjs} +2182 -2959
  86. package/dist/token-goat-chunk-NMD42SFQ.mjs +434 -0
  87. package/dist/token-goat-chunk-NOSS5VWY.mjs +174 -0
  88. package/dist/{token-goat-chunk-KQNZDCBD.mjs → token-goat-chunk-NSNSPPBG.mjs} +25 -3
  89. package/dist/token-goat-chunk-OBOFIHKN.mjs +38 -0
  90. package/dist/token-goat-chunk-OBRFJ5O5.mjs +76 -0
  91. package/dist/{token-goat-chunk-JTQQGXZH.mjs → token-goat-chunk-ODBT2USM.mjs} +124 -57
  92. package/dist/token-goat-chunk-OS5EM5PP.mjs +107 -0
  93. package/dist/token-goat-chunk-OUKDTVNU.mjs +1178 -0
  94. package/dist/token-goat-chunk-OXFMP75N.mjs +566 -0
  95. package/dist/{token-goat-chunk-DZX2YDPT.mjs → token-goat-chunk-OYIYKDDT.mjs} +2 -2
  96. package/dist/{token-goat-chunk-QCLDAQTS.mjs → token-goat-chunk-P6HQSWQ3.mjs} +50 -53
  97. package/dist/token-goat-chunk-P6VGNTQT.mjs +71 -0
  98. package/dist/{token-goat-chunk-7BXSNBY5.mjs → token-goat-chunk-PFWIMH2E.mjs} +23 -15
  99. package/dist/token-goat-chunk-PJZXIS3G.mjs +39 -0
  100. package/dist/token-goat-chunk-PUO5INXP.mjs +606 -0
  101. package/dist/{token-goat-chunk-GFBSN7BD.mjs → token-goat-chunk-PX5PQWTY.mjs} +22 -250
  102. package/dist/token-goat-chunk-Q5QDBC6O.mjs +111 -0
  103. package/dist/token-goat-chunk-QFNQXSDT.mjs +40 -0
  104. package/dist/{token-goat-chunk-FBNQNSJK.mjs → token-goat-chunk-QH7YVYOY.mjs} +2198 -2782
  105. package/dist/{token-goat-chunk-64FBPDTK.mjs → token-goat-chunk-QLMUHEPB.mjs} +12 -9
  106. package/dist/{token-goat-chunk-RZRTDST7.mjs → token-goat-chunk-QQOJIHL3.mjs} +37 -11
  107. package/dist/{token-goat-chunk-XKI4SEMX.mjs → token-goat-chunk-QQTWJY2O.mjs} +19 -0
  108. package/dist/{token-goat-chunk-U4N3BN2W.mjs → token-goat-chunk-QYHO5CPH.mjs} +3 -2
  109. package/dist/token-goat-chunk-RELAVWAD.mjs +27 -0
  110. package/dist/{token-goat-chunk-ETBHVDB6.mjs → token-goat-chunk-RSLPOBKQ.mjs} +22 -11
  111. package/dist/token-goat-chunk-SAMFDIS2.mjs +712 -0
  112. package/dist/token-goat-chunk-SDELXLDM.mjs +48 -0
  113. package/dist/{token-goat-chunk-4JJS54TR.mjs → token-goat-chunk-SOAFZNNZ.mjs} +161 -38
  114. package/dist/{token-goat-chunk-664RTTUV.mjs → token-goat-chunk-SRTHT7KV.mjs} +21 -16
  115. package/dist/{token-goat-chunk-4FVIAHSI.mjs → token-goat-chunk-T5P5ACNQ.mjs} +7 -6
  116. package/dist/token-goat-chunk-T5YGG4V3.mjs +45 -0
  117. package/dist/token-goat-chunk-TAUZ4OFS.mjs +110 -0
  118. package/dist/{token-goat-chunk-COTXZHTS.mjs → token-goat-chunk-TM6MC754.mjs} +4 -3
  119. package/dist/token-goat-chunk-TWUKBOMP.mjs +72 -0
  120. package/dist/{token-goat-chunk-3CHUNJ2O.mjs → token-goat-chunk-U2KSB4SG.mjs} +8 -5
  121. package/dist/{token-goat-chunk-3Z5S4KGM.mjs → token-goat-chunk-U4WHMG6Y.mjs} +29 -49
  122. package/dist/{token-goat-chunk-PY533T7F.mjs → token-goat-chunk-UGJHGR5A.mjs} +21 -15
  123. package/dist/{token-goat-chunk-CYCEYAEO.mjs → token-goat-chunk-UOUDVA5U.mjs} +1 -1
  124. package/dist/{token-goat-chunk-JDHE26RP.mjs → token-goat-chunk-URRJ33GR.mjs} +16 -5
  125. package/dist/{token-goat-chunk-56EIMS3E.mjs → token-goat-chunk-UZOROKIS.mjs} +23 -17
  126. package/dist/{token-goat-chunk-CZ3LUXYZ.mjs → token-goat-chunk-VIHGGGEI.mjs} +427 -308
  127. package/dist/token-goat-chunk-VTJLAA7P.mjs +21 -0
  128. package/dist/token-goat-chunk-VWDXLT4F.mjs +678 -0
  129. package/dist/{token-goat-chunk-YARZFCZS.mjs → token-goat-chunk-VWZA2H4P.mjs} +62 -53
  130. package/dist/{token-goat-chunk-SQSSNQPE.mjs → token-goat-chunk-VXEXMJDL.mjs} +3979 -4745
  131. package/dist/token-goat-chunk-WBA5SKT4.mjs +547 -0
  132. package/dist/{token-goat-chunk-SJHWVNDQ.mjs → token-goat-chunk-WDH44VAU.mjs} +7 -4
  133. package/dist/token-goat-chunk-X2SUP3EI.mjs +107 -0
  134. package/dist/token-goat-chunk-X3BELZSJ.mjs +125 -0
  135. package/dist/{token-goat-chunk-FZ3NEW5O.mjs → token-goat-chunk-XLRBNZCC.mjs} +13 -8
  136. package/dist/{token-goat-chunk-Z44YO3QZ.mjs → token-goat-chunk-XRKUX6CM.mjs} +1 -1
  137. package/dist/token-goat-chunk-XX6O25RN.mjs +82 -0
  138. package/dist/token-goat-chunk-XZSUHBVS.mjs +65 -0
  139. package/dist/{token-goat-chunk-WY3L4DVT.mjs → token-goat-chunk-Y2ZTQOCL.mjs} +13 -8
  140. package/dist/{token-goat-chunk-UQ5UK2T7.mjs → token-goat-chunk-YB4VMGK2.mjs} +1 -1
  141. package/dist/token-goat-chunk-YBIIY3HR.mjs +51 -0
  142. package/dist/{token-goat-chunk-ZQSJMO2R.mjs → token-goat-chunk-YHVDKQBR.mjs} +105 -105
  143. package/dist/{token-goat-chunk-H2K3QP6H.mjs → token-goat-chunk-YJB5XLWI.mjs} +8 -6
  144. package/dist/{token-goat-chunk-ZCDTCVIS.mjs → token-goat-chunk-YKB6AQG3.mjs} +5 -2
  145. package/dist/token-goat-chunk-YMTG2YA5.mjs +35 -0
  146. package/dist/token-goat-chunk-YPBZYQRV.mjs +40 -0
  147. package/dist/{token-goat-chunk-HOJLCGDP.mjs → token-goat-chunk-YY6AVUFL.mjs} +2033 -2251
  148. package/dist/token-goat-chunk-Z7N5OMMP.mjs +98 -0
  149. package/dist/token-goat-chunk-ZNMNUPAZ.mjs +938 -0
  150. package/dist/token-goat-hook-client.cjs +1 -1
  151. package/dist/token-goat-hook-client.mjs +3 -3
  152. package/dist/token-goat-hook.mjs +67 -38
  153. package/dist/token-goat.core.mjs +4 -4
  154. package/docs/C4_RUNTIME_ARCHITECTURE.md +1 -1
  155. package/docs/cli.md +40 -21
  156. package/docs/install.md +19 -9
  157. package/docs/security.md +5 -3
  158. package/package.json +2 -1
  159. package/dist/token-goat-chunk-5KDMCMF2.mjs +0 -362
  160. package/dist/token-goat-chunk-6QMAS7AB.mjs +0 -42
  161. package/dist/token-goat-chunk-7F2UBPD3.mjs +0 -397
  162. package/dist/token-goat-chunk-ARDNEC2U.mjs +0 -248
  163. package/dist/token-goat-chunk-ATCPY7EQ.mjs +0 -134
  164. package/dist/token-goat-chunk-EFHMMIGP.mjs +0 -68
  165. package/dist/token-goat-chunk-IVALLT3S.mjs +0 -48
  166. package/dist/token-goat-chunk-JDU3EXSU.mjs +0 -65
  167. package/dist/token-goat-chunk-MKPF4CL5.mjs +0 -37
  168. package/dist/token-goat-chunk-RC35RBUL.mjs +0 -312
  169. package/dist/token-goat-chunk-USILZ3T3.mjs +0 -53
  170. package/dist/token-goat-chunk-VL3YIFHZ.mjs +0 -2975
  171. package/dist/token-goat-chunk-XU4P6Z24.mjs +0 -133
  172. package/dist/token-goat-chunk-Y776AENC.mjs +0 -1597
@@ -0,0 +1,307 @@
1
+ import { createRequire as __cjsRequire } from 'node:module';
2
+ const require = __cjsRequire(import.meta.url);
3
+ import {
4
+ formatAge
5
+ } from "./token-goat-chunk-SAMFDIS2.mjs";
6
+ import {
7
+ findProject
8
+ } from "./token-goat-chunk-4GBVPH3D.mjs";
9
+ import {
10
+ LOCK_WAIT_MS_HARDENED,
11
+ atomicWriteText,
12
+ countNoun,
13
+ ensureDirSync,
14
+ withFileLock,
15
+ withRetryOnLock
16
+ } from "./token-goat-chunk-HU4TORC5.mjs";
17
+ import {
18
+ sleepSync
19
+ } from "./token-goat-chunk-AM5V6GSX.mjs";
20
+ import {
21
+ fenceUntrustedFileContent
22
+ } from "./token-goat-chunk-FNFBKLRD.mjs";
23
+ import {
24
+ dataDir
25
+ } from "./token-goat-chunk-CO3UYX6G.mjs";
26
+ import {
27
+ init_define_import_meta_env
28
+ } from "./token-goat-chunk-A37V4PBF.mjs";
29
+
30
+ // src/project_memory.ts
31
+ init_define_import_meta_env();
32
+ import * as fs from "node:fs";
33
+ import * as path from "node:path";
34
+ var MAX_ENTRIES = 30;
35
+ var MAX_VALUE_LEN = 300;
36
+ var MAX_TOTAL_CHARS = 4e3;
37
+ var KEY_RE = /^[A-Za-z0-9_-]{1,80}$/;
38
+ var SET_AT_RE = /^#\s*set\s+(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z)$/;
39
+ var ANCHOR_RE = /^#\s*anchor:\s*(\S.*)::([^:@\s]+)@([0-9a-f]{64})$/;
40
+ function anchorLabel(status) {
41
+ if (status === "changed") return " (changed since note)";
42
+ if (status === "gone") return " (anchored symbol gone)";
43
+ return "";
44
+ }
45
+ function anchorLine(anchor) {
46
+ const line = `# anchor: ${anchor.file}::${anchor.symbol}@${anchor.sha}`;
47
+ const back = ANCHOR_RE.exec(line);
48
+ return back !== null && back[1] === anchor.file && back[2] === anchor.symbol ? line : null;
49
+ }
50
+ function noteMap() {
51
+ return /* @__PURE__ */ Object.create(null);
52
+ }
53
+ function ordinal(a, b) {
54
+ return a < b ? -1 : a > b ? 1 : 0;
55
+ }
56
+ function memoryPath(projectHash) {
57
+ return path.join(dataDir(), "projects", `${projectHash}_memory.toml`);
58
+ }
59
+ function validateKey(key) {
60
+ if (!KEY_RE.test(key)) {
61
+ throw new Error(
62
+ `Invalid memory key ${JSON.stringify(key)}: use only letters, digits, hyphens, underscores (max 80 chars)`
63
+ );
64
+ }
65
+ }
66
+ function parseTOML(content, unparsed = [], setAt = /* @__PURE__ */ new Map(), anchors = /* @__PURE__ */ new Map()) {
67
+ const result = noteMap();
68
+ let pendingSetAt;
69
+ let pendingAnchor;
70
+ for (const [i, line] of content.split("\n").entries()) {
71
+ const trimmed = line.trim();
72
+ if (!trimmed) {
73
+ continue;
74
+ }
75
+ if (trimmed.startsWith("#")) {
76
+ const time = SET_AT_RE.exec(trimmed)?.[1];
77
+ if (time !== void 0 && !Number.isNaN(Date.parse(time))) pendingSetAt = time;
78
+ const anchor = ANCHOR_RE.exec(trimmed);
79
+ if (anchor !== null) pendingAnchor = { file: anchor[1], symbol: anchor[2], sha: anchor[3] };
80
+ continue;
81
+ }
82
+ const entrySetAt = pendingSetAt;
83
+ const entryAnchor = pendingAnchor;
84
+ pendingSetAt = void 0;
85
+ pendingAnchor = void 0;
86
+ const match = trimmed.match(/^([A-Za-z0-9_-]+)\s*=\s*"(.*)"\s*$/s);
87
+ if (match) {
88
+ const [, key, value] = match;
89
+ if (key && value !== void 0) {
90
+ const unescaped = value.replace(/\\(u202[89]|[\\nrt"])/g, (_, c) => {
91
+ switch (c) {
92
+ case "u2028":
93
+ return "\u2028";
94
+ case "u2029":
95
+ return "\u2029";
96
+ case "\\":
97
+ return "\\";
98
+ case "n":
99
+ return "\n";
100
+ case "r":
101
+ return "\r";
102
+ case '"':
103
+ return '"';
104
+ default:
105
+ return _;
106
+ }
107
+ });
108
+ result[key] = unescaped;
109
+ if (entrySetAt === void 0) setAt.delete(key);
110
+ else setAt.set(key, entrySetAt);
111
+ if (entryAnchor === void 0) anchors.delete(key);
112
+ else anchors.set(key, entryAnchor);
113
+ }
114
+ } else {
115
+ unparsed.push(i + 1);
116
+ }
117
+ }
118
+ return result;
119
+ }
120
+ function loadRaw(filePath, forUpdate = false, setAt, anchors) {
121
+ let content = "";
122
+ try {
123
+ withRetryOnLock(() => {
124
+ content = fs.readFileSync(filePath, "utf-8");
125
+ });
126
+ } catch (err) {
127
+ if (err.code === "ENOENT") return noteMap();
128
+ throw err;
129
+ }
130
+ const unparsed = [];
131
+ const entries = parseTOML(content, unparsed, setAt, anchors);
132
+ if (forUpdate && unparsed.length > 0) {
133
+ const one = unparsed.length === 1;
134
+ throw new Error(`Not updating ${filePath}: ${one ? "line" : "lines"} ${unparsed.join(", ")} ${one ? "is" : "are"} not in the key = "value" form, and saving would drop ${one ? "it" : "them"}. Fix or remove ${one ? "it" : "them"}, then try again.`);
135
+ }
136
+ return entries;
137
+ }
138
+ function save(filePath, entries, setAt = /* @__PURE__ */ new Map(), anchors = /* @__PURE__ */ new Map()) {
139
+ const lines = [];
140
+ const sorted = Object.entries(entries).sort(([a], [b]) => ordinal(a, b));
141
+ for (const [k, v] of sorted) {
142
+ const escaped = v.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\r/g, "\\r").replace(/\n/g, "\\n").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
143
+ const time = setAt.get(k);
144
+ if (time !== void 0) lines.push(`# set ${time}`);
145
+ const anchor = anchors.get(k);
146
+ const anchored = anchor === void 0 ? null : anchorLine(anchor);
147
+ if (anchored !== null) lines.push(anchored);
148
+ lines.push(`${k} = "${escaped}"`);
149
+ }
150
+ const content = lines.length > 0 ? lines.join("\n") + "\n" : "";
151
+ const dir = path.dirname(filePath);
152
+ ensureDirSync(dir);
153
+ atomicWriteText(filePath, content);
154
+ }
155
+ function loadEntries(projectHash) {
156
+ return loadRaw(memoryPath(projectHash));
157
+ }
158
+ function loadDatedEntries(projectHash) {
159
+ const setAt = /* @__PURE__ */ new Map();
160
+ const anchors = /* @__PURE__ */ new Map();
161
+ const entries = loadRaw(memoryPath(projectHash), false, setAt, anchors);
162
+ const result = noteMap();
163
+ for (const [key, value] of Object.entries(entries)) {
164
+ const note = { value };
165
+ const time = setAt.get(key);
166
+ if (time !== void 0) note.setAt = time;
167
+ const anchor = anchors.get(key);
168
+ if (anchor !== void 0) note.anchor = anchor;
169
+ result[key] = note;
170
+ }
171
+ return result;
172
+ }
173
+ function noteAgeLabel(note, now = Date.now()) {
174
+ if (note.setAt === void 0) return "";
175
+ return ` (set ${formatAge(Math.max(0, now - Date.parse(note.setAt)))} ago)`;
176
+ }
177
+ function oneLineNoteValue(value) {
178
+ return value.replace(/\r\n|[\r\n\u0085\u2028\u2029]/g, "\\n");
179
+ }
180
+ function byRecency(a, aSetAt, b, bSetAt) {
181
+ const ta = aSetAt === void 0 ? Number.NEGATIVE_INFINITY : Date.parse(aSetAt);
182
+ const tb = bSetAt === void 0 ? Number.NEGATIVE_INFINITY : Date.parse(bSetAt);
183
+ return ta !== tb ? ta > tb ? -1 : 1 : ordinal(a, b);
184
+ }
185
+ function setEntry(projectHash, key, value, anchor) {
186
+ validateKey(key);
187
+ const p = memoryPath(projectHash);
188
+ const dir = path.dirname(p);
189
+ ensureDirSync(dir);
190
+ const result = { evicted: [] };
191
+ const doSet = () => {
192
+ const setAt = /* @__PURE__ */ new Map();
193
+ const anchors = /* @__PURE__ */ new Map();
194
+ const entries = loadRaw(p, true, setAt, anchors);
195
+ const old = Object.hasOwn(entries, key) ? entries[key] : void 0;
196
+ if (old !== void 0) result.previous = old;
197
+ const isNewKey = !Object.hasOwn(entries, key);
198
+ if (isNewKey && Object.keys(entries).length >= MAX_ENTRIES) {
199
+ const keysToKeep = MAX_ENTRIES - 1;
200
+ const allKeys = Object.keys(entries).sort((a, b) => byRecency(a, setAt.get(a), b, setAt.get(b)));
201
+ for (const k of allKeys.slice(keysToKeep)) {
202
+ result.evicted.push(k);
203
+ delete entries[k];
204
+ setAt.delete(k);
205
+ anchors.delete(k);
206
+ }
207
+ }
208
+ entries[key] = value;
209
+ setAt.set(key, (/* @__PURE__ */ new Date()).toISOString());
210
+ if (anchor === void 0) anchors.delete(key);
211
+ else anchors.set(key, anchor);
212
+ save(p, entries, setAt, anchors);
213
+ return true;
214
+ };
215
+ underNotesLock(p, doSet);
216
+ return result;
217
+ }
218
+ function underNotesLock(p, update) {
219
+ const lockPath = `${p}.lock`;
220
+ ensureDirSync(path.dirname(p));
221
+ for (let attempt = 1; attempt <= 3; attempt++) {
222
+ if (withFileLock(lockPath, update, { waitMs: LOCK_WAIT_MS_HARDENED }) !== void 0) return;
223
+ if (fs.existsSync(lockPath)) break;
224
+ if (attempt < 3) sleepSync(50 * attempt);
225
+ }
226
+ throw new Error(`Could not lock ${p} for writing; no note was changed. Another token-goat process may be writing notes: try again.`);
227
+ }
228
+ function unsetEntry(projectHash, key) {
229
+ validateKey(key);
230
+ const p = memoryPath(projectHash);
231
+ let removed = false;
232
+ const doUnset = () => {
233
+ const setAt = /* @__PURE__ */ new Map();
234
+ const anchors = /* @__PURE__ */ new Map();
235
+ const entries = loadRaw(p, true, setAt, anchors);
236
+ if (Object.hasOwn(entries, key)) {
237
+ delete entries[key];
238
+ save(p, entries, setAt, anchors);
239
+ removed = true;
240
+ }
241
+ return true;
242
+ };
243
+ underNotesLock(p, doUnset);
244
+ return removed;
245
+ }
246
+ function clearAll(projectHash) {
247
+ const p = memoryPath(projectHash);
248
+ const doClear = () => {
249
+ if (fs.existsSync(p)) {
250
+ save(p, {});
251
+ }
252
+ return true;
253
+ };
254
+ underNotesLock(p, doClear);
255
+ }
256
+ function buildInjection(projectHash, root, statusOf) {
257
+ try {
258
+ const entries = loadDatedEntries(projectHash);
259
+ if (Object.keys(entries).length === 0) {
260
+ return null;
261
+ }
262
+ const now = Date.now();
263
+ const header = '### Project notes (`token-goat note set <key> "<finding>"`)';
264
+ const render = (shown2, skipped) => {
265
+ const parts = [header];
266
+ if (shown2.length > 0) parts.push(fenceUntrustedFileContent(shown2.join("\n")));
267
+ if (skipped > 0) parts.push(`- (+${countNoun(skipped, "more memory entry", "more memory entries")} omitted)`);
268
+ return parts.join("\n");
269
+ };
270
+ const entries_list = Object.entries(entries).sort(([a, na], [b, nb]) => byRecency(a, na.setAt, b, nb.setAt));
271
+ const shown = [];
272
+ for (const [key, note] of entries_list.slice(0, MAX_ENTRIES)) {
273
+ const val = note.value;
274
+ const display = val.length <= MAX_VALUE_LEN ? val : val.slice(0, MAX_VALUE_LEN) + "\u2026";
275
+ const flag = root === void 0 || statusOf === void 0 || note.anchor === void 0 ? "" : anchorLabel(statusOf(root, note.anchor));
276
+ const line = `- **${key}**${noteAgeLabel(note, now)}${flag}: ${oneLineNoteValue(display)}`;
277
+ if (render([...shown, line], entries_list.length - shown.length - 1).length > MAX_TOTAL_CHARS) break;
278
+ shown.push(line);
279
+ }
280
+ return render(shown, entries_list.length - shown.length);
281
+ } catch {
282
+ return null;
283
+ }
284
+ }
285
+ function projectNotesFor(cwd, statusOf) {
286
+ if (cwd === void 0) return null;
287
+ try {
288
+ const project = findProject(cwd);
289
+ return project === null ? null : buildInjection(project.hash, project.root, statusOf);
290
+ } catch {
291
+ return null;
292
+ }
293
+ }
294
+
295
+ export {
296
+ MAX_ENTRIES,
297
+ anchorLabel,
298
+ anchorLine,
299
+ loadEntries,
300
+ loadDatedEntries,
301
+ noteAgeLabel,
302
+ oneLineNoteValue,
303
+ setEntry,
304
+ unsetEntry,
305
+ clearAll,
306
+ projectNotesFor
307
+ };
@@ -2,10 +2,10 @@ import { createRequire as __cjsRequire } from 'node:module';
2
2
  const require = __cjsRequire(import.meta.url);
3
3
  import {
4
4
  ensureDirSync
5
- } from "./token-goat-chunk-GOLEOXZP.mjs";
5
+ } from "./token-goat-chunk-HU4TORC5.mjs";
6
6
  import {
7
7
  dataDir
8
- } from "./token-goat-chunk-VES7EL7O.mjs";
8
+ } from "./token-goat-chunk-CO3UYX6G.mjs";
9
9
  import {
10
10
  init_define_import_meta_env
11
11
  } from "./token-goat-chunk-A37V4PBF.mjs";
@@ -1,5 +1,8 @@
1
1
  import { createRequire as __cjsRequire } from 'node:module';
2
2
  const require = __cjsRequire(import.meta.url);
3
+ import {
4
+ echoedValue
5
+ } from "./token-goat-chunk-GGGG7RWB.mjs";
3
6
  import {
4
7
  foldPath,
5
8
  isInsideRoot,
@@ -14,7 +17,7 @@ import {
14
17
  dataDir,
15
18
  ensureStorageRootPrivate,
16
19
  isTokenGoatStorage
17
- } from "./token-goat-chunk-VES7EL7O.mjs";
20
+ } from "./token-goat-chunk-CO3UYX6G.mjs";
18
21
  import {
19
22
  init_define_import_meta_env
20
23
  } from "./token-goat-chunk-A37V4PBF.mjs";
@@ -725,12 +728,14 @@ function runGit(args, opts = {}) {
725
728
  const result = spawnSync("git", fullArgs, {
726
729
  ...opts.cwd !== void 0 ? { cwd: opts.cwd } : {},
727
730
  ...opts.timeoutMs !== void 0 ? { timeout: opts.timeoutMs } : {},
731
+ ...opts.input !== void 0 ? { input: opts.input } : {},
728
732
  encoding: "utf-8",
729
733
  windowsHide: true,
730
734
  maxBuffer: 200 * 1024 * 1024
731
735
  });
732
736
  if (result.error) {
733
- return { stdout: "", stderr: String(result.error.message ?? result.error), exitCode: -1 };
737
+ const timedOut = result.error.code === "ETIMEDOUT";
738
+ return { stdout: "", stderr: String(result.error.message ?? result.error), exitCode: -1, ...timedOut ? { timedOut } : {} };
734
739
  }
735
740
  return {
736
741
  stdout: result.stdout ?? "",
@@ -923,11 +928,21 @@ function containsLineRun(haystack, needle) {
923
928
  if (n.length === 0 || n.length > h.length) return false;
924
929
  return ("\n" + h + "\n").includes("\n" + n + "\n");
925
930
  }
931
+ function isSequentialPagingChain(ranges, minChainLength = 3) {
932
+ if (ranges.length < minChainLength) return false;
933
+ const slice = ranges.slice(-minChainLength);
934
+ const steps = (isStep) => slice.every((curr, i) => i === 0 || isStep(slice[i - 1], curr));
935
+ const inReach = (gap) => gap >= -25 && gap <= 60;
936
+ return steps(([s1, e1], [s2]) => s2 > s1 && inReach(s2 - e1)) || steps(([s1], [s2, e2]) => s2 < s1 && inReach(s1 - e2));
937
+ }
926
938
  var LOCK_WAIT_MS = 2e3;
927
939
  var LOCK_STALE_MS = 5e3;
928
940
  var LOCK_WAIT_MS_HARDENED = 15e3;
929
941
  var LOCK_LIVE_HOLDER_MAX_MS = 6e4;
930
942
  var LOCK_EPERM_RUN_MS = 1e3;
943
+ function lockPollMs(attempt, waitMs) {
944
+ return Math.max(1, Math.min(20 * attempt, 200, Math.floor(waitMs / 50)));
945
+ }
931
946
  function lockHolderAlive(token) {
932
947
  const pid = Number(/^(\d+):/.exec(token)?.[1]);
933
948
  if (!Number.isSafeInteger(pid) || pid <= 0 || pid === process.pid) return false;
@@ -978,8 +993,12 @@ function withFileLock(lockPath, fn, opts = {}) {
978
993
  } catch (err) {
979
994
  if (process.platform === "win32" && errnoCode(err) === "EPERM") {
980
995
  epermSince ??= Date.now();
981
- if (Date.now() >= deadline || Date.now() - epermSince >= LOCK_EPERM_RUN_MS) return void 0;
982
- sleepSync(Math.min(20 * ++attempt, 200));
996
+ if (Date.now() >= deadline) {
997
+ opts.onContended?.();
998
+ return void 0;
999
+ }
1000
+ if (Date.now() - epermSince >= LOCK_EPERM_RUN_MS) return void 0;
1001
+ sleepSync(lockPollMs(++attempt, waitMs));
983
1002
  continue;
984
1003
  }
985
1004
  if (!isEExist(err)) return void 0;
@@ -993,8 +1012,11 @@ function withFileLock(lockPath, fn, opts = {}) {
993
1012
  stale = false;
994
1013
  }
995
1014
  if (stale && stealAbandoned(lockPath, staleMs)) continue;
996
- if (Date.now() >= deadline) return void 0;
997
- sleepSync(Math.min(20 * ++attempt, 200));
1015
+ if (Date.now() >= deadline) {
1016
+ opts.onContended?.();
1017
+ return void 0;
1018
+ }
1019
+ sleepSync(lockPollMs(++attempt, waitMs));
998
1020
  }
999
1021
  try {
1000
1022
  return fn();
@@ -1021,20 +1043,6 @@ function compileGrepMatcher(pattern) {
1021
1043
  const re = guarded.re;
1022
1044
  return (candidate) => re.test(candidate);
1023
1045
  }
1024
- function grepFilteredToEmptyNotice(preFilterCount, grep, nounSingular, nounPlural) {
1025
- const noun = preFilterCount === 1 ? nounSingular : nounPlural;
1026
- const verb = preFilterCount === 1 ? "was" : "were";
1027
- const pronoun = preFilterCount === 1 ? "it" : "them";
1028
- return ` (all ${preFilterCount} ${noun} ${verb} filtered out by --grep ${grep} -- widen or drop the filter to see ${pronoun})`;
1029
- }
1030
- function filtersFilteredToEmptyNotice(preFilterCount, activeFilters, nounSingular, nounPlural, reassurance) {
1031
- const noun = preFilterCount === 1 ? nounSingular : nounPlural;
1032
- const cause = activeFilters.length === 0 ? "the active filter" : activeFilters.join(" + ");
1033
- const knob = activeFilters.length > 1 ? "filters" : "filter";
1034
- const verb = preFilterCount === 1 ? "was" : "were";
1035
- const tail = reassurance === void 0 ? "" : `; ${reassurance}`;
1036
- return ` (all ${preFilterCount} ${noun} ${verb} filtered out by ${cause}${tail} -- widen or drop the ${knob} to see them)`;
1037
- }
1038
1046
  function countNoun(count, singular, plural = `${singular}s`) {
1039
1047
  return `${count} ${count === 1 ? singular : plural}`;
1040
1048
  }
@@ -1070,25 +1078,25 @@ function extractErrorMessage(err, fallback = "") {
1070
1078
  }
1071
1079
  function requireStrictInt(flag, raw) {
1072
1080
  if (!/^-?\d+$/.test(raw)) {
1073
- throw new Error(`${flag} must be a number, got: "${raw}"`);
1081
+ throw new Error(`${flag} must be a number, got: ${echoedValue(raw)}`);
1074
1082
  }
1075
1083
  const n = Number.parseInt(raw, 10);
1076
1084
  if (!Number.isFinite(n)) {
1077
- throw new Error(`${flag} must be a number, got: "${raw}"`);
1085
+ throw new Error(`${flag} must be a number, got: ${echoedValue(raw)}`);
1078
1086
  }
1079
1087
  return n;
1080
1088
  }
1081
1089
  function requireNonNegativeStrictInt(flag, raw) {
1082
1090
  const n = requireStrictInt(flag, raw);
1083
1091
  if (n < 0) {
1084
- throw new Error(`${flag} must be a non-negative number, got: "${raw}"`);
1092
+ throw new Error(`${flag} must be a non-negative number, got: ${echoedValue(raw)}`);
1085
1093
  }
1086
1094
  return n;
1087
1095
  }
1088
1096
  function requirePositiveStrictInt(flag, raw) {
1089
1097
  const n = requireStrictInt(flag, raw);
1090
1098
  if (n <= 0) {
1091
- throw new Error(`${flag} must be a positive number, got: "${raw}"`);
1099
+ throw new Error(`${flag} must be a positive number, got: ${echoedValue(raw)}`);
1092
1100
  }
1093
1101
  return n;
1094
1102
  }
@@ -1207,6 +1215,15 @@ function recordCreatedRootKey(filePath, rootKey) {
1207
1215
  function takeCreatedRootKey(filePath, rootKey) {
1208
1216
  return takeCreatedConfig(rootKeyMarker(filePath, rootKey));
1209
1217
  }
1218
+ function turnedOffMarker(filePath, key) {
1219
+ return `${filePath}#turned-off=${key}:true`;
1220
+ }
1221
+ function recordTurnedOffSetting(filePath, key) {
1222
+ recordCreatedConfig(turnedOffMarker(filePath, key));
1223
+ }
1224
+ function takeTurnedOffSetting(filePath, key) {
1225
+ return takeCreatedConfig(turnedOffMarker(filePath, key));
1226
+ }
1210
1227
  function recordCreatedBackup(backupPath) {
1211
1228
  recordCreatedConfig(backupPath);
1212
1229
  }
@@ -1285,6 +1302,8 @@ export {
1285
1302
  takeCreatedConfig,
1286
1303
  recordCreatedRootKey,
1287
1304
  takeCreatedRootKey,
1305
+ recordTurnedOffSetting,
1306
+ takeTurnedOffSetting,
1288
1307
  removeCreatedBackups,
1289
1308
  ensureDirRecordingCreation,
1290
1309
  removeCreatedIfEmpty,
@@ -1327,14 +1346,13 @@ export {
1327
1346
  cappedSourceBytesSaved,
1328
1347
  IDENTICAL_READ_MIN_BODY_BYTES,
1329
1348
  containsLineRun,
1349
+ isSequentialPagingChain,
1330
1350
  LOCK_WAIT_MS_HARDENED,
1331
1351
  withFileLock,
1332
1352
  stripLower,
1333
1353
  sanitizeIdForFilename,
1334
1354
  toKB,
1335
1355
  compileGrepMatcher,
1336
- grepFilteredToEmptyNotice,
1337
- filtersFilteredToEmptyNotice,
1338
1356
  countNoun,
1339
1357
  excludeTestsHiddenNote,
1340
1358
  countContentLines,
@@ -3,13 +3,13 @@ const require = __cjsRequire(import.meta.url);
3
3
  import {
4
4
  computeSymbolFingerprints,
5
5
  symbolNamesInFile
6
- } from "./token-goat-chunk-PU7V3FD6.mjs";
6
+ } from "./token-goat-chunk-COPNXRJM.mjs";
7
7
  import {
8
8
  resolveIndexPath
9
9
  } from "./token-goat-chunk-FNFBKLRD.mjs";
10
10
  import {
11
11
  globalDbPath
12
- } from "./token-goat-chunk-VES7EL7O.mjs";
12
+ } from "./token-goat-chunk-CO3UYX6G.mjs";
13
13
  import {
14
14
  init_define_import_meta_env
15
15
  } from "./token-goat-chunk-A37V4PBF.mjs";
@@ -8,14 +8,14 @@ import {
8
8
  isCodexInstalled,
9
9
  isCopilotCliInstalled,
10
10
  isInstalled
11
- } from "./token-goat-chunk-OJBNYTJP.mjs";
11
+ } from "./token-goat-chunk-7MAOA6X4.mjs";
12
12
  import {
13
13
  loadConfig
14
- } from "./token-goat-chunk-7IN2MKDS.mjs";
14
+ } from "./token-goat-chunk-7EZTZOMC.mjs";
15
15
  import {
16
16
  recordCreatedBy,
17
17
  upsertDelimitedBlock
18
- } from "./token-goat-chunk-GOLEOXZP.mjs";
18
+ } from "./token-goat-chunk-HU4TORC5.mjs";
19
19
  import {
20
20
  init_define_import_meta_env
21
21
  } from "./token-goat-chunk-A37V4PBF.mjs";
@@ -130,13 +130,13 @@ function checkInstructionGates(rootDir = process.cwd()) {
130
130
  return {
131
131
  name: "Instruction gate",
132
132
  status: "warn",
133
- message: `missing in ${unGated} and in the user-level instruction files 'token-goat install' writes (agents will bypass token-goat and read whole files). Run 'token-goat doctor --fix' to inject automatically.`
133
+ message: `missing in ${unGated} and in the user-level instruction files \`token-goat install\` writes (agents will bypass token-goat and read whole files). Run \`token-goat doctor --fix\` to inject automatically.`
134
134
  };
135
135
  }
136
136
  return {
137
137
  name: "Instruction gate",
138
138
  status: "warn",
139
- message: "missing: no user-level instruction file carries it and no project instruction file was found (CLAUDE.md, AGENTS.md, or .github/copilot-instructions.md). Run 'token-goat install', or 'token-goat doctor --fix' to create CLAUDE.md with the routing gate."
139
+ message: "missing: no user-level instruction file carries it and no project instruction file was found (CLAUDE.md, AGENTS.md, or .github/copilot-instructions.md). Run `token-goat install`, or `token-goat doctor --fix` to create CLAUDE.md with the routing gate."
140
140
  };
141
141
  }
142
142
  function repairInstructionGates(rootDir = process.cwd()) {
@@ -192,7 +192,7 @@ function checkHarnessCacheEfficiency(rootDir = process.cwd()) {
192
192
  return {
193
193
  name: "Harness efficiency",
194
194
  status: "warn",
195
- message: `${ideDetected.join(", ")} workspace detected without CLI harness config. IDE hooks cannot fold/trim built-in reads. If you also use a CLI agent, run 'token-goat install' for Claude Code, or 'token-goat install --codex' or '--copilot' for those.`
195
+ message: `${ideDetected.join(", ")} workspace detected without CLI harness config. IDE hooks cannot fold/trim built-in reads. If you also use a CLI agent, run \`token-goat install\` for Claude Code, or \`token-goat install --codex\` or '--copilot' for those.`
196
196
  };
197
197
  }
198
198
  if (cliDetected.length > 0) {