@wrongstack/core 0.313.0 → 0.316.1

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 (343) hide show
  1. package/dist/chronicle/index.js +84 -6391
  2. package/dist/chronicle/legacy-journal-import.d.ts +0 -6
  3. package/dist/chronicle/metrics-ingest.d.ts +14 -0
  4. package/dist/chronicle/metrics-schema.d.ts +10 -1
  5. package/dist/chronicle/metrics-store.d.ts +20 -2
  6. package/dist/chronicle/project-server.js +98 -4874
  7. package/dist/chronicle/sink.d.ts +13 -0
  8. package/dist/chronicle/sqlite-journal.d.ts +20 -2
  9. package/dist/chunk-25LSLC3G.js +334 -0
  10. package/dist/chunk-27QIURLN.js +1073 -0
  11. package/dist/chunk-2FK4WTFF.js +207 -0
  12. package/dist/chunk-2YU4WVBW.js +134 -0
  13. package/dist/chunk-3AGWVSS7.js +4608 -0
  14. package/dist/chunk-3BDV7RL3.js +211 -0
  15. package/dist/chunk-3ECENVHL.js +325 -0
  16. package/dist/chunk-3XPVB7BA.js +135 -0
  17. package/dist/chunk-45WI72ZB.js +16884 -0
  18. package/dist/chunk-4BMVPOHO.js +3748 -0
  19. package/dist/chunk-4I7HGVVA.js +363 -0
  20. package/dist/chunk-4LCZVJVF.js +317 -0
  21. package/dist/chunk-4SJNS7OB.js +217 -0
  22. package/dist/chunk-4VWO3ZXL.js +342 -0
  23. package/dist/chunk-57GEWK5X.js +26 -0
  24. package/dist/chunk-5BMIE7QG.js +46 -0
  25. package/dist/chunk-5S437PRC.js +50 -0
  26. package/dist/chunk-5XDUGTKN.js +511 -0
  27. package/dist/chunk-5YPSXQXM.js +1443 -0
  28. package/dist/chunk-6FHWXLPT.js +10 -0
  29. package/dist/chunk-6H5GEOET.js +2406 -0
  30. package/dist/chunk-6NWEVFEL.js +151 -0
  31. package/dist/chunk-AYW5YINX.js +58 -0
  32. package/dist/chunk-B4AMLZPB.js +9 -0
  33. package/dist/chunk-B7F4WVP4.js +65 -0
  34. package/dist/chunk-BJHVULHO.js +55 -0
  35. package/dist/chunk-BPBKKBUK.js +2085 -0
  36. package/dist/chunk-BYD345OX.js +589 -0
  37. package/dist/chunk-C27KDLOX.js +279 -0
  38. package/dist/chunk-CU546ESW.js +597 -0
  39. package/dist/chunk-DLHHXUAM.js +172 -0
  40. package/dist/chunk-DOTHQSJ2.js +429 -0
  41. package/dist/chunk-DYLPMV4Q.js +711 -0
  42. package/dist/chunk-EODDVJBM.js +82 -0
  43. package/dist/chunk-F3JWNST7.js +361 -0
  44. package/dist/chunk-FC2ZGRF3.js +140 -0
  45. package/dist/chunk-FCBTO76Z.js +5786 -0
  46. package/dist/chunk-FHZVFYSL.js +396 -0
  47. package/dist/chunk-FNXVT7HF.js +52 -0
  48. package/dist/chunk-FWNLEZYG.js +259 -0
  49. package/dist/chunk-FXQLIX3K.js +211 -0
  50. package/dist/chunk-G5S3S5ZN.js +38 -0
  51. package/dist/chunk-GDQ7CZRQ.js +116 -0
  52. package/dist/chunk-GJJGJB2R.js +1374 -0
  53. package/dist/chunk-GTCU6DZ3.js +1 -0
  54. package/dist/chunk-HA4ZYA6T.js +178 -0
  55. package/dist/chunk-HI3JGZR2.js +188 -0
  56. package/dist/chunk-HMLIGAU7.js +395 -0
  57. package/dist/chunk-HXKZ7OBQ.js +303 -0
  58. package/dist/chunk-I7DALG7J.js +292 -0
  59. package/dist/chunk-IRUTEHCE.js +960 -0
  60. package/dist/chunk-IYFBFX34.js +86 -0
  61. package/dist/chunk-J2WRWR37.js +1104 -0
  62. package/dist/chunk-JFPJ6LLQ.js +129 -0
  63. package/dist/chunk-JMULFFLN.js +9 -0
  64. package/dist/chunk-JO4MGB6Z.js +1264 -0
  65. package/dist/chunk-JVKB2TBL.js +48 -0
  66. package/dist/chunk-JX7VBZDK.js +31 -0
  67. package/dist/chunk-K6BXGITA.js +931 -0
  68. package/dist/chunk-KDQJCT2J.js +45 -0
  69. package/dist/chunk-KJ2ZTQSL.js +47 -0
  70. package/dist/chunk-KZMSZV32.js +187 -0
  71. package/dist/chunk-LA7CLDRW.js +129 -0
  72. package/dist/chunk-LHOA5DWA.js +28 -0
  73. package/dist/chunk-LSMMOS2Z.js +119 -0
  74. package/dist/chunk-LX5QWLBL.js +27 -0
  75. package/dist/chunk-LXWCMQNJ.js +789 -0
  76. package/dist/chunk-M27LIEKV.js +2829 -0
  77. package/dist/chunk-MJPHJRAL.js +663 -0
  78. package/dist/chunk-MTL4O5YR.js +228 -0
  79. package/dist/chunk-NDBIPFNY.js +102 -0
  80. package/dist/chunk-NEMIWEXC.js +1199 -0
  81. package/dist/chunk-NHJ75HXY.js +1 -0
  82. package/dist/chunk-NIOAGFPB.js +1510 -0
  83. package/dist/chunk-NS52ISWS.js +355 -0
  84. package/dist/chunk-NSOFPKGT.js +5352 -0
  85. package/dist/chunk-NVIZG63R.js +757 -0
  86. package/dist/chunk-O37BQ65S.js +21 -0
  87. package/dist/chunk-OOYZPOXM.js +308 -0
  88. package/dist/chunk-OSGLYW5J.js +28 -0
  89. package/dist/chunk-PFCMSSUF.js +1640 -0
  90. package/dist/chunk-PFZO3C6H.js +14 -0
  91. package/dist/chunk-PGRVXIMY.js +158 -0
  92. package/dist/chunk-PHH7LD45.js +113 -0
  93. package/dist/chunk-PISBFBJN.js +109 -0
  94. package/dist/chunk-POOOIWE5.js +9 -0
  95. package/dist/chunk-PQNS3U7Z.js +1240 -0
  96. package/dist/chunk-QSTSJOCK.js +402 -0
  97. package/dist/chunk-RFQMOKWK.js +282 -0
  98. package/dist/chunk-RJIZEJ42.js +30 -0
  99. package/dist/chunk-RTOTNK3P.js +484 -0
  100. package/dist/chunk-RXKSDUAU.js +1172 -0
  101. package/dist/chunk-S45JPKQN.js +3317 -0
  102. package/dist/chunk-SAFHACFA.js +152 -0
  103. package/dist/chunk-SQJVFEBV.js +41 -0
  104. package/dist/chunk-SVT4RNTR.js +49 -0
  105. package/dist/chunk-SWUFN7XM.js +43 -0
  106. package/dist/chunk-SXMVYC5H.js +174 -0
  107. package/dist/chunk-SZ6AYUIZ.js +23 -0
  108. package/dist/chunk-TBRL2RCC.js +9 -0
  109. package/dist/chunk-TCCHINEF.js +655 -0
  110. package/dist/chunk-THEGTRAG.js +316 -0
  111. package/dist/chunk-TR4LQE7L.js +2256 -0
  112. package/dist/chunk-TRT2HRWZ.js +18 -0
  113. package/dist/chunk-TWJMGXCI.js +900 -0
  114. package/dist/chunk-U45AXT5D.js +1023 -0
  115. package/dist/chunk-U4FWBSO3.js +509 -0
  116. package/dist/chunk-UBGDX6FI.js +147 -0
  117. package/dist/chunk-UJILKYES.js +75 -0
  118. package/dist/chunk-ULMAQV3T.js +234 -0
  119. package/dist/chunk-VVBP6KGT.js +9 -0
  120. package/dist/chunk-W5VITDM2.js +168 -0
  121. package/dist/chunk-WAHQVNWT.js +194 -0
  122. package/dist/chunk-WBPVKEEE.js +227 -0
  123. package/dist/chunk-WGGYRBXH.js +5434 -0
  124. package/dist/chunk-WLYKU45P.js +5770 -0
  125. package/dist/chunk-WP7BVANJ.js +53 -0
  126. package/dist/chunk-WQQON3SV.js +473 -0
  127. package/dist/chunk-WQTOVMGV.js +119 -0
  128. package/dist/chunk-XBDP4QPW.js +7 -0
  129. package/dist/chunk-XEBHSJLT.js +103 -0
  130. package/dist/chunk-XF4VUMKW.js +231 -0
  131. package/dist/chunk-XQ2ECNK3.js +1 -0
  132. package/dist/chunk-Y5YXDM7D.js +74 -0
  133. package/dist/chunk-YOPAUVU4.js +2588 -0
  134. package/dist/chunk-YPT4A46F.js +362 -0
  135. package/dist/chunk-YWXT3JNM.js +425 -0
  136. package/dist/chunk-YY6APYUM.js +49 -0
  137. package/dist/chunk-Z2IJUO45.js +691 -0
  138. package/dist/chunk-ZHZ2Y2DH.js +1643 -0
  139. package/dist/chunk-ZT7JNIGX.js +152 -0
  140. package/dist/coordination/agent-monitor.d.ts +9 -1
  141. package/dist/coordination/agent-subagent-runner.d.ts +1 -1
  142. package/dist/coordination/agents/agent-prompts.d.ts +8 -0
  143. package/dist/coordination/agents/index.d.ts +33 -1
  144. package/dist/coordination/agents/index.js +184 -6269
  145. package/dist/coordination/agents/phase3-wave1-platform.d.ts +1 -3
  146. package/dist/coordination/agents/phase3-wave2-meta.d.ts +1 -3
  147. package/dist/coordination/agents/phase8-wave3-products.d.ts +1 -3
  148. package/dist/coordination/agents/phase9-wave4-platform-meta.d.ts +1 -3
  149. package/dist/coordination/agents/project-agent-identity.d.ts +11 -11
  150. package/dist/coordination/agents/types.d.ts +13 -2
  151. package/dist/coordination/brain-monitor.d.ts +30 -7
  152. package/dist/coordination/collab-debug.d.ts +1 -1
  153. package/dist/coordination/collab-pause.d.ts +1 -1
  154. package/dist/coordination/delegate-tool.d.ts +7 -5
  155. package/dist/coordination/director-kanban-queue-helpers.d.ts +1 -0
  156. package/dist/coordination/director-options.d.ts +7 -0
  157. package/dist/coordination/director-spawn-model.d.ts +17 -0
  158. package/dist/coordination/director-tools.d.ts +2 -2
  159. package/dist/coordination/director.d.ts +12 -0
  160. package/dist/coordination/dispatcher.d.ts +8 -0
  161. package/dist/coordination/fleet-bus.d.ts +35 -4
  162. package/dist/coordination/fleet-supervisor.d.ts +10 -2
  163. package/dist/coordination/fleet.d.ts +16 -7
  164. package/dist/coordination/index.d.ts +4 -0
  165. package/dist/coordination/index.js +402 -34324
  166. package/dist/coordination/kanban-dispatch-port.d.ts +2 -2
  167. package/dist/coordination/mailbox-http-router.d.ts +4 -3
  168. package/dist/coordination/mailbox-http-validation.d.ts +1 -1
  169. package/dist/coordination/mailbox-project-server.js +48 -3276
  170. package/dist/coordination/mailbox-types.d.ts +24 -6
  171. package/dist/coordination/model-tier-leader.d.ts +122 -0
  172. package/dist/coordination/model-tier.d.ts +122 -0
  173. package/dist/coordination/multi-agent-coordinator.d.ts +24 -0
  174. package/dist/coordination/origin-session.d.ts +16 -0
  175. package/dist/coordination/provider-status-tracker.d.ts +41 -5
  176. package/dist/coordination/session-note-hub.d.ts +44 -0
  177. package/dist/coordination/session-note-tool.d.ts +10 -0
  178. package/dist/core/agent.d.ts +15 -2
  179. package/dist/core/context.d.ts +22 -3
  180. package/dist/core/index.d.ts +2 -0
  181. package/dist/core/index.js +239 -12360
  182. package/dist/core/model-ref.js +5 -23
  183. package/dist/core/provider-runner.d.ts +36 -1
  184. package/dist/core/request-conversation-binding.d.ts +37 -0
  185. package/dist/core/session-notes.d.ts +25 -0
  186. package/dist/core/system-prompt-builder.d.ts +11 -2
  187. package/dist/core/system-prompt-variants.d.ts +78 -0
  188. package/dist/design/index.js +50 -1087
  189. package/dist/execution/auto-compaction-middleware.d.ts +11 -0
  190. package/dist/execution/autonomy-brain.d.ts +2 -1
  191. package/dist/execution/autonomy-prompt-contributor.d.ts +7 -2
  192. package/dist/execution/compaction-core.d.ts +4 -4
  193. package/dist/execution/eternal-autonomy.d.ts +1 -1
  194. package/dist/execution/index.d.ts +1 -1
  195. package/dist/execution/index.js +1615 -21895
  196. package/dist/execution/model-runtime.d.ts +0 -7
  197. package/dist/execution/parallel-eternal-engine.d.ts +7 -7
  198. package/dist/execution/prompt-enhancer.js +16 -535
  199. package/dist/execution/retry-policy.d.ts +31 -1
  200. package/dist/extension/index.js +7 -311
  201. package/dist/goal/index.js +33 -3435
  202. package/dist/hooks/index.js +14 -1138
  203. package/dist/hq/index.js +114 -5139
  204. package/dist/hq/persistence/event-log.d.ts +0 -1
  205. package/dist/hq/persistence.d.ts +4 -4
  206. package/dist/hq/protocol.js +21 -668
  207. package/dist/hq/publisher.d.ts +2 -0
  208. package/dist/index.d.ts +14 -11
  209. package/dist/index.js +1502 -92655
  210. package/dist/infrastructure/index.d.ts +4 -4
  211. package/dist/infrastructure/index.js +504 -5230
  212. package/dist/infrastructure/token-counter.d.ts +9 -0
  213. package/dist/kernel/events/agent-events.d.ts +77 -3
  214. package/dist/kernel/events/brain-events.d.ts +12 -0
  215. package/dist/kernel/events/provider-events.d.ts +22 -1
  216. package/dist/kernel/events/session-events.d.ts +14 -0
  217. package/dist/kernel/events/tool-events.d.ts +13 -0
  218. package/dist/kernel/index.js +14 -992
  219. package/dist/mailbox-attach.d.ts +1 -1
  220. package/dist/models/index.js +41 -1117
  221. package/dist/notifications/index.js +3 -108
  222. package/dist/observability/event-bridge.d.ts +25 -5
  223. package/dist/observability/index.d.ts +9 -8
  224. package/dist/observability/index.js +477 -631
  225. package/dist/observability/tool-usage-source.d.ts +65 -0
  226. package/dist/plugin/index.d.ts +5 -0
  227. package/dist/plugin/index.js +600 -14835
  228. package/dist/plugins/auto-review-plugin.d.ts +3 -2
  229. package/dist/plugins/review-finding-commands.d.ts +0 -8
  230. package/dist/plugins/review-finding-store.js +22 -0
  231. package/dist/plugins/review-finding-types.js +19 -0
  232. package/dist/plugins/review-report-integration.js +21 -0
  233. package/dist/plugins/review-report-store.js +20 -0
  234. package/dist/plugins/review-report-types.js +13 -0
  235. package/dist/prompts/index.js +14 -948
  236. package/dist/registry/index.js +9 -822
  237. package/dist/registry/tool-registry.d.ts +59 -9
  238. package/dist/registry-7N4O3E7W.js +14 -0
  239. package/dist/replay/index.js +6 -84
  240. package/dist/security/capabilities.d.ts +6 -0
  241. package/dist/security/file-permissions.d.ts +1 -1
  242. package/dist/security/index.js +161 -2235
  243. package/dist/security/permission-policy.d.ts +12 -1
  244. package/dist/security/secret-scrubber.d.ts +15 -0
  245. package/dist/session-catalog/index.d.ts +1 -0
  246. package/dist/session-catalog/index.js +41 -2103
  247. package/dist/session-catalog/project-server.js +59 -1435
  248. package/dist/session-catalog/protocol.d.ts +32 -1
  249. package/dist/session-catalog/registry.d.ts +17 -1
  250. package/dist/session-catalog/session-agents.d.ts +56 -0
  251. package/dist/session-catalog/store-rebuild.d.ts +14 -0
  252. package/dist/session-catalog/store-schema.d.ts +26 -0
  253. package/dist/session-catalog/store.d.ts +27 -1
  254. package/dist/session-note-attach.d.ts +9 -0
  255. package/dist/skills/index.js +35 -1578
  256. package/dist/statusline/index.d.ts +43 -0
  257. package/dist/statusline/index.js +102 -0
  258. package/dist/storage/board-store-port.d.ts +2 -2
  259. package/dist/storage/config-loader/in-project-policy.d.ts +29 -0
  260. package/dist/storage/config-loader.d.ts +3 -2
  261. package/dist/storage/file-session-writer.d.ts +4 -2
  262. package/dist/storage/goal-coordination.d.ts +6 -1
  263. package/dist/storage/goal-kanban.d.ts +4 -1
  264. package/dist/storage/index.d.ts +12 -4
  265. package/dist/storage/index.js +198 -15601
  266. package/dist/storage/input-history-store.d.ts +2 -4
  267. package/dist/storage/memory-curator.d.ts +133 -0
  268. package/dist/storage/session-agent-attribution.d.ts +39 -0
  269. package/dist/storage/session-doctor.d.ts +109 -0
  270. package/dist/storage/session-event-bridge.d.ts +5 -7
  271. package/dist/storage/session-outcome.d.ts +42 -0
  272. package/dist/storage/session-recovery.d.ts +55 -0
  273. package/dist/storage/session-store/load-session-data.d.ts +11 -0
  274. package/dist/storage/session-store/prune-helpers.d.ts +1 -1
  275. package/dist/storage/session-store/resume-session.d.ts +0 -2
  276. package/dist/storage/session-store/types.d.ts +8 -0
  277. package/dist/storage/session-store.d.ts +3 -3
  278. package/dist/storage/session-summary-tracker.d.ts +8 -1
  279. package/dist/storage/session-write-buffer.d.ts +18 -0
  280. package/dist/storage/session-writer-truncate.d.ts +2 -0
  281. package/dist/tasking/index.js +10 -676
  282. package/dist/tools/fallback-manage-tools.d.ts +6 -4
  283. package/dist/tools/index.js +52 -9590
  284. package/dist/tools/model-tier-set-tool.d.ts +66 -0
  285. package/dist/types/agent-bridge.d.ts +2 -1
  286. package/dist/types/config/autonomy.d.ts +5 -0
  287. package/dist/types/config/mcp-features.d.ts +7 -0
  288. package/dist/types/config/model-tiers.d.ts +148 -0
  289. package/dist/types/config/root.d.ts +9 -0
  290. package/dist/types/config/tools.d.ts +73 -0
  291. package/dist/types/config/ui.d.ts +1 -1
  292. package/dist/types/config.d.ts +1 -0
  293. package/dist/types/context.d.ts +2 -0
  294. package/dist/types/default-config.d.ts +6 -0
  295. package/dist/types/errors.d.ts +20 -1
  296. package/dist/types/index.d.ts +11 -9
  297. package/dist/types/index.js +131 -1342
  298. package/dist/types/multi-agent.d.ts +43 -0
  299. package/dist/types/plugin.d.ts +1 -1
  300. package/dist/types/provider-runner.d.ts +8 -0
  301. package/dist/types/provider.d.ts +15 -0
  302. package/dist/types/runtime-capability-manifest.d.ts +1 -1
  303. package/dist/types/secret-scrubber.d.ts +15 -0
  304. package/dist/types/session-markers.d.ts +37 -10
  305. package/dist/types/session-markers.js +8 -144
  306. package/dist/types/session-timeline.d.ts +197 -0
  307. package/dist/types/session-timeline.js +12 -0
  308. package/dist/types/session.d.ts +172 -11
  309. package/dist/types/system-prompt.d.ts +27 -0
  310. package/dist/utils/config-backup.d.ts +9 -1
  311. package/dist/utils/error.js +3 -4
  312. package/dist/utils/expect-defined.js +3 -9
  313. package/dist/utils/heap-watchdog.js +6 -706
  314. package/dist/utils/index.js +271 -5685
  315. package/dist/utils/message-invariants.d.ts +4 -1
  316. package/dist/utils/regex-guard.d.ts +1 -1
  317. package/dist/utils/sage-output-block.js +5 -42
  318. package/dist/utils/socket-path.d.ts +1 -1
  319. package/dist/utils/token-estimate.d.ts +6 -2
  320. package/dist/utils/wstack-paths.d.ts +2 -0
  321. package/dist/wiring/proxy-rewrite.d.ts +46 -0
  322. package/dist/wiring/proxy-rewrite.js +24 -121
  323. package/dist/worktree/index.js +6 -887
  324. package/instructions/agents/explore-companion.md +45 -18
  325. package/instructions/agents/memory-curator.md +34 -22
  326. package/instructions/coordination/director-preamble.md +12 -7
  327. package/instructions/coordination/subagent-baseline.md +26 -5
  328. package/instructions/leader-after-task.md +4 -1
  329. package/instructions/llm/chimera-review.md +30 -9
  330. package/instructions/llm/memory-curator.md +31 -0
  331. package/instructions/sections/tool/delegation-compact.md +2 -0
  332. package/instructions/sections/tool/delegation-full.md +5 -1
  333. package/instructions/sections/tool/mailbox-compact.md +5 -1
  334. package/instructions/sections/tool/mailbox-full.md +3 -0
  335. package/instructions/sections/tool/session-note-compact.md +3 -0
  336. package/instructions/sections/tool/session-note-full.md +15 -0
  337. package/instructions/system-lite.md +9 -4
  338. package/instructions/system-pro.md +66 -143
  339. package/instructions/system.md +73 -175
  340. package/package.json +32 -4
  341. package/dist/coordination/agents.d.ts +0 -8
  342. package/dist/coordination/transport.d.ts +0 -2
  343. package/dist/storage/session-writer/session-writer-summary-tracker.d.ts +0 -28
