@pugi/cli 0.1.0-beta.8 → 0.1.0-beta.88

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 (405) hide show
  1. package/CHANGELOG.md +132 -0
  2. package/LICENSE +1 -1
  3. package/THIRD_PARTY_NOTICES.md +40 -0
  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/smoke.js +133 -0
  11. package/dist/core/agent-progress/cleanup.js +134 -0
  12. package/dist/core/agent-progress/schema.js +144 -0
  13. package/dist/core/agent-progress/writer.js +101 -0
  14. package/dist/core/agents/adaptive-router.js +330 -0
  15. package/dist/core/agents/query-decomposer.js +297 -0
  16. package/dist/core/agents/registry.js +3 -3
  17. package/dist/core/approvals/shortcut-resolver.js +98 -0
  18. package/dist/core/artifact-chain/dispatcher.js +148 -0
  19. package/dist/core/artifact-chain/exporter.js +164 -0
  20. package/dist/core/artifact-chain/state.js +243 -0
  21. package/dist/core/artifact-chain/steps.js +169 -0
  22. package/dist/core/ask-user/question.js +92 -0
  23. package/dist/core/audit/audit-trail.js +275 -0
  24. package/dist/core/auth/ensure-authenticated.js +129 -0
  25. package/dist/core/auth/env-provider.js +238 -0
  26. package/dist/core/auto-open-browser.js +4 -4
  27. package/dist/core/auto-update/channels.js +122 -0
  28. package/dist/core/auto-update/checker.js +241 -0
  29. package/dist/core/auto-update/state.js +235 -0
  30. package/dist/core/bare-mode/index.js +107 -0
  31. package/dist/core/bash/redirect.js +281 -0
  32. package/dist/core/bash-classifier.js +436 -40
  33. package/dist/core/checkpoint/resumer.js +149 -0
  34. package/dist/core/checkpoint/rewinder.js +291 -0
  35. package/dist/core/checkpoints/shadow-git.js +670 -0
  36. package/dist/core/citations/parser.js +109 -0
  37. package/dist/core/classifier/yolo-classifier.js +88 -0
  38. package/dist/core/codegraph/decision-store.js +248 -0
  39. package/dist/core/codegraph/detect-repo.js +459 -0
  40. package/dist/core/codegraph/install.js +134 -0
  41. package/dist/core/codegraph/offer-hook.js +220 -0
  42. package/dist/core/compact/auto-trigger.js +96 -0
  43. package/dist/core/compact/buffer-rewriter.js +115 -0
  44. package/dist/core/compact/summarizer.js +208 -0
  45. package/dist/core/compact/token-counter.js +108 -0
  46. package/dist/core/consensus/anvil-fanout.js +25 -25
  47. package/dist/core/consensus/diff-capture.js +121 -12
  48. package/dist/core/consensus/rubric.js +21 -21
  49. package/dist/core/context/builder.js +6 -6
  50. package/dist/core/context/compaction-events.js +8 -8
  51. package/dist/core/context/compaction.js +31 -31
  52. package/dist/core/context/index.js +15 -8
  53. package/dist/core/context/invariants.js +51 -51
  54. package/dist/core/context/markdown-loader.js +28 -10
  55. package/dist/core/context/markdown-traverse.js +255 -0
  56. package/dist/core/context/pugiignore.js +41 -41
  57. package/dist/core/context/repo-skeleton.js +37 -37
  58. package/dist/core/context/tool-eviction.js +55 -0
  59. package/dist/core/context/watcher.js +32 -32
  60. package/dist/core/context/working-set.js +23 -23
  61. package/dist/core/coordinator/agent-tools.js +77 -0
  62. package/dist/core/coordinator/agent-toolset.js +65 -0
  63. package/dist/core/coordinator/fsm.js +73 -0
  64. package/dist/core/coordinator/mode-fsm.js +70 -0
  65. package/dist/core/cost/rate-card.js +129 -0
  66. package/dist/core/cost/tracker.js +221 -0
  67. package/dist/core/credentials.js +12 -12
  68. package/dist/core/cron/scheduler.js +138 -0
  69. package/dist/core/denial-tracking/index.js +8 -0
  70. package/dist/core/denial-tracking/state.js +264 -0
  71. package/dist/core/diagnostics/probe-runner.js +93 -0
  72. package/dist/core/diagnostics/probes/api.js +46 -0
  73. package/dist/core/diagnostics/probes/auth.js +93 -0
  74. package/dist/core/diagnostics/probes/bare-mode.js +42 -0
  75. package/dist/core/diagnostics/probes/cli-version.js +127 -0
  76. package/dist/core/diagnostics/probes/config.js +72 -0
  77. package/dist/core/diagnostics/probes/denial-tracking.js +57 -0
  78. package/dist/core/diagnostics/probes/disk.js +81 -0
  79. package/dist/core/diagnostics/probes/engine-live.js +46 -0
  80. package/dist/core/diagnostics/probes/git.js +65 -0
  81. package/dist/core/diagnostics/probes/hooks.js +118 -0
  82. package/dist/core/diagnostics/probes/mcp.js +75 -0
  83. package/dist/core/diagnostics/probes/node.js +59 -0
  84. package/dist/core/diagnostics/probes/pnpm.js +36 -0
  85. package/dist/core/diagnostics/probes/pugi-md.js +89 -0
  86. package/dist/core/diagnostics/probes/sandbox.js +40 -0
  87. package/dist/core/diagnostics/probes/session.js +74 -0
  88. package/dist/core/diagnostics/probes/status-snapshot.js +488 -0
  89. package/dist/core/diagnostics/probes/workspace.js +63 -0
  90. package/dist/core/diagnostics/types.js +70 -0
  91. package/dist/core/dispatch/cache-cleanup.js +197 -0
  92. package/dist/core/dispatch/cache-handoff.js +295 -0
  93. package/dist/core/edits/apply-patch-layer-e.js +189 -0
  94. package/dist/core/edits/dispatch.js +293 -7
  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 +3 -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 +322 -0
  108. package/dist/core/engine/anvil-client.js +151 -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 +134 -16
  117. package/dist/core/engine/strip-internal-fields.js +124 -0
  118. package/dist/core/engine/tool-bridge.js +1295 -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 +44 -0
  129. package/dist/core/hooks/index.js +15 -0
  130. package/dist/core/hooks/registry.js +213 -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/image/renderer.js +71 -0
  141. package/dist/core/init/detector.js +582 -0
  142. package/dist/core/init/template-renderer.js +242 -0
  143. package/dist/core/jobs/registry.js +18 -18
  144. package/dist/core/ledger/results-tsv.js +142 -0
  145. package/dist/core/log-discipline/stdout-redirect.js +51 -0
  146. package/dist/core/lsp/cache.js +105 -0
  147. package/dist/core/lsp/client.js +776 -0
  148. package/dist/core/lsp/language-detect.js +66 -0
  149. package/dist/core/lsp/post-edit-diagnostics.js +171 -0
  150. package/dist/core/lsp/symbol-tools.js +372 -0
  151. package/dist/core/mcp/client.js +97 -28
  152. package/dist/core/mcp/http-server.js +553 -0
  153. package/dist/core/mcp/orchestrator-tools.js +662 -0
  154. package/dist/core/mcp/permission.js +190 -0
  155. package/dist/core/mcp/registry.js +39 -17
  156. package/dist/core/mcp/server-tools.js +219 -0
  157. package/dist/core/mcp/server.js +397 -0
  158. package/dist/core/mcp/trust.js +10 -10
  159. package/dist/core/memory/dual-write.js +416 -0
  160. package/dist/core/memory/passive-extract.js +130 -0
  161. package/dist/core/memory/phase1-kinds.js +20 -0
  162. package/dist/core/memory/secret-scanner.js +304 -0
  163. package/dist/core/memory-sync/queue.js +170 -0
  164. package/dist/core/metrics/extract.js +113 -0
  165. package/dist/core/modes/roo-modes.js +68 -0
  166. package/dist/core/onboarding/ensure-initialized.js +133 -0
  167. package/dist/core/onboarding/marker.js +111 -0
  168. package/dist/core/onboarding/telemetry-state.js +108 -0
  169. package/dist/core/output-style/presets.js +176 -0
  170. package/dist/core/output-style/state.js +185 -0
  171. package/dist/core/path-security.js +287 -5
  172. package/dist/core/permission.js +82 -22
  173. package/dist/core/permissions/auto-classifier.js +124 -0
  174. package/dist/core/permissions/bash-parser.js +371 -0
  175. package/dist/core/permissions/circuit-breaker.js +83 -0
  176. package/dist/core/permissions/constrained-edit.js +91 -0
  177. package/dist/core/permissions/gate.js +278 -0
  178. package/dist/core/permissions/index.js +20 -0
  179. package/dist/core/permissions/mode.js +174 -0
  180. package/dist/core/permissions/network-egress.js +137 -0
  181. package/dist/core/permissions/state.js +241 -0
  182. package/dist/core/permissions/tool-class.js +93 -0
  183. package/dist/core/plan-mode/ui-state.js +51 -0
  184. package/dist/core/plans/plan-artifact.js +721 -0
  185. package/dist/core/policy-limits/etag-store.js +122 -0
  186. package/dist/core/prd-check/parser.js +215 -0
  187. package/dist/core/prd-check/reporter.js +127 -0
  188. package/dist/core/prd-check/session-review.js +557 -0
  189. package/dist/core/prd-check/verifiers.js +223 -0
  190. package/dist/core/prompt-cache/client-cache.js +99 -0
  191. package/dist/core/prompts/assembly.js +29 -0
  192. package/dist/core/prompts/registry.js +364 -0
  193. package/dist/core/pugi-md/cc-compat-rules.js +735 -0
  194. package/dist/core/pugi-md/context-injector.js +76 -0
  195. package/dist/core/pugi-md/walk-up.js +207 -0
  196. package/dist/core/python/uv-installer.js +270 -0
  197. package/dist/core/python/uv-resolver.js +83 -0
  198. package/dist/core/rate-limit/narrator.js +146 -0
  199. package/dist/core/recipes/cli-types.js +20 -0
  200. package/dist/core/recipes/loader.js +103 -0
  201. package/dist/core/recipes/runner.js +345 -0
  202. package/dist/core/recipes/schema.js +587 -0
  203. package/dist/core/release-notes/parser.js +241 -0
  204. package/dist/core/release-notes/state.js +116 -0
  205. package/dist/core/repl/ask.js +37 -37
  206. package/dist/core/repl/cancellation.js +26 -26
  207. package/dist/core/repl/cap-warning.js +4 -4
  208. package/dist/core/repl/clipboard-read.js +11 -11
  209. package/dist/core/repl/dispatch-fsm.js +12 -12
  210. package/dist/core/repl/history-search.js +15 -15
  211. package/dist/core/repl/history.js +28 -18
  212. package/dist/core/repl/kill-ring.js +5 -5
  213. package/dist/core/repl/model-pricing.js +135 -0
  214. package/dist/core/repl/privacy-banner.js +22 -22
  215. package/dist/core/repl/session.js +2157 -214
  216. package/dist/core/repl/slash-commands.js +533 -40
  217. package/dist/core/repl/store/index.js +1 -1
  218. package/dist/core/repl/store/jsonl-log.js +22 -22
  219. package/dist/core/repl/store/lockfile.js +10 -10
  220. package/dist/core/repl/store/session-store.js +136 -107
  221. package/dist/core/repl/store/types.js +15 -15
  222. package/dist/core/repl/store/uuid-v7.js +12 -12
  223. package/dist/core/repl/workspace-context.js +43 -21
  224. package/dist/core/repo-map/build.js +125 -0
  225. package/dist/core/repo-map/cache.js +185 -0
  226. package/dist/core/repo-map/extractor.js +254 -0
  227. package/dist/core/repo-map/formatter.js +145 -0
  228. package/dist/core/repo-map/page-rank.js +105 -0
  229. package/dist/core/repo-map/scanner.js +211 -0
  230. package/dist/core/retry-budget/budget.js +284 -0
  231. package/dist/core/retry-budget/index.js +5 -0
  232. package/dist/core/retry-budget/retry-cap.js +74 -0
  233. package/dist/core/routing/lead-worker.js +43 -0
  234. package/dist/core/routing/pre-flight-estimator.js +108 -0
  235. package/dist/core/runs/run-tree.js +103 -0
  236. package/dist/core/security/injection-scanner.js +367 -0
  237. package/dist/core/security/output-filter.js +418 -0
  238. package/dist/core/session/env-file.js +105 -0
  239. package/dist/core/session/section-budgets.js +140 -0
  240. package/dist/core/session.js +92 -0
  241. package/dist/core/settings.js +298 -5
  242. package/dist/core/share/formatter.js +271 -0
  243. package/dist/core/share/redactor.js +221 -0
  244. package/dist/core/share/uploader.js +267 -0
  245. package/dist/core/skills/defaults.js +457 -0
  246. package/dist/core/skills/loader.js +22 -22
  247. package/dist/core/skills/sources.js +27 -27
  248. package/dist/core/smoke/headless-driver.js +174 -0
  249. package/dist/core/smoke/orchestrator.js +194 -0
  250. package/dist/core/smoke/runner.js +238 -0
  251. package/dist/core/smoke/scenario-parser.js +316 -0
  252. package/dist/core/statusline.js +99 -0
  253. package/dist/core/subagents/dispatcher-real.js +600 -0
  254. package/dist/core/subagents/dispatcher.js +132 -43
  255. package/dist/core/subagents/index.js +19 -6
  256. package/dist/core/subagents/isolation-matrix.js +213 -0
  257. package/dist/core/subagents/spawn.js +19 -4
  258. package/dist/core/telemetry/emitter.js +229 -0
  259. package/dist/core/telemetry/queue.js +251 -0
  260. package/dist/core/theme/context.js +91 -0
  261. package/dist/core/theme/presets.js +228 -0
  262. package/dist/core/theme/state.js +181 -0
  263. package/dist/core/todos/invariant.js +10 -0
  264. package/dist/core/todos/state.js +177 -0
  265. package/dist/core/tool-schema/compressor.js +89 -0
  266. package/dist/core/transport/version-interceptor.js +166 -0
  267. package/dist/core/trust.js +2 -2
  268. package/dist/core/tui/thinking-block.js +64 -0
  269. package/dist/core/vim/keymap.js +288 -0
  270. package/dist/core/vim/state.js +92 -0
  271. package/dist/core/watch-markers/marker-watcher.js +133 -0
  272. package/dist/core/worktree-manager/cleanup.js +123 -0
  273. package/dist/core/worktree-manager/manager.js +303 -0
  274. package/dist/index.js +36 -0
  275. package/dist/runtime/bootstrap.js +190 -0
  276. package/dist/runtime/cli.js +4203 -493
  277. package/dist/runtime/commands/agents.js +30 -30
  278. package/dist/runtime/commands/budget.js +5 -5
  279. package/dist/runtime/commands/cancel.js +231 -0
  280. package/dist/runtime/commands/chain.js +489 -0
  281. package/dist/runtime/commands/codegraph-status.js +227 -0
  282. package/dist/runtime/commands/compact.js +297 -0
  283. package/dist/runtime/commands/config.js +73 -39
  284. package/dist/runtime/commands/cost.js +199 -0
  285. package/dist/runtime/commands/delegate.js +244 -13
  286. package/dist/runtime/commands/dispatch.js +126 -0
  287. package/dist/runtime/commands/doctor.js +579 -0
  288. package/dist/runtime/commands/feedback.js +184 -0
  289. package/dist/runtime/commands/hooks.js +184 -0
  290. package/dist/runtime/commands/init.js +254 -0
  291. package/dist/runtime/commands/lsp.js +368 -0
  292. package/dist/runtime/commands/mcp.js +879 -0
  293. package/dist/runtime/commands/memory.js +582 -0
  294. package/dist/runtime/commands/model.js +237 -0
  295. package/dist/runtime/commands/onboarding.js +275 -0
  296. package/dist/runtime/commands/patch.js +128 -0
  297. package/dist/runtime/commands/permissions.js +112 -0
  298. package/dist/runtime/commands/plan.js +143 -0
  299. package/dist/runtime/commands/prd-check.js +285 -0
  300. package/dist/runtime/commands/privacy.js +17 -17
  301. package/dist/runtime/commands/recipe.js +325 -0
  302. package/dist/runtime/commands/redo-blob-store.js +92 -0
  303. package/dist/runtime/commands/redo.js +361 -0
  304. package/dist/runtime/commands/release-notes.js +229 -0
  305. package/dist/runtime/commands/repo-map.js +95 -0
  306. package/dist/runtime/commands/report.js +299 -0
  307. package/dist/runtime/commands/resume.js +118 -0
  308. package/dist/runtime/commands/review-consensus.js +68 -53
  309. package/dist/runtime/commands/rewind.js +333 -0
  310. package/dist/runtime/commands/roster.js +14 -14
  311. package/dist/runtime/commands/sessions.js +163 -0
  312. package/dist/runtime/commands/share.js +316 -0
  313. package/dist/runtime/commands/skills.js +31 -31
  314. package/dist/runtime/commands/status.js +186 -0
  315. package/dist/runtime/commands/stickers.js +82 -0
  316. package/dist/runtime/commands/style.js +194 -0
  317. package/dist/runtime/commands/theme.js +196 -0
  318. package/dist/runtime/commands/undo.js +54 -22
  319. package/dist/runtime/commands/update.js +289 -0
  320. package/dist/runtime/commands/vim.js +140 -0
  321. package/dist/runtime/commands/worktree.js +177 -0
  322. package/dist/runtime/commands/worktrees.js +155 -0
  323. package/dist/runtime/headless-repl.js +195 -0
  324. package/dist/runtime/headless.js +543 -0
  325. package/dist/runtime/load-hooks-or-exit.js +71 -0
  326. package/dist/runtime/plan-decompose.js +531 -0
  327. package/dist/runtime/sigint-guard.js +272 -0
  328. package/dist/runtime/update-check.js +28 -28
  329. package/dist/runtime/version.js +65 -0
  330. package/dist/skills/bundled/batch.js +617 -0
  331. package/dist/skills/bundled/index.js +45 -0
  332. package/dist/skills/bundled/loop.js +358 -0
  333. package/dist/skills/bundled/remember.js +383 -0
  334. package/dist/skills/bundled/simplify.js +289 -0
  335. package/dist/skills/bundled/skillify.js +373 -0
  336. package/dist/skills/bundled/stuck.js +558 -0
  337. package/dist/skills/bundled/verify.js +439 -0
  338. package/dist/testing/vcr.js +486 -0
  339. package/dist/tools/agent-tool.js +229 -0
  340. package/dist/tools/apply-patch.js +556 -0
  341. package/dist/tools/ask-user-question.js +288 -0
  342. package/dist/tools/ask-user.js +115 -0
  343. package/dist/tools/bash.js +624 -46
  344. package/dist/tools/brief.js +224 -0
  345. package/dist/tools/enter-worktree.js +250 -0
  346. package/dist/tools/exit-worktree.js +147 -0
  347. package/dist/tools/file-tools.js +161 -44
  348. package/dist/tools/lsp-tools.js +189 -0
  349. package/dist/tools/mcp-tool.js +260 -0
  350. package/dist/tools/multi-edit.js +361 -0
  351. package/dist/tools/powershell.js +268 -0
  352. package/dist/tools/registry.js +85 -0
  353. package/dist/tools/skill-tool.js +96 -0
  354. package/dist/tools/sleep.js +99 -0
  355. package/dist/tools/synthetic-output.js +133 -0
  356. package/dist/tools/tasks.js +208 -0
  357. package/dist/tools/todo-write.js +184 -0
  358. package/dist/tools/verify-plan-execution.js +295 -0
  359. package/dist/tools/web-fetch-injection-scanner.js +207 -0
  360. package/dist/tools/web-fetch.js +195 -10
  361. package/dist/tools/web-search.js +458 -0
  362. package/dist/tui/agent-progress-card.js +111 -0
  363. package/dist/tui/agent-tree.js +11 -1
  364. package/dist/tui/ask-modal.js +14 -14
  365. package/dist/tui/ask-user-question-chips.js +257 -0
  366. package/dist/tui/ask-user-question-prompt.js +203 -0
  367. package/dist/tui/compact-banner.js +81 -0
  368. package/dist/tui/conversation-pane.js +85 -11
  369. package/dist/tui/cost-table.js +111 -0
  370. package/dist/tui/device-flow.js +2 -2
  371. package/dist/tui/doctor-table.js +46 -0
  372. package/dist/tui/feedback-prompt.js +156 -0
  373. package/dist/tui/input-box.js +247 -32
  374. package/dist/tui/login-picker.js +3 -3
  375. package/dist/tui/markdown-render.js +6 -6
  376. package/dist/tui/onboarding-wizard.js +240 -0
  377. package/dist/tui/permissions-picker.js +86 -0
  378. package/dist/tui/render.js +35 -0
  379. package/dist/tui/repl-render.js +332 -54
  380. package/dist/tui/repl-splash-art.js +16 -16
  381. package/dist/tui/repl-splash-mascot.js +48 -24
  382. package/dist/tui/repl-splash.js +22 -22
  383. package/dist/tui/repl.js +124 -44
  384. package/dist/tui/slash-palette.js +6 -6
  385. package/dist/tui/splash.js +2 -2
  386. package/dist/tui/status-bar.js +109 -31
  387. package/dist/tui/status-table.js +7 -0
  388. package/dist/tui/stickers-art.js +136 -0
  389. package/dist/tui/style-table.js +28 -0
  390. package/dist/tui/theme-table.js +29 -0
  391. package/dist/tui/thinking-spinner.js +123 -0
  392. package/dist/tui/tool-stream-pane.js +53 -4
  393. package/dist/tui/update-banner.js +27 -2
  394. package/dist/tui/vim-input.js +267 -0
  395. package/dist/tui/welcome-banner.js +107 -0
  396. package/dist/tui/welcome-data.js +293 -0
  397. package/dist/tui/workspace-context.js +2 -2
  398. package/docs/examples/codegraph.mcp.json +10 -0
  399. package/package.json +25 -7
  400. package/test/scenarios/codegen-create-file.scenario.txt +13 -0
  401. package/test/scenarios/compact-force.scenario.txt +11 -0
  402. package/test/scenarios/identity.scenario.txt +11 -0
  403. package/test/scenarios/persona-handoff.scenario.txt +11 -0
  404. package/test/scenarios/walkback.scenario.txt +12 -0
  405. package/dist/core/engine/compaction-hook.js +0 -154
