@pugi/cli 0.1.0-beta.10 → 0.1.0-beta.100

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 (445) hide show
  1. package/CHANGELOG.md +132 -0
  2. package/LICENSE +1 -1
  3. package/README.md +53 -11
  4. package/assets/pugi-prozr2-mascot.ansi +9 -0
  5. package/bin/run.js +33 -1
  6. package/dist/commands/deploy.js +40 -40
  7. package/dist/commands/flatten.js +191 -0
  8. package/dist/commands/jobs-watch.js +201 -0
  9. package/dist/commands/jobs.js +42 -27
  10. package/dist/commands/retro.js +210 -0
  11. package/dist/commands/smoke.js +133 -0
  12. package/dist/core/agent-progress/cleanup.js +134 -0
  13. package/dist/core/agent-progress/schema.js +144 -0
  14. package/dist/core/agent-progress/writer.js +101 -0
  15. package/dist/core/agents/adaptive-router.js +330 -0
  16. package/dist/core/agents/query-decomposer.js +297 -0
  17. package/dist/core/agents/registry.js +3 -3
  18. package/dist/core/approvals/shortcut-resolver.js +98 -0
  19. package/dist/core/artifact-chain/dispatcher.js +148 -0
  20. package/dist/core/artifact-chain/exporter.js +164 -0
  21. package/dist/core/artifact-chain/state.js +243 -0
  22. package/dist/core/artifact-chain/steps.js +169 -0
  23. package/dist/core/ask-user/question.js +92 -0
  24. package/dist/core/audit/audit-trail.js +275 -0
  25. package/dist/core/auth/ensure-authenticated.js +129 -0
  26. package/dist/core/auth/env-provider.js +238 -0
  27. package/dist/core/auto-open-browser.js +4 -4
  28. package/dist/core/auto-update/channels.js +122 -0
  29. package/dist/core/auto-update/checker.js +241 -0
  30. package/dist/core/auto-update/state.js +235 -0
  31. package/dist/core/bare-mode/index.js +107 -0
  32. package/dist/core/bash/redirect.js +281 -0
  33. package/dist/core/bash-classifier.js +436 -40
  34. package/dist/core/checkpoint/resumer.js +149 -0
  35. package/dist/core/checkpoint/rewinder.js +291 -0
  36. package/dist/core/checkpoints/shadow-git.js +670 -0
  37. package/dist/core/citations/parser.js +109 -0
  38. package/dist/core/classifier/yolo-classifier.js +88 -0
  39. package/dist/core/codegraph/db.js +506 -0
  40. package/dist/core/codegraph/decision-store.js +248 -0
  41. package/dist/core/codegraph/detect-repo.js +459 -0
  42. package/dist/core/codegraph/install.js +134 -0
  43. package/dist/core/codegraph/offer-hook.js +220 -0
  44. package/dist/core/codegraph/parser.js +71 -0
  45. package/dist/core/codegraph/types.js +34 -0
  46. package/dist/core/compact/auto-trigger.js +96 -0
  47. package/dist/core/compact/buffer-rewriter.js +115 -0
  48. package/dist/core/compact/summarizer.js +208 -0
  49. package/dist/core/compact/token-counter.js +108 -0
  50. package/dist/core/consensus/anvil-fanout.js +25 -25
  51. package/dist/core/consensus/diff-capture.js +121 -12
  52. package/dist/core/consensus/rubric.js +21 -21
  53. package/dist/core/context/builder.js +6 -6
  54. package/dist/core/context/compaction-events.js +8 -8
  55. package/dist/core/context/compaction.js +31 -31
  56. package/dist/core/context/index.js +15 -8
  57. package/dist/core/context/invariants.js +51 -51
  58. package/dist/core/context/markdown-loader.js +28 -10
  59. package/dist/core/context/markdown-traverse.js +255 -0
  60. package/dist/core/context/pugiignore.js +41 -41
  61. package/dist/core/context/repo-skeleton.js +37 -37
  62. package/dist/core/context/tool-eviction.js +55 -0
  63. package/dist/core/context/watcher.js +32 -32
  64. package/dist/core/context/working-set.js +23 -23
  65. package/dist/core/coordinator/agent-tools.js +77 -0
  66. package/dist/core/coordinator/agent-toolset.js +65 -0
  67. package/dist/core/coordinator/fsm.js +73 -0
  68. package/dist/core/coordinator/mode-fsm.js +70 -0
  69. package/dist/core/cost/rate-card.js +129 -0
  70. package/dist/core/cost/tracker.js +221 -0
  71. package/dist/core/credentials.js +13 -13
  72. package/dist/core/cron/scheduler.js +138 -0
  73. package/dist/core/denial-tracking/index.js +8 -0
  74. package/dist/core/denial-tracking/state.js +264 -0
  75. package/dist/core/diagnostics/probe-runner.js +93 -0
  76. package/dist/core/diagnostics/probes/api.js +46 -0
  77. package/dist/core/diagnostics/probes/auth.js +93 -0
  78. package/dist/core/diagnostics/probes/bare-mode.js +42 -0
  79. package/dist/core/diagnostics/probes/cli-version.js +127 -0
  80. package/dist/core/diagnostics/probes/config.js +72 -0
  81. package/dist/core/diagnostics/probes/denial-tracking.js +57 -0
  82. package/dist/core/diagnostics/probes/disk.js +81 -0
  83. package/dist/core/diagnostics/probes/engine-live.js +46 -0
  84. package/dist/core/diagnostics/probes/git.js +65 -0
  85. package/dist/core/diagnostics/probes/hooks.js +118 -0
  86. package/dist/core/diagnostics/probes/mcp.js +75 -0
  87. package/dist/core/diagnostics/probes/node.js +59 -0
  88. package/dist/core/diagnostics/probes/pnpm.js +36 -0
  89. package/dist/core/diagnostics/probes/pugi-md.js +89 -0
  90. package/dist/core/diagnostics/probes/sandbox.js +72 -0
  91. package/dist/core/diagnostics/probes/session.js +74 -0
  92. package/dist/core/diagnostics/probes/status-snapshot.js +488 -0
  93. package/dist/core/diagnostics/probes/workspace.js +63 -0
  94. package/dist/core/diagnostics/types.js +70 -0
  95. package/dist/core/dispatch/cache-cleanup.js +197 -0
  96. package/dist/core/dispatch/cache-handoff.js +295 -0
  97. package/dist/core/edits/apply-patch-layer-e.js +189 -0
  98. package/dist/core/edits/dispatch.js +333 -7
  99. package/dist/core/edits/format-detector.js +260 -0
  100. package/dist/core/edits/format-matrix.js +26 -0
  101. package/dist/core/edits/fuzzy-ladder.js +650 -0
  102. package/dist/core/edits/index.js +5 -1
  103. package/dist/core/edits/journal.js +199 -0
  104. package/dist/core/edits/layer-a-apply.js +15 -15
  105. package/dist/core/edits/layer-a-fuzzy-apply.js +198 -0
  106. package/dist/core/edits/layer-b-apply.js +9 -9
  107. package/dist/core/edits/layer-c-apply.js +6 -6
  108. package/dist/core/edits/layer-d-ast.js +557 -14
  109. package/dist/core/edits/marker-parser.js +12 -12
  110. package/dist/core/edits/security-gate.js +27 -27
  111. package/dist/core/edits/verify-hook.js +273 -0
  112. package/dist/core/edits/worktree.js +29 -29
  113. package/dist/core/engine/anvil-client.js +214 -26
  114. package/dist/core/engine/auto-compact.js +247 -0
  115. package/dist/core/engine/budgets.js +220 -0
  116. package/dist/core/engine/compact-llm-summarizer.js +124 -0
  117. package/dist/core/engine/context-prefix.js +155 -0
  118. package/dist/core/engine/index.js +1 -1
  119. package/dist/core/engine/intensity.js +163 -0
  120. package/dist/core/engine/intent.js +260 -0
  121. package/dist/core/engine/native-pugi.js +1559 -227
  122. package/dist/core/engine/prompts.js +187 -19
  123. package/dist/core/engine/strip-internal-fields.js +124 -0
  124. package/dist/core/engine/tool-bridge.js +1887 -59
  125. package/dist/core/engine/verification-patterns.js +195 -0
  126. package/dist/core/evaluation/golden-dataset.js +293 -0
  127. package/dist/core/feedback/queue.js +177 -0
  128. package/dist/core/feedback/submitter.js +145 -0
  129. package/dist/core/file-cache.js +113 -1
  130. package/dist/core/flatten/flatten-repo.js +439 -0
  131. package/dist/core/format/osc8-link.js +28 -0
  132. package/dist/core/hook-chains.js +392 -0
  133. package/dist/core/hooks/citation-verify-hook.js +138 -0
  134. package/dist/core/hooks/citation-verify.js +112 -0
  135. package/dist/core/hooks/events.js +46 -0
  136. package/dist/core/hooks/index.js +15 -0
  137. package/dist/core/hooks/registry.js +216 -0
  138. package/dist/core/hooks/runner.js +236 -0
  139. package/dist/core/hooks/v2/event-emitter.js +115 -0
  140. package/dist/core/hooks/v2/executor.js +282 -0
  141. package/dist/core/hooks/v2/index.js +25 -0
  142. package/dist/core/hooks/v2/lifecycle.js +104 -0
  143. package/dist/core/hooks/v2/loader.js +216 -0
  144. package/dist/core/hooks/v2/matcher.js +125 -0
  145. package/dist/core/hooks/v2/trust.js +143 -0
  146. package/dist/core/hooks/v2/types.js +86 -0
  147. package/dist/core/hooks/worktree-events.js +158 -0
  148. package/dist/core/image/renderer.js +71 -0
  149. package/dist/core/init/detector.js +582 -0
  150. package/dist/core/init/template-renderer.js +242 -0
  151. package/dist/core/jobs/registry.js +18 -18
  152. package/dist/core/ledger/results-tsv.js +142 -0
  153. package/dist/core/log-discipline/stdout-redirect.js +51 -0
  154. package/dist/core/lsp/cache.js +105 -0
  155. package/dist/core/lsp/client.js +551 -41
  156. package/dist/core/lsp/language-detect.js +66 -0
  157. package/dist/core/lsp/post-edit-diagnostics.js +171 -0
  158. package/dist/core/lsp/server-detect.js +173 -0
  159. package/dist/core/lsp/symbol-cache.js +162 -0
  160. package/dist/core/lsp/symbol-tools.js +664 -0
  161. package/dist/core/mcp/client.js +97 -28
  162. package/dist/core/mcp/http-server.js +553 -0
  163. package/dist/core/mcp/orchestrator-config.js +192 -0
  164. package/dist/core/mcp/orchestrator-tools.js +806 -0
  165. package/dist/core/mcp/permission.js +190 -0
  166. package/dist/core/mcp/registry.js +39 -17
  167. package/dist/core/mcp/server-tools.js +219 -0
  168. package/dist/core/mcp/server.js +397 -0
  169. package/dist/core/mcp/trust.js +10 -10
  170. package/dist/core/memory/dual-write.js +416 -0
  171. package/dist/core/memory/passive-extract.js +130 -0
  172. package/dist/core/memory/phase1-kinds.js +20 -0
  173. package/dist/core/memory/secret-scanner.js +304 -0
  174. package/dist/core/memory-sync/queue.js +170 -0
  175. package/dist/core/metrics/extract.js +113 -0
  176. package/dist/core/modes/roo-modes.js +68 -0
  177. package/dist/core/notes/notes-paths.js +113 -0
  178. package/dist/core/notes/notes-recorder.js +140 -0
  179. package/dist/core/notes/notes-writer.js +53 -0
  180. package/dist/core/notes/renderers.js +0 -0
  181. package/dist/core/notes/slug.js +105 -0
  182. package/dist/core/onboarding/ensure-initialized.js +133 -0
  183. package/dist/core/onboarding/marker.js +111 -0
  184. package/dist/core/onboarding/telemetry-state.js +108 -0
  185. package/dist/core/output-style/presets.js +176 -0
  186. package/dist/core/output-style/state.js +185 -0
  187. package/dist/core/path-security.js +287 -5
  188. package/dist/core/permission.js +82 -22
  189. package/dist/core/permissions/auto-classifier.js +124 -0
  190. package/dist/core/permissions/bash-parser.js +371 -0
  191. package/dist/core/permissions/circuit-breaker.js +83 -0
  192. package/dist/core/permissions/constrained-edit.js +91 -0
  193. package/dist/core/permissions/gate.js +278 -0
  194. package/dist/core/permissions/index.js +20 -0
  195. package/dist/core/permissions/mode.js +174 -0
  196. package/dist/core/permissions/network-egress.js +137 -0
  197. package/dist/core/permissions/state.js +241 -0
  198. package/dist/core/permissions/tool-class.js +107 -0
  199. package/dist/core/plan-mode/ui-state.js +51 -0
  200. package/dist/core/plans/plan-artifact.js +721 -0
  201. package/dist/core/policy-limits/etag-store.js +122 -0
  202. package/dist/core/prd-check/parser.js +215 -0
  203. package/dist/core/prd-check/reporter.js +127 -0
  204. package/dist/core/prd-check/session-review.js +557 -0
  205. package/dist/core/prd-check/verifiers.js +223 -0
  206. package/dist/core/prompt-cache/client-cache.js +99 -0
  207. package/dist/core/prompts/assembly.js +29 -0
  208. package/dist/core/prompts/registry.js +364 -0
  209. package/dist/core/pugi-gitignore.js +52 -0
  210. package/dist/core/pugi-md/cc-compat-rules.js +735 -0
  211. package/dist/core/pugi-md/context-injector.js +76 -0
  212. package/dist/core/pugi-md/walk-up.js +207 -0
  213. package/dist/core/python/uv-installer.js +270 -0
  214. package/dist/core/python/uv-resolver.js +83 -0
  215. package/dist/core/rate-limit/narrator.js +146 -0
  216. package/dist/core/recipes/cli-types.js +20 -0
  217. package/dist/core/recipes/loader.js +103 -0
  218. package/dist/core/recipes/runner.js +345 -0
  219. package/dist/core/recipes/schema.js +587 -0
  220. package/dist/core/release-notes/parser.js +241 -0
  221. package/dist/core/release-notes/state.js +116 -0
  222. package/dist/core/repl/ask.js +37 -37
  223. package/dist/core/repl/cancellation.js +26 -26
  224. package/dist/core/repl/cap-warning.js +4 -4
  225. package/dist/core/repl/clipboard-read.js +11 -11
  226. package/dist/core/repl/dispatch-fsm.js +12 -12
  227. package/dist/core/repl/engine-bridge.js +303 -0
  228. package/dist/core/repl/history-search.js +15 -15
  229. package/dist/core/repl/history.js +28 -18
  230. package/dist/core/repl/kill-ring.js +5 -5
  231. package/dist/core/repl/model-pricing.js +135 -0
  232. package/dist/core/repl/privacy-banner.js +22 -22
  233. package/dist/core/repl/session.js +2690 -229
  234. package/dist/core/repl/slash-commands.js +540 -41
  235. package/dist/core/repl/store/index.js +1 -1
  236. package/dist/core/repl/store/jsonl-log.js +22 -22
  237. package/dist/core/repl/store/lockfile.js +10 -10
  238. package/dist/core/repl/store/session-store.js +136 -107
  239. package/dist/core/repl/store/types.js +15 -15
  240. package/dist/core/repl/store/uuid-v7.js +12 -12
  241. package/dist/core/repl/tool-route.js +382 -0
  242. package/dist/core/repl/workspace-context.js +43 -21
  243. package/dist/core/repo-map/build.js +125 -0
  244. package/dist/core/repo-map/cache.js +185 -0
  245. package/dist/core/repo-map/extractor.js +254 -0
  246. package/dist/core/repo-map/formatter.js +145 -0
  247. package/dist/core/repo-map/page-rank.js +105 -0
  248. package/dist/core/repo-map/scanner.js +211 -0
  249. package/dist/core/retro/git-collector.js +251 -0
  250. package/dist/core/retro/health-card.js +25 -0
  251. package/dist/core/retro/metrics.js +342 -0
  252. package/dist/core/retro/narrative.js +249 -0
  253. package/dist/core/retro/plane-collector.js +274 -0
  254. package/dist/core/retro/pr-issue-link.js +65 -0
  255. package/dist/core/retro/types.js +16 -0
  256. package/dist/core/retry-budget/budget.js +284 -0
  257. package/dist/core/retry-budget/index.js +5 -0
  258. package/dist/core/retry-budget/retry-cap.js +74 -0
  259. package/dist/core/routing/lead-worker.js +43 -0
  260. package/dist/core/routing/pre-flight-estimator.js +108 -0
  261. package/dist/core/runs/run-tree.js +103 -0
  262. package/dist/core/sandboxing/adapter.js +29 -0
  263. package/dist/core/sandboxing/index.js +49 -0
  264. package/dist/core/sandboxing/none.js +19 -0
  265. package/dist/core/sandboxing/seatbelt.js +183 -0
  266. package/dist/core/security/injection-scanner.js +367 -0
  267. package/dist/core/security/output-filter.js +418 -0
  268. package/dist/core/session/env-file.js +105 -0
  269. package/dist/core/session/section-budgets.js +140 -0
  270. package/dist/core/session.js +119 -0
  271. package/dist/core/settings.js +378 -5
  272. package/dist/core/share/formatter.js +271 -0
  273. package/dist/core/share/redactor.js +221 -0
  274. package/dist/core/share/uploader.js +267 -0
  275. package/dist/core/skills/defaults.js +30 -30
  276. package/dist/core/skills/loader.js +22 -22
  277. package/dist/core/skills/sources.js +27 -27
  278. package/dist/core/smoke/headless-driver.js +174 -0
  279. package/dist/core/smoke/orchestrator.js +194 -0
  280. package/dist/core/smoke/runner.js +238 -0
  281. package/dist/core/smoke/scenario-parser.js +316 -0
  282. package/dist/core/statusline.js +99 -0
  283. package/dist/core/subagents/dispatcher-real.js +600 -0
  284. package/dist/core/subagents/dispatcher.js +146 -52
  285. package/dist/core/subagents/index.js +19 -6
  286. package/dist/core/subagents/isolation-matrix.js +213 -0
  287. package/dist/core/subagents/spawn.js +19 -4
  288. package/dist/core/telemetry/emitter.js +229 -0
  289. package/dist/core/telemetry/queue.js +251 -0
  290. package/dist/core/theme/context.js +91 -0
  291. package/dist/core/theme/presets.js +228 -0
  292. package/dist/core/theme/state.js +181 -0
  293. package/dist/core/todos/invariant.js +10 -0
  294. package/dist/core/todos/state.js +177 -0
  295. package/dist/core/tool-schema/compressor.js +89 -0
  296. package/dist/core/transport/version-interceptor.js +166 -0
  297. package/dist/core/trust.js +2 -2
  298. package/dist/core/tui/thinking-block.js +64 -0
  299. package/dist/core/vim/keymap.js +288 -0
  300. package/dist/core/vim/state.js +92 -0
  301. package/dist/core/watch-markers/marker-watcher.js +133 -0
  302. package/dist/core/worktree/include-parser.js +249 -0
  303. package/dist/core/worktree-manager/cleanup.js +123 -0
  304. package/dist/core/worktree-manager/manager.js +303 -0
  305. package/dist/index.js +36 -0
  306. package/dist/runtime/bootstrap.js +190 -0
  307. package/dist/runtime/cli.js +4345 -561
  308. package/dist/runtime/commands/agents.js +31 -31
  309. package/dist/runtime/commands/budget.js +5 -5
  310. package/dist/runtime/commands/cancel.js +231 -0
  311. package/dist/runtime/commands/chain.js +489 -0
  312. package/dist/runtime/commands/codegraph-status.js +227 -0
  313. package/dist/runtime/commands/compact.js +297 -0
  314. package/dist/runtime/commands/config.js +74 -40
  315. package/dist/runtime/commands/cost.js +199 -0
  316. package/dist/runtime/commands/delegate.js +27 -4
  317. package/dist/runtime/commands/dispatch.js +126 -0
  318. package/dist/runtime/commands/doctor.js +579 -0
  319. package/dist/runtime/commands/feedback.js +184 -0
  320. package/dist/runtime/commands/hooks.js +187 -0
  321. package/dist/runtime/commands/index-cmd.js +353 -0
  322. package/dist/runtime/commands/init.js +254 -0
  323. package/dist/runtime/commands/lsp.js +200 -38
  324. package/dist/runtime/commands/mcp.js +935 -0
  325. package/dist/runtime/commands/memory.js +582 -0
  326. package/dist/runtime/commands/model.js +237 -0
  327. package/dist/runtime/commands/onboarding.js +275 -0
  328. package/dist/runtime/commands/patch.js +12 -12
  329. package/dist/runtime/commands/permissions.js +112 -0
  330. package/dist/runtime/commands/plan.js +143 -0
  331. package/dist/runtime/commands/prd-check.js +285 -0
  332. package/dist/runtime/commands/privacy.js +17 -17
  333. package/dist/runtime/commands/recipe.js +325 -0
  334. package/dist/runtime/commands/redo-blob-store.js +92 -0
  335. package/dist/runtime/commands/redo.js +361 -0
  336. package/dist/runtime/commands/release-notes.js +229 -0
  337. package/dist/runtime/commands/repo-map.js +95 -0
  338. package/dist/runtime/commands/report.js +299 -0
  339. package/dist/runtime/commands/resume.js +118 -0
  340. package/dist/runtime/commands/review-consensus.js +68 -53
  341. package/dist/runtime/commands/rewind.js +333 -0
  342. package/dist/runtime/commands/roster.js +14 -14
  343. package/dist/runtime/commands/servers.js +236 -0
  344. package/dist/runtime/commands/sessions.js +163 -0
  345. package/dist/runtime/commands/share.js +316 -0
  346. package/dist/runtime/commands/skills.js +31 -31
  347. package/dist/runtime/commands/status.js +186 -0
  348. package/dist/runtime/commands/stickers.js +82 -0
  349. package/dist/runtime/commands/style.js +194 -0
  350. package/dist/runtime/commands/theme.js +196 -0
  351. package/dist/runtime/commands/undo.js +54 -22
  352. package/dist/runtime/commands/update.js +289 -0
  353. package/dist/runtime/commands/vim.js +140 -0
  354. package/dist/runtime/commands/worktree.js +8 -8
  355. package/dist/runtime/commands/worktrees.js +155 -0
  356. package/dist/runtime/deprecation-warning.js +69 -0
  357. package/dist/runtime/engine-exit-code.js +50 -0
  358. package/dist/runtime/headless-repl.js +195 -0
  359. package/dist/runtime/headless.js +548 -0
  360. package/dist/runtime/load-hooks-or-exit.js +71 -0
  361. package/dist/runtime/plan-decompose.js +22 -22
  362. package/dist/runtime/sigint-guard.js +272 -0
  363. package/dist/runtime/stream-renderer.js +195 -0
  364. package/dist/runtime/update-check.js +28 -28
  365. package/dist/runtime/version.js +65 -0
  366. package/dist/runtime/worktree-bootstrap.js +579 -0
  367. package/dist/skills/bundled/batch.js +617 -0
  368. package/dist/skills/bundled/index.js +45 -0
  369. package/dist/skills/bundled/loop.js +358 -0
  370. package/dist/skills/bundled/remember.js +383 -0
  371. package/dist/skills/bundled/simplify.js +289 -0
  372. package/dist/skills/bundled/skillify.js +373 -0
  373. package/dist/skills/bundled/stuck.js +558 -0
  374. package/dist/skills/bundled/verify.js +439 -0
  375. package/dist/testing/vcr.js +486 -0
  376. package/dist/tools/agent-tool.js +229 -0
  377. package/dist/tools/apply-patch.js +89 -28
  378. package/dist/tools/ask-user-question.js +337 -0
  379. package/dist/tools/ask-user.js +115 -0
  380. package/dist/tools/bash.js +624 -46
  381. package/dist/tools/brief.js +224 -0
  382. package/dist/tools/cron.js +433 -0
  383. package/dist/tools/enter-worktree.js +250 -0
  384. package/dist/tools/exit-worktree.js +147 -0
  385. package/dist/tools/file-tools.js +161 -44
  386. package/dist/tools/http-request.js +336 -0
  387. package/dist/tools/lsp-tools.js +377 -1
  388. package/dist/tools/mcp-tool.js +260 -0
  389. package/dist/tools/multi-edit.js +361 -0
  390. package/dist/tools/powershell.js +268 -0
  391. package/dist/tools/registry.js +120 -5
  392. package/dist/tools/server-tools.js +892 -0
  393. package/dist/tools/skill-tool.js +96 -0
  394. package/dist/tools/sleep.js +99 -0
  395. package/dist/tools/synthetic-output.js +133 -0
  396. package/dist/tools/tasks.js +208 -0
  397. package/dist/tools/todo-write.js +184 -0
  398. package/dist/tools/verify-plan-execution.js +295 -0
  399. package/dist/tools/web-fetch-injection-scanner.js +207 -0
  400. package/dist/tools/web-fetch.js +195 -10
  401. package/dist/tools/web-search.js +458 -0
  402. package/dist/tui/agent-progress-card.js +111 -0
  403. package/dist/tui/agent-tree.js +22 -1
  404. package/dist/tui/ask-modal.js +14 -14
  405. package/dist/tui/ask-user-question-chips.js +315 -0
  406. package/dist/tui/ask-user-question-prompt.js +203 -0
  407. package/dist/tui/compact-banner.js +81 -0
  408. package/dist/tui/conversation-pane.js +85 -11
  409. package/dist/tui/cost-table.js +111 -0
  410. package/dist/tui/device-flow.js +2 -2
  411. package/dist/tui/doctor-table.js +46 -0
  412. package/dist/tui/feedback-prompt.js +156 -0
  413. package/dist/tui/input-box.js +247 -32
  414. package/dist/tui/login-picker.js +3 -3
  415. package/dist/tui/markdown-render.js +6 -6
  416. package/dist/tui/multi-file-diff-approval.js +375 -0
  417. package/dist/tui/onboarding-wizard.js +240 -0
  418. package/dist/tui/permissions-picker.js +86 -0
  419. package/dist/tui/render.js +36 -1
  420. package/dist/tui/repl-render.js +239 -25
  421. package/dist/tui/repl-splash-art.js +16 -16
  422. package/dist/tui/repl-splash-mascot.js +48 -24
  423. package/dist/tui/repl-splash.js +22 -22
  424. package/dist/tui/repl.js +125 -45
  425. package/dist/tui/slash-palette.js +6 -6
  426. package/dist/tui/splash.js +2 -2
  427. package/dist/tui/status-bar.js +109 -31
  428. package/dist/tui/status-table.js +7 -0
  429. package/dist/tui/stickers-art.js +136 -0
  430. package/dist/tui/style-table.js +28 -0
  431. package/dist/tui/theme-table.js +29 -0
  432. package/dist/tui/thinking-spinner.js +123 -0
  433. package/dist/tui/tool-stream-pane.js +53 -4
  434. package/dist/tui/update-banner.js +27 -2
  435. package/dist/tui/vim-input.js +267 -0
  436. package/dist/tui/welcome-banner.js +107 -0
  437. package/dist/tui/welcome-data.js +293 -0
  438. package/dist/tui/workspace-context.js +2 -2
  439. package/package.json +21 -5
  440. package/test/scenarios/codegen-create-file.scenario.txt +13 -0
  441. package/test/scenarios/compact-force.scenario.txt +12 -0
  442. package/test/scenarios/identity.scenario.txt +11 -0
  443. package/test/scenarios/persona-handoff.scenario.txt +12 -0
  444. package/test/scenarios/walkback.scenario.txt +12 -0
  445. package/dist/core/engine/compaction-hook.js +0 -154
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Codegraph MCP install helper — .
3
+ *
4
+ * Writes the codegraph MCP server config к `.pugi/mcp.json` so the
5
+ * registry loader picks it up on the next dispatch. Mirrors the
6
+ * Phase 1 example config at `apps/pugi-cli/docs/examples/codegraph.mcp.json`
7
+ * — same `codegraph serve --mcp` command + `pending` trust state. The
8
+ * operator still has to run `pugi mcp trust codegraph` before tools
9
+ * actually surface; the install path NEVER auto-trusts, by design.
10
+ *
11
+ * Idempotent: re-running on a workspace that already has a `codegraph`
12
+ * entry is a no-op + returns `{ status: 'already-installed' }`. Other
13
+ * MCP servers in the same file are preserved.
14
+ *
15
+ * The function is intentionally NOT bundled into core/mcp/ to keep
16
+ * the codegraph product (install copy, decision store, language gate)
17
+ * one cohesive module. The MCP registry is a generic surface; the
18
+ * codegraph adoption is a feature on top of it.
19
+ */
20
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
21
+ import { resolve } from 'node:path';
22
+ /**
23
+ * Canonical config shape we write into `.pugi/mcp.json` under the
24
+ * `codegraph` key. Matches `mcpServerConfigSchema` (Zod) in
25
+ * core/mcp/client.ts and the published example at docs/examples/
26
+ * codegraph.mcp.json. Drift here MUST land alongside a registry
27
+ * schema change OR the next dispatch crashes with a validation error.
28
+ */
29
+ export const CODEGRAPH_MCP_ENTRY = Object.freeze({
30
+ command: 'codegraph',
31
+ args: Object.freeze(['serve', '--mcp']),
32
+ env: Object.freeze({}),
33
+ trust: 'pending',
34
+ });
35
+ /**
36
+ * Documentation URL surfaced after a successful install so the operator
37
+ * knows how to actually run codegraph index commands. Single source of
38
+ * truth — both the init flow and the /codegraph-status command pull
39
+ * from this constant.
40
+ */
41
+ export const CODEGRAPH_DOCS_URL = 'https://github.com/colbymchenry/codegraph';
42
+ /**
43
+ * Merge the codegraph entry into `.pugi/mcp.json`. Creates the file
44
+ * (with `{ schema: 1, servers: { codegraph: ... } }`) when it does not
45
+ * exist. Preserves every other server entry on disk.
46
+ *
47
+ * @param workspaceRoot absolute path to the project root that owns the
48
+ * `.pugi/` directory. The caller is responsible for
49
+ * ensuring `.pugi/` exists (the install helper
50
+ * creates it as a defensive fallback).
51
+ */
52
+ export function installCodegraphMcpEntry(workspaceRoot) {
53
+ const pugiDir = resolve(workspaceRoot, '.pugi');
54
+ const configPath = resolve(pugiDir, 'mcp.json');
55
+ try {
56
+ if (!existsSync(pugiDir)) {
57
+ mkdirSync(pugiDir, { recursive: true });
58
+ }
59
+ let existing = {};
60
+ if (existsSync(configPath)) {
61
+ try {
62
+ const raw = readFileSync(configPath, 'utf8');
63
+ if (raw.trim().length > 0) {
64
+ const parsed = JSON.parse(raw);
65
+ if (parsed && typeof parsed === 'object') {
66
+ existing = parsed;
67
+ }
68
+ }
69
+ }
70
+ catch (error) {
71
+ return {
72
+ status: 'failed',
73
+ reason: `cannot parse existing .pugi/mcp.json: ${error.message}`,
74
+ };
75
+ }
76
+ }
77
+ const servers = (existing.servers && typeof existing.servers === 'object')
78
+ ? { ...existing.servers }
79
+ : {};
80
+ if (servers['codegraph']) {
81
+ return { status: 'already-installed', configPath };
82
+ }
83
+ servers['codegraph'] = {
84
+ command: CODEGRAPH_MCP_ENTRY.command,
85
+ args: [...CODEGRAPH_MCP_ENTRY.args],
86
+ env: { ...CODEGRAPH_MCP_ENTRY.env },
87
+ trust: CODEGRAPH_MCP_ENTRY.trust,
88
+ };
89
+ const out = {
90
+ schema: typeof existing.schema === 'number' ? existing.schema : 1,
91
+ servers,
92
+ };
93
+ writeFileSync(configPath, `${JSON.stringify(out, null, 2)}\n`, { mode: 0o600 });
94
+ return { status: 'installed', configPath };
95
+ }
96
+ catch (error) {
97
+ return { status: 'failed', reason: error.message };
98
+ }
99
+ }
100
+ /**
101
+ * Check whether `.pugi/mcp.json` already declares the `codegraph`
102
+ * server. Pure best-effort — a malformed file returns false (we err
103
+ * on the side of "not installed" so the operator can re-trigger the
104
+ * install path instead of being silently locked out).
105
+ *
106
+ * Returns the parsed `trust` state when present so callers can render
107
+ * the right status copy ("declared, awaiting trust" vs "active").
108
+ */
109
+ export function detectCodegraphInstalled(workspaceRoot) {
110
+ const configPath = resolve(workspaceRoot, '.pugi/mcp.json');
111
+ if (!existsSync(configPath)) {
112
+ return { installed: false, trust: null, configPath };
113
+ }
114
+ try {
115
+ const raw = readFileSync(configPath, 'utf8');
116
+ if (raw.trim().length === 0) {
117
+ return { installed: false, trust: null, configPath };
118
+ }
119
+ const parsed = JSON.parse(raw);
120
+ const codegraph = parsed.servers?.['codegraph'];
121
+ if (!codegraph) {
122
+ return { installed: false, trust: null, configPath };
123
+ }
124
+ return {
125
+ installed: true,
126
+ trust: codegraph.trust === 'trusted' || codegraph.trust === 'denied' ? codegraph.trust : 'pending',
127
+ configPath,
128
+ };
129
+ }
130
+ catch {
131
+ return { installed: false, trust: null, configPath };
132
+ }
133
+ }
134
+ //# sourceMappingURL=install.js.map
@@ -0,0 +1,220 @@
1
+ /**
2
+ * Codegraph offer hook — .
3
+ *
4
+ * Single integration point used by both `pugi init` (standalone CLI
5
+ * entry) AND the REPL's `/init` slash so the decision logic + telemetry
6
+ * fan-out stays single-sourced. The hook is split into two halves:
7
+ *
8
+ * 1. `evaluateOffer({ workspaceRoot, nowIso })` — pure: decides if
9
+ * we should prompt, returns the detection result + suggested copy
10
+ * so the UI layer can render it however it likes (Y/n prompt in
11
+ * a TTY, JSON envelope in --no-tty mode, system pane line in the
12
+ * REPL).
13
+ * 2. `applyOfferDecision({ workspaceRoot, accepted, … })` — side-
14
+ * effectful: persists the operator's verdict + runs the install
15
+ * if accepted + emits the right telemetry event.
16
+ *
17
+ * Telemetry events emitted (when consent allows):
18
+ * - `codegraph.offer.shown` — every time we surface the prompt
19
+ * - `codegraph.offer.accepted` — operator said yes
20
+ * - `codegraph.offer.declined` — operator said no
21
+ * - `codegraph.install.success` — mcp.json merge succeeded
22
+ * - `codegraph.install.failed` — mcp.json merge failed (rare)
23
+ * - `codegraph.reminder.shown` — cold-start nudge surfaced
24
+ * - `codegraph.stale-index.shown` — index > STALE_INDEX_DAYS
25
+ *
26
+ * All telemetry is best-effort fire-and-forget; emit() never throws.
27
+ *
28
+ * The hook NEVER prompts directly — it has no TTY contract. The
29
+ * caller MUST resolve the operator's verdict OR call `applyOfferDecision`
30
+ * with `accepted: false` to record a decline.
31
+ */
32
+ import { detectRepo, buildOfferCopy } from './detect-repo.js';
33
+ import { shouldOfferOnInit, recordDecision, readDecision, shouldNudgeStaleIndex, indexAgeDays, } from './decision-store.js';
34
+ import { installCodegraphMcpEntry, detectCodegraphInstalled, CODEGRAPH_DOCS_URL, } from './install.js';
35
+ import { emit } from '../telemetry/emitter.js';
36
+ /**
37
+ * Pure evaluation. Reads detection + decision store. NEVER writes.
38
+ * Reads NEVER throw — corrupt JSON returns "first-run". Tests rely on
39
+ * this so they can drive `evaluateOffer` repeatedly without setup.
40
+ */
41
+ export function evaluateOffer(input) {
42
+ const detection = detectRepo(input.workspaceRoot);
43
+ if (!detection.isRepo) {
44
+ return { shouldPrompt: false, reason: detection.reason, detection };
45
+ }
46
+ if (!detection.offerCodegraph) {
47
+ return { shouldPrompt: false, reason: 'size-or-language-gate', detection };
48
+ }
49
+ // If codegraph is already declared в mcp.json, skip — the operator
50
+ // already adopted it (maybe via Phase 1 manual install). Cold-start
51
+ // hook covers the stale-index nudge separately.
52
+ const installed = detectCodegraphInstalled(input.workspaceRoot);
53
+ if (installed.installed) {
54
+ return { shouldPrompt: false, reason: 'already-installed', detection };
55
+ }
56
+ if (!input.ignorePriorDecision) {
57
+ const cadence = shouldOfferOnInit(input.workspaceRoot, input.nowIso);
58
+ if (!cadence.shouldOffer) {
59
+ return { shouldPrompt: false, reason: cadence.reason, detection };
60
+ }
61
+ }
62
+ return {
63
+ shouldPrompt: true,
64
+ detection: detection,
65
+ promptCopy: buildOfferCopy(detection),
66
+ docsUrl: CODEGRAPH_DOCS_URL,
67
+ reason: 'first-run',
68
+ };
69
+ }
70
+ export function applyOfferDecision(input) {
71
+ const decision = recordDecision(input.workspaceRoot, {
72
+ accepted: input.accepted,
73
+ ...(input.nowIso ? { nowIso: input.nowIso } : {}),
74
+ });
75
+ emitOfferTelemetry(input.accepted ? 'codegraph.offer.accepted' : 'codegraph.offer.declined', {
76
+ sizeCategory: input.detection.sizeCategory,
77
+ primaryLanguage: input.detection.languages[0] ?? 'unknown',
78
+ primarySymbolCount: input.detection.primarySymbolCount,
79
+ });
80
+ if (!input.accepted) {
81
+ return { kind: 'declined', decision };
82
+ }
83
+ const install = installCodegraphMcpEntry(input.workspaceRoot);
84
+ if (install.status === 'failed') {
85
+ emitOfferTelemetry('codegraph.install.failed', {
86
+ reason: install.reason.slice(0, 64),
87
+ });
88
+ return { kind: 'accepted-install-failed', decision, install };
89
+ }
90
+ emitOfferTelemetry('codegraph.install.success', {
91
+ sizeCategory: input.detection.sizeCategory,
92
+ primaryLanguage: input.detection.languages[0] ?? 'unknown',
93
+ alreadyInstalled: install.status === 'already-installed',
94
+ });
95
+ return {
96
+ kind: 'accepted-installed',
97
+ decision,
98
+ install,
99
+ docsUrl: CODEGRAPH_DOCS_URL,
100
+ trustCommand: 'pugi mcp trust codegraph',
101
+ };
102
+ }
103
+ /**
104
+ * Surface the offer telemetry "shown" event. Called by the init flow
105
+ * once it has decided to actually render the prompt (so a `--no-tty`
106
+ * invocation that skipped the prompt does not count as a shown event).
107
+ */
108
+ export function emitOfferShown(detection) {
109
+ emitOfferTelemetry('codegraph.offer.shown', {
110
+ sizeCategory: detection.sizeCategory,
111
+ primaryLanguage: detection.languages[0] ?? 'unknown',
112
+ primarySymbolCount: detection.primarySymbolCount,
113
+ });
114
+ }
115
+ /**
116
+ * Compute the cold-start nudge. Pure read — never writes. The session
117
+ * module decides whether to render the message AND whether to call
118
+ * `markReindexChecked(...)` after the operator dismisses it (so the
119
+ * once-per-day throttle on `shouldNudgeStaleIndex` works).
120
+ */
121
+ export function evaluateColdStart(input) {
122
+ const detection = detectRepo(input.workspaceRoot);
123
+ if (!detection.isRepo) {
124
+ return { kind: 'silent', reason: detection.reason };
125
+ }
126
+ const decision = readDecision(input.workspaceRoot);
127
+ // Stale-index path takes priority — an accepted operator should be
128
+ // nudged about freshness before a never-asked operator is nudged
129
+ // about installation.
130
+ if (decision && decision.accepted) {
131
+ if (shouldNudgeStaleIndex(decision, input.nowIso)) {
132
+ const age = indexAgeDays(decision, input.nowIso) ?? 0;
133
+ emitOfferTelemetry('codegraph.stale-index.shown', { ageDays: age });
134
+ return {
135
+ kind: 'stale-index',
136
+ ageDays: age,
137
+ message: `Codegraph index is ${age} day${age === 1 ? '' : 's'} old. Run /codegraph-status to refresh.`,
138
+ };
139
+ }
140
+ return { kind: 'silent', reason: 'fresh-index' };
141
+ }
142
+ if (!detection.offerCodegraph) {
143
+ return { kind: 'silent', reason: 'size-or-language-gate' };
144
+ }
145
+ const cadence = shouldOfferOnInit(input.workspaceRoot, input.nowIso);
146
+ if (!cadence.shouldOffer) {
147
+ return { kind: 'silent', reason: cadence.reason };
148
+ }
149
+ if (cadence.reason !== 'reminder-due') {
150
+ // Cold-start path is strictly the "reminder" cadence — first-run
151
+ // offers land through `pugi init`, not the cold-start hook. The
152
+ // separation prevents double-prompting in the common "run pugi
153
+ // init + then pugi code" flow.
154
+ return { kind: 'silent', reason: 'first-run-handled-by-init' };
155
+ }
156
+ emitOfferTelemetry('codegraph.reminder.shown', {
157
+ sizeCategory: detection.sizeCategory,
158
+ primaryLanguage: detection.languages[0] ?? 'unknown',
159
+ });
160
+ return {
161
+ kind: 'remind',
162
+ detection,
163
+ message: `${buildOfferCopy(detection)} (last declined ${humanAge(decision?.offeredAt, input.nowIso)} ago)`,
164
+ };
165
+ }
166
+ /**
167
+ * Fire one telemetry event. Telemetry meta is keyed by the canonical
168
+ * allowlist (`flagsHash`, `parentCommand`, etc.); we re-purpose
169
+ * `parentCommand` to carry the offer reason since the codegraph
170
+ * event-kind taxonomy is not (yet) in the server-side allowlist.
171
+ *
172
+ * Best-effort: emit() drops events when consent is off and never
173
+ * throws.
174
+ */
175
+ function emitOfferTelemetry(command, meta) {
176
+ const stringMeta = {};
177
+ for (const [k, v] of Object.entries(meta)) {
178
+ // Promote everything через the canonical `parentCommand` slot OR
179
+ // safe-numeric counters (retryCount). Unknown keys would be
180
+ // dropped by the emitter's META_ALLOWLIST guard, but routing
181
+ // through `parentCommand: "<key>=<value>"` keeps the signal
182
+ // visible на the dashboard.
183
+ if (typeof v === 'number') {
184
+ stringMeta.retryCount = v;
185
+ }
186
+ else if (typeof v === 'boolean') {
187
+ stringMeta.cacheHit = v;
188
+ }
189
+ else {
190
+ stringMeta.parentCommand = `${k}=${String(v).slice(0, 32)}`;
191
+ }
192
+ }
193
+ emit({
194
+ command,
195
+ kind: 'tool-call',
196
+ success: true,
197
+ meta: stringMeta,
198
+ });
199
+ }
200
+ /**
201
+ * Format the elapsed time since `priorIso` in human-readable units
202
+ * (days / weeks). Pure — exposed for spec parity. Falls back to
203
+ * "earlier" when prior is missing OR unparseable.
204
+ */
205
+ function humanAge(priorIso, nowIso) {
206
+ if (!priorIso)
207
+ return 'earlier';
208
+ const now = nowIso ? Date.parse(nowIso) : Date.now();
209
+ const prior = Date.parse(priorIso);
210
+ if (!Number.isFinite(prior))
211
+ return 'earlier';
212
+ const days = Math.max(0, Math.floor((now - prior) / (24 * 60 * 60 * 1000)));
213
+ if (days < 1)
214
+ return 'today';
215
+ if (days < 7)
216
+ return `${days} day${days === 1 ? '' : 's'}`;
217
+ const weeks = Math.floor(days / 7);
218
+ return `${weeks} week${weeks === 1 ? '' : 's'}`;
219
+ }
220
+ //# sourceMappingURL=offer-hook.js.map
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Pugi local symbol index - tree-sitter parser stub.
3
+ *
4
+ * This file is intentionally a stub. Real tree-sitter integration ships
5
+ * in follow-up PR L1, which adds:
6
+ *
7
+ * - `tree-sitter` runtime dependency
8
+ * - per-language grammar deps: `tree-sitter-typescript` (covers TS+TSX),
9
+ * `tree-sitter-javascript` (covers JS+JSX), `tree-sitter-python`,
10
+ * `tree-sitter-go`, `tree-sitter-rust`
11
+ * - per-language extractor modules under `./parsers/<lang>.ts` that
12
+ * walk the parsed CST and emit `Symbol[]` + `Edge[]`
13
+ * - file fingerprint (sha256) computation
14
+ * - extension routing (`.ts` / `.tsx` → typescript, `.py` → python, etc.)
15
+ *
16
+ * Keeping the stub deliberately broken (returns empty arrays + a flag)
17
+ * lets the rest of the scaffold ship in this PR without smuggling in
18
+ * tree-sitter native modules. tree-sitter has a prebuilt-binary
19
+ * distribution but it is one more wheel-per-platform surface that
20
+ * compounds the install-time risk the session-store memo warned about
21
+ * (see `core/repl/store/session-store.ts` lines 20-36).
22
+ *
23
+ * The `parseFile` signature is the long-term contract - PR L1 fills
24
+ * the body without changing the type. Other modules (`db.ts`, the
25
+ * future watcher in PR L2) wire against this signature today; the
26
+ * unit tests in `test/codegraph-db.spec.ts` exercise `db.ts` directly
27
+ * via hand-built symbol arrays so they pass without a real parser.
28
+ */
29
+ /**
30
+ * Parse one source file and return its symbol + edge contribution.
31
+ *
32
+ * TODO(PR L1): replace this body with a real tree-sitter extraction
33
+ * pipeline. The signature is frozen - db.ts + the watcher + the MCP
34
+ * tool layer wire against it as-is today.
35
+ *
36
+ * @param path Absolute or workspace-relative path. The real impl will
37
+ * read the file, sha256 it, route by extension to the right
38
+ * tree-sitter grammar, and walk the resulting CST.
39
+ */
40
+ export async function parseFile(path) {
41
+ // Touch the parameter so TS strict noUnusedParameters doesn't fire.
42
+ // The real impl in PR L1 reads the file at this path.
43
+ void path;
44
+ return {
45
+ symbols: [],
46
+ edges: [],
47
+ stub: true,
48
+ };
49
+ }
50
+ /**
51
+ * Stable list of file extensions the v1 parser will support. Exported
52
+ * so the watcher (PR L2) and the CLI command (`pugi index`) can
53
+ * pre-filter the file walk without instantiating a parser. The set
54
+ * mirrors `INDEXED_LANGUAGES` in `./types.ts`.
55
+ *
56
+ * `.cjs` and `.mjs` map to javascript; `.tsx` and `.jsx` map to
57
+ * typescript / javascript respectively (tree-sitter-typescript ships
58
+ * a TSX grammar variant; same for JSX in tree-sitter-javascript).
59
+ */
60
+ export const PARSEABLE_EXTENSIONS = Object.freeze([
61
+ '.ts',
62
+ '.tsx',
63
+ '.js',
64
+ '.jsx',
65
+ '.mjs',
66
+ '.cjs',
67
+ '.py',
68
+ '.go',
69
+ '.rs',
70
+ ]);
71
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Pugi local symbol index - type definitions.
3
+ *
4
+ * Companion to `db.ts` (SQLite + FTS5 wrapper) and `parser.ts` (tree-sitter
5
+ * extractor, stub today, real impl in follow-up PR L1). These types are the
6
+ * cross-module contract: the parser produces `Symbol[]` + `Edge[]`, the db
7
+ * layer inserts them, the MCP tools consume the query result types.
8
+ *
9
+ * Distinct from the third-party CodeGraph install scaffold that already
10
+ * lives in the same directory (`detect-repo.ts`, `offer-hook.ts`,
11
+ * `install.ts`, `decision-store.ts`). Those manage adoption of the upstream
12
+ * colbymchenry/codegraph MCP server. This file is the Pugi-native index.
13
+ * See the design memo at
14
+ * `docs/research/2026-06-05-pugi-index-codegraph-design.md` for the full
15
+ * architecture rationale.
16
+ *
17
+ * Naming convention: every type defined here is `Symbol` / `Edge` /
18
+ * `IndexedFile` / `*Result` / `*Options`. The interface is intentionally
19
+ * narrow - five v1 languages, four MCP tools, one SQLite database file.
20
+ */
21
+ /**
22
+ * Schema version tracked in the `_migrations` table. v1 ships with this
23
+ * PR (files + symbols + edges + FTS5 virtual + triggers). Bumping this
24
+ * MUST land a matching `applyMigration(N, db)` branch in `db.ts`.
25
+ */
26
+ export const INDEX_SCHEMA_VERSION = 1;
27
+ export const INDEXED_LANGUAGES = Object.freeze([
28
+ 'typescript',
29
+ 'javascript',
30
+ 'python',
31
+ 'go',
32
+ 'rust',
33
+ ]);
34
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Auto-compact threshold gate.
3
+ *
4
+ * Decides whether the conversation buffer has crossed the threshold
5
+ * percent of the active model's context window. The check runs after
6
+ * every operator/persona turn before the NEXT operator input lands so
7
+ * the compaction completes BEFORE the model would have rejected the
8
+ * request with a context-overflow error.
9
+ *
10
+ * Design choices:
11
+ *
12
+ * - Pure function. The caller passes (tokenCount, windowSize, env).
13
+ * The gate returns a verdict; the session module owns the side
14
+ * effect of invoking the summariser. Pure-function shape keeps the
15
+ * spec exhaustive and the call site readable.
16
+ *
17
+ * - Hysteresis: once a compaction lands, the marker resets the
18
+ * baseline token count to "summary + tail" — the gate looks at the
19
+ * POST-marker tokens only. This is enforced upstream by the caller
20
+ * passing the post-marker count; the gate itself has no memory.
21
+ *
22
+ * - Two env knobs:
23
+ * PUGI_AUTOCOMPACT_DISABLED=1 — kill switch
24
+ * PUGI_AUTOCOMPACT_THRESHOLD=N — float in (0, 1] (default 0.75)
25
+ * Anything outside (0, 1] is rejected and the gate falls back to
26
+ * the default. Bad input never crashes the REPL.
27
+ */
28
+ /** Default trip point as a fraction of the context window. */
29
+ export const DEFAULT_THRESHOLD = 0.75;
30
+ /**
31
+ * Decide whether to fire `/compact` automatically. Pure; safe to call
32
+ * after every turn.
33
+ */
34
+ export function evaluateAutoCompact(input) {
35
+ const env = input.env ?? process.env;
36
+ const threshold = resolveThreshold(env);
37
+ if (input.windowSize <= 0 || !Number.isFinite(input.windowSize)) {
38
+ return {
39
+ kind: 'skip',
40
+ reason: 'invalid-window',
41
+ tokenCount: input.tokenCount,
42
+ windowSize: input.windowSize,
43
+ threshold,
44
+ pressure: 0,
45
+ };
46
+ }
47
+ if (env['PUGI_AUTOCOMPACT_DISABLED'] === '1') {
48
+ return {
49
+ kind: 'skip',
50
+ reason: 'disabled',
51
+ tokenCount: input.tokenCount,
52
+ windowSize: input.windowSize,
53
+ threshold,
54
+ pressure: roundPressure(input.tokenCount / input.windowSize),
55
+ };
56
+ }
57
+ const pressure = roundPressure(input.tokenCount / input.windowSize);
58
+ if (pressure >= threshold) {
59
+ return {
60
+ kind: 'fire',
61
+ tokenCount: input.tokenCount,
62
+ windowSize: input.windowSize,
63
+ threshold,
64
+ pressure,
65
+ };
66
+ }
67
+ return {
68
+ kind: 'skip',
69
+ reason: 'below-threshold',
70
+ tokenCount: input.tokenCount,
71
+ windowSize: input.windowSize,
72
+ threshold,
73
+ pressure,
74
+ };
75
+ }
76
+ /**
77
+ * Resolve the threshold from env, clamping to the (0, 1] open-closed
78
+ * interval. Bad input silently falls back to DEFAULT_THRESHOLD so the
79
+ * REPL never crashes on a malformed environment variable.
80
+ */
81
+ function resolveThreshold(env) {
82
+ const raw = env['PUGI_AUTOCOMPACT_THRESHOLD'];
83
+ if (!raw)
84
+ return DEFAULT_THRESHOLD;
85
+ const parsed = Number.parseFloat(raw);
86
+ if (!Number.isFinite(parsed) || parsed <= 0 || parsed > 1) {
87
+ return DEFAULT_THRESHOLD;
88
+ }
89
+ return parsed;
90
+ }
91
+ function roundPressure(raw) {
92
+ if (!Number.isFinite(raw) || raw < 0)
93
+ return 0;
94
+ return Math.round(raw * 1000) / 1000;
95
+ }
96
+ //# sourceMappingURL=auto-trigger.js.map
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Type guard: discriminate a SessionEvent against the `compaction`
3
+ * kind. Used by replay code so the boundary marker drives a different
4
+ * code path than `user`/`persona`/`system` transcript rows.
5
+ */
6
+ export function isCompactBoundary(event) {
7
+ if (event.kind !== 'compaction')
8
+ return false;
9
+ const p = event.payload;
10
+ if (p === null || typeof p !== 'object')
11
+ return false;
12
+ if (p.version !== 1)
13
+ return false;
14
+ if (p.trigger !== 'manual' && p.trigger !== 'auto')
15
+ return false;
16
+ if (typeof p.summary !== 'string' || p.summary.length === 0)
17
+ return false;
18
+ if (typeof p.summaryTokenCount !== 'number')
19
+ return false;
20
+ if (typeof p.summaryTurnsBefore !== 'number')
21
+ return false;
22
+ if (typeof p.keptTailTurns !== 'number')
23
+ return false;
24
+ if (typeof p.coversUntilOffset !== 'number')
25
+ return false;
26
+ return true;
27
+ }
28
+ /**
29
+ * Append one `compaction` boundary marker to the SessionStore. Returns
30
+ * the SessionEvent we wrote so the caller can echo it into the in-
31
+ * memory transcript without a re-read. Throws on store error so the
32
+ * caller surfaces the failure inline.
33
+ */
34
+ export async function appendCompactBoundary(input) {
35
+ const ts = (input.now ?? (() => Date.now()))();
36
+ const payload = {
37
+ version: 1,
38
+ trigger: input.trigger,
39
+ summary: input.summary,
40
+ summaryTokenCount: input.summaryTokenCount,
41
+ summaryTurnsBefore: input.summaryTurnsBefore,
42
+ keptTailTurns: input.keptTailTurns,
43
+ coversUntilOffset: input.coversUntilOffset,
44
+ };
45
+ const event = {
46
+ t: ts,
47
+ kind: 'compaction',
48
+ payload,
49
+ };
50
+ await input.store.appendEvent(event);
51
+ return event;
52
+ }
53
+ /**
54
+ * Apply replay masking to a chronological event list. Given the full
55
+ * ordered events.jsonl content, return only the events the caller
56
+ * should render: every event AFTER the latest `compaction` boundary,
57
+ * plus the boundary itself (so the renderer can show the banner +
58
+ * summary), and the K kept-tail events that landed BEFORE the boundary
59
+ * but were preserved per the marker's `keptTailTurns`.
60
+ *
61
+ * Mask logic:
62
+ * 1. Walk events. Find the LATEST boundary by offset.
63
+ * 2. Index 0 .. coversUntilOffset-1 are masked, EXCEPT the last
64
+ * `keptTailTurns` of that range (which are the verbatim tail).
65
+ * 3. The boundary event itself + everything after it stays.
66
+ *
67
+ * Why we expose this here (and not in session.ts): keeping the mask
68
+ * logic next to the writer means the wire format is owned by one
69
+ * module. session.ts depends on this; this depends on nothing in
70
+ * session.ts. Unidirectional.
71
+ */
72
+ export function applyCompactMask(events) {
73
+ // Find latest compaction event.
74
+ let latestIdx = -1;
75
+ let latestPayload = null;
76
+ for (let i = events.length - 1; i >= 0; i -= 1) {
77
+ const ev = events[i];
78
+ if (isCompactBoundary(ev)) {
79
+ latestIdx = i;
80
+ latestPayload = ev.payload;
81
+ break;
82
+ }
83
+ }
84
+ if (latestIdx === -1 || latestPayload === null) {
85
+ return events;
86
+ }
87
+ // `coversUntilOffset` is the count of events that existed in the
88
+ // store immediately before the marker append. Events 0 ..
89
+ // coversUntilOffset-1 are summarised; events keptTailTurns of them
90
+ // are surfaced anyway as the verbatim tail.
91
+ const cap = Math.max(0, Math.min(latestPayload.coversUntilOffset, latestIdx));
92
+ const tailKeepCount = Math.max(0, Math.min(latestPayload.keptTailTurns, cap));
93
+ // Take the LAST tailKeepCount events from the masked range, but only
94
+ // those that represent renderable turns (user/persona/system).
95
+ // Boundary markers and tool stream events are NOT counted as turns
96
+ // for the tail-keep window — using them would let the keptTailTurns
97
+ // budget be consumed by infra events and the operator would lose
98
+ // the last K real turns. The spec is about "last K human-visible
99
+ // turns", not "last K events".
100
+ const tailSlice = [];
101
+ for (let i = cap - 1; i >= 0 && tailSlice.length < tailKeepCount; i -= 1) {
102
+ const ev = events[i];
103
+ if (ev.kind === 'user' || ev.kind === 'persona' || ev.kind === 'system') {
104
+ tailSlice.push(ev);
105
+ }
106
+ }
107
+ tailSlice.reverse();
108
+ // After the marker: everything that landed AFTER the boundary
109
+ // append. These are post-compaction events the user has not yet
110
+ // seen folded into a summary; they pass through verbatim.
111
+ const afterMarker = events.slice(latestIdx + 1);
112
+ const markerEvent = events[latestIdx];
113
+ return [...tailSlice, markerEvent, ...afterMarker];
114
+ }
115
+ //# sourceMappingURL=buffer-rewriter.js.map