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

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 (464) hide show
  1. package/CHANGELOG.md +132 -0
  2. package/LICENSE +1 -1
  3. package/README.md +55 -11
  4. package/assets/pugi-prozr2-mascot.ansi +9 -0
  5. package/bin/run.js +33 -1
  6. package/dist/commands/deploy.js +40 -40
  7. package/dist/commands/flatten.js +191 -0
  8. package/dist/commands/jobs-watch.js +201 -0
  9. package/dist/commands/jobs.js +42 -27
  10. package/dist/commands/retro.js +210 -0
  11. package/dist/commands/smoke.js +133 -0
  12. package/dist/core/agent-progress/cleanup.js +134 -0
  13. package/dist/core/agent-progress/schema.js +144 -0
  14. package/dist/core/agent-progress/writer.js +101 -0
  15. package/dist/core/agents/adaptive-router.js +330 -0
  16. package/dist/core/agents/query-decomposer.js +297 -0
  17. package/dist/core/agents/registry.js +3 -3
  18. package/dist/core/approvals/shortcut-resolver.js +98 -0
  19. package/dist/core/artifact-chain/dispatcher.js +148 -0
  20. package/dist/core/artifact-chain/exporter.js +164 -0
  21. package/dist/core/artifact-chain/state.js +243 -0
  22. package/dist/core/artifact-chain/steps.js +169 -0
  23. package/dist/core/ask-user/question.js +92 -0
  24. package/dist/core/audit/audit-trail.js +275 -0
  25. package/dist/core/auth/ensure-authenticated.js +129 -0
  26. package/dist/core/auth/env-provider.js +238 -0
  27. package/dist/core/auto-open-browser.js +4 -4
  28. package/dist/core/auto-update/channels.js +122 -0
  29. package/dist/core/auto-update/checker.js +241 -0
  30. package/dist/core/auto-update/state.js +235 -0
  31. package/dist/core/bare-mode/index.js +107 -0
  32. package/dist/core/bash/redirect.js +281 -0
  33. package/dist/core/bash-classifier.js +436 -40
  34. package/dist/core/checkpoint/resumer.js +149 -0
  35. package/dist/core/checkpoint/rewinder.js +291 -0
  36. package/dist/core/checkpoints/shadow-git.js +670 -0
  37. package/dist/core/citations/parser.js +109 -0
  38. package/dist/core/classifier/yolo-classifier.js +88 -0
  39. package/dist/core/codegraph/db.js +506 -0
  40. package/dist/core/codegraph/decision-store.js +248 -0
  41. package/dist/core/codegraph/detect-repo.js +459 -0
  42. package/dist/core/codegraph/install.js +134 -0
  43. package/dist/core/codegraph/offer-hook.js +220 -0
  44. package/dist/core/codegraph/parser.js +598 -0
  45. package/dist/core/codegraph/queries/go.scm +57 -0
  46. package/dist/core/codegraph/queries/javascript.scm +56 -0
  47. package/dist/core/codegraph/queries/python.scm +55 -0
  48. package/dist/core/codegraph/queries/rust.scm +63 -0
  49. package/dist/core/codegraph/queries/typescript.scm +91 -0
  50. package/dist/core/codegraph/reindex.js +218 -0
  51. package/dist/core/codegraph/resolve-edges.js +107 -0
  52. package/dist/core/codegraph/types.js +34 -0
  53. package/dist/core/codegraph/watcher.js +440 -0
  54. package/dist/core/compact/auto-trigger.js +96 -0
  55. package/dist/core/compact/buffer-rewriter.js +115 -0
  56. package/dist/core/compact/summarizer.js +208 -0
  57. package/dist/core/compact/token-counter.js +108 -0
  58. package/dist/core/consensus/anvil-fanout.js +25 -25
  59. package/dist/core/consensus/diff-capture.js +121 -12
  60. package/dist/core/consensus/rubric.js +21 -21
  61. package/dist/core/context/builder.js +6 -6
  62. package/dist/core/context/compaction-events.js +8 -8
  63. package/dist/core/context/compaction.js +31 -31
  64. package/dist/core/context/index.js +15 -8
  65. package/dist/core/context/invariants.js +51 -51
  66. package/dist/core/context/markdown-loader.js +28 -10
  67. package/dist/core/context/markdown-traverse.js +255 -0
  68. package/dist/core/context/pugiignore.js +41 -41
  69. package/dist/core/context/repo-skeleton.js +37 -37
  70. package/dist/core/context/tool-eviction.js +55 -0
  71. package/dist/core/context/watcher.js +32 -32
  72. package/dist/core/context/working-set.js +23 -23
  73. package/dist/core/coordinator/agent-tools.js +77 -0
  74. package/dist/core/coordinator/agent-toolset.js +65 -0
  75. package/dist/core/coordinator/fsm.js +73 -0
  76. package/dist/core/coordinator/mode-fsm.js +70 -0
  77. package/dist/core/cost/rate-card.js +129 -0
  78. package/dist/core/cost/tracker.js +221 -0
  79. package/dist/core/credentials.js +13 -13
  80. package/dist/core/cron/scheduler.js +138 -0
  81. package/dist/core/denial-tracking/index.js +8 -0
  82. package/dist/core/denial-tracking/state.js +264 -0
  83. package/dist/core/diagnostics/probe-runner.js +93 -0
  84. package/dist/core/diagnostics/probes/api.js +46 -0
  85. package/dist/core/diagnostics/probes/auth.js +93 -0
  86. package/dist/core/diagnostics/probes/bare-mode.js +42 -0
  87. package/dist/core/diagnostics/probes/cli-version.js +127 -0
  88. package/dist/core/diagnostics/probes/config.js +72 -0
  89. package/dist/core/diagnostics/probes/denial-tracking.js +57 -0
  90. package/dist/core/diagnostics/probes/disk.js +81 -0
  91. package/dist/core/diagnostics/probes/engine-live.js +46 -0
  92. package/dist/core/diagnostics/probes/git.js +65 -0
  93. package/dist/core/diagnostics/probes/hooks.js +118 -0
  94. package/dist/core/diagnostics/probes/mcp.js +75 -0
  95. package/dist/core/diagnostics/probes/node.js +59 -0
  96. package/dist/core/diagnostics/probes/pnpm.js +36 -0
  97. package/dist/core/diagnostics/probes/pugi-md.js +89 -0
  98. package/dist/core/diagnostics/probes/sandbox.js +67 -0
  99. package/dist/core/diagnostics/probes/session.js +74 -0
  100. package/dist/core/diagnostics/probes/status-snapshot.js +488 -0
  101. package/dist/core/diagnostics/probes/workspace.js +63 -0
  102. package/dist/core/diagnostics/types.js +70 -0
  103. package/dist/core/dispatch/cache-cleanup.js +197 -0
  104. package/dist/core/dispatch/cache-handoff.js +295 -0
  105. package/dist/core/edits/apply-patch-layer-e.js +189 -0
  106. package/dist/core/edits/dispatch.js +333 -7
  107. package/dist/core/edits/format-detector.js +260 -0
  108. package/dist/core/edits/format-matrix.js +26 -0
  109. package/dist/core/edits/fuzzy-ladder.js +650 -0
  110. package/dist/core/edits/index.js +5 -1
  111. package/dist/core/edits/journal.js +199 -0
  112. package/dist/core/edits/layer-a-apply.js +15 -15
  113. package/dist/core/edits/layer-a-fuzzy-apply.js +198 -0
  114. package/dist/core/edits/layer-b-apply.js +9 -9
  115. package/dist/core/edits/layer-c-apply.js +6 -6
  116. package/dist/core/edits/layer-d-ast.js +557 -14
  117. package/dist/core/edits/marker-parser.js +12 -12
  118. package/dist/core/edits/security-gate.js +27 -27
  119. package/dist/core/edits/verify-hook.js +273 -0
  120. package/dist/core/edits/worktree.js +29 -29
  121. package/dist/core/engine/anvil-client.js +214 -26
  122. package/dist/core/engine/auto-compact.js +247 -0
  123. package/dist/core/engine/budgets.js +220 -0
  124. package/dist/core/engine/compact-llm-summarizer.js +124 -0
  125. package/dist/core/engine/context-prefix.js +155 -0
  126. package/dist/core/engine/index.js +1 -1
  127. package/dist/core/engine/intensity.js +163 -0
  128. package/dist/core/engine/intent.js +260 -0
  129. package/dist/core/engine/native-pugi.js +1559 -227
  130. package/dist/core/engine/prompts.js +219 -19
  131. package/dist/core/engine/strip-internal-fields.js +124 -0
  132. package/dist/core/engine/tool-bridge.js +1887 -59
  133. package/dist/core/engine/verification-patterns.js +195 -0
  134. package/dist/core/eval/v1/ledger.js +83 -0
  135. package/dist/core/eval/v1/runner.js +280 -0
  136. package/dist/core/eval/v1/scoring.js +68 -0
  137. package/dist/core/eval/v1/task-loader.js +191 -0
  138. package/dist/core/eval/v1/types.js +14 -0
  139. package/dist/core/eval/v1/verifier.js +176 -0
  140. package/dist/core/eval/v1/yaml-parser.js +250 -0
  141. package/dist/core/evaluation/golden-dataset.js +293 -0
  142. package/dist/core/feedback/queue.js +177 -0
  143. package/dist/core/feedback/submitter.js +145 -0
  144. package/dist/core/file-cache.js +113 -1
  145. package/dist/core/flatten/flatten-repo.js +439 -0
  146. package/dist/core/format/osc8-link.js +28 -0
  147. package/dist/core/hook-chains.js +392 -0
  148. package/dist/core/hooks/citation-verify-hook.js +138 -0
  149. package/dist/core/hooks/citation-verify.js +112 -0
  150. package/dist/core/hooks/events.js +46 -0
  151. package/dist/core/hooks/index.js +15 -0
  152. package/dist/core/hooks/registry.js +216 -0
  153. package/dist/core/hooks/runner.js +236 -0
  154. package/dist/core/hooks/v2/event-emitter.js +115 -0
  155. package/dist/core/hooks/v2/executor.js +282 -0
  156. package/dist/core/hooks/v2/index.js +25 -0
  157. package/dist/core/hooks/v2/lifecycle.js +104 -0
  158. package/dist/core/hooks/v2/loader.js +216 -0
  159. package/dist/core/hooks/v2/matcher.js +125 -0
  160. package/dist/core/hooks/v2/trust.js +143 -0
  161. package/dist/core/hooks/v2/types.js +86 -0
  162. package/dist/core/hooks/worktree-events.js +158 -0
  163. package/dist/core/image/renderer.js +71 -0
  164. package/dist/core/init/detector.js +582 -0
  165. package/dist/core/init/template-renderer.js +242 -0
  166. package/dist/core/jobs/registry.js +18 -18
  167. package/dist/core/ledger/results-tsv.js +142 -0
  168. package/dist/core/log-discipline/stdout-redirect.js +51 -0
  169. package/dist/core/lsp/cache.js +105 -0
  170. package/dist/core/lsp/client.js +551 -41
  171. package/dist/core/lsp/language-detect.js +66 -0
  172. package/dist/core/lsp/post-edit-diagnostics.js +171 -0
  173. package/dist/core/lsp/server-detect.js +173 -0
  174. package/dist/core/lsp/symbol-cache.js +162 -0
  175. package/dist/core/lsp/symbol-tools.js +664 -0
  176. package/dist/core/mcp/client.js +97 -28
  177. package/dist/core/mcp/http-server.js +553 -0
  178. package/dist/core/mcp/orchestrator-config.js +192 -0
  179. package/dist/core/mcp/orchestrator-tools.js +806 -0
  180. package/dist/core/mcp/permission.js +190 -0
  181. package/dist/core/mcp/registry.js +39 -17
  182. package/dist/core/mcp/server-tools.js +219 -0
  183. package/dist/core/mcp/server.js +397 -0
  184. package/dist/core/mcp/trust.js +10 -10
  185. package/dist/core/memory/dual-write.js +416 -0
  186. package/dist/core/memory/passive-extract.js +130 -0
  187. package/dist/core/memory/phase1-kinds.js +20 -0
  188. package/dist/core/memory/secret-scanner.js +304 -0
  189. package/dist/core/memory-sync/queue.js +170 -0
  190. package/dist/core/metrics/extract.js +113 -0
  191. package/dist/core/modes/roo-modes.js +68 -0
  192. package/dist/core/notes/notes-paths.js +113 -0
  193. package/dist/core/notes/notes-recorder.js +140 -0
  194. package/dist/core/notes/notes-writer.js +53 -0
  195. package/dist/core/notes/renderers.js +0 -0
  196. package/dist/core/notes/slug.js +105 -0
  197. package/dist/core/onboarding/ensure-initialized.js +133 -0
  198. package/dist/core/onboarding/marker.js +111 -0
  199. package/dist/core/onboarding/telemetry-state.js +108 -0
  200. package/dist/core/output-style/presets.js +176 -0
  201. package/dist/core/output-style/state.js +185 -0
  202. package/dist/core/path-security.js +287 -5
  203. package/dist/core/permission.js +82 -22
  204. package/dist/core/permissions/auto-classifier.js +124 -0
  205. package/dist/core/permissions/bash-parser.js +371 -0
  206. package/dist/core/permissions/circuit-breaker.js +83 -0
  207. package/dist/core/permissions/constrained-edit.js +91 -0
  208. package/dist/core/permissions/gate.js +278 -0
  209. package/dist/core/permissions/index.js +20 -0
  210. package/dist/core/permissions/mode.js +174 -0
  211. package/dist/core/permissions/network-egress.js +137 -0
  212. package/dist/core/permissions/state.js +241 -0
  213. package/dist/core/permissions/tool-class.js +107 -0
  214. package/dist/core/plan-mode/ui-state.js +51 -0
  215. package/dist/core/plans/plan-artifact.js +721 -0
  216. package/dist/core/policy-limits/etag-store.js +122 -0
  217. package/dist/core/prd-check/parser.js +215 -0
  218. package/dist/core/prd-check/reporter.js +127 -0
  219. package/dist/core/prd-check/session-review.js +557 -0
  220. package/dist/core/prd-check/verifiers.js +223 -0
  221. package/dist/core/prompt-cache/client-cache.js +99 -0
  222. package/dist/core/prompts/assembly.js +29 -0
  223. package/dist/core/prompts/registry.js +364 -0
  224. package/dist/core/pugi-gitignore.js +52 -0
  225. package/dist/core/pugi-md/cc-compat-rules.js +735 -0
  226. package/dist/core/pugi-md/context-injector.js +76 -0
  227. package/dist/core/pugi-md/walk-up.js +207 -0
  228. package/dist/core/python/uv-installer.js +270 -0
  229. package/dist/core/python/uv-resolver.js +83 -0
  230. package/dist/core/rate-limit/narrator.js +146 -0
  231. package/dist/core/recipes/cli-types.js +20 -0
  232. package/dist/core/recipes/loader.js +103 -0
  233. package/dist/core/recipes/runner.js +345 -0
  234. package/dist/core/recipes/schema.js +587 -0
  235. package/dist/core/release-notes/parser.js +241 -0
  236. package/dist/core/release-notes/state.js +116 -0
  237. package/dist/core/repl/ask.js +37 -37
  238. package/dist/core/repl/cancellation.js +26 -26
  239. package/dist/core/repl/cap-warning.js +4 -4
  240. package/dist/core/repl/clipboard-read.js +11 -11
  241. package/dist/core/repl/dispatch-fsm.js +12 -12
  242. package/dist/core/repl/engine-bridge.js +303 -0
  243. package/dist/core/repl/history-search.js +15 -15
  244. package/dist/core/repl/history.js +28 -18
  245. package/dist/core/repl/kill-ring.js +5 -5
  246. package/dist/core/repl/model-pricing.js +135 -0
  247. package/dist/core/repl/privacy-banner.js +22 -22
  248. package/dist/core/repl/session.js +2690 -229
  249. package/dist/core/repl/slash-commands.js +540 -41
  250. package/dist/core/repl/store/index.js +1 -1
  251. package/dist/core/repl/store/jsonl-log.js +22 -22
  252. package/dist/core/repl/store/lockfile.js +10 -10
  253. package/dist/core/repl/store/session-store.js +136 -107
  254. package/dist/core/repl/store/types.js +15 -15
  255. package/dist/core/repl/store/uuid-v7.js +12 -12
  256. package/dist/core/repl/tool-route.js +382 -0
  257. package/dist/core/repl/workspace-context.js +43 -21
  258. package/dist/core/repo-map/build.js +125 -0
  259. package/dist/core/repo-map/cache.js +185 -0
  260. package/dist/core/repo-map/extractor.js +254 -0
  261. package/dist/core/repo-map/formatter.js +145 -0
  262. package/dist/core/repo-map/page-rank.js +105 -0
  263. package/dist/core/repo-map/scanner.js +211 -0
  264. package/dist/core/retro/git-collector.js +251 -0
  265. package/dist/core/retro/health-card.js +25 -0
  266. package/dist/core/retro/metrics.js +342 -0
  267. package/dist/core/retro/narrative.js +249 -0
  268. package/dist/core/retro/plane-collector.js +274 -0
  269. package/dist/core/retro/pr-issue-link.js +65 -0
  270. package/dist/core/retro/types.js +16 -0
  271. package/dist/core/retry-budget/budget.js +284 -0
  272. package/dist/core/retry-budget/index.js +5 -0
  273. package/dist/core/retry-budget/retry-cap.js +74 -0
  274. package/dist/core/routing/lead-worker.js +43 -0
  275. package/dist/core/routing/pre-flight-estimator.js +108 -0
  276. package/dist/core/runs/run-tree.js +103 -0
  277. package/dist/core/sandboxing/adapter.js +43 -0
  278. package/dist/core/sandboxing/bubblewrap.js +209 -0
  279. package/dist/core/sandboxing/index.js +78 -0
  280. package/dist/core/sandboxing/none.js +19 -0
  281. package/dist/core/sandboxing/policy.js +97 -0
  282. package/dist/core/sandboxing/seatbelt.js +231 -0
  283. package/dist/core/security/injection-scanner.js +367 -0
  284. package/dist/core/security/output-filter.js +418 -0
  285. package/dist/core/session/env-file.js +105 -0
  286. package/dist/core/session/section-budgets.js +140 -0
  287. package/dist/core/session.js +119 -0
  288. package/dist/core/settings.js +402 -5
  289. package/dist/core/share/formatter.js +271 -0
  290. package/dist/core/share/redactor.js +221 -0
  291. package/dist/core/share/uploader.js +267 -0
  292. package/dist/core/skills/defaults.js +30 -30
  293. package/dist/core/skills/loader.js +22 -22
  294. package/dist/core/skills/sources.js +27 -27
  295. package/dist/core/smoke/headless-driver.js +174 -0
  296. package/dist/core/smoke/orchestrator.js +194 -0
  297. package/dist/core/smoke/runner.js +238 -0
  298. package/dist/core/smoke/scenario-parser.js +316 -0
  299. package/dist/core/statusline.js +99 -0
  300. package/dist/core/subagents/dispatcher-real.js +600 -0
  301. package/dist/core/subagents/dispatcher.js +146 -52
  302. package/dist/core/subagents/index.js +19 -6
  303. package/dist/core/subagents/isolation-matrix.js +213 -0
  304. package/dist/core/subagents/spawn.js +19 -4
  305. package/dist/core/telemetry/emitter.js +229 -0
  306. package/dist/core/telemetry/queue.js +251 -0
  307. package/dist/core/theme/context.js +91 -0
  308. package/dist/core/theme/presets.js +228 -0
  309. package/dist/core/theme/state.js +181 -0
  310. package/dist/core/todos/invariant.js +10 -0
  311. package/dist/core/todos/state.js +177 -0
  312. package/dist/core/tool-schema/compressor.js +89 -0
  313. package/dist/core/transport/version-interceptor.js +166 -0
  314. package/dist/core/trust.js +2 -2
  315. package/dist/core/tui/thinking-block.js +64 -0
  316. package/dist/core/vim/keymap.js +288 -0
  317. package/dist/core/vim/state.js +92 -0
  318. package/dist/core/watch-markers/marker-watcher.js +133 -0
  319. package/dist/core/worktree/include-parser.js +249 -0
  320. package/dist/core/worktree-manager/cleanup.js +123 -0
  321. package/dist/core/worktree-manager/manager.js +303 -0
  322. package/dist/index.js +36 -0
  323. package/dist/runtime/bootstrap.js +190 -0
  324. package/dist/runtime/cli.js +4403 -561
  325. package/dist/runtime/commands/agents.js +31 -31
  326. package/dist/runtime/commands/budget.js +5 -5
  327. package/dist/runtime/commands/cancel.js +231 -0
  328. package/dist/runtime/commands/chain.js +489 -0
  329. package/dist/runtime/commands/codegraph-status.js +227 -0
  330. package/dist/runtime/commands/compact.js +297 -0
  331. package/dist/runtime/commands/config.js +74 -40
  332. package/dist/runtime/commands/cost.js +199 -0
  333. package/dist/runtime/commands/delegate.js +27 -4
  334. package/dist/runtime/commands/dispatch.js +126 -0
  335. package/dist/runtime/commands/doctor.js +579 -0
  336. package/dist/runtime/commands/eval-v1.js +266 -0
  337. package/dist/runtime/commands/feedback.js +184 -0
  338. package/dist/runtime/commands/hooks.js +187 -0
  339. package/dist/runtime/commands/index-cmd.js +459 -0
  340. package/dist/runtime/commands/init.js +254 -0
  341. package/dist/runtime/commands/lsp.js +200 -38
  342. package/dist/runtime/commands/mcp.js +935 -0
  343. package/dist/runtime/commands/memory.js +582 -0
  344. package/dist/runtime/commands/model.js +237 -0
  345. package/dist/runtime/commands/onboarding.js +275 -0
  346. package/dist/runtime/commands/patch.js +12 -12
  347. package/dist/runtime/commands/permissions.js +112 -0
  348. package/dist/runtime/commands/plan.js +143 -0
  349. package/dist/runtime/commands/prd-check.js +285 -0
  350. package/dist/runtime/commands/privacy.js +17 -17
  351. package/dist/runtime/commands/recipe.js +325 -0
  352. package/dist/runtime/commands/redo-blob-store.js +92 -0
  353. package/dist/runtime/commands/redo.js +361 -0
  354. package/dist/runtime/commands/release-notes.js +229 -0
  355. package/dist/runtime/commands/repo-map.js +95 -0
  356. package/dist/runtime/commands/report.js +299 -0
  357. package/dist/runtime/commands/resume.js +118 -0
  358. package/dist/runtime/commands/review-consensus.js +68 -53
  359. package/dist/runtime/commands/rewind.js +333 -0
  360. package/dist/runtime/commands/roster.js +14 -14
  361. package/dist/runtime/commands/servers-cli.js +182 -0
  362. package/dist/runtime/commands/servers.js +236 -0
  363. package/dist/runtime/commands/sessions.js +163 -0
  364. package/dist/runtime/commands/share.js +316 -0
  365. package/dist/runtime/commands/skills.js +31 -31
  366. package/dist/runtime/commands/status.js +186 -0
  367. package/dist/runtime/commands/stickers.js +82 -0
  368. package/dist/runtime/commands/style.js +194 -0
  369. package/dist/runtime/commands/theme.js +196 -0
  370. package/dist/runtime/commands/undo.js +54 -22
  371. package/dist/runtime/commands/update.js +289 -0
  372. package/dist/runtime/commands/vim.js +140 -0
  373. package/dist/runtime/commands/worktree.js +8 -8
  374. package/dist/runtime/commands/worktrees.js +155 -0
  375. package/dist/runtime/deprecation-warning.js +69 -0
  376. package/dist/runtime/engine-exit-code.js +50 -0
  377. package/dist/runtime/headless-repl.js +195 -0
  378. package/dist/runtime/headless.js +548 -0
  379. package/dist/runtime/load-hooks-or-exit.js +71 -0
  380. package/dist/runtime/plan-decompose.js +22 -22
  381. package/dist/runtime/sigint-guard.js +272 -0
  382. package/dist/runtime/stream-renderer.js +195 -0
  383. package/dist/runtime/update-check.js +28 -28
  384. package/dist/runtime/version.js +65 -0
  385. package/dist/runtime/worktree-bootstrap.js +579 -0
  386. package/dist/skills/bundled/batch.js +617 -0
  387. package/dist/skills/bundled/index.js +45 -0
  388. package/dist/skills/bundled/loop.js +358 -0
  389. package/dist/skills/bundled/remember.js +383 -0
  390. package/dist/skills/bundled/simplify.js +289 -0
  391. package/dist/skills/bundled/skillify.js +373 -0
  392. package/dist/skills/bundled/stuck.js +558 -0
  393. package/dist/skills/bundled/verify.js +439 -0
  394. package/dist/testing/vcr.js +486 -0
  395. package/dist/tools/agent-tool.js +229 -0
  396. package/dist/tools/apply-patch.js +89 -28
  397. package/dist/tools/ask-user-question.js +337 -0
  398. package/dist/tools/ask-user.js +115 -0
  399. package/dist/tools/bash.js +811 -49
  400. package/dist/tools/brief.js +224 -0
  401. package/dist/tools/cron.js +433 -0
  402. package/dist/tools/enter-worktree.js +250 -0
  403. package/dist/tools/exit-worktree.js +147 -0
  404. package/dist/tools/file-tools.js +161 -44
  405. package/dist/tools/http-request.js +336 -0
  406. package/dist/tools/lsp-tools.js +377 -1
  407. package/dist/tools/mcp-tool.js +260 -0
  408. package/dist/tools/multi-edit.js +361 -0
  409. package/dist/tools/powershell.js +268 -0
  410. package/dist/tools/registry.js +120 -5
  411. package/dist/tools/server-tools.js +892 -0
  412. package/dist/tools/skill-tool.js +96 -0
  413. package/dist/tools/sleep.js +99 -0
  414. package/dist/tools/synthetic-output.js +133 -0
  415. package/dist/tools/tasks.js +208 -0
  416. package/dist/tools/todo-write.js +184 -0
  417. package/dist/tools/verify-plan-execution.js +295 -0
  418. package/dist/tools/web-fetch-injection-scanner.js +207 -0
  419. package/dist/tools/web-fetch.js +195 -10
  420. package/dist/tools/web-search.js +458 -0
  421. package/dist/tui/agent-progress-card.js +111 -0
  422. package/dist/tui/agent-tree.js +22 -1
  423. package/dist/tui/ask-modal.js +14 -14
  424. package/dist/tui/ask-user-question-chips.js +315 -0
  425. package/dist/tui/ask-user-question-prompt.js +203 -0
  426. package/dist/tui/compact-banner.js +81 -0
  427. package/dist/tui/conversation-pane.js +85 -11
  428. package/dist/tui/cost-table.js +111 -0
  429. package/dist/tui/device-flow.js +2 -2
  430. package/dist/tui/doctor-table.js +46 -0
  431. package/dist/tui/feedback-prompt.js +156 -0
  432. package/dist/tui/input-box.js +247 -32
  433. package/dist/tui/login-picker.js +3 -3
  434. package/dist/tui/markdown-render.js +6 -6
  435. package/dist/tui/multi-file-diff-approval.js +375 -0
  436. package/dist/tui/onboarding-wizard.js +240 -0
  437. package/dist/tui/permissions-picker.js +86 -0
  438. package/dist/tui/render.js +36 -1
  439. package/dist/tui/repl-render.js +239 -25
  440. package/dist/tui/repl-splash-art.js +16 -16
  441. package/dist/tui/repl-splash-mascot.js +48 -24
  442. package/dist/tui/repl-splash.js +22 -22
  443. package/dist/tui/repl.js +125 -45
  444. package/dist/tui/slash-palette.js +6 -6
  445. package/dist/tui/splash.js +2 -2
  446. package/dist/tui/status-bar.js +109 -31
  447. package/dist/tui/status-table.js +7 -0
  448. package/dist/tui/stickers-art.js +136 -0
  449. package/dist/tui/style-table.js +28 -0
  450. package/dist/tui/theme-table.js +29 -0
  451. package/dist/tui/thinking-spinner.js +123 -0
  452. package/dist/tui/tool-stream-pane.js +53 -4
  453. package/dist/tui/update-banner.js +27 -2
  454. package/dist/tui/vim-input.js +267 -0
  455. package/dist/tui/welcome-banner.js +107 -0
  456. package/dist/tui/welcome-data.js +293 -0
  457. package/dist/tui/workspace-context.js +2 -2
  458. package/package.json +29 -6
  459. package/test/scenarios/codegen-create-file.scenario.txt +13 -0
  460. package/test/scenarios/compact-force.scenario.txt +12 -0
  461. package/test/scenarios/identity.scenario.txt +11 -0
  462. package/test/scenarios/persona-handoff.scenario.txt +12 -0
  463. package/test/scenarios/walkback.scenario.txt +12 -0
  464. package/dist/core/engine/compaction-hook.js +0 -154