@@ -8,19 +8,19 @@ import { cleanupTmp, fetchSource } from '../../core/skills/sources.js';
8
8
  import { hashAgentFile, recordTrust, revokeTrust, verifyTrust, } from '../../core/skills/trust.js';
9
9
  const USAGE = [
10
10
  'Usage:',
11
- ' pugi agents list [--global|--workspace] Show installed agents.',
12
- ' pugi agents install <source> [--global|--workspace] [--yes] [--as <slug>]',
13
- ' Fetch + trust-prompt + activate an agent.',
14
- ' pugi agents info <slug> Show metadata + body preview.',
15
- ' pugi agents remove <slug> [--global|--workspace] Delete an installed agent.',
11
+ ' pugi agents list [--global|--workspace] Show installed agents.',
12
+ ' pugi agents install <source> [--global|--workspace] [--yes] [--as <slug>]',
13
+ ' Fetch + trust-prompt + activate an agent.',
14
+ ' pugi agents info <slug> Show metadata + body preview.',
15
+ ' pugi agents remove <slug> [--global|--workspace] Delete an installed agent.',
16
16
  '',
17
17
  'Source forms accepted by `install` (same as `pugi skills install`):',
18
- ' gh:owner/repo/path/to/agent.md[@ref]',
19
- ' https://github.com/...',
20
- ' anthropic:<slug>',
21
- ' npm:<package>',
22
- ' ./path/to/agent.md or /abs/path/to/agent.md',
23
- ' <slug> Catalog lookup (catalog.pugi.dev).',
18
+ ' gh:owner/repo/path/to/agent.md[@ref]',
19
+ ' https://github.com/...',
20
+ ' anthropic:<slug>',
21
+ ' npm:<package>',
22
+ ' ./path/to/agent.md or /abs/path/to/agent.md',
23
+ ' <slug> Catalog lookup (catalog.pugi.dev).',
24
24
  ].join('\n');
