@pugi/cli 0.1.0-beta.7 → 0.1.0-beta.87

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 (402) hide show
  1. package/CHANGELOG.md +96 -0
  2. package/THIRD_PARTY_NOTICES.md +40 -0
  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 +2 -2
  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 +12 -12
  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 +293 -7
  94. package/dist/core/edits/format-matrix.js +26 -0
  95. package/dist/core/edits/fuzzy-ladder.js +650 -0
  96. package/dist/core/edits/index.js +3 -1
  97. package/dist/core/edits/journal.js +199 -0
  98. package/dist/core/edits/layer-a-apply.js +15 -15
  99. package/dist/core/edits/layer-a-fuzzy-apply.js +198 -0
  100. package/dist/core/edits/layer-b-apply.js +9 -9
  101. package/dist/core/edits/layer-c-apply.js +6 -6
  102. package/dist/core/edits/layer-d-ast.js +557 -14
  103. package/dist/core/edits/marker-parser.js +12 -12
  104. package/dist/core/edits/security-gate.js +27 -27
  105. package/dist/core/edits/verify-hook.js +273 -0
  106. package/dist/core/edits/worktree.js +322 -0
  107. package/dist/core/engine/anvil-client.js +140 -26
  108. package/dist/core/engine/auto-compact.js +179 -0
  109. package/dist/core/engine/budgets.js +186 -0
  110. package/dist/core/engine/context-prefix.js +155 -0
  111. package/dist/core/engine/index.js +1 -1
  112. package/dist/core/engine/intensity.js +158 -0
  113. package/dist/core/engine/intent.js +260 -0
  114. package/dist/core/engine/native-pugi.js +1295 -227
  115. package/dist/core/engine/prompts.js +134 -16
  116. package/dist/core/engine/strip-internal-fields.js +124 -0
  117. package/dist/core/engine/tool-bridge.js +1295 -59
  118. package/dist/core/evaluation/golden-dataset.js +293 -0
  119. package/dist/core/feedback/queue.js +177 -0
  120. package/dist/core/feedback/submitter.js +145 -0
  121. package/dist/core/file-cache.js +113 -1
  122. package/dist/core/flatten/flatten-repo.js +439 -0
  123. package/dist/core/format/osc8-link.js +28 -0
  124. package/dist/core/hook-chains.js +392 -0
  125. package/dist/core/hooks/citation-verify-hook.js +138 -0
  126. package/dist/core/hooks/citation-verify.js +112 -0
  127. package/dist/core/hooks/events.js +44 -0
  128. package/dist/core/hooks/index.js +15 -0
  129. package/dist/core/hooks/registry.js +213 -0
  130. package/dist/core/hooks/runner.js +236 -0
  131. package/dist/core/hooks/v2/event-emitter.js +115 -0
  132. package/dist/core/hooks/v2/executor.js +282 -0
  133. package/dist/core/hooks/v2/index.js +25 -0
  134. package/dist/core/hooks/v2/lifecycle.js +104 -0
  135. package/dist/core/hooks/v2/loader.js +216 -0
  136. package/dist/core/hooks/v2/matcher.js +125 -0
  137. package/dist/core/hooks/v2/trust.js +143 -0
  138. package/dist/core/hooks/v2/types.js +86 -0
  139. package/dist/core/image/renderer.js +71 -0
  140. package/dist/core/init/detector.js +582 -0
  141. package/dist/core/init/template-renderer.js +242 -0
  142. package/dist/core/jobs/registry.js +18 -18
  143. package/dist/core/ledger/results-tsv.js +142 -0
  144. package/dist/core/log-discipline/stdout-redirect.js +51 -0
  145. package/dist/core/lsp/cache.js +105 -0
  146. package/dist/core/lsp/client.js +776 -0
  147. package/dist/core/lsp/language-detect.js +66 -0
  148. package/dist/core/lsp/post-edit-diagnostics.js +171 -0
  149. package/dist/core/lsp/symbol-tools.js +372 -0
  150. package/dist/core/mcp/client.js +97 -28
  151. package/dist/core/mcp/http-server.js +553 -0
  152. package/dist/core/mcp/orchestrator-tools.js +662 -0
  153. package/dist/core/mcp/permission.js +190 -0
  154. package/dist/core/mcp/registry.js +39 -17
  155. package/dist/core/mcp/server-tools.js +219 -0
  156. package/dist/core/mcp/server.js +397 -0
  157. package/dist/core/mcp/trust.js +10 -10
  158. package/dist/core/memory/dual-write.js +416 -0
  159. package/dist/core/memory/passive-extract.js +130 -0
  160. package/dist/core/memory/phase1-kinds.js +20 -0
  161. package/dist/core/memory/secret-scanner.js +304 -0
  162. package/dist/core/memory-sync/queue.js +170 -0
  163. package/dist/core/metrics/extract.js +113 -0
  164. package/dist/core/modes/roo-modes.js +68 -0
  165. package/dist/core/onboarding/ensure-initialized.js +133 -0
  166. package/dist/core/onboarding/marker.js +111 -0
  167. package/dist/core/onboarding/telemetry-state.js +108 -0
  168. package/dist/core/output-style/presets.js +176 -0
  169. package/dist/core/output-style/state.js +185 -0
  170. package/dist/core/path-security.js +287 -5
  171. package/dist/core/permission.js +82 -22
  172. package/dist/core/permissions/auto-classifier.js +124 -0
  173. package/dist/core/permissions/bash-parser.js +371 -0
  174. package/dist/core/permissions/circuit-breaker.js +83 -0
  175. package/dist/core/permissions/constrained-edit.js +91 -0
  176. package/dist/core/permissions/gate.js +278 -0
  177. package/dist/core/permissions/index.js +20 -0
  178. package/dist/core/permissions/mode.js +174 -0
  179. package/dist/core/permissions/network-egress.js +137 -0
  180. package/dist/core/permissions/state.js +241 -0
  181. package/dist/core/permissions/tool-class.js +93 -0
  182. package/dist/core/plan-mode/ui-state.js +51 -0
  183. package/dist/core/plans/plan-artifact.js +721 -0
  184. package/dist/core/policy-limits/etag-store.js +122 -0
  185. package/dist/core/prd-check/parser.js +215 -0
  186. package/dist/core/prd-check/reporter.js +127 -0
  187. package/dist/core/prd-check/session-review.js +557 -0
  188. package/dist/core/prd-check/verifiers.js +223 -0
  189. package/dist/core/prompt-cache/client-cache.js +99 -0
  190. package/dist/core/prompts/assembly.js +29 -0
  191. package/dist/core/prompts/registry.js +364 -0
  192. package/dist/core/pugi-md/cc-compat-rules.js +735 -0
  193. package/dist/core/pugi-md/context-injector.js +76 -0
  194. package/dist/core/pugi-md/walk-up.js +207 -0
  195. package/dist/core/python/uv-installer.js +270 -0
  196. package/dist/core/python/uv-resolver.js +83 -0
  197. package/dist/core/rate-limit/narrator.js +146 -0
  198. package/dist/core/recipes/cli-types.js +20 -0
  199. package/dist/core/recipes/loader.js +103 -0
  200. package/dist/core/recipes/runner.js +345 -0
  201. package/dist/core/recipes/schema.js +587 -0
  202. package/dist/core/release-notes/parser.js +241 -0
  203. package/dist/core/release-notes/state.js +116 -0
  204. package/dist/core/repl/ask.js +37 -37
  205. package/dist/core/repl/cancellation.js +26 -26
  206. package/dist/core/repl/cap-warning.js +4 -4
  207. package/dist/core/repl/clipboard-read.js +11 -11
  208. package/dist/core/repl/dispatch-fsm.js +12 -12
  209. package/dist/core/repl/history-search.js +15 -15
  210. package/dist/core/repl/history.js +28 -18
  211. package/dist/core/repl/kill-ring.js +5 -5
  212. package/dist/core/repl/model-pricing.js +135 -0
  213. package/dist/core/repl/privacy-banner.js +22 -22
  214. package/dist/core/repl/session.js +2157 -214
  215. package/dist/core/repl/slash-commands.js +533 -40
  216. package/dist/core/repl/store/index.js +1 -1
  217. package/dist/core/repl/store/jsonl-log.js +22 -22
  218. package/dist/core/repl/store/lockfile.js +10 -10
  219. package/dist/core/repl/store/session-store.js +136 -107
  220. package/dist/core/repl/store/types.js +15 -15
  221. package/dist/core/repl/store/uuid-v7.js +12 -12
  222. package/dist/core/repl/workspace-context.js +43 -21
  223. package/dist/core/repo-map/build.js +125 -0
  224. package/dist/core/repo-map/cache.js +185 -0
  225. package/dist/core/repo-map/extractor.js +254 -0
  226. package/dist/core/repo-map/formatter.js +145 -0
  227. package/dist/core/repo-map/page-rank.js +105 -0
  228. package/dist/core/repo-map/scanner.js +211 -0
  229. package/dist/core/retry-budget/budget.js +284 -0
  230. package/dist/core/retry-budget/index.js +5 -0
  231. package/dist/core/retry-budget/retry-cap.js +74 -0
  232. package/dist/core/routing/lead-worker.js +43 -0
  233. package/dist/core/routing/pre-flight-estimator.js +108 -0
  234. package/dist/core/runs/run-tree.js +103 -0
  235. package/dist/core/security/injection-scanner.js +367 -0
  236. package/dist/core/security/output-filter.js +418 -0
  237. package/dist/core/session/env-file.js +105 -0
  238. package/dist/core/session/section-budgets.js +140 -0
  239. package/dist/core/session.js +92 -0
  240. package/dist/core/settings.js +286 -5
  241. package/dist/core/share/formatter.js +271 -0
  242. package/dist/core/share/redactor.js +221 -0
  243. package/dist/core/share/uploader.js +267 -0
  244. package/dist/core/skills/defaults.js +457 -0
  245. package/dist/core/skills/loader.js +22 -22
  246. package/dist/core/skills/sources.js +27 -27
  247. package/dist/core/smoke/headless-driver.js +174 -0
  248. package/dist/core/smoke/orchestrator.js +194 -0
  249. package/dist/core/smoke/runner.js +238 -0
  250. package/dist/core/smoke/scenario-parser.js +316 -0
  251. package/dist/core/statusline.js +99 -0
  252. package/dist/core/subagents/dispatcher-real.js +600 -0
  253. package/dist/core/subagents/dispatcher.js +132 -43
  254. package/dist/core/subagents/index.js +19 -6
  255. package/dist/core/subagents/isolation-matrix.js +213 -0
  256. package/dist/core/subagents/spawn.js +19 -4
  257. package/dist/core/telemetry/emitter.js +229 -0
  258. package/dist/core/telemetry/queue.js +251 -0
  259. package/dist/core/theme/context.js +91 -0
  260. package/dist/core/theme/presets.js +228 -0
  261. package/dist/core/theme/state.js +181 -0
  262. package/dist/core/todos/invariant.js +10 -0
  263. package/dist/core/todos/state.js +177 -0
  264. package/dist/core/tool-schema/compressor.js +89 -0
  265. package/dist/core/transport/version-interceptor.js +166 -0
  266. package/dist/core/trust.js +2 -2
  267. package/dist/core/tui/thinking-block.js +64 -0
  268. package/dist/core/vim/keymap.js +288 -0
  269. package/dist/core/vim/state.js +92 -0
  270. package/dist/core/watch-markers/marker-watcher.js +133 -0
  271. package/dist/core/worktree-manager/cleanup.js +123 -0
  272. package/dist/core/worktree-manager/manager.js +303 -0
  273. package/dist/index.js +28 -0
  274. package/dist/runtime/bootstrap.js +190 -0
  275. package/dist/runtime/cli.js +4162 -488
  276. package/dist/runtime/commands/agents.js +30 -30
  277. package/dist/runtime/commands/budget.js +5 -5
  278. package/dist/runtime/commands/cancel.js +231 -0
  279. package/dist/runtime/commands/chain.js +489 -0
  280. package/dist/runtime/commands/codegraph-status.js +227 -0
  281. package/dist/runtime/commands/compact.js +297 -0
  282. package/dist/runtime/commands/config.js +32 -32
  283. package/dist/runtime/commands/cost.js +199 -0
  284. package/dist/runtime/commands/delegate.js +244 -13
  285. package/dist/runtime/commands/dispatch.js +126 -0
  286. package/dist/runtime/commands/doctor.js +579 -0
  287. package/dist/runtime/commands/feedback.js +184 -0
  288. package/dist/runtime/commands/hooks.js +184 -0
  289. package/dist/runtime/commands/init.js +254 -0
  290. package/dist/runtime/commands/lsp.js +368 -0
  291. package/dist/runtime/commands/mcp.js +879 -0
  292. package/dist/runtime/commands/memory.js +582 -0
  293. package/dist/runtime/commands/model.js +237 -0
  294. package/dist/runtime/commands/onboarding.js +275 -0
  295. package/dist/runtime/commands/patch.js +128 -0
  296. package/dist/runtime/commands/permissions.js +112 -0
  297. package/dist/runtime/commands/plan.js +143 -0
  298. package/dist/runtime/commands/prd-check.js +285 -0
  299. package/dist/runtime/commands/privacy.js +17 -17
  300. package/dist/runtime/commands/recipe.js +325 -0
  301. package/dist/runtime/commands/redo-blob-store.js +92 -0
  302. package/dist/runtime/commands/redo.js +361 -0
  303. package/dist/runtime/commands/release-notes.js +229 -0
  304. package/dist/runtime/commands/repo-map.js +95 -0
  305. package/dist/runtime/commands/report.js +299 -0
  306. package/dist/runtime/commands/resume.js +118 -0
  307. package/dist/runtime/commands/review-consensus.js +68 -53
  308. package/dist/runtime/commands/rewind.js +333 -0
  309. package/dist/runtime/commands/roster.js +14 -14
  310. package/dist/runtime/commands/sessions.js +163 -0
  311. package/dist/runtime/commands/share.js +316 -0
  312. package/dist/runtime/commands/skills.js +31 -31
  313. package/dist/runtime/commands/status.js +186 -0
  314. package/dist/runtime/commands/stickers.js +82 -0
  315. package/dist/runtime/commands/style.js +194 -0
  316. package/dist/runtime/commands/theme.js +196 -0
  317. package/dist/runtime/commands/undo.js +54 -22
  318. package/dist/runtime/commands/update.js +289 -0
  319. package/dist/runtime/commands/vim.js +140 -0
  320. package/dist/runtime/commands/worktree.js +177 -0
  321. package/dist/runtime/commands/worktrees.js +155 -0
  322. package/dist/runtime/headless-repl.js +195 -0
  323. package/dist/runtime/headless.js +543 -0
  324. package/dist/runtime/load-hooks-or-exit.js +71 -0
  325. package/dist/runtime/plan-decompose.js +531 -0
  326. package/dist/runtime/update-check.js +28 -28
  327. package/dist/runtime/version.js +65 -0
  328. package/dist/skills/bundled/batch.js +617 -0
  329. package/dist/skills/bundled/index.js +45 -0
  330. package/dist/skills/bundled/loop.js +358 -0
  331. package/dist/skills/bundled/remember.js +383 -0
  332. package/dist/skills/bundled/simplify.js +289 -0
  333. package/dist/skills/bundled/skillify.js +373 -0
  334. package/dist/skills/bundled/stuck.js +558 -0
  335. package/dist/skills/bundled/verify.js +439 -0
  336. package/dist/testing/vcr.js +486 -0
  337. package/dist/tools/agent-tool.js +229 -0
  338. package/dist/tools/apply-patch.js +556 -0
  339. package/dist/tools/ask-user-question.js +222 -0
  340. package/dist/tools/ask-user.js +115 -0
  341. package/dist/tools/bash.js +623 -45
  342. package/dist/tools/brief.js +224 -0
  343. package/dist/tools/enter-worktree.js +250 -0
  344. package/dist/tools/exit-worktree.js +147 -0
  345. package/dist/tools/file-tools.js +161 -44
  346. package/dist/tools/lsp-tools.js +189 -0
  347. package/dist/tools/mcp-tool.js +260 -0
  348. package/dist/tools/multi-edit.js +361 -0
  349. package/dist/tools/powershell.js +268 -0
  350. package/dist/tools/registry.js +85 -0
  351. package/dist/tools/skill-tool.js +96 -0
  352. package/dist/tools/sleep.js +99 -0
  353. package/dist/tools/synthetic-output.js +133 -0
  354. package/dist/tools/tasks.js +208 -0
  355. package/dist/tools/todo-write.js +184 -0
  356. package/dist/tools/verify-plan-execution.js +295 -0
  357. package/dist/tools/web-fetch-injection-scanner.js +207 -0
  358. package/dist/tools/web-fetch.js +195 -10
  359. package/dist/tools/web-search.js +458 -0
  360. package/dist/tui/agent-progress-card.js +111 -0
  361. package/dist/tui/agent-tree.js +11 -1
  362. package/dist/tui/ask-modal.js +14 -14
  363. package/dist/tui/ask-user-question-prompt.js +203 -0
  364. package/dist/tui/compact-banner.js +81 -0
  365. package/dist/tui/conversation-pane.js +85 -11
  366. package/dist/tui/cost-table.js +111 -0
  367. package/dist/tui/device-flow.js +2 -2
  368. package/dist/tui/doctor-table.js +46 -0
  369. package/dist/tui/feedback-prompt.js +156 -0
  370. package/dist/tui/input-box.js +247 -32
  371. package/dist/tui/login-picker.js +3 -3
  372. package/dist/tui/markdown-render.js +6 -6
  373. package/dist/tui/onboarding-wizard.js +240 -0
  374. package/dist/tui/permissions-picker.js +86 -0
  375. package/dist/tui/render.js +35 -0
  376. package/dist/tui/repl-render.js +332 -54
  377. package/dist/tui/repl-splash-art.js +16 -16
  378. package/dist/tui/repl-splash-mascot.js +48 -24
  379. package/dist/tui/repl-splash.js +22 -22
  380. package/dist/tui/repl.js +124 -44
  381. package/dist/tui/slash-palette.js +6 -6
  382. package/dist/tui/splash.js +2 -2
  383. package/dist/tui/status-bar.js +109 -31
  384. package/dist/tui/status-table.js +7 -0
  385. package/dist/tui/stickers-art.js +136 -0
  386. package/dist/tui/style-table.js +28 -0
  387. package/dist/tui/theme-table.js +29 -0
  388. package/dist/tui/thinking-spinner.js +123 -0
  389. package/dist/tui/tool-stream-pane.js +53 -4
  390. package/dist/tui/update-banner.js +27 -2
  391. package/dist/tui/vim-input.js +267 -0
  392. package/dist/tui/welcome-banner.js +107 -0
  393. package/dist/tui/welcome-data.js +293 -0
  394. package/dist/tui/workspace-context.js +2 -2
  395. package/docs/examples/codegraph.mcp.json +10 -0
  396. package/package.json +23 -6
  397. package/test/scenarios/codegen-create-file.scenario.txt +13 -0
  398. package/test/scenarios/compact-force.scenario.txt +11 -0
  399. package/test/scenarios/identity.scenario.txt +11 -0
  400. package/test/scenarios/persona-handoff.scenario.txt +11 -0
  401. package/test/scenarios/walkback.scenario.txt +12 -0
  402. package/dist/core/engine/compaction-hook.js +0 -154
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Dispatch FSM — Sprint α6.9 Phase 1 (agent loop FSM + cancellation).
2
+ * Dispatch FSM — Sprint Phase 1 (agent loop FSM + cancellation).
3
3
  *