@@ -0,0 +1,333 @@
1
+ /**
2
+ * `/rewind` runtime — .
3
+ *
4
+ * Three invocation modes, sharing one runner:
5
+ *
6
+ * - `/rewind N` drop the last N operator turns + every
7
+ * tool call that landed between.
8
+ * - `/rewind --to <id>` rewind to a specific event index from the
9
+ * visible (post-mask) transcript.
10
+ * - `/rewind` interactive picker — surfaces the last 10
11
+ * user-turn boundaries (newest-first) and
12
+ * returns a payload the caller can use to
13
+ * mount a select prompt.
14
+ *
15
+ * The rewind is APPEND-ONLY: we never delete events. `applyRewindMask`
16
+ * elides the masked range on read; `pugi sessions undo-rewind` appends
17
+ * an inverse marker that nullifies the latest rewind so operators have
18
+ * a reliable escape hatch.
19
+ *
20
+ * Surface contract (same shape as `runCompactCommand`):
21
+ *
22
+ * - Returns a structured result for the JSON path.
23
+ * - Calls `ctx.writeOutput(payload, text)` once per invocation.
24
+ * - Throws ONLY on programmer-error. Store failures, missing
25
+ * sessions, etc. are surfaced as `failed_*` statuses.
26
+ *
27
+ * Exit codes (mapped by the dispatcher in cli.ts):
28
+ *
29
+ * 0 — marker appended OR picker surfaced
30
+ * 1 — store unavailable / session not found
31
+ * 2 — noop (asked to drop 0 turns, nothing to rewind, etc.)
32
+ */
33
+ import { homedir } from 'node:os';
34
+ import { slugForCwd } from '../../core/repl/history.js';
35
+ import { appendRewindMarker, buildRewindPickerRows, pickRewindTargetForTurns, resolveEventIdToIndex, } from '../../core/checkpoint/rewinder.js';
36
+ import { loadFromStore } from '../../core/checkpoint/resumer.js';
37
+ import { SqliteSessionStore, resolveProjectStoreDir, } from '../../core/repl/store/session-store.js';
38
+ /**
39
+ * Entry point reused by the slash command + the top-level dispatcher.
40
+ *
41
+ * `args` accepts:
42
+ * - `[]` picker mode
43
+ * - `["N"]` drop last N turns
44
+ * - `["--to", "<id>"]` rewind to event id
45
+ *
46
+ * Both `-N` and `--turns N` are accepted for parity with the upstream tool's
47
+ * `--turns` flag.
48
+ */
49
+ export async function runRewindCommand(args, ctx) {
50
+ const parsed = parseRewindArgs(args);
51
+ if (parsed.kind === 'error') {
52
+ return emit(ctx, {
53
+ command: 'rewind',
54
+ status: 'failed_parse',
55
+ reason: parsed.message,
56
+ }, parsed.message);
57
+ }
58
+ // Resolve session + store.
59
+ const slug = slugForCwd(ctx.workspaceRoot);
60
+ let store = ctx.store ?? null;
61
+ let sessionId = ctx.sessionId ?? null;
62
+ let storeOpenedHere = false;
63
+ if (store === null) {
64
+ sessionId = sessionId ?? (await pickMostRecentSessionIdReadOnly(slug));
65
+ if (!sessionId) {
66
+ return emit(ctx, {
67
+ command: 'rewind',
68
+ status: 'failed_no_session',
69
+ reason: 'No active session to rewind. Start a REPL with `pugi`.',
70
+ });
71
+ }
72
+ const opened = await openLiveStore(slug, sessionId);
73
+ if (!opened) {
74
+ return emit(ctx, {
75
+ command: 'rewind',
76
+ status: 'failed_store',
77
+ sessionId,
78
+ reason: 'Could not open local session store (lock held by another REPL?).',
79
+ });
80
+ }
81
+ store = opened;
82
+ storeOpenedHere = true;
83
+ }
84
+ else if (sessionId === null) {
85
+ const rows = await store.listSessions({ project: slug, limit: 1, status: 'active' });
86
+ if (rows.length === 0) {
87
+ return emit(ctx, {
88
+ command: 'rewind',
89
+ status: 'failed_no_session',
90
+ reason: 'No active session to rewind.',
91
+ });
92
+ }
93
+ sessionId = rows[0].id;
94
+ }
95
+ try {
96
+ const loaded = await loadFromStore(store, sessionId);
97
+ if (!loaded) {
98
+ return emit(ctx, {
99
+ command: 'rewind',
100
+ status: 'failed_no_session',
101
+ sessionId,
102
+ reason: `Session '${sessionId}' not found.`,
103
+ });
104
+ }
105
+ // Picker mode: surface the last 10 user-turn boundaries.
106
+ if (parsed.kind === 'picker') {
107
+ const rows = buildRewindPickerRows(loaded.rawEvents, 10);
108
+ if (rows.length === 0) {
109
+ return emit(ctx, {
110
+ command: 'rewind',
111
+ status: 'noop_empty',
112
+ sessionId,
113
+ reason: 'No operator turns to rewind to.',
114
+ }, 'Nothing to rewind — no operator turns yet.');
115
+ }
116
+ const pickerRows = rows.map((r) => ({
117
+ visibleIndex: r.visibleIndex,
118
+ turnsAgo: r.turnsAgo,
119
+ preview: r.preview,
120
+ timestampEpochMs: r.timestampEpochMs,
121
+ }));
122
+ const text = renderPicker(pickerRows);
123
+ return emit(ctx, {
124
+ command: 'rewind',
125
+ status: 'picker',
126
+ sessionId,
127
+ pickerRows,
128
+ }, text);
129
+ }
130
+ // Resolve target index.
131
+ let toEventIndex;
132
+ let turnsRewound;
133
+ if (parsed.kind === 'turns') {
134
+ if (parsed.n <= 0) {
135
+ return emit(ctx, {
136
+ command: 'rewind',
137
+ status: 'noop_zero',
138
+ sessionId,
139
+ reason: 'Asked to drop 0 turns — nothing to do.',
140
+ }, 'Asked to drop 0 turns — nothing to do.');
141
+ }
142
+ const target = pickRewindTargetForTurns(loaded.rawEvents, parsed.n);
143
+ if (target.turnsRewound === 0) {
144
+ return emit(ctx, {
145
+ command: 'rewind',
146
+ status: 'noop_empty',
147
+ sessionId,
148
+ reason: 'No operator turns to rewind.',
149
+ }, 'No operator turns to rewind.');
150
+ }
151
+ toEventIndex = target.toEventIndex;
152
+ turnsRewound = target.turnsRewound;
153
+ }
154
+ else {
155
+ // mode === 'to-event'
156
+ const resolvedIdx = resolveEventIdToIndex(loaded.rawEvents, parsed.eventId);
157
+ if (resolvedIdx === null) {
158
+ return emit(ctx, {
159
+ command: 'rewind',
160
+ status: 'failed_parse',
161
+ sessionId,
162
+ reason: `Could not resolve event id '${parsed.eventId}'. Try \`/rewind\` for the picker.`,
163
+ });
164
+ }
165
+ toEventIndex = resolvedIdx;
166
+ // Count user turns in the masked range to report turnsRewound.
167
+ turnsRewound = countUserTurnsAfter(loaded.rawEvents, toEventIndex);
168
+ }
169
+ const fromEventIndex = loaded.rawEvents.length;
170
+ await appendRewindMarker({
171
+ store,
172
+ toEventIndex,
173
+ fromEventIndex,
174
+ turnsRewound,
175
+ reason: parsed.kind === 'turns' ? 'manual' : 'to-event',
176
+ ...(ctx.now !== undefined ? { now: ctx.now } : {}),
177
+ });
178
+ // Reload + recompute visible count for the operator banner.
179
+ const after = await loadFromStore(store, sessionId);
180
+ const visibleAfter = after?.visibleEvents.length ?? 0;
181
+ const banner = `Rewound ${turnsRewound} turn${turnsRewound === 1 ? '' : 's'} ` +
182
+ `(to event ${toEventIndex < 0 ? 'start' : `#${toEventIndex + 1}`}). ` +
183
+ `${visibleAfter} event${visibleAfter === 1 ? '' : 's'} now visible. ` +
184
+ `Undo with \`pugi sessions undo-rewind\`.`;
185
+ return emit(ctx, {
186
+ command: 'rewind',
187
+ status: 'rewound',
188
+ sessionId,
189
+ turnsRewound,
190
+ toEventIndex,
191
+ fromEventIndex,
192
+ visibleAfter,
193
+ }, banner);
194
+ }
195
+ finally {
196
+ if (storeOpenedHere && store) {
197
+ try {
198
+ await store.close();
199
+ }
200
+ catch {
201
+ /* idempotent */
202
+ }
203
+ }
204
+ }
205
+ }
206
+ /**
207
+ * Accepts:
208
+ * pugi rewind -> picker
209
+ * pugi rewind 3 -> drop 3 turns
210
+ * pugi rewind --turns 3 -> same
211
+ * pugi rewind --to 12 -> rewind to event index 12 (1-based visible)
212
+ * pugi rewind --to #12 -> rewind to event index 12 (0-based hidden)
213
+ */
214
+ function parseRewindArgs(args) {
215
+ if (args.length === 0)
216
+ return { kind: 'picker' };
217
+ const head = args[0];
218
+ // --to <id>
219
+ if (head === '--to' || head === '-t') {
220
+ const eventId = args[1];
221
+ if (!eventId) {
222
+ return {
223
+ kind: 'error',
224
+ message: 'Usage: pugi rewind --to <event-id>',
225
+ };
226
+ }
227
+ return { kind: 'to-event', eventId };
228
+ }
229
+ if (head.startsWith('--to=')) {
230
+ const eventId = head.slice('--to='.length);
231
+ if (eventId.length === 0) {
232
+ return {
233
+ kind: 'error',
234
+ message: 'Usage: pugi rewind --to <event-id>',
235
+ };
236
+ }
237
+ return { kind: 'to-event', eventId };
238
+ }
239
+ // --turns N OR -N OR positional N
240
+ if (head === '--turns' || head === '-n') {
241
+ const n = Number.parseInt(args[1] ?? '', 10);
242
+ if (!Number.isFinite(n) || n < 0) {
243
+ return {
244
+ kind: 'error',
245
+ message: 'Usage: pugi rewind --turns <N>',
246
+ };
247
+ }
248
+ return { kind: 'turns', n };
249
+ }
250
+ if (head.startsWith('--turns=')) {
251
+ const n = Number.parseInt(head.slice('--turns='.length), 10);
252
+ if (!Number.isFinite(n) || n < 0) {
253
+ return {
254
+ kind: 'error',
255
+ message: 'Usage: pugi rewind --turns <N>',
256
+ };
257
+ }
258
+ return { kind: 'turns', n };
259
+ }
260
+ // Bare integer: positional turns count.
261
+ const positional = Number.parseInt(head, 10);
262
+ if (Number.isFinite(positional) && positional >= 0) {
263
+ return { kind: 'turns', n: positional };
264
+ }
265
+ return {
266
+ kind: 'error',
267
+ message: `Unknown argument '${head}'. Try \`pugi rewind\`, \`pugi rewind <N>\`, or \`pugi rewind --to <id>\`.`,
268
+ };
269
+ }
270
+ function emit(ctx, payload, text) {
271
+ const human = text ?? payload.reason ?? `rewind: ${payload.status}`;
272
+ ctx.writeOutput(payload, human);
273
+ return payload;
274
+ }
275
+ function renderPicker(rows) {
276
+ const lines = ['Rewind picker — pick a turn boundary:', ''];
277
+ for (const r of rows) {
278
+ const tag = `[#${r.visibleIndex.toString().padStart(3)}]`;
279
+ const ago = `${r.turnsAgo}t ago`.padStart(8);
280
+ lines.push(` ${tag} ${ago} ${r.preview}`);
281
+ }
282
+ lines.push('', 'Rewind with: pugi rewind --to <#N> (or `pugi rewind <turnsToDrop>`).');
283
+ return lines.join('\n');
284
+ }
285
+ function countUserTurnsAfter(events, toEventIndex) {
286
+ let count = 0;
287
+ for (let i = toEventIndex + 1; i < events.length; i += 1) {
288
+ if (events[i].kind === 'user')
289
+ count += 1;
290
+ }
291
+ return count;
292
+ }
293
+ /**
294
+ * Open the SqliteSessionStore for the workspace's project slug, bound
295
+ * to `sessionId`. Returns null when the lock is held by another REPL.
296
+ */
297
+ async function openLiveStore(projectSlug, sessionId) {
298
+ try {
299
+ const store = new SqliteSessionStore({ projectSlug, home: homedir() });
300
+ await store.open({
301
+ id: sessionId,
302
+ workspaceRoot: process.cwd(),
303
+ projectSlug,
304
+ });
305
+ return store;
306
+ }
307
+ catch {
308
+ return null;
309
+ }
310
+ }
311
+ /**
312
+ * Discover the most recent active session id for a project slug,
313
+ * without taking the writer lockfile. Used by the standalone CLI path
314
+ * (no `--session` flag) so a live REPL holding the lock does not block
315
+ * the lookup.
316
+ */
317
+ async function pickMostRecentSessionIdReadOnly(projectSlug) {
318
+ try {
319
+ const dir = resolveProjectStoreDir(projectSlug, homedir());
320
+ const view = await SqliteSessionStore.openReadOnly(dir);
321
+ try {
322
+ const rows = await view.list({ project: projectSlug, limit: 1, status: 'active' });
323
+ return rows.length > 0 ? rows[0].id : null;
324
+ }
325
+ finally {
326
+ await view.close();
327
+ }
328
+ }
329
+ catch {
330
+ return null;
331
+ }
332
+ }
333
+ //# sourceMappingURL=rewind.js.map
@@ -1,26 +1,26 @@
1
1
  /**
2
- * `pugi roster` command - α7.5 Tier 1 instantiation Phase 1.
2
+ * `pugi roster` command - Tier 1 instantiation Phase 1.
3
3
  *
4
4
  * Lists the live Tier 1 personas with display name, role, and routing
5
5
  * tag. The CLI walks two sources in order:
6
6
  *
7
- * 1. The local @pugi/personas roster (THE_TEN). Always succeeds; the
8
- * ten brand-canonical personas are baked into the SDK.
9
- * 2. The remote `GET /api/pugi/sessions/roster` endpoint when the
10
- * operator has a valid credential. The remote response carries the
11
- * server-side dispatch role + dispatchTag for each slug so the
12
- * operator sees the actual routing decision the dispatcher will
13
- * apply on a `pugi delegate <slug>` call.
7
+ * 1. The local @pugi/personas roster (THE_TEN). Always succeeds; the
8
+ * ten brand-canonical personas are baked into the SDK.
9
+ * 2. The remote `GET /api/pugi/sessions/roster` endpoint when the
10
+ * operator has a valid credential. The remote response carries the
11
+ * server-side dispatch role + dispatchTag for each slug so the
12
+ * operator sees the actual routing decision the dispatcher will
13
+ * apply on a `pugi delegate <slug>` call.
14
14
  *
15
15
  * The command never fails if the network is unreachable - it falls back
16
16
  * to local-only output with a one-line warning. This matches the
17
- * local-first contract (ADR-0037): the operator can still see who is on
17
+ * local-first contract : the operator can still see who is on
18
18
  * the team without an API key.
19
19
  *
20
20
  * Output:
21
- * - text default: a 3-column table (slug | name | role).
22
- * - --json: a structured array of { slug, name, role, totem,
23
- * dispatchTag } records, used by scripted callers.
21
+ * - text default: a 3-column table (slug | name | role).
22
+ * - --json: a structured array of { slug, name, role, totem,
23
+ * dispatchTag } records, used by scripted callers.
24
24
  */
