@pugi/cli 0.1.0-beta.9 → 0.1.0-beta.91

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 (411) hide show
  1. package/CHANGELOG.md +132 -0
  2. package/LICENSE +1 -1
  3. package/assets/pugi-prozr2-mascot.ansi +9 -0
  4. package/bin/run.js +33 -1
  5. package/dist/commands/deploy.js +40 -40
  6. package/dist/commands/flatten.js +191 -0
  7. package/dist/commands/jobs-watch.js +201 -0
  8. package/dist/commands/jobs.js +42 -27
  9. package/dist/commands/smoke.js +133 -0
  10. package/dist/core/agent-progress/cleanup.js +134 -0
  11. package/dist/core/agent-progress/schema.js +144 -0
  12. package/dist/core/agent-progress/writer.js +101 -0
  13. package/dist/core/agents/adaptive-router.js +330 -0
  14. package/dist/core/agents/query-decomposer.js +297 -0
  15. package/dist/core/agents/registry.js +3 -3
  16. package/dist/core/approvals/shortcut-resolver.js +98 -0
  17. package/dist/core/artifact-chain/dispatcher.js +148 -0
  18. package/dist/core/artifact-chain/exporter.js +164 -0
  19. package/dist/core/artifact-chain/state.js +243 -0
  20. package/dist/core/artifact-chain/steps.js +169 -0
  21. package/dist/core/ask-user/question.js +92 -0
  22. package/dist/core/audit/audit-trail.js +275 -0
  23. package/dist/core/auth/ensure-authenticated.js +129 -0
  24. package/dist/core/auth/env-provider.js +238 -0
  25. package/dist/core/auto-open-browser.js +4 -4
  26. package/dist/core/auto-update/channels.js +122 -0
  27. package/dist/core/auto-update/checker.js +241 -0
  28. package/dist/core/auto-update/state.js +235 -0
  29. package/dist/core/bare-mode/index.js +107 -0
  30. package/dist/core/bash/redirect.js +281 -0
  31. package/dist/core/bash-classifier.js +436 -40
  32. package/dist/core/checkpoint/resumer.js +149 -0
  33. package/dist/core/checkpoint/rewinder.js +291 -0
  34. package/dist/core/checkpoints/shadow-git.js +670 -0
  35. package/dist/core/citations/parser.js +109 -0
  36. package/dist/core/classifier/yolo-classifier.js +88 -0
  37. package/dist/core/codegraph/decision-store.js +248 -0
  38. package/dist/core/codegraph/detect-repo.js +459 -0
  39. package/dist/core/codegraph/install.js +134 -0
  40. package/dist/core/codegraph/offer-hook.js +220 -0
  41. package/dist/core/compact/auto-trigger.js +96 -0
  42. package/dist/core/compact/buffer-rewriter.js +115 -0
  43. package/dist/core/compact/summarizer.js +208 -0
  44. package/dist/core/compact/token-counter.js +108 -0
  45. package/dist/core/consensus/anvil-fanout.js +25 -25
  46. package/dist/core/consensus/diff-capture.js +121 -12
  47. package/dist/core/consensus/rubric.js +21 -21
  48. package/dist/core/context/builder.js +6 -6
  49. package/dist/core/context/compaction-events.js +8 -8
  50. package/dist/core/context/compaction.js +31 -31
  51. package/dist/core/context/index.js +15 -8
  52. package/dist/core/context/invariants.js +51 -51
  53. package/dist/core/context/markdown-loader.js +28 -10
  54. package/dist/core/context/markdown-traverse.js +255 -0
  55. package/dist/core/context/pugiignore.js +41 -41
  56. package/dist/core/context/repo-skeleton.js +37 -37
  57. package/dist/core/context/tool-eviction.js +55 -0
  58. package/dist/core/context/watcher.js +32 -32
  59. package/dist/core/context/working-set.js +23 -23
  60. package/dist/core/coordinator/agent-tools.js +77 -0
  61. package/dist/core/coordinator/agent-toolset.js +65 -0
  62. package/dist/core/coordinator/fsm.js +73 -0
  63. package/dist/core/coordinator/mode-fsm.js +70 -0
  64. package/dist/core/cost/rate-card.js +129 -0
  65. package/dist/core/cost/tracker.js +221 -0
  66. package/dist/core/credentials.js +13 -13
  67. package/dist/core/cron/scheduler.js +138 -0
  68. package/dist/core/denial-tracking/index.js +8 -0
  69. package/dist/core/denial-tracking/state.js +264 -0
  70. package/dist/core/diagnostics/probe-runner.js +93 -0
  71. package/dist/core/diagnostics/probes/api.js +46 -0
  72. package/dist/core/diagnostics/probes/auth.js +93 -0
  73. package/dist/core/diagnostics/probes/bare-mode.js +42 -0
  74. package/dist/core/diagnostics/probes/cli-version.js +127 -0
  75. package/dist/core/diagnostics/probes/config.js +72 -0
  76. package/dist/core/diagnostics/probes/denial-tracking.js +57 -0
  77. package/dist/core/diagnostics/probes/disk.js +81 -0
  78. package/dist/core/diagnostics/probes/engine-live.js +46 -0
  79. package/dist/core/diagnostics/probes/git.js +65 -0
  80. package/dist/core/diagnostics/probes/hooks.js +118 -0
  81. package/dist/core/diagnostics/probes/mcp.js +75 -0
  82. package/dist/core/diagnostics/probes/node.js +59 -0
  83. package/dist/core/diagnostics/probes/pnpm.js +36 -0
  84. package/dist/core/diagnostics/probes/pugi-md.js +89 -0
  85. package/dist/core/diagnostics/probes/sandbox.js +40 -0
  86. package/dist/core/diagnostics/probes/session.js +74 -0
  87. package/dist/core/diagnostics/probes/status-snapshot.js +488 -0
  88. package/dist/core/diagnostics/probes/workspace.js +63 -0
  89. package/dist/core/diagnostics/types.js +70 -0
  90. package/dist/core/dispatch/cache-cleanup.js +197 -0
  91. package/dist/core/dispatch/cache-handoff.js +295 -0
  92. package/dist/core/edits/apply-patch-layer-e.js +189 -0
  93. package/dist/core/edits/dispatch.js +333 -7
  94. package/dist/core/edits/format-detector.js +260 -0
  95. package/dist/core/edits/format-matrix.js +26 -0
  96. package/dist/core/edits/fuzzy-ladder.js +650 -0
  97. package/dist/core/edits/index.js +5 -1
  98. package/dist/core/edits/journal.js +199 -0
  99. package/dist/core/edits/layer-a-apply.js +15 -15
  100. package/dist/core/edits/layer-a-fuzzy-apply.js +198 -0
  101. package/dist/core/edits/layer-b-apply.js +9 -9
  102. package/dist/core/edits/layer-c-apply.js +6 -6
  103. package/dist/core/edits/layer-d-ast.js +557 -14
  104. package/dist/core/edits/marker-parser.js +12 -12
  105. package/dist/core/edits/security-gate.js +27 -27
  106. package/dist/core/edits/verify-hook.js +273 -0
  107. package/dist/core/edits/worktree.js +29 -29
  108. package/dist/core/engine/anvil-client.js +214 -26
  109. package/dist/core/engine/auto-compact.js +179 -0
  110. package/dist/core/engine/budgets.js +186 -0
  111. package/dist/core/engine/context-prefix.js +155 -0
  112. package/dist/core/engine/index.js +1 -1
  113. package/dist/core/engine/intensity.js +158 -0
  114. package/dist/core/engine/intent.js +260 -0
  115. package/dist/core/engine/native-pugi.js +1295 -227
  116. package/dist/core/engine/prompts.js +129 -19
  117. package/dist/core/engine/strip-internal-fields.js +124 -0
  118. package/dist/core/engine/tool-bridge.js +1792 -59
  119. package/dist/core/evaluation/golden-dataset.js +293 -0
  120. package/dist/core/feedback/queue.js +177 -0
  121. package/dist/core/feedback/submitter.js +145 -0
  122. package/dist/core/file-cache.js +113 -1
  123. package/dist/core/flatten/flatten-repo.js +439 -0
  124. package/dist/core/format/osc8-link.js +28 -0
  125. package/dist/core/hook-chains.js +392 -0
  126. package/dist/core/hooks/citation-verify-hook.js +138 -0
  127. package/dist/core/hooks/citation-verify.js +112 -0
  128. package/dist/core/hooks/events.js +46 -0
  129. package/dist/core/hooks/index.js +15 -0
  130. package/dist/core/hooks/registry.js +216 -0
  131. package/dist/core/hooks/runner.js +236 -0
  132. package/dist/core/hooks/v2/event-emitter.js +115 -0
  133. package/dist/core/hooks/v2/executor.js +282 -0
  134. package/dist/core/hooks/v2/index.js +25 -0
  135. package/dist/core/hooks/v2/lifecycle.js +104 -0
  136. package/dist/core/hooks/v2/loader.js +216 -0
  137. package/dist/core/hooks/v2/matcher.js +125 -0
  138. package/dist/core/hooks/v2/trust.js +143 -0
  139. package/dist/core/hooks/v2/types.js +86 -0
  140. package/dist/core/hooks/worktree-events.js +158 -0
  141. package/dist/core/image/renderer.js +71 -0
  142. package/dist/core/init/detector.js +582 -0
  143. package/dist/core/init/template-renderer.js +242 -0
  144. package/dist/core/jobs/registry.js +18 -18
  145. package/dist/core/ledger/results-tsv.js +142 -0
  146. package/dist/core/log-discipline/stdout-redirect.js +51 -0
  147. package/dist/core/lsp/cache.js +105 -0
  148. package/dist/core/lsp/client.js +551 -41
  149. package/dist/core/lsp/language-detect.js +66 -0
  150. package/dist/core/lsp/post-edit-diagnostics.js +171 -0
  151. package/dist/core/lsp/server-detect.js +173 -0
  152. package/dist/core/lsp/symbol-cache.js +162 -0
  153. package/dist/core/lsp/symbol-tools.js +664 -0
  154. package/dist/core/mcp/client.js +97 -28
  155. package/dist/core/mcp/http-server.js +553 -0
  156. package/dist/core/mcp/orchestrator-tools.js +662 -0
  157. package/dist/core/mcp/permission.js +190 -0
  158. package/dist/core/mcp/registry.js +39 -17
  159. package/dist/core/mcp/server-tools.js +219 -0
  160. package/dist/core/mcp/server.js +397 -0
  161. package/dist/core/mcp/trust.js +10 -10
  162. package/dist/core/memory/dual-write.js +416 -0
  163. package/dist/core/memory/passive-extract.js +130 -0
  164. package/dist/core/memory/phase1-kinds.js +20 -0
  165. package/dist/core/memory/secret-scanner.js +304 -0
  166. package/dist/core/memory-sync/queue.js +170 -0
  167. package/dist/core/metrics/extract.js +113 -0
  168. package/dist/core/modes/roo-modes.js +68 -0
  169. package/dist/core/onboarding/ensure-initialized.js +133 -0
  170. package/dist/core/onboarding/marker.js +111 -0
  171. package/dist/core/onboarding/telemetry-state.js +108 -0
  172. package/dist/core/output-style/presets.js +176 -0
  173. package/dist/core/output-style/state.js +185 -0
  174. package/dist/core/path-security.js +287 -5
  175. package/dist/core/permission.js +82 -22
  176. package/dist/core/permissions/auto-classifier.js +124 -0
  177. package/dist/core/permissions/bash-parser.js +371 -0
  178. package/dist/core/permissions/circuit-breaker.js +83 -0
  179. package/dist/core/permissions/constrained-edit.js +91 -0
  180. package/dist/core/permissions/gate.js +278 -0
  181. package/dist/core/permissions/index.js +20 -0
  182. package/dist/core/permissions/mode.js +174 -0
  183. package/dist/core/permissions/network-egress.js +137 -0
  184. package/dist/core/permissions/state.js +241 -0
  185. package/dist/core/permissions/tool-class.js +93 -0
  186. package/dist/core/plan-mode/ui-state.js +51 -0
  187. package/dist/core/plans/plan-artifact.js +721 -0
  188. package/dist/core/policy-limits/etag-store.js +122 -0
  189. package/dist/core/prd-check/parser.js +215 -0
  190. package/dist/core/prd-check/reporter.js +127 -0
  191. package/dist/core/prd-check/session-review.js +557 -0
  192. package/dist/core/prd-check/verifiers.js +223 -0
  193. package/dist/core/prompt-cache/client-cache.js +99 -0
  194. package/dist/core/prompts/assembly.js +29 -0
  195. package/dist/core/prompts/registry.js +364 -0
  196. package/dist/core/pugi-md/cc-compat-rules.js +735 -0
  197. package/dist/core/pugi-md/context-injector.js +76 -0
  198. package/dist/core/pugi-md/walk-up.js +207 -0
  199. package/dist/core/python/uv-installer.js +270 -0
  200. package/dist/core/python/uv-resolver.js +83 -0
  201. package/dist/core/rate-limit/narrator.js +146 -0
  202. package/dist/core/recipes/cli-types.js +20 -0
  203. package/dist/core/recipes/loader.js +103 -0
  204. package/dist/core/recipes/runner.js +345 -0
  205. package/dist/core/recipes/schema.js +587 -0
  206. package/dist/core/release-notes/parser.js +241 -0
  207. package/dist/core/release-notes/state.js +116 -0
  208. package/dist/core/repl/ask.js +37 -37
  209. package/dist/core/repl/cancellation.js +26 -26
  210. package/dist/core/repl/cap-warning.js +4 -4
  211. package/dist/core/repl/clipboard-read.js +11 -11
  212. package/dist/core/repl/dispatch-fsm.js +12 -12
  213. package/dist/core/repl/history-search.js +15 -15
  214. package/dist/core/repl/history.js +28 -18
  215. package/dist/core/repl/kill-ring.js +5 -5
  216. package/dist/core/repl/model-pricing.js +135 -0
  217. package/dist/core/repl/privacy-banner.js +22 -22
  218. package/dist/core/repl/session.js +2148 -217
  219. package/dist/core/repl/slash-commands.js +501 -41
  220. package/dist/core/repl/store/index.js +1 -1
  221. package/dist/core/repl/store/jsonl-log.js +22 -22
  222. package/dist/core/repl/store/lockfile.js +10 -10
  223. package/dist/core/repl/store/session-store.js +136 -107
  224. package/dist/core/repl/store/types.js +15 -15
  225. package/dist/core/repl/store/uuid-v7.js +12 -12
  226. package/dist/core/repl/workspace-context.js +43 -21
  227. package/dist/core/repo-map/build.js +125 -0
  228. package/dist/core/repo-map/cache.js +185 -0
  229. package/dist/core/repo-map/extractor.js +254 -0
  230. package/dist/core/repo-map/formatter.js +145 -0
  231. package/dist/core/repo-map/page-rank.js +105 -0
  232. package/dist/core/repo-map/scanner.js +211 -0
  233. package/dist/core/retry-budget/budget.js +284 -0
  234. package/dist/core/retry-budget/index.js +5 -0
  235. package/dist/core/retry-budget/retry-cap.js +74 -0
  236. package/dist/core/routing/lead-worker.js +43 -0
  237. package/dist/core/routing/pre-flight-estimator.js +108 -0
  238. package/dist/core/runs/run-tree.js +103 -0
  239. package/dist/core/security/injection-scanner.js +367 -0
  240. package/dist/core/security/output-filter.js +418 -0
  241. package/dist/core/session/env-file.js +105 -0
  242. package/dist/core/session/section-budgets.js +140 -0
  243. package/dist/core/session.js +92 -0
  244. package/dist/core/settings.js +324 -5
  245. package/dist/core/share/formatter.js +271 -0
  246. package/dist/core/share/redactor.js +221 -0
  247. package/dist/core/share/uploader.js +267 -0
  248. package/dist/core/skills/defaults.js +30 -30
  249. package/dist/core/skills/loader.js +22 -22
  250. package/dist/core/skills/sources.js +27 -27
  251. package/dist/core/smoke/headless-driver.js +174 -0
  252. package/dist/core/smoke/orchestrator.js +194 -0
  253. package/dist/core/smoke/runner.js +238 -0
  254. package/dist/core/smoke/scenario-parser.js +316 -0
  255. package/dist/core/statusline.js +99 -0
  256. package/dist/core/subagents/dispatcher-real.js +600 -0
  257. package/dist/core/subagents/dispatcher.js +132 -43
  258. package/dist/core/subagents/index.js +19 -6
  259. package/dist/core/subagents/isolation-matrix.js +213 -0
  260. package/dist/core/subagents/spawn.js +19 -4
  261. package/dist/core/telemetry/emitter.js +229 -0
  262. package/dist/core/telemetry/queue.js +251 -0
  263. package/dist/core/theme/context.js +91 -0
  264. package/dist/core/theme/presets.js +228 -0
  265. package/dist/core/theme/state.js +181 -0
  266. package/dist/core/todos/invariant.js +10 -0
  267. package/dist/core/todos/state.js +177 -0
  268. package/dist/core/tool-schema/compressor.js +89 -0
  269. package/dist/core/transport/version-interceptor.js +166 -0
  270. package/dist/core/trust.js +2 -2
  271. package/dist/core/tui/thinking-block.js +64 -0
  272. package/dist/core/vim/keymap.js +288 -0
  273. package/dist/core/vim/state.js +92 -0
  274. package/dist/core/watch-markers/marker-watcher.js +133 -0
  275. package/dist/core/worktree/include-parser.js +249 -0
  276. package/dist/core/worktree-manager/cleanup.js +123 -0
  277. package/dist/core/worktree-manager/manager.js +303 -0
  278. package/dist/index.js +36 -0
  279. package/dist/runtime/bootstrap.js +190 -0
  280. package/dist/runtime/cli.js +4185 -549
  281. package/dist/runtime/commands/agents.js +31 -31
  282. package/dist/runtime/commands/budget.js +5 -5
  283. package/dist/runtime/commands/cancel.js +231 -0
  284. package/dist/runtime/commands/chain.js +489 -0
  285. package/dist/runtime/commands/codegraph-status.js +227 -0
  286. package/dist/runtime/commands/compact.js +297 -0
  287. package/dist/runtime/commands/config.js +73 -39
  288. package/dist/runtime/commands/cost.js +199 -0
  289. package/dist/runtime/commands/delegate.js +27 -4
  290. package/dist/runtime/commands/dispatch.js +126 -0
  291. package/dist/runtime/commands/doctor.js +579 -0
  292. package/dist/runtime/commands/feedback.js +184 -0
  293. package/dist/runtime/commands/hooks.js +187 -0
  294. package/dist/runtime/commands/init.js +254 -0
  295. package/dist/runtime/commands/lsp.js +200 -38
  296. package/dist/runtime/commands/mcp.js +879 -0
  297. package/dist/runtime/commands/memory.js +582 -0
  298. package/dist/runtime/commands/model.js +237 -0
  299. package/dist/runtime/commands/onboarding.js +275 -0
  300. package/dist/runtime/commands/patch.js +12 -12
  301. package/dist/runtime/commands/permissions.js +112 -0
  302. package/dist/runtime/commands/plan.js +143 -0
  303. package/dist/runtime/commands/prd-check.js +285 -0
  304. package/dist/runtime/commands/privacy.js +17 -17
  305. package/dist/runtime/commands/recipe.js +325 -0
  306. package/dist/runtime/commands/redo-blob-store.js +92 -0
  307. package/dist/runtime/commands/redo.js +361 -0
  308. package/dist/runtime/commands/release-notes.js +229 -0
  309. package/dist/runtime/commands/repo-map.js +95 -0
  310. package/dist/runtime/commands/report.js +299 -0
  311. package/dist/runtime/commands/resume.js +118 -0
  312. package/dist/runtime/commands/review-consensus.js +68 -53
  313. package/dist/runtime/commands/rewind.js +333 -0
  314. package/dist/runtime/commands/roster.js +14 -14
  315. package/dist/runtime/commands/sessions.js +163 -0
  316. package/dist/runtime/commands/share.js +316 -0
  317. package/dist/runtime/commands/skills.js +31 -31
  318. package/dist/runtime/commands/status.js +186 -0
  319. package/dist/runtime/commands/stickers.js +82 -0
  320. package/dist/runtime/commands/style.js +194 -0
  321. package/dist/runtime/commands/theme.js +196 -0
  322. package/dist/runtime/commands/undo.js +54 -22
  323. package/dist/runtime/commands/update.js +289 -0
  324. package/dist/runtime/commands/vim.js +140 -0
  325. package/dist/runtime/commands/worktree.js +8 -8
  326. package/dist/runtime/commands/worktrees.js +155 -0
  327. package/dist/runtime/headless-repl.js +195 -0
  328. package/dist/runtime/headless.js +543 -0
  329. package/dist/runtime/load-hooks-or-exit.js +71 -0
  330. package/dist/runtime/plan-decompose.js +22 -22
  331. package/dist/runtime/sigint-guard.js +272 -0
  332. package/dist/runtime/update-check.js +28 -28
  333. package/dist/runtime/version.js +65 -0
  334. package/dist/runtime/worktree-bootstrap.js +579 -0
  335. package/dist/skills/bundled/batch.js +617 -0
  336. package/dist/skills/bundled/index.js +45 -0
  337. package/dist/skills/bundled/loop.js +358 -0
  338. package/dist/skills/bundled/remember.js +383 -0
  339. package/dist/skills/bundled/simplify.js +289 -0
  340. package/dist/skills/bundled/skillify.js +373 -0
  341. package/dist/skills/bundled/stuck.js +558 -0
  342. package/dist/skills/bundled/verify.js +439 -0
  343. package/dist/testing/vcr.js +486 -0
  344. package/dist/tools/agent-tool.js +229 -0
  345. package/dist/tools/apply-patch.js +89 -28
  346. package/dist/tools/ask-user-question.js +337 -0
  347. package/dist/tools/ask-user.js +115 -0
  348. package/dist/tools/bash.js +624 -46
  349. package/dist/tools/brief.js +224 -0
  350. package/dist/tools/cron.js +433 -0
  351. package/dist/tools/enter-worktree.js +250 -0
  352. package/dist/tools/exit-worktree.js +147 -0
  353. package/dist/tools/file-tools.js +161 -44
  354. package/dist/tools/lsp-tools.js +377 -1
  355. package/dist/tools/mcp-tool.js +260 -0
  356. package/dist/tools/multi-edit.js +361 -0
  357. package/dist/tools/powershell.js +268 -0
  358. package/dist/tools/registry.js +99 -4
  359. package/dist/tools/skill-tool.js +96 -0
  360. package/dist/tools/sleep.js +99 -0
  361. package/dist/tools/synthetic-output.js +133 -0
  362. package/dist/tools/tasks.js +208 -0
  363. package/dist/tools/todo-write.js +184 -0
  364. package/dist/tools/verify-plan-execution.js +295 -0
  365. package/dist/tools/web-fetch-injection-scanner.js +207 -0
  366. package/dist/tools/web-fetch.js +195 -10
  367. package/dist/tools/web-search.js +458 -0
  368. package/dist/tui/agent-progress-card.js +111 -0
  369. package/dist/tui/agent-tree.js +11 -1
  370. package/dist/tui/ask-modal.js +14 -14
  371. package/dist/tui/ask-user-question-chips.js +315 -0
  372. package/dist/tui/ask-user-question-prompt.js +203 -0
  373. package/dist/tui/compact-banner.js +81 -0
  374. package/dist/tui/conversation-pane.js +85 -11
  375. package/dist/tui/cost-table.js +111 -0
  376. package/dist/tui/device-flow.js +2 -2
  377. package/dist/tui/doctor-table.js +46 -0
  378. package/dist/tui/feedback-prompt.js +156 -0
  379. package/dist/tui/input-box.js +247 -32
  380. package/dist/tui/login-picker.js +3 -3
  381. package/dist/tui/markdown-render.js +6 -6
  382. package/dist/tui/multi-file-diff-approval.js +375 -0
  383. package/dist/tui/onboarding-wizard.js +240 -0
  384. package/dist/tui/permissions-picker.js +86 -0
  385. package/dist/tui/render.js +36 -1
  386. package/dist/tui/repl-render.js +176 -25
  387. package/dist/tui/repl-splash-art.js +16 -16
  388. package/dist/tui/repl-splash-mascot.js +48 -24
  389. package/dist/tui/repl-splash.js +22 -22
  390. package/dist/tui/repl.js +125 -45
  391. package/dist/tui/slash-palette.js +6 -6
  392. package/dist/tui/splash.js +2 -2
  393. package/dist/tui/status-bar.js +109 -31
  394. package/dist/tui/status-table.js +7 -0
  395. package/dist/tui/stickers-art.js +136 -0
  396. package/dist/tui/style-table.js +28 -0
  397. package/dist/tui/theme-table.js +29 -0
  398. package/dist/tui/thinking-spinner.js +123 -0
  399. package/dist/tui/tool-stream-pane.js +53 -4
  400. package/dist/tui/update-banner.js +27 -2
  401. package/dist/tui/vim-input.js +267 -0
  402. package/dist/tui/welcome-banner.js +107 -0
  403. package/dist/tui/welcome-data.js +293 -0
  404. package/dist/tui/workspace-context.js +2 -2
  405. package/package.json +31 -16
  406. package/test/scenarios/codegen-create-file.scenario.txt +13 -0
  407. package/test/scenarios/compact-force.scenario.txt +12 -0
  408. package/test/scenarios/identity.scenario.txt +12 -0
  409. package/test/scenarios/persona-handoff.scenario.txt +12 -0
  410. package/test/scenarios/walkback.scenario.txt +12 -0
  411. package/dist/core/engine/compaction-hook.js +0 -154