25
25
  export async function runAgentsCommand(args, ctx) {
26
26
  const sub = args[0];
@@ -101,8 +101,8 @@ async function runAgentsList(args, ctx) {
101
101
  for (const { agent, trust } of verdicts) {
102
102
  const model = agent.frontmatter.metadata.model ? ` model=${String(agent.frontmatter.metadata.model)}` : '';
103
103
  const trustMark = trust.status === 'trusted' ? '[trusted]' : trust.status === 'unsigned' ? '[unsigned]' : '[mismatch]';
104
- lines.push(` ${agent.slug.padEnd(28)} ${agent.scope.padEnd(10)} ${trustMark.padEnd(11)}${model}`);
105
- lines.push(` ${truncate(agent.frontmatter.description, 80)}`);
104
+ lines.push(` ${agent.slug.padEnd(28)} ${agent.scope.padEnd(10)} ${trustMark.padEnd(11)}${model}`);
105
+ lines.push(` ${truncate(agent.frontmatter.description, 80)}`);
106
106
  }
107
107
  ctx.writeOutput({ command: 'agents.list', agents: verdicts }, lines.join('\n'));
108
108
  }
@@ -243,9 +243,9 @@ async function runAgentsInstall(args, ctx) {
243
243
  source: fetched.sourceUrl,
244
244
  }, [
245
245
  `Installed agent "${slug}" (${scope}).`,
246
- ` Path: ${targetPath}`,
247
- ` Source: ${fetched.sourceUrl}`,
248
- ` sha256: ${sha256}`,
246
+ ` Path: ${targetPath}`,
247
+ ` Source: ${fetched.sourceUrl}`,
248
+ ` sha256: ${sha256}`,
249
249
  ].join('\n'));