25
25
  import { THE_TEN } from '@pugi/personas';
26
26
  import { fetchPersonaRoster, } from '@pugi/sdk';
@@ -85,7 +85,7 @@ export function renderRosterTable(rows) {
85
85
  dispatchTag: Math.max(head.dispatchTag.length, ...rows.map((r) => r.dispatchTag.length)),
86
86
  };
87
87
  const pad = (s, width) => s + ' '.repeat(Math.max(0, width - s.length));
88
- const line = (r) => [pad(r.slug, widths.slug), pad(r.name, widths.name), pad(r.totem, widths.totem), pad(r.role, widths.role), pad(r.dispatchTag, widths.dispatchTag)].join(' ');
88
+ const line = (r) => [pad(r.slug, widths.slug), pad(r.name, widths.name), pad(r.totem, widths.totem), pad(r.role, widths.role), pad(r.dispatchTag, widths.dispatchTag)].join(' ');
89
89
  const header = line(head);
90
90
  const sep = '-'.repeat(header.length);
91
91
  return [header, sep, ...rows.map((r) => line(r))].join('\n');
@@ -107,7 +107,7 @@ export async function resolveRoster(config) {
107
107
  return { rows: mergeRoster(THE_TEN, result.response.personas), warning: null };
108
108
  }
109
109
  const reason = result.status === 'endpoint_missing'