@@ -0,0 +1,416 @@
1
+ /**
2
+ * Pugi CLI dual-write client — Memory Phase 1 (2026-05-27, ).
3
+ *
4
+ * Promotes the per-session NDJSON event log (Memory Phase 0, PR)
5
+ * to a best-effort Prisma row store via the admin-api endpoint:
6
+ *
7
+ * POST /api/pugi/sessions/:sessionId/events
8
+ *
9
+ * Design contract:
10
+ *
11
+ * 1. Local NDJSON is the SOURCE OF TRUTH. The dual-write client is
12
+ * fire-and-forget — a network failure NEVER blocks the local
13
+ * append path, and the operator never loses data because the
14
+ * .pugi/sessions/<id>/events.<n>.jsonl file is always written
15
+ * first by the SessionStore.
16
+ *
17
+ * 2. Async + debounced. Events are buffered in memory and flushed on
18
+ * a timer (default 250 ms) or when the buffer crosses the batch
19
+ * cap (default 50). The debounce + buffer keeps the network cost
20
+ * proportional to operator activity, not per-event.
21
+ *
22
+ * 3. Retry with backoff. A failed flush retries up to 3 times with
23
+ * exponential backoff (250 ms / 750 ms / 2250 ms). Failure beyond
24
+ * that drops the batch; the next flush brings in the backlog from
25
+ * the local NDJSON via the resume path.
26
+ *
27
+ * 4. Resume marker. The client tracks `lastSyncedSeq` per session in
28
+ * `~/.pugi/memory-sync/<sessionId>.json`. On `flushBacklog()` it
29
+ * reads any events from the local NDJSON whose seq > lastSyncedSeq
30
+ * and posts them in order. The marker is updated only on a
31
+ * successful POST so a crash mid-flush retries the unsent batch.
32
+ *
33
+ * 5. Kill switch. `PUGI_MEMORY_PHASE1_PRISMA_PERSIST_ENABLED=false`
34
+ * shuts the dual-write off entirely (env var, no settings file
35
+ * round-trip). The client is also a no-op when no credentials are
36
+ * available — anon CLI sessions never POST.
37
+ *
38
+ * 6. Schema contract. The kinds mirror
39
+ * `apps/admin-api/src/pugi-session-events/pugi-session-events.types.ts`
40
+ * PUGI_SESSION_EVENT_KINDS. The CLI's broader NDJSON kind set
41
+ * (`user`, `persona`, `rewind-marker`, etc.) is REMAPPED to the
42
+ * Phase-1 closed set inside `eventToPhase1()` — adding a new
43
+ * Phase-1 kind requires a coordinated CLI + server bump.
44
+ *
45
+ * The client carries no Nest / Prisma deps — pure node:fs + global
46
+ * fetch so it boots inside the CLI's REPL workflow without dragging in
47
+ * the admin-api graph.
48
+ */
49
+ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync, } from 'node:fs';
50
+ import { homedir } from 'node:os';
51
+ import { resolve } from 'node:path';
52
+ import { PUGI_SESSION_EVENT_KINDS, } from './phase1-kinds.js';
53
+ /* ------------------------------------------------------------------ */
54
+ /* Constants */
55
+ /* ------------------------------------------------------------------ */
56
+ export const DEFAULT_DEBOUNCE_MS = 250;
57
+ export const DEFAULT_MAX_BATCH_SIZE = 50;
58
+ export const DEFAULT_MAX_RETRIES = 3;
59
+ /** Server-side hard ceiling (mirror of admin-api MAX_BATCH_EVENTS). */
60
+ const SERVER_MAX_BATCH_EVENTS = 200;
61
+ /** Env kill-switch. Unset / 'true' / '1' = enabled. 'false' / '0' = off. */
62
+ export function isDualWriteEnabledFromEnv(env = process.env) {
63
+ const raw = env.PUGI_MEMORY_PHASE1_PRISMA_PERSIST_ENABLED;
64
+ if (raw === undefined || raw === '')
65
+ return true;
66
+ const v = raw.toLowerCase().trim();
67
+ return v !== 'false' && v !== '0' && v !== 'off' && v !== 'no';
68
+ }
69
+ /** Env override for debounce (ms). Falls back to DEFAULT_DEBOUNCE_MS. */
70
+ export function debounceMsFromEnv(env = process.env) {
71
+ const raw = env.PUGI_MEMORY_DUAL_WRITE_DEBOUNCE_MS;
72
+ if (!raw)
73
+ return DEFAULT_DEBOUNCE_MS;
74
+ const n = Number.parseInt(raw, 10);
75
+ if (!Number.isFinite(n) || n < 0 || n > 60_000)
76
+ return DEFAULT_DEBOUNCE_MS;
77
+ return n;
78
+ }
79
+ export function defaultStateDir(home = homedir()) {
80
+ return resolve(home, '.pugi', 'memory-sync');
81
+ }
82
+ export function syncStatePath(sessionId, stateDir) {
83
+ return resolve(stateDir, `${sessionId}.json`);
84
+ }
85
+ export function readSyncState(sessionId, stateDir = defaultStateDir()) {
86
+ const p = syncStatePath(sessionId, stateDir);
87
+ if (!existsSync(p))
88
+ return 0;
89
+ try {
90
+ const raw = readFileSync(p, 'utf-8');
91
+ const parsed = JSON.parse(raw);
92
+ if (parsed.schema === 1 &&
93
+ typeof parsed.lastSyncedSeq === 'number' &&
94
+ Number.isInteger(parsed.lastSyncedSeq) &&
95
+ parsed.lastSyncedSeq >= 0) {
96
+ return parsed.lastSyncedSeq;
97
+ }
98
+ }
99
+ catch {
100
+ // Best effort — a corrupt state file means "resync from zero".
101
+ return 0;
102
+ }
103
+ return 0;
104
+ }
105
+ export function writeSyncState(sessionId, lastSyncedSeq, stateDir = defaultStateDir()) {
106
+ if (!existsSync(stateDir)) {
107
+ mkdirSync(stateDir, { recursive: true, mode: 0o700 });
108
+ }
109
+ const p = syncStatePath(sessionId, stateDir);
110
+ const record = {
111
+ schema: 1,
112
+ sessionId,
113
+ lastSyncedSeq,
114
+ updatedAt: new Date().toISOString(),
115
+ };
116
+ // Atomic write: temp + rename so a crash mid-write leaves either the
117
+ // old contents or the new — never a partial JSON document.
118
+ const tmp = `${p}.tmp-${process.pid}-${Date.now()}`;
119
+ writeFileSync(tmp, JSON.stringify(record), { encoding: 'utf-8', mode: 0o600 });
120
+ renameSync(tmp, p);
121
+ }
122
+ /* ------------------------------------------------------------------ */
123
+ /* DualWriteClient */
124
+ /* ------------------------------------------------------------------ */
125
+ /**
126
+ * Compute the next backoff delay (ms). Exponential growth from the
127
+ * debounce base — 1× / 3× / 9× — keeps the retry storm bounded.
128
+ */
129
+ export function nextBackoffMs(attempt, base) {
130
+ // attempt 1 -> base, attempt 2 -> 3×base, attempt 3 -> 9×base.
131
+ return base * Math.pow(3, Math.max(0, attempt - 1));
132
+ }
133
+ /**
134
+ * Tiny await-able sleeper. Public for tests that want a deterministic
135
+ * scheduler — production callers go through the internal debounce
136
+ * timer, not this helper.
137
+ */
138
+ function sleep(ms, scheduler = setTimeout) {
139
+ return new Promise((res) => scheduler(res, Math.max(0, ms)));
140
+ }
141
+ /**
142
+ * Buffered, debounced, retry-capable dual-write client.
143
+ *
144
+ * One instance per active session. The CLI's SessionStore creates one
145
+ * at `openSession()` and disposes it at `archive()` / `process.exit()`.
146
+ * The instance retains its own buffer + flushing promise so concurrent
147
+ * `enqueue()` calls from multiple producers (REPL turn + subagent
148
+ * dispatcher) coalesce into the same batch.
149
+ */
150
+ export class DualWriteClient {
151
+ cfg;
152
+ buffer = [];
153
+ flushTimer = null;
154
+ /**
155
+ * Active flush promise (null when idle). Re-using the in-flight
156
+ * promise lets `enqueue` callers tail-chain a pending flush instead
157
+ * of stacking N flushes when the CLI is in a hot loop.
158
+ */
159
+ flushing = null;
160
+ /** Disposed clients reject further enqueues quietly. */
161
+ disposed = false;
162
+ /** Track the highest server-acknowledged seq. */
163
+ highestSyncedSeq;
164
+ constructor(config) {
165
+ const stateDir = config.stateDir ?? defaultStateDir();
166
+ this.cfg = {
167
+ apiUrl: config.apiUrl.replace(/\/+$/, ''),
168
+ apiKey: config.apiKey,
169
+ sessionId: config.sessionId,
170
+ debounceMs: config.debounceMs ?? debounceMsFromEnv(),
171
+ maxBatchSize: Math.min(config.maxBatchSize ?? DEFAULT_MAX_BATCH_SIZE, SERVER_MAX_BATCH_EVENTS),
172
+ maxRetries: config.maxRetries ?? DEFAULT_MAX_RETRIES,
173
+ fetchImpl: config.fetchImpl ?? globalThis.fetch,
174
+ stateDir,
175
+ };
176
+ this.highestSyncedSeq = readSyncState(config.sessionId, stateDir);
177
+ }
178
+ /** Currently-known synced seq (read-through for callers). */
179
+ get lastSyncedSeq() {
180
+ return this.highestSyncedSeq;
181
+ }
182
+ /**
183
+ * Buffer an event for the next flush. Returns immediately — the
184
+ * actual POST happens on the debounce timer.
185
+ *
186
+ * The producer (SessionStore) is expected to have ALREADY written
187
+ * the local NDJSON line before calling this. The dual-write client
188
+ * never touches the NDJSON itself.
189
+ */
190
+ enqueue(event) {
191
+ if (this.disposed)
192
+ return;
193
+ if (!isValidPhase1Kind(event.kind)) {
194
+ // Quietly ignore events the Phase-1 schema cannot represent. The
195
+ // local NDJSON keeps them; a future Phase-1.1 may widen the kind
196
+ // set.
197
+ return;
198
+ }
199
+ if (!Number.isInteger(event.seq) || event.seq <= 0)
200
+ return;
201
+ this.buffer.push(event);
202
+ // Crossed the batch cap — flush eagerly to bound buffer growth.
203
+ if (this.buffer.length >= this.cfg.maxBatchSize) {
204
+ this.scheduleFlush(0);
205
+ return;
206
+ }
207
+ this.scheduleFlush(this.cfg.debounceMs);
208
+ }
209
+ /**
210
+ * Force any pending events out. Used at session archive / shutdown
211
+ * so the trailing batch lands before the process exits.
212
+ */
213
+ async flush() {
214
+ if (this.flushTimer) {
215
+ clearTimeout(this.flushTimer);
216
+ this.flushTimer = null;
217
+ }
218
+ return this.doFlush();
219
+ }
220
+ /**
221
+ * Mark the client disposed. Subsequent enqueues are no-ops. Pending
222
+ * flush is awaited so the caller can `await client.dispose()` to
223
+ * fence completion.
224
+ */
225
+ async dispose() {
226
+ this.disposed = true;
227
+ if (this.flushTimer) {
228
+ clearTimeout(this.flushTimer);
229
+ this.flushTimer = null;
230
+ }
231
+ if (this.flushing) {
232
+ try {
233
+ await this.flushing;
234
+ }
235
+ catch {
236
+ // ignore
237
+ }
238
+ }
239
+ }
240
+ /**
241
+ * Backlog catch-up. The caller passes the local NDJSON's events
242
+ * (already filtered to the session) — the client posts any whose
243
+ * seq > lastSyncedSeq, in order, in batches of maxBatchSize.
244
+ *
245
+ * Returns the aggregate FlushResult across all batches (sums
246
+ * persisted + duplicate counts, lastSeq is the max).
247
+ */
248
+ async flushBacklog(allEvents) {
249
+ const pending = allEvents
250
+ .filter((e) => e.seq > this.highestSyncedSeq && isValidPhase1Kind(e.kind))
251
+ .sort((a, b) => a.seq - b.seq);
252
+ if (pending.length === 0) {
253
+ return {
254
+ persistedCount: 0,
255
+ duplicateCount: 0,
256
+ lastSeq: this.highestSyncedSeq,
257
+ };
258
+ }
259
+ let totalPersisted = 0;
260
+ let totalDuplicates = 0;
261
+ let maxLastSeq = this.highestSyncedSeq;
262
+ for (let i = 0; i < pending.length; i += this.cfg.maxBatchSize) {
263
+ const batch = pending.slice(i, i + this.cfg.maxBatchSize);
264
+ const result = await this.postBatchWithRetry(batch);
265
+ if (!result)
266
+ break; // surrender — backlog stays for next session
267
+ totalPersisted += result.persistedCount;
268
+ totalDuplicates += result.duplicateCount;
269
+ maxLastSeq = Math.max(maxLastSeq, result.lastSeq);
270
+ }
271
+ return {
272
+ persistedCount: totalPersisted,
273
+ duplicateCount: totalDuplicates,
274
+ lastSeq: maxLastSeq,
275
+ };
276
+ }
277
+ /* ---------------- internal ---------------- */
278
+ scheduleFlush(delay) {
279
+ if (this.flushTimer)
280
+ clearTimeout(this.flushTimer);
281
+ this.flushTimer = setTimeout(() => {
282
+ this.flushTimer = null;
283
+ // doFlush handles its own error swallowing; we drop the floating
284
+ // promise on the floor on purpose so the timer callback returns
285
+ // synchronously (Node requires that).
286
+ void this.doFlush();
287
+ }, delay);
288
+ }
289
+ async doFlush() {
290
+ if (this.flushing)
291
+ return this.flushing;
292
+ if (this.buffer.length === 0)
293
+ return null;
294
+ const drained = this.buffer.splice(0, this.buffer.length);
295
+ this.flushing = this.postBatchWithRetry(drained);
296
+ try {
297
+ return await this.flushing;
298
+ }
299
+ finally {
300
+ this.flushing = null;
301
+ }
302
+ }
303
+ async postBatchWithRetry(batch) {
304
+ if (batch.length === 0)
305
+ return null;
306
+ // Sort + within-batch dedup (defence in depth — the server also
307
+ // enforces monotonic seq + dedup, but enforcing here keeps the
308
+ // wire payload clean and avoids the 400 on a buggy producer).
309
+ const sorted = [...batch].sort((a, b) => a.seq - b.seq);
310
+ const deduped = [];
311
+ let prevSeq = -1;
312
+ for (const ev of sorted) {
313
+ if (ev.seq === prevSeq)
314
+ continue;
315
+ deduped.push(ev);
316
+ prevSeq = ev.seq;
317
+ }
318
+ for (let attempt = 1; attempt <= this.cfg.maxRetries; attempt++) {
319
+ try {
320
+ const result = await this.doPost(deduped);
321
+ // Persist the lastSyncedSeq marker so a crash before the next
322
+ // flush still rediscovers the high-water-mark on restart.
323
+ if (result.lastSeq > this.highestSyncedSeq) {
324
+ this.highestSyncedSeq = result.lastSeq;
325
+ try {
326
+ writeSyncState(this.cfg.sessionId, this.highestSyncedSeq, this.cfg.stateDir);
327
+ }
328
+ catch {
329
+ // Best effort — a marker write failure does not invalidate
330
+ // the on-server data, only the resume hint.
331
+ }
332
+ }
333
+ return result;
334
+ }
335
+ catch (err) {
336
+ if (attempt === this.cfg.maxRetries) {
337
+ // Final surrender — drop the batch silently. Local NDJSON is
338
+ // authoritative; the next session resume can replay the gap.
339
+ return null;
340
+ }
341
+ await sleep(nextBackoffMs(attempt, this.cfg.debounceMs));
342
+ }
343
+ }
344
+ return null;
345
+ }
346
+ async doPost(events) {
347
+ const url = `${this.cfg.apiUrl}/api/pugi/sessions/${encodeURIComponent(this.cfg.sessionId)}/events`;
348
+ const res = await this.cfg.fetchImpl(url, {
349
+ method: 'POST',
350
+ headers: {
351
+ authorization: `Bearer ${this.cfg.apiKey}`,
352
+ 'content-type': 'application/json',
353
+ accept: 'application/json',
354
+ },
355
+ body: JSON.stringify({ events }),
356
+ });
357
+ if (!res.ok) {
358
+ throw new Error(`dual-write POST ${url} returned ${res.status} ${res.statusText}`);
359
+ }
360
+ const body = (await res.json());
361
+ return {
362
+ persistedCount: body.persistedCount ?? 0,
363
+ duplicateCount: body.duplicateCount ?? 0,
364
+ lastSeq: body.lastSeq ?? 0,
365
+ };
366
+ }
367
+ }
368
+ /** Validate a kind string against the Phase-1 closed set. */
369
+ export function isValidPhase1Kind(value) {
370
+ return PUGI_SESSION_EVENT_KINDS.includes(value);
371
+ }
372
+ /* ------------------------------------------------------------------ */
373
+ /* Kind remap (CLI broad set -> Phase-1 closed set) */
374
+ /* ------------------------------------------------------------------ */
375
+ /**
376
+ * Map the CLI's broader NDJSON kind set to the Phase-1 server-side set.
377
+ * Returns `null` when the kind has no Phase-1 representation — the
378
+ * caller should drop that event from the dual-write (the local NDJSON
379
+ * still carries it for offline analysis).
380
+ *
381
+ * The CLI's kind set lives in
382
+ * `apps/pugi-cli/src/core/repl/store/types.ts`:
383
+ *
384
+ * 'user' -> 'turn.user'
385
+ * 'persona' -> 'turn.assistant'
386
+ * 'system' -> 'system'
387
+ * 'tool.start' -> 'tool.call'
388
+ * 'tool.result' -> 'tool.result'
389
+ * 'agent.spawned' -> 'dispatch.start'
390
+ * 'agent.completed'-> 'dispatch.end'
391
+ * 'compaction' -> 'compact.boundary'
392
+ * 'rewind-marker' -> null (Phase-1 has no analog yet)
393
+ */
394
+ export function cliKindToPhase1(cliKind) {
395
+ switch (cliKind) {
396
+ case 'user':
397
+ return 'turn.user';
398
+ case 'persona':
399
+ return 'turn.assistant';
400
+ case 'system':
401
+ return 'system';
402
+ case 'tool.start':
403
+ return 'tool.call';
404
+ case 'tool.result':
405
+ return 'tool.result';
406
+ case 'agent.spawned':
407
+ return 'dispatch.start';
408
+ case 'agent.completed':
409
+ return 'dispatch.end';
410
+ case 'compaction':
411
+ return 'compact.boundary';
412
+ default:
413
+ return null;
414
+ }
415
+ }
416
+ //# sourceMappingURL=dual-write.js.map
@@ -0,0 +1,130 @@
1
+ import { estimateTokens } from '../compact/token-counter.js';
2
+ const VALID_KINDS = new Set([
3
+ 'preference',
4
+ 'decision',
5
+ 'context',
6
+ 'fact',
7
+ ]);
8
+ const DEFAULT_MAX_ITEMS = 8;
9
+ const DEFAULT_MIN_CONFIDENCE = 0.6;
10
+ const DEFAULT_MAX_INPUT_TOKENS = 6000;
11
+ function genId() {
12
+ const rand = Math.random().toString(36).slice(2, 10);
13
+ return `mem-${rand}`;
14
+ }
15
+ function truncateTurns(turns, maxInputTokens) {
16
+ if (turns.length === 0)
17
+ return [];
18
+ const kept = [];
19
+ let total = 0;
20
+ for (let i = turns.length - 1; i >= 0; i -= 1) {
21
+ const turn = turns[i];
22
+ if (!turn)
23
+ continue;
24
+ const cost = estimateTokens(`${turn.role}: ${turn.content}`);
25
+ if (total + cost > maxInputTokens && kept.length > 0) {
26
+ break;
27
+ }
28
+ kept.unshift(turn);
29
+ total += cost;
30
+ }
31
+ return kept;
32
+ }
33
+ function buildPrompt(turns) {
34
+ const dialog = turns
35
+ .map((t) => `[${t.id}] ${t.role}: ${t.content}`)
36
+ .join('\n');
37
+ return [
38
+ 'You extract persistable memory items from a dialog between a user and an assistant.',
39
+ 'Return strict JSON with shape:',
40
+ '{ "items": [ { "kind": "preference"|"decision"|"context"|"fact", "body": "1-2 sentences", "confidence": 0..1, "sourceTurn": "<turn id>" } ] }',
41
+ 'Rules:',
42
+ '- Only include facts worth remembering across future sessions.',
43
+ '- Skip greetings, small talk, transient state, and tool noise.',
44
+ '- Confidence reflects how clearly the dialog supports the fact.',
45
+ '- Never invent facts that are not present in the dialog.',
46
+ '- If nothing is worth keeping, return { "items": [] }.',
47
+ 'Dialog:',
48
+ dialog,
49
+ 'Respond with JSON only.',
50
+ ].join('\n');
51
+ }
52
+ function extractJsonObject(raw) {
53
+ const trimmed = raw.trim();
54
+ const start = trimmed.indexOf('{');
55
+ const end = trimmed.lastIndexOf('}');
56
+ if (start === -1 || end === -1 || end <= start) {
57
+ throw new Error('no-json');
58
+ }
59
+ return JSON.parse(trimmed.slice(start, end + 1));
60
+ }
61
+ function isRecord(value) {
62
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
63
+ }
64
+ function validateItem(value) {
65
+ if (!isRecord(value))
66
+ return null;
67
+ const { kind, body, confidence, sourceTurn } = value;
68
+ if (typeof kind !== 'string' || !VALID_KINDS.has(kind)) {
69
+ return null;
70
+ }
71
+ if (typeof body !== 'string' || body.trim().length === 0) {
72
+ return null;
73
+ }
74
+ if (typeof confidence !== 'number' || Number.isNaN(confidence)) {
75
+ return null;
76
+ }
77
+ if (confidence < 0 || confidence > 1) {
78
+ return null;
79
+ }
80
+ const out = {
81
+ kind: kind,
82
+ body: body.trim(),
83
+ confidence,
84
+ };
85
+ if (typeof sourceTurn === 'string' && sourceTurn.length > 0) {
86
+ out.sourceTurn = sourceTurn;
87
+ }
88
+ return out;
89
+ }
90
+ export async function extractPassiveMemory(options) {
91
+ const { transport, dialogTurns, maxItems = DEFAULT_MAX_ITEMS, minConfidence = DEFAULT_MIN_CONFIDENCE, maxInputTokens = DEFAULT_MAX_INPUT_TOKENS, } = options;
92
+ if (dialogTurns.length === 0) {
93
+ return { items: [], usedFallback: false };
94
+ }
95
+ const truncated = truncateTurns(dialogTurns, maxInputTokens);
96
+ const prompt = buildPrompt(truncated);
97
+ let raw;
98
+ try {
99
+ raw = await transport(prompt);
100
+ }
101
+ catch {
102
+ return { items: [], usedFallback: true, reason: 'transport-error' };
103
+ }
104
+ let parsed;
105
+ try {
106
+ parsed = extractJsonObject(raw);
107
+ }
108
+ catch {
109
+ return { items: [], usedFallback: true, reason: 'parse-failed' };
110
+ }
111
+ if (!isRecord(parsed) || !Array.isArray(parsed.items)) {
112
+ return { items: [], usedFallback: true, reason: 'parse-failed' };
113
+ }
114
+ const validated = [];
115
+ for (const candidate of parsed.items) {
116
+ const item = validateItem(candidate);
117
+ if (!item)
118
+ continue;
119
+ if (item.confidence < minConfidence)
120
+ continue;
121
+ validated.push({ id: genId(), ...item });
122
+ }
123
+ if (validated.length === 0) {
124
+ return { items: [], usedFallback: true, reason: 'no-signal' };
125
+ }
126
+ validated.sort((a, b) => b.confidence - a.confidence);
127
+ const capped = validated.slice(0, maxItems);
128
+ return { items: capped, usedFallback: false };
129
+ }
130
+ //# sourceMappingURL=passive-extract.js.map
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Phase-1 event kind closed set — mirror of
3
+ * `apps/admin-api/src/pugi-session-events/pugi-session-events.types.ts`
4
+ * PUGI_SESSION_EVENT_KINDS.
5
+ *
6
+ * Kept as a separate file so the CLI does not import from admin-api
7
+ * (would drag the whole Nest graph). The TWO lists must stay in
8
+ * lockstep — a new kind requires editing both files.
9
+ */
10
+ export const PUGI_SESSION_EVENT_KINDS = [
11
+ 'turn.user',
12
+ 'turn.assistant',
13
+ 'tool.call',
14
+ 'tool.result',
15
+ 'dispatch.start',
16
+ 'dispatch.end',
17
+ 'compact.boundary',
18
+ 'system',
19
+ ];
20
+ //# sourceMappingURL=phase1-kinds.js.map