@pugi/cli 0.1.0-beta.99 → 1.0.0-alpha.10

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 (448) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +11 -191
  3. package/bin/pugi +8 -0
  4. package/package.json +15 -71
  5. package/postinstall.mjs +31 -0
  6. package/CHANGELOG.md +0 -132
  7. package/THIRD_PARTY_NOTICES.md +0 -40
  8. package/assets/pugi-mascot.ansi +0 -16
  9. package/assets/pugi-prozr2-mascot.ansi +0 -9
  10. package/bin/run.js +0 -34
  11. package/dist/commands/deploy.js +0 -439
  12. package/dist/commands/flatten.js +0 -191
  13. package/dist/commands/jobs-watch.js +0 -201
  14. package/dist/commands/jobs.js +0 -260
  15. package/dist/commands/retro.js +0 -210
  16. package/dist/commands/smoke.js +0 -133
  17. package/dist/core/agent-progress/cleanup.js +0 -134
  18. package/dist/core/agent-progress/schema.js +0 -144
  19. package/dist/core/agent-progress/writer.js +0 -101
  20. package/dist/core/agents/adaptive-router.js +0 -330
  21. package/dist/core/agents/loader.js +0 -104
  22. package/dist/core/agents/query-decomposer.js +0 -297
  23. package/dist/core/agents/registry.js +0 -69
  24. package/dist/core/approvals/shortcut-resolver.js +0 -98
  25. package/dist/core/artifact-chain/dispatcher.js +0 -148
  26. package/dist/core/artifact-chain/exporter.js +0 -164
  27. package/dist/core/artifact-chain/state.js +0 -243
  28. package/dist/core/artifact-chain/steps.js +0 -169
  29. package/dist/core/ask-user/question.js +0 -92
  30. package/dist/core/audit/audit-trail.js +0 -275
  31. package/dist/core/auth/ensure-authenticated.js +0 -129
  32. package/dist/core/auth/env-provider.js +0 -238
  33. package/dist/core/auto-open-browser.js +0 -128
  34. package/dist/core/auto-update/channels.js +0 -122
  35. package/dist/core/auto-update/checker.js +0 -241
  36. package/dist/core/auto-update/state.js +0 -235
  37. package/dist/core/bare-mode/index.js +0 -107
  38. package/dist/core/bash/redirect.js +0 -281
  39. package/dist/core/bash-classifier.js +0 -1397
  40. package/dist/core/checkpoint/resumer.js +0 -149
  41. package/dist/core/checkpoint/rewinder.js +0 -291
  42. package/dist/core/checkpoints/shadow-git.js +0 -670
  43. package/dist/core/citations/parser.js +0 -109
  44. package/dist/core/classifier/yolo-classifier.js +0 -88
  45. package/dist/core/clipboard.js +0 -70
  46. package/dist/core/codegraph/decision-store.js +0 -248
  47. package/dist/core/codegraph/detect-repo.js +0 -459
  48. package/dist/core/codegraph/install.js +0 -134
  49. package/dist/core/codegraph/offer-hook.js +0 -220
  50. package/dist/core/compact/auto-trigger.js +0 -96
  51. package/dist/core/compact/buffer-rewriter.js +0 -115
  52. package/dist/core/compact/summarizer.js +0 -208
  53. package/dist/core/compact/token-counter.js +0 -108
  54. package/dist/core/consensus/anvil-fanout.js +0 -276
  55. package/dist/core/consensus/diff-capture.js +0 -491
  56. package/dist/core/consensus/rubric.js +0 -233
  57. package/dist/core/context/builder.js +0 -114
  58. package/dist/core/context/compaction-events.js +0 -99
  59. package/dist/core/context/compaction.js +0 -602
  60. package/dist/core/context/index.js +0 -28
  61. package/dist/core/context/invariants.js +0 -250
  62. package/dist/core/context/markdown-loader.js +0 -288
  63. package/dist/core/context/markdown-traverse.js +0 -255
  64. package/dist/core/context/pugiignore.js +0 -316
  65. package/dist/core/context/repo-skeleton.js +0 -533
  66. package/dist/core/context/tool-eviction.js +0 -55
  67. package/dist/core/context/watcher.js +0 -342
  68. package/dist/core/context/working-set.js +0 -165
  69. package/dist/core/coordinator/agent-tools.js +0 -77
  70. package/dist/core/coordinator/agent-toolset.js +0 -65
  71. package/dist/core/coordinator/fsm.js +0 -73
  72. package/dist/core/coordinator/mode-fsm.js +0 -70
  73. package/dist/core/cost/rate-card.js +0 -129
  74. package/dist/core/cost/tracker.js +0 -221
  75. package/dist/core/credentials.js +0 -355
  76. package/dist/core/cron/scheduler.js +0 -138
  77. package/dist/core/denial-tracking/index.js +0 -8
  78. package/dist/core/denial-tracking/state.js +0 -264
  79. package/dist/core/diagnostics/probe-runner.js +0 -93
  80. package/dist/core/diagnostics/probes/api.js +0 -46
  81. package/dist/core/diagnostics/probes/auth.js +0 -93
  82. package/dist/core/diagnostics/probes/bare-mode.js +0 -42
  83. package/dist/core/diagnostics/probes/cli-version.js +0 -127
  84. package/dist/core/diagnostics/probes/config.js +0 -72
  85. package/dist/core/diagnostics/probes/denial-tracking.js +0 -57
  86. package/dist/core/diagnostics/probes/disk.js +0 -81
  87. package/dist/core/diagnostics/probes/engine-live.js +0 -46
  88. package/dist/core/diagnostics/probes/git.js +0 -65
  89. package/dist/core/diagnostics/probes/hooks.js +0 -118
  90. package/dist/core/diagnostics/probes/mcp.js +0 -75
  91. package/dist/core/diagnostics/probes/node.js +0 -59
  92. package/dist/core/diagnostics/probes/pnpm.js +0 -36
  93. package/dist/core/diagnostics/probes/pugi-md.js +0 -89
  94. package/dist/core/diagnostics/probes/sandbox.js +0 -72
  95. package/dist/core/diagnostics/probes/session.js +0 -74
  96. package/dist/core/diagnostics/probes/status-snapshot.js +0 -488
  97. package/dist/core/diagnostics/probes/workspace.js +0 -63
  98. package/dist/core/diagnostics/types.js +0 -70
  99. package/dist/core/dispatch/cache-cleanup.js +0 -197
  100. package/dist/core/dispatch/cache-handoff.js +0 -295
  101. package/dist/core/edits/apply-patch-layer-e.js +0 -189
  102. package/dist/core/edits/dispatch.js +0 -511
  103. package/dist/core/edits/format-detector.js +0 -260
  104. package/dist/core/edits/format-matrix.js +0 -26
  105. package/dist/core/edits/fuzzy-ladder.js +0 -650
  106. package/dist/core/edits/index.js +0 -19
  107. package/dist/core/edits/journal.js +0 -199
  108. package/dist/core/edits/layer-a-apply.js +0 -217
  109. package/dist/core/edits/layer-a-fuzzy-apply.js +0 -198
  110. package/dist/core/edits/layer-b-apply.js +0 -211
  111. package/dist/core/edits/layer-c-apply.js +0 -160
  112. package/dist/core/edits/layer-d-ast.js +0 -572
  113. package/dist/core/edits/marker-parser.js +0 -401
  114. package/dist/core/edits/security-gate.js +0 -223
  115. package/dist/core/edits/verify-hook.js +0 -273
  116. package/dist/core/edits/worktree.js +0 -322
  117. package/dist/core/engine/adapter-runner.js +0 -8
  118. package/dist/core/engine/anvil-client.js +0 -344
  119. package/dist/core/engine/auto-compact.js +0 -179
  120. package/dist/core/engine/budgets.js +0 -195
  121. package/dist/core/engine/context-prefix.js +0 -155
  122. package/dist/core/engine/index.js +0 -12
  123. package/dist/core/engine/intensity.js +0 -163
  124. package/dist/core/engine/intent.js +0 -260
  125. package/dist/core/engine/native-pugi.js +0 -1616
  126. package/dist/core/engine/noop.js +0 -27
  127. package/dist/core/engine/prompts.js +0 -236
  128. package/dist/core/engine/strip-internal-fields.js +0 -124
  129. package/dist/core/engine/tool-bridge.js +0 -2173
  130. package/dist/core/engine/verification-patterns.js +0 -195
  131. package/dist/core/evaluation/golden-dataset.js +0 -293
  132. package/dist/core/feedback/queue.js +0 -177
  133. package/dist/core/feedback/submitter.js +0 -145
  134. package/dist/core/file-cache.js +0 -141
  135. package/dist/core/flatten/flatten-repo.js +0 -439
  136. package/dist/core/format/osc8-link.js +0 -28
  137. package/dist/core/hook-chains.js +0 -392
  138. package/dist/core/hooks/citation-verify-hook.js +0 -138
  139. package/dist/core/hooks/citation-verify.js +0 -112
  140. package/dist/core/hooks/events.js +0 -46
  141. package/dist/core/hooks/index.js +0 -15
  142. package/dist/core/hooks/registry.js +0 -216
  143. package/dist/core/hooks/runner.js +0 -236
  144. package/dist/core/hooks/v2/event-emitter.js +0 -115
  145. package/dist/core/hooks/v2/executor.js +0 -282
  146. package/dist/core/hooks/v2/index.js +0 -25
  147. package/dist/core/hooks/v2/lifecycle.js +0 -104
  148. package/dist/core/hooks/v2/loader.js +0 -216
  149. package/dist/core/hooks/v2/matcher.js +0 -125
  150. package/dist/core/hooks/v2/trust.js +0 -143
  151. package/dist/core/hooks/v2/types.js +0 -86
  152. package/dist/core/hooks/worktree-events.js +0 -158
  153. package/dist/core/hooks.js +0 -415
  154. package/dist/core/image/renderer.js +0 -71
  155. package/dist/core/index-store.js +0 -260
  156. package/dist/core/init/detector.js +0 -582
  157. package/dist/core/init/template-renderer.js +0 -242
  158. package/dist/core/jobs/registry.js +0 -462
  159. package/dist/core/ledger/results-tsv.js +0 -142
  160. package/dist/core/log-discipline/stdout-redirect.js +0 -51
  161. package/dist/core/lsp/cache.js +0 -105
  162. package/dist/core/lsp/client.js +0 -1229
  163. package/dist/core/lsp/language-detect.js +0 -66
  164. package/dist/core/lsp/post-edit-diagnostics.js +0 -171
  165. package/dist/core/lsp/server-detect.js +0 -173
  166. package/dist/core/lsp/symbol-cache.js +0 -162
  167. package/dist/core/lsp/symbol-tools.js +0 -664
  168. package/dist/core/mcp/client.js +0 -385
  169. package/dist/core/mcp/http-server.js +0 -553
  170. package/dist/core/mcp/orchestrator-config.js +0 -192
  171. package/dist/core/mcp/orchestrator-tools.js +0 -806
  172. package/dist/core/mcp/permission.js +0 -190
  173. package/dist/core/mcp/registry.js +0 -193
  174. package/dist/core/mcp/server-tools.js +0 -219
  175. package/dist/core/mcp/server.js +0 -397
  176. package/dist/core/mcp/trust.js +0 -91
  177. package/dist/core/memory/dual-write.js +0 -416
  178. package/dist/core/memory/passive-extract.js +0 -130
  179. package/dist/core/memory/phase1-kinds.js +0 -20
  180. package/dist/core/memory/secret-scanner.js +0 -304
  181. package/dist/core/memory-sync/queue.js +0 -170
  182. package/dist/core/metrics/extract.js +0 -113
  183. package/dist/core/modes/roo-modes.js +0 -68
  184. package/dist/core/onboarding/ensure-initialized.js +0 -133
  185. package/dist/core/onboarding/marker.js +0 -111
  186. package/dist/core/onboarding/telemetry-state.js +0 -108
  187. package/dist/core/output-style/presets.js +0 -176
  188. package/dist/core/output-style/state.js +0 -185
  189. package/dist/core/path-security.js +0 -345
  190. package/dist/core/permission.js +0 -369
  191. package/dist/core/permissions/auto-classifier.js +0 -124
  192. package/dist/core/permissions/bash-parser.js +0 -371
  193. package/dist/core/permissions/circuit-breaker.js +0 -83
  194. package/dist/core/permissions/constrained-edit.js +0 -91
  195. package/dist/core/permissions/gate.js +0 -278
  196. package/dist/core/permissions/index.js +0 -20
  197. package/dist/core/permissions/mode.js +0 -174
  198. package/dist/core/permissions/network-egress.js +0 -137
  199. package/dist/core/permissions/state.js +0 -241
  200. package/dist/core/permissions/tool-class.js +0 -107
  201. package/dist/core/plan-mode/ui-state.js +0 -51
  202. package/dist/core/plans/plan-artifact.js +0 -721
  203. package/dist/core/policy-limits/etag-store.js +0 -122
  204. package/dist/core/prd-check/parser.js +0 -215
  205. package/dist/core/prd-check/reporter.js +0 -127
  206. package/dist/core/prd-check/session-review.js +0 -557
  207. package/dist/core/prd-check/verifiers.js +0 -223
  208. package/dist/core/prompt-cache/client-cache.js +0 -99
  209. package/dist/core/prompts/assembly.js +0 -29
  210. package/dist/core/prompts/registry.js +0 -364
  211. package/dist/core/pugi-gitignore.js +0 -52
  212. package/dist/core/pugi-md/cc-compat-rules.js +0 -735
  213. package/dist/core/pugi-md/context-injector.js +0 -76
  214. package/dist/core/pugi-md/walk-up.js +0 -207
  215. package/dist/core/python/uv-installer.js +0 -270
  216. package/dist/core/python/uv-resolver.js +0 -83
  217. package/dist/core/rate-limit/narrator.js +0 -146
  218. package/dist/core/recipes/cli-types.js +0 -20
  219. package/dist/core/recipes/loader.js +0 -103
  220. package/dist/core/recipes/runner.js +0 -345
  221. package/dist/core/recipes/schema.js +0 -587
  222. package/dist/core/release-notes/parser.js +0 -241
  223. package/dist/core/release-notes/state.js +0 -116
  224. package/dist/core/repl/ask.js +0 -512
  225. package/dist/core/repl/cancellation.js +0 -98
  226. package/dist/core/repl/cap-warning.js +0 -91
  227. package/dist/core/repl/clipboard-read.js +0 -174
  228. package/dist/core/repl/dispatch-fsm.js +0 -220
  229. package/dist/core/repl/engine-bridge.js +0 -303
  230. package/dist/core/repl/history-search.js +0 -175
  231. package/dist/core/repl/history.js +0 -182
  232. package/dist/core/repl/kill-ring.js +0 -138
  233. package/dist/core/repl/model-pricing.js +0 -135
  234. package/dist/core/repl/privacy-banner.js +0 -71
  235. package/dist/core/repl/session.js +0 -4962
  236. package/dist/core/repl/slash-commands.js +0 -747
  237. package/dist/core/repl/store/index.js +0 -12
  238. package/dist/core/repl/store/jsonl-log.js +0 -321
  239. package/dist/core/repl/store/lockfile.js +0 -155
  240. package/dist/core/repl/store/session-store.js +0 -821
  241. package/dist/core/repl/store/types.js +0 -44
  242. package/dist/core/repl/store/uuid-v7.js +0 -68
  243. package/dist/core/repl/tool-route.js +0 -382
  244. package/dist/core/repl/workspace-context.js +0 -206
  245. package/dist/core/repo-map/build.js +0 -125
  246. package/dist/core/repo-map/cache.js +0 -185
  247. package/dist/core/repo-map/extractor.js +0 -254
  248. package/dist/core/repo-map/formatter.js +0 -145
  249. package/dist/core/repo-map/page-rank.js +0 -105
  250. package/dist/core/repo-map/scanner.js +0 -211
  251. package/dist/core/retro/git-collector.js +0 -251
  252. package/dist/core/retro/health-card.js +0 -25
  253. package/dist/core/retro/metrics.js +0 -342
  254. package/dist/core/retro/narrative.js +0 -249
  255. package/dist/core/retro/plane-collector.js +0 -274
  256. package/dist/core/retro/pr-issue-link.js +0 -65
  257. package/dist/core/retro/types.js +0 -16
  258. package/dist/core/retry-budget/budget.js +0 -284
  259. package/dist/core/retry-budget/index.js +0 -5
  260. package/dist/core/retry-budget/retry-cap.js +0 -74
  261. package/dist/core/routing/lead-worker.js +0 -43
  262. package/dist/core/routing/pre-flight-estimator.js +0 -108
  263. package/dist/core/runs/run-tree.js +0 -103
  264. package/dist/core/sandboxing/adapter.js +0 -29
  265. package/dist/core/sandboxing/index.js +0 -49
  266. package/dist/core/sandboxing/none.js +0 -19
  267. package/dist/core/sandboxing/seatbelt.js +0 -183
  268. package/dist/core/security/injection-scanner.js +0 -367
  269. package/dist/core/security/output-filter.js +0 -418
  270. package/dist/core/session/env-file.js +0 -105
  271. package/dist/core/session/section-budgets.js +0 -140
  272. package/dist/core/session.js +0 -377
  273. package/dist/core/settings.js +0 -400
  274. package/dist/core/share/formatter.js +0 -271
  275. package/dist/core/share/redactor.js +0 -221
  276. package/dist/core/share/uploader.js +0 -267
  277. package/dist/core/skills/defaults.js +0 -457
  278. package/dist/core/skills/loader.js +0 -454
  279. package/dist/core/skills/sources.js +0 -480
  280. package/dist/core/skills/trust.js +0 -172
  281. package/dist/core/smoke/headless-driver.js +0 -174
  282. package/dist/core/smoke/orchestrator.js +0 -194
  283. package/dist/core/smoke/runner.js +0 -238
  284. package/dist/core/smoke/scenario-parser.js +0 -316
  285. package/dist/core/statusline.js +0 -99
  286. package/dist/core/subagents/dispatcher-real.js +0 -600
  287. package/dist/core/subagents/dispatcher.js +0 -352
  288. package/dist/core/subagents/index.js +0 -39
  289. package/dist/core/subagents/isolation-matrix.js +0 -213
  290. package/dist/core/subagents/spawn.js +0 -101
  291. package/dist/core/telemetry/emitter.js +0 -229
  292. package/dist/core/telemetry/queue.js +0 -251
  293. package/dist/core/theme/context.js +0 -91
  294. package/dist/core/theme/presets.js +0 -228
  295. package/dist/core/theme/state.js +0 -181
  296. package/dist/core/todos/invariant.js +0 -10
  297. package/dist/core/todos/state.js +0 -177
  298. package/dist/core/tool-schema/compressor.js +0 -89
  299. package/dist/core/transport/version-interceptor.js +0 -166
  300. package/dist/core/trust.js +0 -109
  301. package/dist/core/tui/thinking-block.js +0 -64
  302. package/dist/core/vim/keymap.js +0 -288
  303. package/dist/core/vim/state.js +0 -92
  304. package/dist/core/watch-markers/marker-watcher.js +0 -133
  305. package/dist/core/worktree/include-parser.js +0 -249
  306. package/dist/core/worktree-manager/cleanup.js +0 -123
  307. package/dist/core/worktree-manager/manager.js +0 -303
  308. package/dist/index.js +0 -44
  309. package/dist/runtime/bootstrap.js +0 -190
  310. package/dist/runtime/cli.js +0 -8121
  311. package/dist/runtime/commands/agents.js +0 -385
  312. package/dist/runtime/commands/budget.js +0 -192
  313. package/dist/runtime/commands/cancel.js +0 -231
  314. package/dist/runtime/commands/chain.js +0 -489
  315. package/dist/runtime/commands/codegraph-status.js +0 -227
  316. package/dist/runtime/commands/compact.js +0 -297
  317. package/dist/runtime/commands/config.js +0 -595
  318. package/dist/runtime/commands/cost.js +0 -199
  319. package/dist/runtime/commands/delegate.js +0 -312
  320. package/dist/runtime/commands/dispatch.js +0 -126
  321. package/dist/runtime/commands/doctor.js +0 -579
  322. package/dist/runtime/commands/feedback.js +0 -184
  323. package/dist/runtime/commands/hooks.js +0 -187
  324. package/dist/runtime/commands/init.js +0 -254
  325. package/dist/runtime/commands/lsp.js +0 -368
  326. package/dist/runtime/commands/mcp.js +0 -935
  327. package/dist/runtime/commands/memory.js +0 -582
  328. package/dist/runtime/commands/model.js +0 -237
  329. package/dist/runtime/commands/onboarding.js +0 -275
  330. package/dist/runtime/commands/patch.js +0 -128
  331. package/dist/runtime/commands/permissions.js +0 -112
  332. package/dist/runtime/commands/plan.js +0 -143
  333. package/dist/runtime/commands/prd-check.js +0 -285
  334. package/dist/runtime/commands/privacy.js +0 -107
  335. package/dist/runtime/commands/recipe.js +0 -325
  336. package/dist/runtime/commands/redo-blob-store.js +0 -92
  337. package/dist/runtime/commands/redo.js +0 -361
  338. package/dist/runtime/commands/release-notes.js +0 -229
  339. package/dist/runtime/commands/repo-map.js +0 -95
  340. package/dist/runtime/commands/report.js +0 -299
  341. package/dist/runtime/commands/resume.js +0 -118
  342. package/dist/runtime/commands/review-consensus.js +0 -414
  343. package/dist/runtime/commands/rewind.js +0 -333
  344. package/dist/runtime/commands/roster.js +0 -117
  345. package/dist/runtime/commands/sessions.js +0 -163
  346. package/dist/runtime/commands/share.js +0 -316
  347. package/dist/runtime/commands/skills.js +0 -401
  348. package/dist/runtime/commands/status.js +0 -186
  349. package/dist/runtime/commands/stickers.js +0 -82
  350. package/dist/runtime/commands/style.js +0 -194
  351. package/dist/runtime/commands/theme.js +0 -196
  352. package/dist/runtime/commands/undo.js +0 -361
  353. package/dist/runtime/commands/update.js +0 -289
  354. package/dist/runtime/commands/vim.js +0 -140
  355. package/dist/runtime/commands/worktree.js +0 -177
  356. package/dist/runtime/commands/worktrees.js +0 -155
  357. package/dist/runtime/deprecation-warning.js +0 -69
  358. package/dist/runtime/engine-exit-code.js +0 -50
  359. package/dist/runtime/headless-repl.js +0 -195
  360. package/dist/runtime/headless.js +0 -548
  361. package/dist/runtime/load-hooks-or-exit.js +0 -71
  362. package/dist/runtime/plan-decompose.js +0 -531
  363. package/dist/runtime/sigint-guard.js +0 -272
  364. package/dist/runtime/stream-renderer.js +0 -195
  365. package/dist/runtime/update-check.js +0 -294
  366. package/dist/runtime/version.js +0 -65
  367. package/dist/runtime/worktree-bootstrap.js +0 -579
  368. package/dist/skills/bundled/batch.js +0 -617
  369. package/dist/skills/bundled/index.js +0 -45
  370. package/dist/skills/bundled/loop.js +0 -358
  371. package/dist/skills/bundled/remember.js +0 -383
  372. package/dist/skills/bundled/simplify.js +0 -289
  373. package/dist/skills/bundled/skillify.js +0 -373
  374. package/dist/skills/bundled/stuck.js +0 -558
  375. package/dist/skills/bundled/verify.js +0 -439
  376. package/dist/testing/vcr.js +0 -486
  377. package/dist/tools/agent-tool.js +0 -229
  378. package/dist/tools/apply-patch.js +0 -556
  379. package/dist/tools/ask-user-question.js +0 -337
  380. package/dist/tools/ask-user.js +0 -115
  381. package/dist/tools/bash.js +0 -1238
  382. package/dist/tools/brief.js +0 -224
  383. package/dist/tools/cron.js +0 -433
  384. package/dist/tools/enter-worktree.js +0 -250
  385. package/dist/tools/exit-worktree.js +0 -147
  386. package/dist/tools/file-tools.js +0 -553
  387. package/dist/tools/http-request.js +0 -336
  388. package/dist/tools/lsp-tools.js +0 -565
  389. package/dist/tools/mcp-tool.js +0 -260
  390. package/dist/tools/multi-edit.js +0 -361
  391. package/dist/tools/powershell.js +0 -268
  392. package/dist/tools/registry.js +0 -166
  393. package/dist/tools/server-tools.js +0 -892
  394. package/dist/tools/skill-tool.js +0 -96
  395. package/dist/tools/sleep.js +0 -99
  396. package/dist/tools/synthetic-output.js +0 -133
  397. package/dist/tools/tasks.js +0 -208
  398. package/dist/tools/todo-write.js +0 -184
  399. package/dist/tools/verify-plan-execution.js +0 -295
  400. package/dist/tools/web-fetch-injection-scanner.js +0 -207
  401. package/dist/tools/web-fetch.js +0 -720
  402. package/dist/tools/web-search.js +0 -458
  403. package/dist/tui/agent-progress-card.js +0 -111
  404. package/dist/tui/agent-tree-pane.js +0 -9
  405. package/dist/tui/agent-tree.js +0 -87
  406. package/dist/tui/ask-cli.js +0 -52
  407. package/dist/tui/ask-modal.js +0 -211
  408. package/dist/tui/ask-user-question-chips.js +0 -315
  409. package/dist/tui/ask-user-question-prompt.js +0 -203
  410. package/dist/tui/compact-banner.js +0 -81
  411. package/dist/tui/conversation-pane.js +0 -164
  412. package/dist/tui/cost-table.js +0 -111
  413. package/dist/tui/device-flow.js +0 -142
  414. package/dist/tui/doctor-table.js +0 -46
  415. package/dist/tui/feedback-prompt.js +0 -156
  416. package/dist/tui/input-box.js +0 -732
  417. package/dist/tui/login-picker.js +0 -69
  418. package/dist/tui/markdown-render.js +0 -266
  419. package/dist/tui/multi-file-diff-approval.js +0 -375
  420. package/dist/tui/onboarding-wizard.js +0 -240
  421. package/dist/tui/permissions-picker.js +0 -86
  422. package/dist/tui/render.js +0 -160
  423. package/dist/tui/repl-render.js +0 -770
  424. package/dist/tui/repl-splash-art.js +0 -64
  425. package/dist/tui/repl-splash-mascot.js +0 -154
  426. package/dist/tui/repl-splash.js +0 -117
  427. package/dist/tui/repl.js +0 -378
  428. package/dist/tui/slash-palette.js +0 -106
  429. package/dist/tui/splash-data.js +0 -61
  430. package/dist/tui/splash.js +0 -31
  431. package/dist/tui/status-bar.js +0 -209
  432. package/dist/tui/status-table.js +0 -7
  433. package/dist/tui/stickers-art.js +0 -136
  434. package/dist/tui/style-table.js +0 -28
  435. package/dist/tui/theme-table.js +0 -29
  436. package/dist/tui/thinking-spinner.js +0 -123
  437. package/dist/tui/tool-stream-pane.js +0 -140
  438. package/dist/tui/update-banner.js +0 -33
  439. package/dist/tui/vim-input.js +0 -267
  440. package/dist/tui/welcome-banner.js +0 -107
  441. package/dist/tui/welcome-data.js +0 -293
  442. package/dist/tui/workspace-context.js +0 -105
  443. package/docs/examples/codegraph.mcp.json +0 -10
  444. package/test/scenarios/codegen-create-file.scenario.txt +0 -13
  445. package/test/scenarios/compact-force.scenario.txt +0 -12
  446. package/test/scenarios/identity.scenario.txt +0 -11
  447. package/test/scenarios/persona-handoff.scenario.txt +0 -12
  448. package/test/scenarios/walkback.scenario.txt +0 -12