110
- ? 'runtime does not expose /api/pugi/sessions/roster (upgrade admin-api to α7.5+)'
110
+ ? 'runtime does not expose /api/pugi/sessions/roster (upgrade admin-api to +)'
111
111
  : result.message;
112
112
  return {
113
113
  rows: mergeRoster(THE_TEN, null),
@@ -0,0 +1,182 @@
1
+ /**
2
+ * PR M (2026-06-05): `pugi servers` top-level CLI surface.
3
+ *
4
+ * Operator pain (CEO 2026-06-05): PR H #919 added the `/servers` slash
5
+ * command so the REPL can list and kill processes tracked by
6
+ * `server_start`. That covers the in-REPL case, but the most painful
7
+ * regression is when the operator closes the REPL (Ctrl+D, crash,
8
+ * accidental window close) and a Vite/Next dev server keeps holding
9
+ * port 5173. With the slash-only surface, the only way back is
10
+ * `lsof -i :5173 | xargs kill -9`. `pugi servers` ports the same
11
+ * primitive to a shell-invocable subcommand so the orphan path is one
12
+ * command: `pugi servers stop all`.
13
+ *
14
+ * Surface mirrors the slash exactly to keep operator muscle memory:
15
+ *
16
+ * pugi servers list tracked servers
17
+ * pugi servers stop <runId> kill by srv-<uuid>
18
+ * pugi servers stop <pid> kill by numeric pid
19
+ * pugi servers stop all kill every alive entry
20
+ * pugi servers --workspace <path> use <path>/.pugi/runs/ instead
21
+ * of process.cwd() (orphan rescue)
22
+ * pugi servers --help print usage + exit 0
23
+ *
24
+ * This is a thin wrapper around `listServers` / `stopServers` /
25
+ * `runServersCommand` already exported by `commands/servers.ts` (the
26
+ * slash-command runner). Library coverage of the underlying primitive
27
+ * lives in `test/servers-command.spec.ts`; this module owns only the
28
+ * argv contract + exit codes, mirroring the `flatten-command` /
29
+ * `flatten-repo` split.
30
+ *
31
+ * Exit codes:
32
+ * 0 - success (list, empty, stopped, --help)
33
+ * 2 - invalid CLI args (unknown flag, missing target, malformed --workspace)
34
+ * 3 - not-found (stop <unknown>)
35
+ *
36
+ * The `--workspace` flag is parsed locally rather than pulled from the
37
+ * global `CliFlags` because `flags.workspace` already means something
38
+ * different (the headless workspace slug surfaced in `session.start`),
39
+ * and `flags.cwd` is reserved for the `--print` headless path. Local
40
+ * parsing keeps the wrapper self-contained and avoids a global-state
41
+ * collision the way `commands/index-cmd.ts` and `commands/flatten.ts`
42
+ * already do.
43
+ */
44
+ import { resolve } from 'node:path';
45
+ import { runServersCommand, } from './servers.js';
46
+ /**
47
+ * Single entry-point. Returns the desired process exit code so the
48
+ * dispatcher in `runtime/cli.ts` can propagate it via
49
+ * `process.exitCode`. Mirrors the `runIndexCommand` / `runFlattenCommand`
50
+ * shape.
51
+ */
52
+ export async function runServersCliCommand(args, ctx) {
53
+ const parsed = parseArgs(args);
54
+ switch (parsed.kind) {
55
+ case 'help':
56
+ return printHelp(ctx);
57
+ case 'error':
58
+ ctx.writeOutput({ ok: false, command: 'servers', error: parsed.message }, `pugi servers: ${parsed.message}`);
59
+ return 2;
60
+ case 'list':
61
+ case 'stop': {
62
+ const workspaceRoot = parsed.workspaceOverride !== null
63
+ ? resolve(parsed.workspaceOverride)
64
+ : ctx.workspaceRoot;
65
+ const lines = [];
66
+ const io = {
67
+ write: (line) => lines.push(line),
68
+ };
69
+ const mode = parsed.kind === 'list'
70
+ ? { kind: 'list' }
71
+ : { kind: 'stop', target: parsed.target };
72
+ const result = await runServersCommand(mode, io, { workspaceRoot });
73
+ const text = lines.join('\n');
74
+ ctx.writeOutput({
75
+ ok: result.kind !== 'not-found' && result.kind !== 'error',
76
+ command: 'servers',
77
+ mode: parsed.kind,
78
+ result,
79
+ }, text);
80
+ if (result.kind === 'not-found')
81
+ return 3;
82
+ if (result.kind === 'error')
83
+ return 1;
84
+ return 0;
85
+ }
86
+ }
87
+ }
88
+ /**
89
+ * Pure argv parser. Exported for the spec to pin canonical shapes.
90
+ *
91
+ * Accepted shapes:
92
+ * [] list
93
+ * ['--help'] | ['-h'] | ['help'] help
94
+ * ['--workspace', '/path'] list, workspace override
95
+ * ['--workspace=/path'] same, fused
96
+ * ['stop', '<target>'] stop
97
+ * ['stop', '<target>', '--workspace', '<p>'] stop with override
98
+ *
99
+ * Unknown flag or `stop` with no target is a structural error (exit 2).
100
+ */
101
+ export function parseArgs(args) {
102
+ let workspaceOverride = null;
103
+ const positional = [];
104
+ for (let i = 0; i < args.length; i += 1) {
105
+ const arg = args[i];
106
+ if (arg === undefined)
107
+ continue;
108
+ if (arg === '--help' || arg === '-h' || arg === 'help') {
109
+ return { kind: 'help' };
110
+ }
111
+ if (arg === '--workspace') {
112
+ const next = args[i + 1];
113
+ if (next === undefined || next.startsWith('-')) {
114
+ return { kind: 'error', message: '--workspace requires a path argument.' };
115
+ }
116
+ workspaceOverride = next;
117
+ i += 1;
118
+ continue;
119
+ }
120
+ if (arg.startsWith('--workspace=')) {
121
+ const value = arg.slice('--workspace='.length);
122
+ if (value.length === 0) {
123
+ return { kind: 'error', message: '--workspace requires a non-empty path.' };
124
+ }
125
+ workspaceOverride = value;
126
+ continue;
127
+ }
128
+ if (arg.startsWith('-')) {
129
+ return { kind: 'error', message: `unknown flag "${arg}"` };
130
+ }
131
+ positional.push(arg);
132
+ }
133
+ if (positional.length === 0) {
134
+ return { kind: 'list', workspaceOverride };
135
+ }
136
+ const [head, ...rest] = positional;
137
+ if (head === 'stop') {
138
+ if (rest.length === 0) {
139
+ return {
140
+ kind: 'error',
141
+ message: 'stop requires a target (runId, pid, or "all").',
142
+ };
143
+ }
144
+ if (rest.length > 1) {
145
+ return {
146
+ kind: 'error',
147
+ message: `stop accepts one target; got ${rest.length}.`,
148
+ };
149
+ }
150
+ return { kind: 'stop', target: rest[0], workspaceOverride };
151
+ }
152
+ return {
153
+ kind: 'error',
154
+ message: `unknown subcommand "${head}". Allowed: stop, --help.`,
155
+ };
156
+ }
157
+ function printHelp(ctx) {
158
+ ctx.writeOutput({ ok: true, command: 'servers', sub: 'help' }, [
159
+ 'pugi servers - list and stop dev servers tracked by server_start.',
160
+ '',
161
+ 'Usage:',
162
+ ' pugi servers List tracked servers (.pugi/runs/srv-*).',
163
+ ' pugi servers stop <runId> Kill one by srv-<uuid> runId.',
164
+ ' pugi servers stop <pid> Kill one by numeric pid.',
165
+ ' pugi servers stop all Kill every alive tracked server.',
166
+ '',
167
+ 'Options:',
168
+ ' --workspace <path> Use <path>/.pugi/runs/ instead of cwd.',
169
+ ' Handy when a server was orphaned in',
170
+ ' another repo and the REPL is gone.',
171
+ ' --help, -h Print this message and exit 0.',
172
+ '',
173
+ 'Exit codes:',
174
+ ' 0 success (list, empty, stopped)',
175
+ ' 2 usage error (unknown flag, missing target)',
176
+ ' 3 not-found (stop target did not match any tracked server)',
177
+ '',
178
+ 'Mirrors the in-REPL `/servers` slash command (PR H, beta.100+).',
179
+ ].join('\n'));
180
+ return 0;
181
+ }
182
+ //# sourceMappingURL=servers-cli.js.map