@@ -0,0 +1,402 @@
1
+ // src/security/secret-scrubber.ts
2
+ var JSON_CREDENTIAL_KEY_ANCHORS = [
3
+ 'Key"',
4
+ 'key"',
5
+ 'KEY"',
6
+ 'token"',
7
+ 'Token"',
8
+ 'TOKEN"',
9
+ 'secret"',
10
+ 'Secret"',
11
+ 'SECRET"',
12
+ 'password"',
13
+ 'Password"',
14
+ 'PASSWORD"',
15
+ 'authorization"',
16
+ 'Authorization"',
17
+ 'bearer"',
18
+ 'Bearer"'
19
+ ];
20
+ var PATTERNS = [
21
+ // Anchored at the start where possible so partial matches inside larger
22
+ // strings don't trigger false positives.
23
+ {
24
+ type: "anthropic_key",
25
+ regex: /(?<![A-Za-z0-9])sk-ant-api\d+-[A-Za-z0-9_-]{20,}(?![A-Za-z0-9])/g,
26
+ anchor: "sk-ant-"
27
+ },
28
+ { type: "openai_key", regex: /(?<![A-Za-z0-9])sk-(?:proj-)?[A-Za-z0-9_-]{20,}(?![A-Za-z0-9])/g, anchor: "sk-" },
29
+ {
30
+ // `xai` is a first-class provider in this codebase, but its key shape was
31
+ // absent here — so the one credential format WrongStack itself hands users
32
+ // was the one the scrubber could not recognize (audit 2026-08-20).
33
+ type: "xai_key",
34
+ regex: /(?<![A-Za-z0-9])xai-[A-Za-z0-9]{20,}(?![A-Za-z0-9])/g,
35
+ anchor: "xai-"
36
+ },
37
+ { type: "github_pat", regex: /(?<![A-Za-z0-9])ghp_[A-Za-z0-9]{36,}(?![A-Za-z0-9])/g, anchor: "ghp_" },
38
+ { type: "github_pat_v2", regex: /(?<![A-Za-z0-9])github_pat_[A-Za-z0-9_]{50,}(?![A-Za-z0-9])/g, anchor: "github_pat_" },
39
+ { type: "aws_access_key", regex: /(?<![A-Za-z0-9])AKIA[0-9A-Z]{16}(?![A-Za-z0-9])/g, anchor: "AKIA" },
40
+ { type: "gcp_key", regex: /(?<![A-Za-z0-9])AIza[0-9A-Za-z_-]{35}(?![A-Za-z0-9])/g, anchor: "AIza" },
41
+ { type: "slack_token", regex: /(?<![A-Za-z0-9-])xox[abpos]-[A-Za-z0-9-]{10,}(?![A-Za-z0-9-])/g, anchor: "xox" },
42
+ {
43
+ type: "stripe_key",
44
+ regex: /(?<![A-Za-z0-9])sk_(?:live|test)_[A-Za-z0-9]{24,}(?![A-Za-z0-9])/g,
45
+ anchor: "sk_"
46
+ },
47
+ {
48
+ type: "twilio_sid",
49
+ regex: /(?<![A-Za-z0-9])AC[a-f0-9]{32}(?![A-Za-z0-9])/g,
50
+ anchor: "AC"
51
+ },
52
+ {
53
+ type: "telegram_bot_token",
54
+ // Telegram tokens are of the form bot<digits>:<alphanum> in URL paths
55
+ regex: /\/bot\d+:[A-Za-z0-9_-]{20,}(?![A-Za-z0-9_-])/g,
56
+ anchor: "/bot"
57
+ },
58
+ {
59
+ type: "jwt",
60
+ // Anchored: look for literal "eyJ" which is unambiguous for JWT header
61
+ regex: /(?<![A-Za-z0-9/+=])eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}(?![A-Za-z0-9/+=])/g,
62
+ anchor: "eyJ"
63
+ },
64
+ {
65
+ type: "private_key",
66
+ // Anchored: start must be BEGIN, end must be END with no extra dashes after END
67
+ regex: /(?:^|\n)-----BEGIN (?:RSA|EC|OPENSSH|DSA|PGP)? ?PRIVATE KEY-----[\s\S]*?-----END[^-]*-----(?:\n|$)/g,
68
+ anchor: "-----BEGIN"
69
+ },
70
+ { type: "mongodb_uri", regex: /mongodb(?:\+srv)?:\/\/[^\s"'`]+/g, anchor: "mongodb" },
71
+ { type: "postgres_uri", regex: /postgres(?:ql)?:\/\/[^\s"'`]+/g, anchor: "postgres" },
72
+ { type: "mysql_uri", regex: /mysql:\/\/[^\s"'`]+/g, anchor: "mysql://" },
73
+ { type: "redis_uri", regex: /redis:\/\/[^\s"'`]+/g, anchor: "redis://" },
74
+ // AI/ML provider keys — modern LLM services with well-known prefixes
75
+ {
76
+ type: "huggingface_token",
77
+ // HuggingFace tokens: hf_ followed by 34 alphanumeric chars
78
+ regex: /(?<![A-Za-z0-9])hf_[A-Za-z0-9]{34}(?![A-Za-z0-9])/g,
79
+ anchor: "hf_"
80
+ },
81
+ {
82
+ type: "replicate_token",
83
+ // Replicate tokens: r8_ followed by 40+ alphanumeric chars
84
+ regex: /(?<![A-Za-z0-9])r8_[A-Za-z0-9]{40,}(?![A-Za-z0-9])/g,
85
+ anchor: "r8_"
86
+ },
87
+ {
88
+ type: "perplexity_key",
89
+ // Perplexity API keys: pplx- followed by 40+ alphanumeric chars
90
+ regex: /(?<![A-Za-z0-9])pplx-[A-Za-z0-9]{40,}(?![A-Za-z0-9])/g,
91
+ anchor: "pplx-"
92
+ },
93
+ {
94
+ type: "groq_key",
95
+ // Groq API keys: gsk_ followed by 40+ alphanumeric chars
96
+ regex: /(?<![A-Za-z0-9])gsk_[A-Za-z0-9]{40,}(?![A-Za-z0-9])/g,
97
+ anchor: "gsk_"
98
+ },
99
+ {
100
+ type: "bearer_token",
101
+ // Anchored with alternation instead of negative lookahead — avoids V8
102
+ // backtracking risk on adversarial input. Bounded at 512 chars.
103
+ // Min 12 chars: some OAuth providers issue shorter-lived tokens (< 20
104
+ // chars). A 12-char base64 string has ~71 bits of entropy — above the
105
+ // threshold where random strings are unlikely to produce false matches.
106
+ // The trailing boundary is a NON-consuming lookahead: two adjacent bearer
107
+ // tokens sharing a single delimiter (`Bearer a… Bearer b…`) must both be
108
+ // redacted. A consuming trailing delimiter would eat the separator the
109
+ // next match needs for its leading anchor, leaking the second token.
110
+ regex: /(?:^|[^A-Za-z0-9_.~+/-])Bearer\s+[A-Za-z0-9._~+/-]{12,512}=*(?=$|[^A-Za-z0-9_.~+/-])/g,
111
+ anchor: "Bearer"
112
+ },
113
+ {
114
+ type: "high_entropy_env",
115
+ // Anchored with alternation instead of lookbehind to avoid backtracking.
116
+ // Value bounded at 512 chars.
117
+ // The trailing boundary is a NON-consuming lookahead so two secrets
118
+ // separated by a single delimiter (one space OR one newline, e.g.
119
+ // `printenv` / `.env` dumps: `API_KEY=… \n SESSION_TOKEN=…`) are BOTH
120
+ // redacted. A consuming trailing `\s` would swallow the separator the
121
+ // next match needs for its leading anchor, so every other secret would
122
+ // leak in plaintext.
123
+ // The leading delimiter is CAPTURED (group 1) and re-emitted by the
124
+ // replacement so the separator between adjacent secrets is preserved
125
+ // rather than collapsed. Capture groups are therefore: 1=leading
126
+ // delimiter, 2=key name, 3=value.
127
+ regex: /(^|\s)([A-Z_]{4,}(?:KEY|TOKEN|SECRET|PASSWORD|PWD|PASSPHRASE))\s*[:=]\s*['"]?([A-Za-z0-9_/+=-]{20,512})['"]?(?=\s|$)/g,
128
+ anchor: ["KEY", "TOKEN", "SECRET", "PASSWORD", "PWD", "PASSPHRASE"]
129
+ },
130
+ {
131
+ type: "json_credential_key",
132
+ // The JSON counterpart to `high_entropy_env`, and the pattern that the
133
+ // now-deleted `JSON_KEY_ANCHORS` list was written for. Without it those
134
+ // anchors only widened the cheap pre-scan — `hasCredentialAnchors` said
135
+ // "this text may hold a secret", every pattern then declined to match, and
136
+ // the value went out verbatim. `high_entropy_env` cannot cover these: it
137
+ // requires an UPPERCASE unquoted key (`API_KEY=…`), so `{"apiKey":"…"}`
138
+ // never matched.
139
+ //
140
+ // Tool results are routinely serialised as JSON, and a credential with no
141
+ // recognisable prefix (Azure, self-hosted gateways, Anthropic/Codex OAuth)
142
+ // has no other pattern that can catch it — this is the only thing standing
143
+ // between such a value and the session JSONL, chronicle, HQ broadcast and
144
+ // the model's own context.
145
+ //
146
+ // The key may carry a prefix (`"anthropicApiKey"`), but the credential word
147
+ // must END the key: `"tokenCount"` and `"maxTokens"` do not match, because
148
+ // the closing quote has to follow the word immediately.
149
+ // Value floor of 8 chars keeps enum-ish values (`"authorization":"none"`)
150
+ // out. Capture groups: 1=key + punctuation, 2=value, 3=closing quote.
151
+ regex: /("[A-Za-z0-9_]*(?:apiKey|api_key|token|secret|password|authorization|bearer|private_key|access_token|refresh_token|client_secret)"\s*:\s*")([^"\\]{8,512})(")/gi,
152
+ anchor: JSON_CREDENTIAL_KEY_ANCHORS
153
+ },
154
+ // ── Ported from packages/plugins credential-patterns.ts (WS-034) ─────────
155
+ // The plugin runtime carried 37 patterns while this scrubber — the one that
156
+ // guards session JSONL, chronicle, HQ broadcast, WebUI events and the auth
157
+ // audit — carried 22. The plugin side already had a parity test; it just did
158
+ // not cover core. Most consequential: WrongStack mints `gho_` tokens itself
159
+ // in the Copilot OAuth flow, and `gh[ousr]_` was absent here.
160
+ {
161
+ type: "github_oauth_token",
162
+ regex: /(?<![A-Za-z0-9])gh[ousr]_[A-Za-z0-9]{36,}(?![A-Za-z0-9])/g,
163
+ anchor: ["gho_", "ghu_", "ghs_", "ghr_"]
164
+ },
165
+ {
166
+ type: "gitlab_pat",
167
+ regex: /(?<![A-Za-z0-9])glpat-[A-Za-z0-9_-]{20,}(?![A-Za-z0-9_-])/g,
168
+ anchor: "glpat-"
169
+ },
170
+ {
171
+ type: "gitlab_runner_token",
172
+ regex: /(?<![A-Za-z0-9])glrt-[A-Za-z0-9_-]{20,}(?![A-Za-z0-9_-])/g,
173
+ anchor: "glrt-"
174
+ },
175
+ {
176
+ type: "npm_token",
177
+ regex: /(?<![A-Za-z0-9])npm_[A-Za-z0-9]{36}(?![A-Za-z0-9])/g,
178
+ anchor: "npm_"
179
+ },
180
+ {
181
+ type: "slack_app_token",
182
+ regex: /(?<![A-Za-z0-9-])xapp-\d-[A-Za-z0-9-]{10,}(?![A-Za-z0-9-])/g,
183
+ anchor: "xapp-"
184
+ },
185
+ {
186
+ type: "slack_webhook",
187
+ regex: /https:\/\/hooks\.slack\.com\/services\/T[A-Za-z0-9_-]+\/B[A-Za-z0-9_-]+\/[A-Za-z0-9]{16,}/g,
188
+ anchor: "hooks.slack.com"
189
+ },
190
+ {
191
+ type: "sendgrid_key",
192
+ regex: /(?<![A-Za-z0-9])SG\.[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}(?![A-Za-z0-9_-])/g,
193
+ anchor: "SG."
194
+ },
195
+ {
196
+ type: "digitalocean_token",
197
+ regex: /(?<![A-Za-z0-9])dop_v1_[a-f0-9]{64}(?![A-Za-z0-9])/g,
198
+ anchor: "dop_v1_"
199
+ },
200
+ {
201
+ type: "doppler_token",
202
+ regex: /(?<![A-Za-z0-9])dp\.(?:pt|st|sa|scim|audit)\.[A-Za-z0-9]{40,}(?![A-Za-z0-9])/g,
203
+ anchor: "dp."
204
+ },
205
+ {
206
+ type: "shopify_token",
207
+ regex: /(?<![A-Za-z0-9])shp(?:at|ca|pa|ss)_[a-fA-F0-9]{32}(?![A-Za-z0-9])/g,
208
+ anchor: "shp"
209
+ },
210
+ {
211
+ type: "docker_pat",
212
+ regex: /(?<![A-Za-z0-9])dckr_pat_[A-Za-z0-9_-]{20,}(?![A-Za-z0-9_-])/g,
213
+ anchor: "dckr_pat_"
214
+ },
215
+ {
216
+ type: "linear_key",
217
+ regex: /(?<![A-Za-z0-9])lin_api_[A-Za-z0-9]{40,}(?![A-Za-z0-9])/g,
218
+ anchor: "lin_api_"
219
+ },
220
+ {
221
+ type: "atlassian_token",
222
+ regex: /(?<![A-Za-z0-9])ATATT3[A-Za-z0-9_\-=]{40,}(?![A-Za-z0-9_\-=])/g,
223
+ anchor: "ATATT3"
224
+ },
225
+ {
226
+ type: "square_token",
227
+ regex: /(?<![A-Za-z0-9])(?:sq0(?:atp|csp)-|EAAA)[A-Za-z0-9_-]{20,}(?![A-Za-z0-9_-])/g,
228
+ anchor: ["sq0atp-", "sq0csp-", "EAAA"]
229
+ },
230
+ {
231
+ type: "google_oauth_client_secret",
232
+ regex: /(?<![A-Za-z0-9_-])GOCSPX-[A-Za-z0-9_-]{20,}(?![A-Za-z0-9_-])/g,
233
+ anchor: "GOCSPX-"
234
+ }
235
+ ];
236
+ var SIMPLE_PATTERNS = PATTERNS.filter(
237
+ (p) => p.type !== "high_entropy_env" && p.type !== "json_credential_key"
238
+ );
239
+ var COMBINED_REGEX = new RegExp(SIMPLE_PATTERNS.map((p) => `(${p.regex.source})`).join("|"), "g");
240
+ var HIGH_ENTROPY_REGEX = PATTERNS.find((p) => p.type === "high_entropy_env").regex;
241
+ var JSON_CREDENTIAL_REGEX = PATTERNS.find((p) => p.type === "json_credential_key").regex;
242
+ var COMBINED_REPLACEMENTS = SIMPLE_PATTERNS.map((p) => `[REDACTED:${p.type}]`);
243
+ var SCRUB_CHUNK_BYTES = 64 * 1024;
244
+ var SCRUB_OVERLAP_BYTES = 1024;
245
+ var PEM_PRIVATE_KEY_BEGIN_RE = /-----BEGIN (?:RSA|EC|OPENSSH|DSA|PGP)? ?PRIVATE KEY-----/;
246
+ var PEM_END_MARKER = "-----END";
247
+ var MAX_PEM_BLOCK_BYTES = 64 * 1024;
248
+ var PEM_END_LINE_TOLERANCE = 64;
249
+ function extendChunkBoundaryPastPem(text, chunkStart, proposedEnd) {
250
+ const head = text.slice(chunkStart, proposedEnd);
251
+ const lastBegin = head.lastIndexOf("-----BEGIN ");
252
+ if (lastBegin === -1) return proposedEnd;
253
+ const fromBegin = text.slice(chunkStart + lastBegin);
254
+ const marker = PEM_PRIVATE_KEY_BEGIN_RE.exec(fromBegin);
255
+ if (marker?.index !== 0) return proposedEnd;
256
+ const bodyStart = marker[0].length;
257
+ const cap = Math.min(text.length, chunkStart + lastBegin + MAX_PEM_BLOCK_BYTES);
258
+ const closeIdx = fromBegin.indexOf(PEM_END_MARKER, bodyStart);
259
+ if (closeIdx === -1 || chunkStart + lastBegin + closeIdx >= cap + PEM_END_LINE_TOLERANCE) {
260
+ return proposedEnd;
261
+ }
262
+ const lineEnd = fromBegin.indexOf("\n", closeIdx);
263
+ const end = lineEnd === -1 ? text.length : chunkStart + lastBegin + lineEnd + 1;
264
+ return Math.max(proposedEnd, end);
265
+ }
266
+ var PATTERN_ANCHORS = [
267
+ ...new Set(
268
+ PATTERNS.flatMap(
269
+ (pattern) => typeof pattern.anchor === "string" ? [pattern.anchor] : [...pattern.anchor]
270
+ )
271
+ )
272
+ ];
273
+ var ALL_ANCHORS = PATTERN_ANCHORS;
274
+ function escapeLiteral(text) {
275
+ return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
276
+ }
277
+ var ANCHOR_PRESCAN = new RegExp(ALL_ANCHORS.map(escapeLiteral).join("|"));
278
+ function hasCredentialAnchors(text) {
279
+ return ANCHOR_PRESCAN.test(text);
280
+ }
281
+ var DefaultSecretScrubber = class {
282
+ scrub(text) {
283
+ if (!text) return text;
284
+ if (!hasCredentialAnchors(text)) return text;
285
+ if (text.length <= SCRUB_CHUNK_BYTES) {
286
+ return this.scrubOne(text);
287
+ }
288
+ const out = [];
289
+ let i = 0;
290
+ while (i < text.length) {
291
+ let end = Math.min(i + SCRUB_CHUNK_BYTES, text.length);
292
+ if (end < text.length) {
293
+ const limit = Math.min(end + SCRUB_OVERLAP_BYTES, text.length);
294
+ let safe = -1;
295
+ for (let j = end; j < limit; j++) {
296
+ const ch = text.charCodeAt(j);
297
+ if (ch === 32 || ch === 9 || ch === 10 || ch === 13) {
298
+ safe = j;
299
+ break;
300
+ }
301
+ }
302
+ end = safe === -1 ? end : safe + 1;
303
+ end = extendChunkBoundaryPastPem(text, i, end);
304
+ }
305
+ out.push(this.scrubOne(text.slice(i, end)));
306
+ i = end;
307
+ }
308
+ return out.join("");
309
+ }
310
+ scrubOne(text) {
311
+ if (!hasCredentialAnchors(text)) return text;
312
+ let out = text.replace(
313
+ COMBINED_REGEX,
314
+ (match, ...groups) => {
315
+ const idx = groups.findIndex((g) => g !== void 0);
316
+ if (idx < 0) return match;
317
+ const replacement = COMBINED_REPLACEMENTS[idx];
318
+ return replacement !== void 0 ? replacement : match;
319
+ }
320
+ );
321
+ out = out.replace(HIGH_ENTROPY_REGEX, (_match, lead, key, _value) => {
322
+ return `${lead}${key}=[REDACTED:high_entropy_env]`;
323
+ });
324
+ out = out.replace(JSON_CREDENTIAL_REGEX, (_match, keyPrefix, _value, closingQuote) => {
325
+ return `${keyPrefix}[REDACTED:json_credential_key]${closingQuote}`;
326
+ });
327
+ return out;
328
+ }
329
+ /**
330
+ * Recursively scrub every string value in an object/array graph. Secrets can
331
+ * appear under any key — a URL query param, an `authorization` header, an
332
+ * arbitrarily-named nested field — so we don't gate recursion on key names.
333
+ * The per-string `scrub()` fast-path (anchor pre-scan) keeps this cheap: any
334
+ * value without a credential anchor returns immediately without regex work.
335
+ */
336
+ scrubObject(obj) {
337
+ const seen = /* @__PURE__ */ new WeakSet();
338
+ const visit = (v) => {
339
+ if (typeof v === "string") return this.scrub(v);
340
+ if (v === null || typeof v !== "object") return v;
341
+ if (seen.has(v)) return v;
342
+ seen.add(v);
343
+ if (Array.isArray(v)) return v.map(visit);
344
+ const out = {};
345
+ for (const [k, val] of Object.entries(v)) {
346
+ out[k] = visit(val);
347
+ }
348
+ return out;
349
+ };
350
+ return visit(obj);
351
+ }
352
+ /**
353
+ * Copy-on-write {@link scrubObject}: clean subtrees come back by reference.
354
+ *
355
+ * `scrubObject` rebuilds the entire graph unconditionally — a new object for
356
+ * every node, a new array for every array — whether or not anything was
357
+ * redacted. On the read path that is almost all waste: measured over a real
358
+ * 133 MB journal, 488k nodes and 309k strings were rebuilt so that FOUR
359
+ * strings could be redacted, costing ~480 ms of allocation and the GC
360
+ * pressure that comes with it. Rebuilding only the spine above an actual
361
+ * redaction gives the same output for a fraction of the garbage.
362
+ *
363
+ * The sharing is why this is a separate method rather than a change to
364
+ * `scrubObject`: see the contract note on `SecretScrubber.scrubObjectShared`.
365
+ */
366
+ scrubObjectShared(obj) {
367
+ const seen = /* @__PURE__ */ new WeakSet();
368
+ const visit = (v) => {
369
+ if (typeof v === "string") return this.scrub(v);
370
+ if (v === null || typeof v !== "object") return v;
371
+ if (seen.has(v)) return v;
372
+ seen.add(v);
373
+ if (Array.isArray(v)) {
374
+ let out2;
375
+ for (let i = 0; i < v.length; i++) {
376
+ const before = v[i];
377
+ const after = visit(before);
378
+ if (after === before) continue;
379
+ out2 ??= [...v];
380
+ out2[i] = after;
381
+ }
382
+ return out2 ?? v;
383
+ }
384
+ const source = v;
385
+ let out;
386
+ for (const k of Object.keys(source)) {
387
+ const before = source[k];
388
+ const after = visit(before);
389
+ if (after === before) continue;
390
+ out ??= { ...source };
391
+ out[k] = after;
392
+ }
393
+ return out ?? v;
394
+ };
395
+ return visit(obj);
396
+ }
397
+ };
398
+
399
+ export {
400
+ DefaultSecretScrubber
401
+ };
402
+ //# sourceMappingURL=chunk-QSTSJOCK.js.map
@@ -0,0 +1,282 @@
1
+ import {
2
+ DefaultSecretScrubber
3
+ } from "./chunk-QSTSJOCK.js";
4
+
5
+ // src/prompts/prompt-journal.ts
6
+ import * as fs from "node:fs/promises";
7
+ import * as path from "node:path";
8
+ var defaultScrubber = new DefaultSecretScrubber();
9
+ var PROMPT_JOURNAL_RAW_MARKER = "promptJournal.raw";
10
+ async function ensureGitignore(projectRoot) {
11
+ const gitignorePath = path.join(projectRoot, ".gitignore");
12
+ try {
13
+ let content = "";
14
+ try {
15
+ content = await fs.readFile(gitignorePath, "utf8");
16
+ } catch {
17
+ content = "";
18
+ }
19
+ if (!content.includes(".wrongstack") && !content.includes(".wrongstack/")) {
20
+ const addition = content.endsWith("\n") || content.length === 0 ? ".wrongstack/\n" : "\n.wrongstack/\n";
21
+ await fs.writeFile(gitignorePath, content + addition, "utf8");
22
+ }
23
+ } catch {
24
+ }
25
+ }
26
+ function sessionFileId(sessionId) {
27
+ const leaf = sessionId.split(/[\\/]/u).pop();
28
+ return leaf && leaf.trim().length > 0 ? leaf : "general";
29
+ }
30
+ async function recordPromptJournalEntry(opts) {
31
+ const now = /* @__PURE__ */ new Date();
32
+ const timestamp = now.toISOString();
33
+ const dateStr = timestamp.slice(0, 10);
34
+ const monthStr = dateStr.slice(0, 7);
35
+ const sessionId = opts.sessionId?.trim() || "general";
36
+ const id = `pmt_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
37
+ const content = defaultScrubber.scrub(opts.content ?? "");
38
+ const rawContent = typeof opts.rawContent === "string" && opts.rawContent.length > 0 ? defaultScrubber.scrub(opts.rawContent) : opts.rawContent;
39
+ const decisionReason = typeof opts.decisionReason === "string" && opts.decisionReason.length > 0 ? defaultScrubber.scrub(opts.decisionReason) : opts.decisionReason;
40
+ const lines = content.split("\n");
41
+ const characterCount = content.length;
42
+ const lineCount = lines.length;
43
+ const tokenEstimate = Math.ceil(characterCount / 4);
44
+ const entry = {
45
+ id,
46
+ timestamp,
47
+ sessionId,
48
+ projectRoot: opts.projectRoot,
49
+ role: opts.role ?? (opts.category === "system_prompt" ? "system" : "user"),
50
+ category: opts.category,
51
+ content,
52
+ rawContent,
53
+ metadata: {
54
+ model: opts.model,
55
+ provider: opts.provider,
56
+ iterationIndex: opts.iterationIndex,
57
+ tokenEstimate,
58
+ characterCount,
59
+ lineCount,
60
+ activeTools: opts.activeTools,
61
+ contextFiles: opts.contextFiles,
62
+ durationMs: opts.durationMs,
63
+ decisionReason,
64
+ tags: opts.tags
65
+ }
66
+ };
67
+ const basePromptsDir = path.join(opts.projectRoot, ".wrongstack", "prompts");
68
+ const dayDir = path.join(basePromptsDir, monthStr, dateStr);
69
+ try {
70
+ await fs.mkdir(dayDir, { recursive: true });
71
+ await ensureGitignore(opts.projectRoot);
72
+ const sessionJsonlFile = path.join(dayDir, `session-${sessionFileId(sessionId)}.jsonl`);
73
+ await fs.appendFile(sessionJsonlFile, JSON.stringify(entry) + "\n", "utf8");
74
+ const sessionMdFile = path.join(dayDir, `session-${sessionFileId(sessionId)}.md`);
75
+ const mdSection = formatEntryMarkdown(entry);
76
+ await fs.appendFile(sessionMdFile, mdSection, "utf8");
77
+ const dailySummaryFile = path.join(dayDir, "daily-summary.md");
78
+ await updateDailySummary(dailySummaryFile, dateStr, entry);
79
+ await updateRootCatalog(basePromptsDir, monthStr, dateStr, sessionId, entry);
80
+ } catch (err) {
81
+ console.error?.(`Failed to write hierarchical prompt journal: ${err}`);
82
+ }
83
+ return entry;
84
+ }
85
+ function formatEntryMarkdown(entry) {
86
+ const tagList = [
87
+ `**Category:** \`${entry.category}\``,
88
+ `**Role:** \`${entry.role}\``,
89
+ entry.metadata.model ? `**Model:** \`${entry.metadata.model}\`` : null,
90
+ `**Tokens (est):** ~${entry.metadata.tokenEstimate}`,
91
+ entry.metadata.iterationIndex !== void 0 ? `**Iteration:** #${entry.metadata.iterationIndex}` : null,
92
+ `**Session:** \`${entry.sessionId}\``
93
+ ].filter(Boolean).join(" | ");
94
+ let md = `
95
+ ### \u{1F4DD} [${entry.timestamp}] \`${entry.id}\`
96
+ ${tagList}
97
+
98
+ `;
99
+ if (entry.metadata.decisionReason) {
100
+ md += `> **Rationale:** ${entry.metadata.decisionReason}
101
+
102
+ `;
103
+ }
104
+ if (entry.metadata.activeTools && entry.metadata.activeTools.length > 0) {
105
+ md += `*Active Tools:* \`${entry.metadata.activeTools.join("`, `")}\`
106
+
107
+ `;
108
+ }
109
+ if (entry.rawContent && entry.rawContent !== entry.content) {
110
+ md += `**Raw Input:**
111
+ \`\`\`text
112
+ ${entry.rawContent.trim()}
113
+ \`\`\`
114
+
115
+ `;
116
+ md += `**Refined / Injected Prompt:**
117
+ \`\`\`text
118
+ ${entry.content.trim()}
119
+ \`\`\`
120
+
121
+ `;
122
+ } else {
123
+ md += `**Prompt Content:**
124
+ \`\`\`text
125
+ ${entry.content.trim()}
126
+ \`\`\`
127
+
128
+ `;
129
+ }
130
+ md += `---
131
+ `;
132
+ return md;
133
+ }
134
+ async function updateDailySummary(summaryFile, dateStr, entry) {
135
+ try {
136
+ let content = "";
137
+ try {
138
+ content = await fs.readFile(summaryFile, "utf8");
139
+ } catch {
140
+ content = `# \u{1F4C5} Daily Prompt Summary \u2014 ${dateStr}
141
+
142
+ | Time | ID | Session | Category | Model | Tokens | Rationale |
143
+ | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
144
+ `;
145
+ }
146
+ const time = entry.timestamp.slice(11, 19);
147
+ const model = entry.metadata.model ?? "-";
148
+ const reason = entry.metadata.decisionReason ? entry.metadata.decisionReason.slice(0, 40) : "-";
149
+ const row = `| ${time} | [\`${entry.id}\`](session-${sessionFileId(entry.sessionId)}.md) | \`${entry.sessionId}\` | \`${entry.category}\` | ${model} | ~${entry.metadata.tokenEstimate} | ${reason} |
150
+ `;
151
+ await fs.writeFile(summaryFile, content + row, "utf8");
152
+ } catch {
153
+ }
154
+ }
155
+ async function updateRootCatalog(baseDir, monthStr, dateStr, sessionId, entry) {
156
+ const indexJsonFile = path.join(baseDir, "index.json");
157
+ const indexMdFile = path.join(baseDir, "index.md");
158
+ let catalog;
159
+ try {
160
+ const raw = await fs.readFile(indexJsonFile, "utf8");
161
+ catalog = JSON.parse(raw);
162
+ } catch {
163
+ catalog = {
164
+ updatedAt: entry.timestamp,
165
+ totalPrompts: 0,
166
+ totalTokensEstimated: 0,
167
+ months: {}
168
+ };
169
+ }
170
+ catalog.updatedAt = entry.timestamp;
171
+ catalog.totalPrompts += 1;
172
+ catalog.totalTokensEstimated += entry.metadata.tokenEstimate;
173
+ if (!catalog.months[monthStr]) {
174
+ catalog.months[monthStr] = { days: {} };
175
+ }
176
+ const monthData = catalog.months[monthStr];
177
+ if (!monthData.days[dateStr]) {
178
+ monthData.days[dateStr] = { sessions: {} };
179
+ }
180
+ const dayData = monthData.days[dateStr];
181
+ if (!dayData.sessions[sessionId]) {
182
+ dayData.sessions[sessionId] = {
183
+ promptCount: 0,
184
+ tokenEstimate: 0,
185
+ lastTimestamp: entry.timestamp,
186
+ categories: {}
187
+ };
188
+ }
189
+ const sessionData = dayData.sessions[sessionId];
190
+ sessionData.promptCount += 1;
191
+ sessionData.tokenEstimate += entry.metadata.tokenEstimate;
192
+ sessionData.lastTimestamp = entry.timestamp;
193
+ sessionData.categories[entry.category] = (sessionData.categories[entry.category] ?? 0) + 1;
194
+ try {
195
+ await fs.writeFile(indexJsonFile, JSON.stringify(catalog, null, 2), "utf8");
196
+ let md = `# \u{1F5C2}\uFE0F Prompt Journal Navigation Index
197
+
198
+ `;
199
+ md += `* **Total Prompts Logged:** ${catalog.totalPrompts}
200
+ `;
201
+ md += `* **Total Tokens (est):** ~${catalog.totalTokensEstimated.toLocaleString()}
202
+ `;
203
+ md += `* **Last Recorded Activity:** ${catalog.updatedAt}
204
+
205
+ `;
206
+ md += `## \u{1F4C5} Recorded Dates & Sessions
207
+
208
+ `;
209
+ md += `| Date | Session | Prompts | Tokens (est) | Daily Log | Session Log |
210
+ `;
211
+ md += `| :--- | :--- | :--- | :--- | :--- | :--- |
212
+ `;
213
+ for (const [m, mObj] of Object.entries(catalog.months).sort().reverse()) {
214
+ for (const [d, dObj] of Object.entries(mObj.days).sort().reverse()) {
215
+ for (const [sId, sData] of Object.entries(dObj.sessions)) {
216
+ const dailyLink = `[daily-summary.md](./${m}/${d}/daily-summary.md)`;
217
+ const sessionLink = `[session-${sessionFileId(sId)}.md](./${m}/${d}/session-${sessionFileId(sId)}.md)`;
218
+ md += `| **${d}** | \`${sId}\` | ${sData.promptCount} | ~${sData.tokenEstimate.toLocaleString()} | ${dailyLink} | ${sessionLink} |
219
+ `;
220
+ }
221
+ }
222
+ }
223
+ await fs.writeFile(indexMdFile, md, "utf8");
224
+ } catch {
225
+ }
226
+ }
227
+ async function getPromptJournalEntries(projectRoot, filter = {}) {
228
+ const basePromptsDir = path.join(projectRoot, ".wrongstack", "prompts");
229
+ const results = [];
230
+ try {
231
+ const months = await fs.readdir(basePromptsDir);
232
+ for (const month of months) {
233
+ if (!/^\d{4}-\d{2}$/.test(month)) continue;
234
+ if (filter.month && filter.month !== month) continue;
235
+ const monthDir = path.join(basePromptsDir, month);
236
+ const days = await fs.readdir(monthDir);
237
+ for (const day of days) {
238
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(day)) continue;
239
+ if (filter.date && filter.date !== day) continue;
240
+ const dayDir = path.join(monthDir, day);
241
+ const files = await fs.readdir(dayDir);
242
+ const jsonlFiles = files.filter((f) => f.startsWith("session-") && f.endsWith(".jsonl"));
243
+ for (const jsonlFile of jsonlFiles) {
244
+ const sessionMatch = jsonlFile.match(/^session-(.+)\.jsonl$/);
245
+ const sId = sessionMatch ? sessionMatch[1] : void 0;
246
+ if (filter.sessionId && sId !== sessionFileId(filter.sessionId)) continue;
247
+ const filePath = path.join(dayDir, jsonlFile);
248
+ const content = await fs.readFile(filePath, "utf8");
249
+ const lines = content.split("\n");
250
+ for (const line of lines) {
251
+ if (!line.trim()) continue;
252
+ try {
253
+ const entry = JSON.parse(line);
254
+ if (filter.sessionId && sessionFileId(entry.sessionId) !== sessionFileId(filter.sessionId)) {
255
+ continue;
256
+ }
257
+ if (filter.category && entry.category !== filter.category) continue;
258
+ if (filter.since && entry.timestamp < filter.since) continue;
259
+ results.push(entry);
260
+ } catch {
261
+ }
262
+ }
263
+ }
264
+ }
265
+ }
266
+ } catch {
267
+ return [];
268
+ }
269
+ results.sort((a, b) => a.timestamp.localeCompare(b.timestamp));
270
+ if (filter.limit && results.length > filter.limit) {
271
+ return results.slice(-filter.limit);
272
+ }
273
+ return results;
274
+ }
275
+
276
+ export {
277
+ PROMPT_JOURNAL_RAW_MARKER,
278
+ ensureGitignore,
279
+ recordPromptJournalEntry,
280
+ getPromptJournalEntries
281
+ };
282
+ //# sourceMappingURL=chunk-RFQMOKWK.js.map