4
4
  * Tracks the lifecycle of a single operator-issued brief from the moment
5
5
  * `POST /api/pugi/sessions/:id/brief` fires until the persona returns a
@@ -10,16 +10,16 @@
10
10
  *
11
11
  * State graph:
12
12
  *
13
- * idle
14
- * │ (brief posted)
15
- *
16
- * awaiting_response ←──────────┐
17
- * │ (next turn)
18
- *
19
- * tool_running ────────────────┘
20
- *
21
- *
22
- * completed
13
+ * idle
14
+ * │ (brief posted)
15
+ *
16
+ * awaiting_response ←──────────┐
17
+ * │ (next turn)
18
+ *
19
+ * tool_running ────────────────┘
20
+ *
21
+ *
22
+ * completed
23
23
  *
24
24
  * Terminal states: `completed`, `failed`, `aborted`. The FSM does not
25
25
  * transition out of a terminal state; a fresh brief mints a new FSM
@@ -143,7 +143,7 @@ export class DispatchFSM {
143
143
  }
144
144
  this.firing = true;
145
145
  try {
146
- // R2 P2 fix (Codex triple-review 2026-05-25): if `commit` throws -
146
+ // R2 P2 fix (Codex triple-review): if `commit` throws -
147
147
  // either the first move or any queued nested move - we MUST flush
148
148
  // the pending queue before propagating the error. Otherwise a
149
149
  // later `transition()` call would drain stale entries left over
@@ -1,5 +1,5 @@
1
1
  /**
2
- * FZF-style history search - Sprint α6.14.
2
+ * FZF-style history search - Sprint .
3
3
  *
4
4
  * Powers the Ctrl+R (reverse) / Ctrl+S (forward) interactive search
5
5
  * mode in the REPL input box. Hand-rolled scorer (no dep) tuned for
@@ -8,14 +8,14 @@
8
8
  *
9
9
  * Scoring model (mirrors fzf v2 mid-priorities, simplified):
10
10
  *
11
- * - Substring match required. Non-matching candidates score 0.
12
- * - Prefix match: +50
13
- * - Word-boundary start (' ', '/', '-', '_'): +20
14
- * - Camel boundary (`abcD` → 'D'): +10
15
- * - Contiguous run bonus: +5 per consecutive char after the first
16
- * - Distance penalty: -1 per gap char between query characters
17
- * - Recency bonus: +0.5 × (recencyRank / total) so newer entries
18
- * break ties in the operator's favour
11
+ * - Substring match required. Non-matching candidates score 0.
12
+ * - Prefix match: +50
13
+ * - Word-boundary start (' ', '/', '-', '_'): +20
14
+ * - Camel boundary (`abcD` → 'D'): +10
15
+ * - Contiguous run bonus: +5 per consecutive char after the first
16
+ * - Distance penalty: -1 per gap char between query characters
17
+ * - Recency bonus: +0.5 × (recencyRank / total) so newer entries
18
+ * break ties in the operator's favour
19
19
  *
20
20
  * The result is a list of matches ordered by descending score with
21
21
  * the matched character positions preserved so the UI can highlight
@@ -23,12 +23,12 @@
23
23
  * or backward (Ctrl+S) modulo the result length.
24
24
  *
25
25
  * Contract:
26
- * - `searchHistory(query, entries, options)` is pure. No I/O.
27
- * - Empty query returns ALL entries newest-first so the operator
28
- * can browse without typing.
29
- * - Matching is case-insensitive on ASCII; non-ASCII characters
30
- * compare as-is.
31
- * - `cycle(state, direction)` is a no-op when there are no matches.
26
+ * - `searchHistory(query, entries, options)` is pure. No I/O.
27
+ * - Empty query returns ALL entries newest-first so the operator
28
+ * can browse without typing.
29
+ * - Matching is case-insensitive on ASCII; non-ASCII characters
30
+ * compare as-is.
31
+ * - `cycle(state, direction)` is a no-op when there are no matches.
32
32
  */
33
33
  const DEFAULT_LIMIT = 50;
34
34
  const WORD_BOUNDARIES = new Set([' ', '/', '-', '_', '.', ',', ':', ';', '\t']);
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Persistent REPL history (per-workspace) - Sprint α6.14.
2
+ * Persistent REPL history (per-workspace) - Sprint .
3
3
  *
4
4
  * Stores submitted briefs in `~/.pugi/history/<workspace-slug>.jsonl`,
5
5
  * one JSON object per line. The format is line-delimited JSON so the
@@ -11,26 +11,27 @@
11
11
  *
12
12
  * Contract:
13
13
  *
14
- * - `append({ home, workspaceSlug, brief })` writes one line. Dedups
15
- * a brief that is identical to the immediately preceding entry
16
- * (most common operator pattern: Up + Enter to re-run).
17
- * - `read({ home, workspaceSlug })` returns entries oldest-first so
18
- * the caller can navigate with `index = entries.length - 1` for
19
- * "most recent" semantics.
20
- * - The file is capped at MAX_ENTRIES; on overflow we keep the most
21
- * recent slice and rewrite. Cheap because briefs are short text
22
- * and the cap is 1000.
23
- * - `slugForCwd(cwd)` normalises a working directory into a safe
24
- * filename component (alphanumerics + `-`, lowercase, slashes
25
- * collapsed). Empty cwd resolves to `default`.
26
- * - Failures (missing $HOME, disk full, EACCES) NEVER throw. History
27
- * is operator comfort, not a contract surface; degrading to "no
28
- * history this session" is correct.
14
+ * - `append({ home, workspaceSlug, brief })` writes one line. Dedups
15
+ * a brief that is identical to the immediately preceding entry
16
+ * (most common operator pattern: Up + Enter to re-run).
17
+ * - `read({ home, workspaceSlug })` returns entries oldest-first so
18
+ * the caller can navigate with `index = entries.length - 1` for
19
+ * "most recent" semantics.
20
+ * - The file is capped at MAX_ENTRIES; on overflow we keep the most
21
+ * recent slice and rewrite. Cheap because briefs are short text
22
+ * and the cap is 1000.
23
+ * - `slugForCwd(cwd)` normalises a working directory into a safe
24
+ * filename component (alphanumerics + `-`, lowercase, slashes
25
+ * collapsed). Empty cwd resolves to `default`.
26
+ * - Failures (missing $HOME, disk full, EACCES) NEVER throw. History
27
+ * is operator comfort, not a contract surface; degrading to "no
28
+ * history this session" is correct.
29
29
  *
30
30
  * Brand voice: file is operator-facing if they `cat` it, so the JSON
31
31
  * keys stay readable English (`brief`, `ts`). No forbidden words.
32
32
  */
33
33
  import { existsSync, mkdirSync, readFileSync, writeFileSync, appendFileSync, renameSync, unlinkSync, } from 'node:fs';
34
+ import { randomBytes } from 'node:crypto';
34
35
  import { homedir } from 'node:os';
35
36
  import { dirname, join } from 'node:path';
36
37
  /** Cap on stored entries per workspace. Drops oldest on overflow. */
@@ -74,10 +75,19 @@ export function append(input) {
74
75
  // half-written file or race a parallel appendFileSync into oblivion.
75
76
  // POSIX renameSync is atomic within a directory; on Windows fs.rename
76
77
  // is atomic too as long as both paths are on the same volume (the tmp
77
- // sibling guarantees that). P2 fix from PR #335 triple-review.
78
+ // sibling guarantees that). P2 fix from PR triple-review.
78
79
  if (existing.length + 1 > MAX_HISTORY_ENTRIES) {
79
80
  const trimmed = [...existing.slice(existing.length + 1 - MAX_HISTORY_ENTRIES), entry];
80
- const tmpPath = `${path}.tmp`;
81
+ // β1b #52 : unique-per-call tmp suffix.
82
+ // Previous form was a fixed `${path}.tmp`, which means two CLI
83
+ // processes hitting the overflow rewrite at the same moment race
84
+ // on the same sibling file. Whichever writeFileSync lands second
85
+ // can corrupt the renameSync target's content (one process's
86
+ // serialized buffer overwrites the other mid-flight). Append a
87
+ // pid + monotonic-ish timestamp + 8 hex random bytes so the tmp
88
+ // names are collision-proof across PIDs, concurrent calls inside
89
+ // one PID, and rapid re-runs that share the same ms timestamp.
90
+ const tmpPath = `${path}.${process.pid}.${Date.now()}.${randomBytes(4).toString('hex')}.tmp`;
81
91
  try {
82
92
  writeFileSync(tmpPath, trimmed.map(serialize).join('\n') + '\n', { mode: 0o600 });
83
93
  renameSync(tmpPath, path);
@@ -1,12 +1,12 @@
1
1
  /**
2
- * Kill ring for the REPL input - Sprint α6.14.
2
+ * Kill ring for the REPL input - Sprint .
3
3
  *
4
4
  * Tiny LIFO buffer that backs the readline-style kill commands:
5
5
  *
6
- * Ctrl+U - kill from cursor to line start
7
- * Ctrl+K - kill from cursor to line end
8
- * Ctrl+W - kill word backwards (whitespace + punctuation delimiter)
9
- * Ctrl+Y - yank the most recent kill at the cursor
6
+ * Ctrl+U - kill from cursor to line start
7
+ * Ctrl+K - kill from cursor to line end
8
+ * Ctrl+W - kill word backwards (whitespace + punctuation delimiter)
9
+ * Ctrl+Y - yank the most recent kill at the cursor
10
10
  *
11
11
  * The ring is bounded (MAX_RING_ENTRIES = 10) so the operator's
12
12
  * recent kills are reachable without leaking memory across long
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Static price ladder keyed by exact model slug.
3
+ *
4
+ * Source: provider list-price pages as of. Keep prefix lookup
5
+ * (`priceForModel`) for forward compat — a `claude-opus-4-8` from a future
6
+ * model-router rebind falls back onto the `claude-opus-` family entry.
7
+ */
8
+ const PRICE_LADDER = new Map([
9
+ // Anthropic Claude family
10
+ ['claude-opus-4-7', { inputUsdPerM: 15.0, outputUsdPerM: 75.0 }],
11
+ ['claude-opus-4-6', { inputUsdPerM: 15.0, outputUsdPerM: 75.0 }],
12
+ ['claude-sonnet-4-6', { inputUsdPerM: 3.0, outputUsdPerM: 15.0 }],
13
+ ['claude-sonnet-4-5', { inputUsdPerM: 3.0, outputUsdPerM: 15.0 }],
14
+ ['claude-haiku-4-5', { inputUsdPerM: 0.8, outputUsdPerM: 4.0 }],
15
+ // OpenAI family — sentinel entries so a `pugi config set` override lands clean.
16
+ ['gpt-4o', { inputUsdPerM: 2.5, outputUsdPerM: 10.0 }],
17
+ ['gpt-4o-mini', { inputUsdPerM: 0.15, outputUsdPerM: 0.6 }],
18
+ ['o3', { inputUsdPerM: 10.0, outputUsdPerM: 40.0 }],
19
+ ['o3-mini', { inputUsdPerM: 1.1, outputUsdPerM: 4.4 }],
20
+ // Mistral
21
+ ['mistral-large', { inputUsdPerM: 2.0, outputUsdPerM: 6.0 }],
22
+ ['mistral-small', { inputUsdPerM: 0.2, outputUsdPerM: 0.6 }],
23
+ // Embeddings — input-only; output is zero so the meter shows a
24
+ // flat per-call cost without inflating the "output" column.
25
+ ['voyage-3', { inputUsdPerM: 0.12, outputUsdPerM: 0 }],
26
+ ['voyage-3-large', { inputUsdPerM: 0.18, outputUsdPerM: 0 }],
27
+ ]);
28
+ /**
29
+ * Family-prefix fallback. Used when an unknown slug starts with a
30
+ * known family stem (e.g. `claude-sonnet-4-7`).
31
+ */
32
+ const FAMILY_PREFIX = [
33
+ ['claude-opus-', { inputUsdPerM: 15.0, outputUsdPerM: 75.0 }],
34
+ ['claude-sonnet-', { inputUsdPerM: 3.0, outputUsdPerM: 15.0 }],
35
+ ['claude-haiku-', { inputUsdPerM: 0.8, outputUsdPerM: 4.0 }],
36
+ ['gpt-4o', { inputUsdPerM: 2.5, outputUsdPerM: 10.0 }],
37
+ ['o3', { inputUsdPerM: 10.0, outputUsdPerM: 40.0 }],
38
+ ['mistral-', { inputUsdPerM: 2.0, outputUsdPerM: 6.0 }],
39
+ ['voyage-', { inputUsdPerM: 0.12, outputUsdPerM: 0 }],
40
+ ];
41
+ /**
42
+ * Default ladder when no model slug is known (e.g. the older admin-api
43
+ * still on the pre- event shape that does not carry `model`). Pinned
44
+ * to Sonnet-tier so the meter is "honestly conservative" — close to the
45
+ * default dispatch lane for `reason` + `codegen` tags.
46
+ */
47
+ const DEFAULT_PRICE = { inputUsdPerM: 3.0, outputUsdPerM: 15.0 };
48
+ /**
49
+ * Look up the price for a model slug. Resolution order:
50
+ * 1. Exact match in `PRICE_LADDER`.
51
+ * 2. Family-prefix match (`startsWith`).
52
+ * 3. Default Sonnet-tier rate.
53
+ *
54
+ * Pure — never throws. The cost meter calls this on every `agent.tokens`
55
+ * frame so it must stay branch-cheap.
56
+ */
57
+ export function priceForModel(model) {
58
+ if (!model || typeof model !== 'string')
59
+ return DEFAULT_PRICE;
60
+ const exact = PRICE_LADDER.get(model);
61
+ if (exact)
62
+ return exact;
63
+ for (const [prefix, price] of FAMILY_PREFIX) {
64
+ if (model.startsWith(prefix))
65
+ return price;
66
+ }
67
+ return DEFAULT_PRICE;
68
+ }
69
+ /**
70
+ * Compute the USD cost for a single (input, output, model) triple.
71
+ * Returns a finite number, never NaN/Infinity, capped at zero floor so
72
+ * a buggy upstream that emits negative deltas (theoretically impossible
73
+ * via Anvil but we stay defensive) does not credit the operator's meter.
74
+ *
75
+ * Pure, deterministic, branch-cheap — called on every `agent.tokens`
76
+ * event so the hot path keeps the math inline.
77
+ */
78
+ export function computeCostUsd(tokensIn, tokensOut, model) {
79
+ const price = priceForModel(model);
80
+ const safeIn = Number.isFinite(tokensIn) && tokensIn > 0 ? tokensIn : 0;
81
+ const safeOut = Number.isFinite(tokensOut) && tokensOut > 0 ? tokensOut : 0;
82
+ const usd = (safeIn * price.inputUsdPerM + safeOut * price.outputUsdPerM) / 1_000_000;
83
+ return Number.isFinite(usd) && usd > 0 ? usd : 0;
84
+ }
85
+ /**
86
+ * Format a token count for the status row. Spec (CEO):
87
+ * - `<1000` → raw integer (e.g. `42`)
88
+ * - `≥1000` → one-decimal `k` (e.g. `1.2k`)
89
+ * - `≥1_000_000` → one-decimal `m` (e.g. `1.0m`)
90
+ *
91
+ * Negative / NaN inputs render as `0`.
92
+ */
93
+ export function formatTokens(value) {
94
+ if (!Number.isFinite(value) || value <= 0)
95
+ return '0';
96
+ if (value < 1_000)
97
+ return Math.floor(value).toString();
98
+ if (value < 1_000_000)
99
+ return `${(value / 1_000).toFixed(1)}k`;
100
+ return `${(value / 1_000_000).toFixed(1)}m`;
101
+ }
102
+ /**
103
+ * Format USD cost for the status row. Spec (CEO):
104
+ * - `≥ $0.01` → `$X.XX` (two decimals)
105
+ * - `< $0.01` (but > 0) → `$X.XXX` (three decimals, shows fractions
106
+ * of a cent honestly instead of rounding to `$0.00`)
107
+ * - `0` / NaN → `$0.00`
108
+ */
109
+ export function formatCostUsd(usd) {
110
+ if (!Number.isFinite(usd) || usd <= 0)
111
+ return '$0.00';
112
+ if (usd >= 0.01)
113
+ return `$${usd.toFixed(2)}`;
114
+ return `$${usd.toFixed(3)}`;
115
+ }
116
+ /**
117
+ * Format an elapsed-ms duration as `1m2s` / `45s` / `2h3m`. Used by the
118
+ * status row's session-duration slot. Floors aggressively — we don't
119
+ * want sub-second decimals stealing column width.
120
+ */
121
+ export function formatDuration(elapsedMs) {
122
+ if (!Number.isFinite(elapsedMs) || elapsedMs <= 0)
123
+ return '0s';
124
+ const totalSec = Math.floor(elapsedMs / 1000);
125
+ if (totalSec < 60)
126
+ return `${totalSec}s`;
127
+ const min = Math.floor(totalSec / 60);
128
+ const sec = totalSec % 60;
129
+ if (min < 60)
130
+ return `${min}m${sec.toString().padStart(2, '0')}s`;
131
+ const hr = Math.floor(min / 60);
132
+ const restMin = min % 60;
133
+ return `${hr}h${restMin.toString().padStart(2, '0')}m`;
134
+ }
135
+ //# sourceMappingURL=model-pricing.js.map
@@ -3,15 +3,15 @@
3
3
  *
4
4
  * Two surfaces:
5
5
  *
6
- * 1. `renderPrivacyBanner(mode)` - one-line banner shown on REPL
7
- * bootstrap (mirrors `apps/admin-api/src/privacy/privacy-mode.ts`
8
- * `PRIVACY_MODE_BANNER` verbatim - keep in sync, the unit spec
9
- * asserts they match).
6
+ * 1. `renderPrivacyBanner(mode)` - one-line banner shown on REPL
7
+ * bootstrap (mirrors `apps/admin-api/src/privacy/privacy-mode.ts`
8
+ * `PRIVACY_MODE_BANNER` verbatim - keep in sync, the unit spec
9
+ * asserts they match).
10
10
  *
11
- * 2. `renderPrivacyContractDoc(mode)` - multi-line contract doc the
12
- * `/privacy` slash command prints. Shows the active mode header
13
- * + the full 3-mode contract so the operator can compare their
14
- * current posture to the alternatives without leaving the REPL.
11
+ * 2. `renderPrivacyContractDoc(mode)` - multi-line contract doc the
12
+ * `/privacy` slash command prints. Shows the active mode header
13
+ * + the full 3-mode contract so the operator can compare their
14
+ * current posture to the alternatives without leaving the REPL.
15
15
  *
16
16
  * The strings are pinned client-side so the contract doc is
17
17
  * available even when the operator is offline / has not authenticated
@@ -46,22 +46,22 @@ export function renderPrivacyBanner(mode) {
46
46
  const CONTRACT_DOC = `
47
47
  Pugi privacy mode contract (alpha 6.13):
48
48
 
49
- strict Maximum privacy. Nothing leaves tenant infra.
50
- - Upstream LLM calls REFUSED (use self-hosted Ollama / llama.cpp).
51
- - External tool calls require per-call confirm.
52
- - Session.db, blobs, transcripts stay on operator disk.
53
- - No telemetry. No error reporting.
49
+ strict Maximum privacy. Nothing leaves tenant infra.
50
+ - Upstream LLM calls REFUSED (use self-hosted Ollama / llama.cpp).
51
+ - External tool calls require per-call confirm.
52
+ - Session.db, blobs, transcripts stay on operator disk.
53
+ - No telemetry. No error reporting.
54
54
 
55
- balanced Default. PII-scrubbed content goes to the upstream LLM.
56
- - 3-layer PII scrubber runs before egress (regex + NER + LLM).
57
- - Tool calls to external services allowed (logged).
58
- - Anonymized telemetry only (counts + error categories).
55
+ balanced Default. PII-scrubbed content goes to the upstream LLM.
56
+ - 3-layer PII scrubber runs before egress (regex + NER + LLM).
57
+ - Tool calls to external services allowed (logged).
58
+ - Anonymized telemetry only (counts + error categories).
59
59
 
60
- permissive Verbatim. Power-user mode.
61
- - Raw prompts forwarded to upstream provider (no scrubbing).
62
- - Tool calls to external services allowed.
63
- - Full error reporting (may include prompt fragments).
64
- - Accepts the upstream provider's data retention policy.
60
+ permissive Verbatim. Power-user mode.
61
+ - Raw prompts forwarded to upstream provider (no scrubbing).
62
+ - Tool calls to external services allowed.
63
+ - Full error reporting (may include prompt fragments).
64
+ - Accepts the upstream provider's data retention policy.
65
65
 
66
66
  Switch with: pugi config set privacy=strict|balanced|permissive
67
67
  `.trim();