@@ -1,361 +0,0 @@
1
- import { execFileSync } from 'node:child_process';
2
- import { existsSync, readFileSync, renameSync, unlinkSync, writeFileSync } from 'node:fs';
3
- import { resolve } from 'node:path';
4
- import { hashContent } from '../../core/file-cache.js';
5
- import { recordFileMutation, recordToolCall, recordToolResult, } from '../../core/session.js';
6
- import { writeBlob } from './redo-blob-store.js';
7
- /**
8
- * `pugi undo` — revert the file mutations from the most recent successful
9
- * `write` / `edit` / `multi_edit` tool result.
10
- *
11
- * Walk strategy:
12
- * 1. Read `.pugi/events.jsonl` line by line into an array.
13
- * 2. Walk backwards. Find the most recent `tool_result` whose
14
- * `status === 'success'` and whose linked `tool_call` names a
15
- * mutating tool (write / edit / multi_edit).
16
- * 3. From that point, gather every `file_mutation` event that shares
17
- * the same `toolCallId`. M1 records one `file_mutation` per
18
- * mutating tool call, but the loop is shaped for the multi_edit
19
- * future case where a single tool call mutates many files.
20
- *
21
- * Restore strategy (M1 — no blob store yet):
22
- * For each mutation we restore from the workspace's git history when
23
- * possible, with a strict safety gate to avoid silently overwriting
24
- * the user's WORK-IN-PROGRESS:
25
- *
26
- * - `operation: create` → unlink the created file iff its current
27
- * sha256 matches the recorded `afterHash`. Skip otherwise (the user
28
- * has edited it since; refuse to delete their work).
29
- * - `operation: update` → restore from `HEAD:<path>` iff (a) the file
30
- * was tracked at HEAD AND (b) the HEAD content's sha256 matches the
31
- * recorded `beforeHash`. Otherwise abort the turn (no partial
32
- * reverts — the spec is atomic).
33
- * - `operation: delete` → restore the deleted file from `HEAD:<path>`
34
- * if tracked there; skip otherwise.
35
- *
36
- * If any single restore is unsafe the whole turn aborts with exit code
37
- * 1 and no files are touched.
38
- *
39
- * Why git as the backing store: the file cache stores hash + metadata
40
- * but NOT raw content (see `core/file-cache.ts`). M1 ships without a
41
- * dedicated blob CAS; `git show HEAD:<path>` is the cheapest authoritative
42
- * source for pre-mutation content as long as the workspace is a git
43
- * repository. The SQLite session store will replace this with a
44
- * proper before-blob ledger.
45
- */
46
- const MUTATING_TOOLS = new Set(['write', 'edit', 'multi_edit']);
47
- export async function runUndoCommand(_args, ctx) {
48
- const eventsPath = resolve(ctx.workspaceRoot, '.pugi/events.jsonl');
49
- if (!existsSync(eventsPath)) {
50
- ctx.writeOutput({ command: 'undo', status: 'noop', reason: 'no_session' }, 'No session events found. Nothing to undo.');
51
- return;
52
- }
53
- const events = parseEvents(eventsPath);
54
- const target = findLastMutationTurn(events);
55
- if (!target) {
56
- ctx.writeOutput({ command: 'undo', status: 'noop', reason: 'no_mutation' }, 'No mutating tool result found in the session log.');
57
- return;
58
- }
59
- if (target.mutations.length === 0) {
60
- ctx.writeOutput({
61
- command: 'undo',
62
- status: 'noop',
63
- reason: 'no_file_mutations',
64
- toolCallId: target.toolCallId,
65
- }, `Tool call ${target.toolCallId} recorded no file mutations.`);
66
- return;
67
- }
68
- // Pre-flight: confirm every mutation is reversible before touching
69
- // disk. This keeps the operation atomic per spec.
70
- const plan = planReverts(ctx.workspaceRoot, target.mutations);
71
- if (plan.aborted) {
72
- ctx.writeOutput({
73
- command: 'undo',
74
- status: 'aborted',
75
- reason: plan.reason,
76
- toolCallId: target.toolCallId,
77
- unsafe: plan.unsafe,
78
- }, `Refusing to undo ${target.toolCallId}: ${plan.reason}`);
79
- process.exitCode = 1;
80
- return;
81
- }
82
- const restored = [];
83
- for (const step of plan.steps) {
84
- try {
85
- // : snapshot the AFTER state into the redo
86
- // blob store BEFORE we revert the file on disk. /redo reads this
87
- // blob keyed by `step.beforeHash` (= original afterHash) to
88
- // reapply the change. We only snapshot for operations that have
89
- // on-disk AFTER content: `create` (file exists, about to be
90
- // deleted) and `update` (file exists, about to be overwritten).
91
- // For `delete` reverts (file was deleted by Pugi, the "after" is
92
- // nothing) redo replays the delete itself — no content needed.
93
- // Best-effort: a blob-store failure must not abort the undo, so
94
- // the writeBlob call is wrapped и any error swallowed.
95
- if (step.operation === 'create' || step.operation === 'update') {
96
- try {
97
- const abs = resolve(ctx.workspaceRoot, step.path);
98
- if (existsSync(abs) && step.beforeHash) {
99
- const current = readFileSync(abs, 'utf8');
100
- // Defensive: only snapshot if the current sha matches the
101
- // pre-revert hash the planner verified. The planner already
102
- // gated this, but a TOCTOU between plan + execute would
103
- // produce a wrong blob — silently dropping it is safer than
104
- // shipping content under the wrong sha.
105
- if (hashContent(current) === step.beforeHash) {
106
- writeBlob(ctx.workspaceRoot, current);
107
- }
108
- }
109
- }
110
- catch {
111
- // Best-effort. Failure to snapshot means /redo will report
112
- // "no captured content" — operator can re-run the mutation
113
- // manually. Better than aborting the undo.
114
- }
115
- }
116
- executeRevert(ctx.workspaceRoot, step);
117
- restored.push({ path: step.path, operation: step.operation });
118
- }
119
- catch (error) {
120
- // A revert failed after pre-flight said it was safe. Surface the
121
- // error and bail out — the spec says no partial state on failure.
122
- const message = error instanceof Error ? error.message : String(error);
123
- ctx.writeOutput({
124
- command: 'undo',
125
- status: 'failed',
126
- reason: message,
127
- toolCallId: target.toolCallId,
128
- restored,
129
- failedAt: step.path,
130
- }, `Undo failed mid-flight on ${step.path}: ${message}`);
131
- process.exitCode = 1;
132
- return;
133
- }
134
- }
135
- // Audit the inverse mutations so the event log explains the undo.
136
- const toolCallId = recordToolCall(ctx.session, 'undo', `revert ${target.toolCallId}`);
137
- for (const step of plan.steps) {
138
- recordFileMutation(ctx.session, {
139
- toolCallId,
140
- path: step.path,
141
- operation: step.operation === 'create' ? 'delete' : 'update',
142
- beforeHash: step.beforeHash,
143
- afterHash: step.afterHash,
144
- });
145
- }
146
- recordToolResult(ctx.session, toolCallId, 'success', `Undid ${restored.length} mutation(s) from ${target.toolCallId}`);
147
- ctx.writeOutput({
148
- command: 'undo',
149
- status: 'ok',
150
- toolCallId: target.toolCallId,
151
- restored,
152
- }, [
153
- `Undid ${restored.length} mutation(s) from ${target.toolCallId}:`,
154
- ...restored.map((entry) => ` ${entry.operation.padEnd(7)} ${entry.path}`),
155
- ].join('\n'));
156
- }
157
- function parseEvents(eventsPath) {
158
- const raw = readFileSync(eventsPath, 'utf8');
159
- const lines = raw.split('\n').filter((line) => line.trim().length > 0);
160
- const out = [];
161
- for (const line of lines) {
162
- try {
163
- const parsed = JSON.parse(line);
164
- if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
165
- out.push(parsed);
166
- }
167
- }
168
- catch {
169
- // Drop malformed lines silently — partial writes mid-shutdown can
170
- // produce them and undo should still work for the rest.
171
- }
172
- }
173
- return out;
174
- }
175
- function findLastMutationTurn(events) {
176
- const toolCalls = new Map();
177
- const results = [];
178
- for (let i = 0; i < events.length; i += 1) {
179
- const event = events[i];
180
- if (!event)
181
- continue;
182
- if (event.type === 'tool_call' && typeof event.id === 'string' && typeof event.tool === 'string') {
183
- toolCalls.set(event.id, { id: event.id, tool: event.tool });
184
- }
185
- else if (event.type === 'tool_result' &&
186
- typeof event.id === 'string' &&
187
- typeof event.toolCallId === 'string' &&
188
- (event.status === 'success' || event.status === 'error' || event.status === 'cancelled')) {
189
- results.push({
190
- id: event.id,
191
- toolCallId: event.toolCallId,
192
- status: event.status,
193
- index: i,
194
- });
195
- }
196
- }
197
- for (let i = results.length - 1; i >= 0; i -= 1) {
198
- const result = results[i];
199
- if (result.status !== 'success')
200
- continue;
201
- const call = toolCalls.get(result.toolCallId);
202
- if (!call)
203
- continue;
204
- if (!MUTATING_TOOLS.has(call.tool))
205
- continue;
206
- // Collect file_mutation events whose toolCallId matches. We do NOT
207
- // window by event index: M1 emits the file_mutation alongside the
208
- // tool_result, but a future iteration that emits them earlier
209
- // (e.g. mid-stream for multi_edit) still maps correctly.
210
- const mutations = [];
211
- for (const event of events) {
212
- if (event.type !== 'file_mutation')
213
- continue;
214
- if (event.toolCallId !== result.toolCallId)
215
- continue;
216
- if (typeof event.path !== 'string')
217
- continue;
218
- if (event.operation !== 'create' &&
219
- event.operation !== 'update' &&
220
- event.operation !== 'delete' &&
221
- event.operation !== 'move') {
222
- continue;
223
- }
224
- mutations.push({
225
- toolCallId: result.toolCallId,
226
- path: event.path,
227
- operation: event.operation,
228
- beforeHash: typeof event.beforeHash === 'string' ? event.beforeHash : undefined,
229
- afterHash: typeof event.afterHash === 'string' ? event.afterHash : undefined,
230
- });
231
- }
232
- return {
233
- toolCallId: result.toolCallId,
234
- resultIndex: result.index,
235
- tool: call.tool,
236
- mutations,
237
- };
238
- }
239
- return null;
240
- }
241
- function planReverts(root, mutations) {
242
- const steps = [];
243
- const unsafe = [];
244
- for (const mutation of mutations) {
245
- const abs = resolve(root, mutation.path);
246
- switch (mutation.operation) {
247
- case 'create': {
248
- if (!existsSync(abs)) {
249
- // Already gone — nothing to undo for this entry.
250
- continue;
251
- }
252
- const current = readFileSync(abs, 'utf8');
253
- const currentHash = hashContent(current);
254
- if (!mutation.afterHash || currentHash !== mutation.afterHash) {
255
- unsafe.push(`${mutation.path}: created by Pugi, then modified by the user — refusing to delete uncommitted work`);
256
- continue;
257
- }
258
- steps.push({
259
- path: mutation.path,
260
- operation: 'create',
261
- beforeHash: mutation.afterHash,
262
- afterHash: undefined,
263
- });
264
- break;
265
- }
266
- case 'update': {
267
- if (!existsSync(abs)) {
268
- unsafe.push(`${mutation.path}: file expected to exist for update revert, not found`);
269
- continue;
270
- }
271
- const current = readFileSync(abs, 'utf8');
272
- const currentHash = hashContent(current);
273
- if (!mutation.afterHash || currentHash !== mutation.afterHash) {
274
- unsafe.push(`${mutation.path}: updated by Pugi, then modified by the user — refusing to overwrite uncommitted work`);
275
- continue;
276
- }
277
- const headContent = readHead(root, mutation.path);
278
- if (headContent === null) {
279
- unsafe.push(`${mutation.path}: no git HEAD version available for revert`);
280
- continue;
281
- }
282
- if (mutation.beforeHash && hashContent(headContent) !== mutation.beforeHash) {
283
- unsafe.push(`${mutation.path}: git HEAD differs from the pre-mutation hash — refusing to restore an unverifiable version`);
284
- continue;
285
- }
286
- steps.push({
287
- path: mutation.path,
288
- operation: 'update',
289
- beforeHash: mutation.afterHash,
290
- afterHash: mutation.beforeHash,
291
- restoreContent: headContent,
292
- });
293
- break;
294
- }
295
- case 'delete': {
296
- const headContent = readHead(root, mutation.path);
297
- if (headContent === null) {
298
- unsafe.push(`${mutation.path}: deleted file has no git HEAD version, cannot restore`);
299
- continue;
300
- }
301
- if (mutation.beforeHash && hashContent(headContent) !== mutation.beforeHash) {
302
- unsafe.push(`${mutation.path}: git HEAD differs from the pre-deletion hash, cannot restore safely`);
303
- continue;
304
- }
305
- steps.push({
306
- path: mutation.path,
307
- operation: 'delete',
308
- beforeHash: undefined,
309
- afterHash: mutation.beforeHash,
310
- restoreContent: headContent,
311
- });
312
- break;
313
- }
314
- case 'move':
315
- // Move reverts are not in M1 scope — the tool layer does not yet
316
- // emit `move` mutations. Flag as unsafe so a future operator who
317
- // hits this gets a clear failure instead of partial revert.
318
- unsafe.push(`${mutation.path}: move undo is not supported in M1`);
319
- break;
320
- }
321
- }
322
- if (unsafe.length > 0) {
323
- return {
324
- aborted: true,
325
- reason: 'one or more files are unsafe to revert',
326
- unsafe,
327
- steps: [],
328
- };
329
- }
330
- return { aborted: false, steps };
331
- }
332
- function executeRevert(root, step) {
333
- const abs = resolve(root, step.path);
334
- if (step.operation === 'create') {
335
- // We previously created the file. Reverting means deleting it.
336
- unlinkSync(abs);
337
- return;
338
- }
339
- if (step.restoreContent === undefined) {
340
- throw new Error(`internal: restoreContent missing for ${step.path}`);
341
- }
342
- // Atomic write via tmp+rename — same pattern as file-tools.writeTool.
343
- const tmp = `${abs}.pugi-undo-${Date.now()}`;
344
- writeFileSync(tmp, step.restoreContent, { encoding: 'utf8', mode: 0o600 });
345
- renameSync(tmp, abs);
346
- }
347
- function readHead(root, path) {
348
- try {
349
- const out = execFileSync('git', ['show', `HEAD:${path}`], {
350
- cwd: root,
351
- encoding: 'utf8',
352
- stdio: ['ignore', 'pipe', 'ignore'],
353
- maxBuffer: 64 * 1024 * 1024,
354
- });
355
- return out;
356
- }
357
- catch {
358
- return null;
359
- }
360
- }
361
- //# sourceMappingURL=undo.js.map
@@ -1,289 +0,0 @@
1
- /**
2
- * — `pugi update` dispatcher.
3
- *
4
- * Top-level command + in-REPL `/update` slash share this handler.
5
- * Both surfaces delegate IO + persistence here so the channel
6
- * resolution, the registry probe, and the install shell-out stay
7
- * single-sourced.
8
- *
9
- * Command grammar:
10
- *
11
- * pugi update -> probe + interactive prompt
12
- * pugi update --check -> probe + JSON envelope (scripted)
13
- * pugi update --channel <name> -> switch channel + probe
14
- * pugi update --apply -> probe + shell `npm i -g …`
15
- * (confirms unless --yes)
16
- * pugi update --apply --yes -> probe + shell, no confirmation
17
- *
18
- * Exit codes:
19
- *
20
- * 0 — happy path (no update OR update completed) OR `--check` JSON
21
- * 1 — install / probe failure with structured error envelope
22
- * 2 — argument error (bad channel, conflicting flags)
23
- *
24
- * R2 atomic swap deferred (sprint plan L27 mention): the upstream behavior
25
- * also describes the upstream tool's R2-backed binary swap. Pugi ships
26
- * exclusively via npm today; building a parallel R2 distribution
27
- * channel + checksum verification + rollback is materially more work
28
- * than the L27 acceptance criteria allow. Document the deferral in
29
- * the PR body and revisit when npm's once-per-day rate-limit or
30
- * outage cadence justifies the parallel pipeline.
31
- */
32
- import { spawn } from 'node:child_process';
33
- import { homedir } from 'node:os';
34
- import { DEFAULT_UPDATE_CHANNEL, UPDATE_CHANNELS, describeChannel, npmTagForChannel, parseUpdateChannel, } from '../../core/auto-update/channels.js';
35
- import { checkForChannelUpdate, } from '../../core/auto-update/checker.js';
36
- import { resolveEffectiveChannel, setUpdateChannel, writeLastCheckedAt, } from '../../core/auto-update/state.js';
37
- import { PUGI_CLI_VERSION } from '../version.js';
38
- /**
39
- * Default subprocess runner. Spawns `npm install -g @pugi/cli@<tag>`
40
- * inheriting stdio so the operator sees the live npm output.
41
- */
42
- export function defaultSpawnInstaller(channel) {
43
- const tag = npmTagForChannel(channel);
44
- const args = ['install', '-g', `@pugi/cli@${tag}`];
45
- return new Promise((resolvePromise) => {
46
- const child = spawn('npm', args, { stdio: 'inherit' });
47
- child.on('exit', (code) => {
48
- resolvePromise(typeof code === 'number' ? code : 1);
49
- });
50
- child.on('error', () => {
51
- // ENOENT / EACCES — npm not on PATH or permission denied. We
52
- // surface a non-zero code so the dispatcher's JSON envelope
53
- // tells the operator the apply failed; the inherited stdio
54
- // already printed the underlying error to the terminal.
55
- resolvePromise(127);
56
- });
57
- });
58
- }
59
- /**
60
- * Parse a CLI / slash argv into our `UpdateCommandFlags`. Returns
61
- * `null` AND writes the usage error via `writeError` for conflicting
62
- * combinations. Both `pugi update` and the in-REPL `/update <args>`
63
- * surface call through this so the validation lives in one place.
64
- */
65
- export function parseUpdateArgs(argv, options = {}) {
66
- let check = false;
67
- let apply = false;
68
- let yes = false;
69
- let json = options.jsonDefault ?? false;
70
- let channel = null;
71
- let channelInvalid;
72
- for (let i = 0; i < argv.length; i += 1) {
73
- const token = argv[i] ?? '';
74
- if (token === '--check') {
75
- check = true;
76
- }
77
- else if (token === '--apply') {
78
- apply = true;
79
- }
80
- else if (token === '--yes' || token === '-y') {
81
- yes = true;
82
- }
83
- else if (token === '--json') {
84
- json = true;
85
- }
86
- else if (token === '--channel') {
87
- const value = argv[i + 1];
88
- i += 1;
89
- const parsed = parseUpdateChannel(value);
90
- if (!parsed) {
91
- channelInvalid = value ?? '';
92
- continue;
93
- }
94
- channel = parsed;
95
- }
96
- else if (token.startsWith('--channel=')) {
97
- const value = token.slice('--channel='.length);
98
- const parsed = parseUpdateChannel(value);
99
- if (!parsed) {
100
- channelInvalid = value;
101
- continue;
102
- }
103
- channel = parsed;
104
- }
105
- else {
106
- return {
107
- error: `pugi update: unknown argument '${token}'. See \`pugi update --help\`.`,
108
- };
109
- }
110
- }
111
- if (channelInvalid !== undefined) {
112
- return {
113
- error: `pugi update: unknown channel '${channelInvalid}'. Allowed: ${UPDATE_CHANNELS.join(' / ')}.`,
114
- };
115
- }
116
- return {
117
- check,
118
- apply,
119
- yes,
120
- json,
121
- channel,
122
- };
123
- }
124
- /**
125
- * Run the full command. Returns the structured envelope so the in-
126
- * REPL slash can decide whether to render the human-readable text OR
127
- * pretty-print the JSON.
128
- */
129
- export async function runUpdateCommand(ctx) {
130
- const flags = ctx.flags;
131
- const home = ctx.home;
132
- // 1. Resolve channel. `--channel <name>` wins; otherwise read the
133
- // persisted preference; otherwise hard default `beta`.
134
- const cliFlagChannel = flags.channel;
135
- const effectiveChannel = resolveEffectiveChannel({
136
- cliFlag: cliFlagChannel,
137
- homeDir: home,
138
- });
139
- // 2. Persist the channel switch BEFORE the probe so a probe failure
140
- // still leaves the operator on the channel they asked for.
141
- let switched = false;
142
- if (cliFlagChannel) {
143
- setUpdateChannel(cliFlagChannel, home);
144
- switched = true;
145
- }
146
- // 3. Probe the registry.
147
- const outcome = await checkForChannelUpdate({
148
- channel: effectiveChannel,
149
- currentVersion: PUGI_CLI_VERSION,
150
- ...(ctx.fetchImpl ? { fetchImpl: ctx.fetchImpl } : {}),
151
- ...(ctx.registryUrl ? { registryUrl: ctx.registryUrl } : {}),
152
- });
153
- // 4. Record the timestamp on a successful probe (regardless of
154
- // whether an update is available). Failed probes do NOT update
155
- // the timestamp so the cold-start banner retries on the next
156
- // invocation.
157
- if (!outcome.error) {
158
- const now = ctx.now ? new Date(ctx.now()) : new Date();
159
- try {
160
- writeLastCheckedAt(now, home);
161
- }
162
- catch {
163
- // Best-effort — a read-only home should not crash the dispatcher.
164
- }
165
- }
166
- // 5. Build the envelope shape ALL action paths share.
167
- const baseEnvelope = {
168
- command: 'update',
169
- ok: outcome.error === null,
170
- available: outcome.available,
171
- channel: outcome.channel,
172
- npmTag: outcome.npmTag,
173
- current: outcome.current,
174
- latest: outcome.latest,
175
- gap: outcome.gap,
176
- installCommand: outcome.installCommand,
177
- action: outcome.error ? 'error' : 'probe',
178
- error: outcome.error,
179
- meta: { cliVersion: PUGI_CLI_VERSION },
180
- };
181
- // 6. --check: emit the envelope, never prompt, never apply.
182
- if (flags.check) {
183
- const text = renderHumanText(baseEnvelope, { switched });
184
- ctx.writeOutput(baseEnvelope, text);
185
- return baseEnvelope;
186
- }
187
- // 7. No update available — bail with a friendly message.
188
- if (!outcome.available || !outcome.latest) {
189
- const envelope = {
190
- ...baseEnvelope,
191
- action: outcome.error ? 'error' : (switched ? 'switch' : 'no_update'),
192
- };
193
- const text = renderHumanText(envelope, { switched });
194
- ctx.writeOutput(envelope, text);
195
- return envelope;
196
- }
197
- // 8. Update IS available. Branch on --apply.
198
- if (!flags.apply) {
199
- // Default: print the offer, suggest the install command, leave
200
- // the install to the operator. Mirrors the upstream behavior note:
201
- // operators install side-effects must remain explicit on the CLI
202
- // happy path — `pugi update` showing the gap is informational,
203
- // `pugi update --apply` is the destructive verb.
204
- const envelope = {
205
- ...baseEnvelope,
206
- action: switched ? 'switch' : 'probe',
207
- };
208
- const text = renderHumanText(envelope, { switched });
209
- ctx.writeOutput(envelope, text);
210
- return envelope;
211
- }
212
- // 9. --apply path. Confirm unless --yes, then spawn npm.
213
- const installer = ctx.spawnInstaller ?? defaultSpawnInstaller;
214
- let confirmed = flags.yes;
215
- if (!confirmed) {
216
- confirmed = await ctx.promptConfirm(`Run \`${outcome.installCommand}\` to update ${outcome.current} -> ${outcome.latest}? [y/N]`);
217
- }
218
- if (!confirmed) {
219
- const envelope = {
220
- ...baseEnvelope,
221
- action: 'probe',
222
- ok: false,
223
- error: 'apply_cancelled_by_operator',
224
- };
225
- const text = `Cancelled. Run \`${outcome.installCommand}\` manually when you are ready.`;
226
- ctx.writeOutput(envelope, text);
227
- return envelope;
228
- }
229
- const exitCode = await installer(outcome.channel);
230
- const applyEnvelope = {
231
- ...baseEnvelope,
232
- action: 'apply',
233
- installExitCode: exitCode,
234
- ok: exitCode === 0,
235
- error: exitCode === 0 ? null : `npm_install_exit_${exitCode}`,
236
- };
237
- const applyText = exitCode === 0
238
- ? `Updated to @pugi/cli@${outcome.latest}. Restart your shell so the new binary takes effect.`
239
- : `Update failed (npm exit ${exitCode}). Try \`${outcome.installCommand}\` manually.`;
240
- ctx.writeOutput(applyEnvelope, applyText);
241
- return applyEnvelope;
242
- }
243
- /**
244
- * Build the operator-readable hint that lives next to the JSON
245
- * envelope. The text + the JSON are both passed to `writeOutput`; the
246
- * caller (`writeOutput` in cli.ts) picks based on `--json`. Exported
247
- * so the spec can assert the literal strings the operator sees.
248
- */
249
- export function renderHumanText(envelope, options = {}) {
250
- const { current, latest, channel, installCommand, available, error } = envelope;
251
- const lines = [];
252
- lines.push(`Channel: ${channel} — ${describeChannel(channel)}`);
253
- if (options.switched) {
254
- lines.push(`Persisted channel selection -> ${channel}.`);
255
- }
256
- if (error) {
257
- lines.push(`Update check failed: ${error}`);
258
- lines.push(`Manual: \`${installCommand}\` (no probe necessary).`);
259
- return lines.join('\n');
260
- }
261
- if (available && latest) {
262
- lines.push(`Update available: ${current} -> ${latest}.`);
263
- lines.push(`Run \`${installCommand}\` to upgrade.`);
264
- lines.push(`Or \`pugi update --apply\` to upgrade with confirmation.`);
265
- return lines.join('\n');
266
- }
267
- lines.push(`Up to date (${current} is the latest on ${channel}).`);
268
- return lines.join('\n');
269
- }
270
- /**
271
- * Render a one-line cold-start hint that callers (REPL boot, doctor
272
- * banner) splice above their own UI. Returns `null` when there is
273
- * nothing to nudge the operator about. Pure — no IO.
274
- */
275
- export function renderUpdateHint(outcome) {
276
- if (!outcome.available || !outcome.latest)
277
- return null;
278
- return `Update available: ${outcome.current} -> ${outcome.latest}. Run \`pugi update\`.`;
279
- }
280
- /**
281
- * Convenience entry point — resolve the effective channel from
282
- * `~/.pugi/config.json` + DEFAULT_UPDATE_CHANNEL without forcing the
283
- * caller to import multiple modules. Used by the cold-start banner +
284
- * the doctor probe.
285
- */
286
- export function effectiveChannel(home = homedir()) {
287
- return resolveEffectiveChannel({ homeDir: home }) ?? DEFAULT_UPDATE_CHANNEL;
288
- }
289
- //# sourceMappingURL=update.js.map