250
250
  }
251
251
  async function runAgentsInfo(args, ctx) {
@@ -270,13 +270,13 @@ async function runAgentsInfo(args, ctx) {
270
270
  const preview = agent.body.slice(0, 800);
271
271
  const lines = [
272
272
  `Agent: ${agent.slug}`,
273
- ` Scope: ${agent.scope}`,
274
- ` Path: ${agent.filePath}`,
275
- ` Description: ${agent.frontmatter.description}`,
276
- ` Model: ${String(agent.frontmatter.metadata.model ?? '(default)')}`,
277
- ` Tools: ${(agent.frontmatter.metadata.tools ?? []).join(', ') || '(none)'}`,
278
- ` Trust: ${trust.status}`,
279
- ` sha256: ${actualSha}`,
273
+ ` Scope: ${agent.scope}`,
274
+ ` Path: ${agent.filePath}`,
275
+ ` Description: ${agent.frontmatter.description}`,
276
+ ` Model: ${String(agent.frontmatter.metadata.model ?? '(default)')}`,
277
+ ` Tools: ${(agent.frontmatter.metadata.tools ?? []).join(', ') || '(none)'}`,
278
+ ` Trust: ${trust.status}`,
279
+ ` sha256: ${actualSha}`,
280
280
  '',
281
281
  'Body preview:',
282
282
  preview,
@@ -347,13 +347,13 @@ async function promptTrust(kind, summary, body) {
347
347
  const banner = [
348
348
  '',
349
349
  `About to install ${kind} "${summary.name}"`,
350
- ` Description: ${summary.description}`,
351
- ` Version: ${summary.version ?? '(unset)'}`,
352
- ` Tools: ${summary.tools.join(', ') || '(none)'}`,
353
- ` Files: ${summary.files}`,
354
- ` Source: ${summary.source}`,
355
- ` Target: ${summary.targetDir}`,
356
- ` sha256: ${summary.sha256}`,
350
+ ` Description: ${summary.description}`,
351
+ ` Version: ${summary.version ?? '(unset)'}`,
352
+ ` Tools: ${summary.tools.join(', ') || '(none)'}`,
353
+ ` Files: ${summary.files}`,
354
+ ` Source: ${summary.source}`,
355
+ ` Target: ${summary.targetDir}`,
356
+ ` sha256: ${summary.sha256}`,
357
357
  '',
358
358
  'This payload becomes part of the system prompt and may influence agent decisions.',
359
359
  'Trust this install? [y/N/info] ',
@@ -41,12 +41,12 @@ export async function runBudgetCommand(args, ctx) {
41
41
  `Estimated cost: $${dollars.toFixed(4)} (output-token rate)`,
42
42
  summary.perCommand.length > 0
43
43
  ? `Per command:\n${summary.perCommand
44
- .map((entry) => ` ${entry.command.padEnd(12)} ${entry.tokens} tokens`)
44
+ .map((entry) => ` ${entry.command.padEnd(12)} ${entry.tokens} tokens`)
45
45
  .join('\n')}`
46
46
  : 'Per command: (no entries)',
47
47
  summary.perPersona.length > 0
48
48
  ? `Per persona:\n${summary.perPersona
49
- .map((entry) => ` ${entry.persona.padEnd(20)} ${entry.tokens} tokens`)
49
+ .map((entry) => ` ${entry.persona.padEnd(20)} ${entry.tokens} tokens`)
50
50
  .join('\n')}`
51
51
  : 'Per persona: (no entries)',
52
52
  ].join('\n');
@@ -104,9 +104,9 @@ function matchesWindow(event, cutoffMs) {
104
104
  /**
105
105
  * Extract a token count from any event shape we know about.
106
106
  *
107
- * - `tool_result.tokensUsed` — engine adapter emits this.
108
- * - `subagent.completed.tokensUsed` — α5.4 subagent runner.
109
- * - `engine.turn.tokensIn/tokensOut` — Anvil F1 metric mirror, future.
107
+ * - `tool_result.tokensUsed` — engine adapter emits this.
108
+ * - `subagent.completed.tokensUsed` — subagent runner.
109
+ * - `engine.turn.tokensIn/tokensOut` — Anvil F1 metric mirror, future.
110
110
  *
111
111
  * Unknown events return 0 so adding new event types upstream never
112
112
  * breaks `pugi budget`.
@@ -0,0 +1,231 @@
1
+ /**
2
+ * `pugi /cancel` slash command — small-CC-parity batch .
3
+ *
4
+ * Bridges the gap between `/jobs` (read-only list of in-flight agents)
5
+ * and `/stop <persona>` (kill-by-persona via admin-api). Cancel is
6
+ * dispatch-id-keyed — operators read `.pugi/agent-progress/*.json` for
7
+ * the active list, then run `/cancel <id>` (or `/cancel all`) to halt.
8
+ *
9
+ * Behaviour matrix:
10
+ *
11
+ * /cancel → table of active dispatches (id · persona
12
+ * · started-at · elapsed · status)
13
+ * /cancel <id> → mark the progress JSON as failed (closest
14
+ * valid schema status to "cancelled" — the
15
+ * schema's closed status set is running/
16
+ * completed/failed) + best-effort POST to
17
+ * the future `/api/pugi/dispatches/:id/cancel`
18
+ * endpoint. If the endpoint 404s we still
19
+ * update the local JSON so /jobs reflects
20
+ * the operator's intent.
21
+ * /cancel all → loop over every running entry
22
+ *
23
+ * # Module contract
24
+ *
25
+ * - Single entry point: `runCancelCommand(args, io, opts)`. The slash
26
+ * dispatcher in `core/repl/session.ts` calls this with the parsed
27
+ * verdict; a future `pugi cancel` shell surface would call it with
28
+ * the same shape. Exit code semantics mirror `/feedback` — cancel
29
+ * never returns non-zero from inside the REPL because the slash
30
+ * surface ignores it; the shell wrapper can branch on the returned
31
+ * result variant.
32
+ *
33
+ * - No real network I/O is required for the unit test path. The
34
+ * `fetcher` seam accepts a stub that resolves to `{ ok: false,
35
+ * status: 404 }` so the spec exercises the local-fallback branch
36
+ * deterministically.
37
+ *
38
+ * - Filesystem reads are best-effort. A missing progress dir / a
39
+ * malformed JSON file simply degrades to "no active dispatches"
40
+ * rather than throwing — the cancel command is a brand surface,
41
+ * never a gate.
42
+ *
43
+ * - followup: a dedicated `/api/pugi/dispatches/:id/cancel`
44
+ * endpoint on admin-api ships in a sibling PR. Until then, the
45
+ * local progress JSON write is the source of truth so `/jobs`
46
+ * and the live `pugi jobs --watch` TUI both reflect the operator
47
+ * verdict instantly.
48
+ */
49
+ import { existsSync, readFileSync, readdirSync, renameSync, writeFileSync } from 'node:fs';
50
+ import { join } from 'node:path';
51
+ import { resolveProgressDir, } from '../../core/agent-progress/writer.js';
52
+ import { validateAgentProgress, } from '../../core/agent-progress/schema.js';
53
+ /**
54
+ * Read every progress file under `dir` and return the running ones.
55
+ * Malformed entries are silently skipped — operator sees a smaller list
56
+ * rather than a crash banner.
57
+ */
58
+ export function readActiveDispatches(dir) {
59
+ if (!existsSync(dir))
60
+ return [];
61
+ const out = [];
62
+ const files = readdirSync(dir).filter((f) => f.endsWith('.json'));
63
+ for (const file of files) {
64
+ try {
65
+ const body = readFileSync(join(dir, file), 'utf8');
66
+ const parsed = JSON.parse(body);
67
+ const verdict = validateAgentProgress(parsed);
68
+ if (verdict.ok && verdict.value.status === 'running') {
69
+ out.push(verdict.value);
70
+ }
71
+ }
72
+ catch {
73
+ // Skip malformed files; the watcher / writer is the source of
74
+ // truth, not the snapshot — a partial read on a half-written
75
+ // tmp file would otherwise crash the cancel surface.
76
+ }
77
+ }
78
+ // Newest-first so the operator's eye lands on the freshest agent.
79
+ return out.sort((a, b) => Date.parse(b.lastUpdate) - Date.parse(a.lastUpdate));
80
+ }
81
+ /**
82
+ * Atomic update: rewrite the progress JSON as `status='failed'`
83
+ * (closest valid status to "cancelled" in the closed schema set) with
84
+ * a marker step description so `/jobs` and the live TUI both display
85
+ * the cancellation. Returns the path on success; bubbles I/O errors.
86
+ *
87
+ * The write uses the same `<file>.tmp-<pid>-<seq>` → rename pattern as
88
+ * the writer module so a chokidar watcher never reads a half-written
89
+ * document. We do NOT import the writer's `writeProgress` because that
90
+ * helper validates and re-clamps every field, which would also reset
91
+ * fields the operator may want to inspect post-cancel (elapsedMs,
92
+ * percentComplete). Cancel preserves the snapshot and only swaps the
93
+ * status + stepDescription + lastUpdate.
94
+ */
95
+ let writeSequence = 0;
96
+ export function markCancelled(dir, agentId, nowIso) {
97
+ const path = join(dir, `${agentId}.json`);
98
+ const body = readFileSync(path, 'utf8');
99
+ const parsed = JSON.parse(body);
100
+ parsed.status = 'failed';
101
+ parsed.stepDescription = '(cancelled by /cancel)';
102
+ parsed.lastUpdate = nowIso;
103
+ writeSequence += 1;
104
+ const tmp = `${path}.tmp-${process.pid}-${writeSequence}`;
105
+ writeFileSync(tmp, `${JSON.stringify(parsed, null, 2)}\n`, 'utf8');
106
+ renameSync(tmp, path);
107
+ return path;
108
+ }
109
+ /**
110
+ * Render a single-line cancel snapshot row. Pure helper so the spec
111
+ * can pin the exact shape without standing up an Ink renderer.
112
+ */
113
+ export function renderCancelRow(entry, nowEpochMs) {
114
+ const id = entry.agentId.length > 24
115
+ ? `${entry.agentId.slice(0, 23)}…`
116
+ : entry.agentId;
117
+ const persona = entry.agentType.length > 18
118
+ ? `${entry.agentType.slice(0, 17)}…`
119
+ : entry.agentType;
120
+ const startedMs = Date.parse(entry.startedAt);
121
+ const elapsedSec = Number.isFinite(startedMs)
122
+ ? Math.max(0, Math.floor((nowEpochMs - startedMs) / 1000))
123
+ : Math.max(0, Math.floor(entry.elapsedMs / 1000));
124
+ const elapsed = elapsedSec >= 60
125
+ ? `${Math.floor(elapsedSec / 60)}m${String(elapsedSec % 60).padStart(2, '0')}s`
126
+ : `${elapsedSec}s`;
127
+ return ` ${id.padEnd(24, ' ')} ${persona.padEnd(18, ' ')} ${elapsed.padStart(6, ' ')} ${entry.status}`;
128
+ }
129
+ /**
130
+ * Main entry point. The slash dispatcher passes a tokenised
131
+ * `CancelMode`; the function returns a structured outcome so the
132
+ * caller can keep / drop the verdict line without re-parsing the I/O
133
+ * sink.
134
+ */
135
+ export async function runCancelCommand(mode, io, opts = {}) {
136
+ const dir = opts.dir ?? resolveProgressDir();
137
+ const now = opts.now ?? Date.now;
138
+ const nowIso = new Date(now()).toISOString();
139
+ let active;
140
+ try {
141
+ active = readActiveDispatches(dir);
142
+ }
143
+ catch (err) {
144
+ const message = err instanceof Error ? err.message : String(err);
145
+ io.write(`/cancel failed reading progress dir: ${message}`);
146
+ return { kind: 'error', message };
147
+ }
148
+ if (mode.kind === 'list') {
149
+ if (active.length === 0) {
150
+ io.write('No active dispatches. Brief one with /brief <text>.');
151
+ return { kind: 'listed', count: 0 };
152
+ }
153
+ io.write(`Active dispatches (${active.length}):`);
154
+ io.write(' dispatch-id persona elapsed status');
155
+ for (const entry of active) {
156
+ io.write(renderCancelRow(entry, now()));
157
+ }
158
+ io.write('Tip: /cancel <dispatch-id> to halt one, /cancel all к halt every running.');
159
+ return { kind: 'listed', count: active.length };
160
+ }
161
+ if (mode.kind === 'all') {
162
+ if (active.length === 0) {
163
+ io.write('Nothing к cancel — no active dispatches.');
164
+ return { kind: 'empty' };
165
+ }
166
+ const cancelled = [];
167
+ let endpointHit = false;
168
+ for (const entry of active) {
169
+ try {
170
+ if (opts.fetcher) {
171
+ const verdict = await opts.fetcher(entry.agentId);
172
+ if (verdict.ok)
173
+ endpointHit = true;
174
+ }
175
+ markCancelled(dir, entry.agentId, nowIso);
176
+ cancelled.push(entry.agentId);
177
+ io.write(`Cancelled ${entry.agentId}`);
178
+ }
179
+ catch (err) {
180
+ const message = err instanceof Error ? err.message : String(err);
181
+ io.write(` could not cancel ${entry.agentId}: ${message}`);
182
+ }
183
+ }
184
+ io.write(`Cancelled ${cancelled.length} of ${active.length} dispatch(es).`);
185
+ return { kind: 'cancelled', count: cancelled.length, ids: cancelled, endpointHit };
186
+ }
187
+ // kind === 'one'
188
+ const target = active.find((a) => a.agentId === mode.dispatchId);
189
+ if (!target) {
190
+ // Try prefix match — operators often type the first 8 chars.
191
+ const prefix = mode.dispatchId.toLowerCase();
192
+ const prefixMatch = active.find((a) => a.agentId.toLowerCase().startsWith(prefix));
193
+ if (!prefixMatch) {
194
+ io.write(`No active dispatch matching '${mode.dispatchId}'. Run /cancel to see the list.`);
195
+ return { kind: 'not-found', query: mode.dispatchId };
196
+ }
197
+ return cancelOne(prefixMatch, dir, nowIso, io, opts);
198
+ }
199
+ return cancelOne(target, dir, nowIso, io, opts);
200
+ }
201
+ async function cancelOne(entry, dir, nowIso, io, opts) {
202
+ let endpointHit = false;
203
+ if (opts.fetcher) {
204
+ try {
205
+ const verdict = await opts.fetcher(entry.agentId);
206
+ endpointHit = verdict.ok;
207
+ }
208
+ catch {
209
+ // network fail → fall through to local-only cancel
210
+ }
211
+ }
212
+ try {
213
+ markCancelled(dir, entry.agentId, nowIso);
214
+ io.write(`Cancelled dispatch ${entry.agentId}.`);
215
+ if (!endpointHit && opts.fetcher) {
216
+ io.write(' (backend cancel endpoint not reachable; progress JSON marked locally)');
217
+ }
218
+ return {
219
+ kind: 'cancelled',
220
+ count: 1,
221
+ ids: [entry.agentId],
222
+ endpointHit,
223
+ };
224
+ }
225
+ catch (err) {
226
+ const message = err instanceof Error ? err.message : String(err);
227
+ io.write(`/cancel ${entry.agentId} failed: ${message}`);
228
+ return { kind: 'error', message };
229
+ }
230
+ }
231
+ //# sourceMappingURL=cancel.js.map