@pugi/cli 0.1.0-beta.1 → 0.1.0-beta.100

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/CHANGELOG.md +132 -0
  2. package/LICENSE +1 -1
  3. package/README.md +53 -11
  4. package/THIRD_PARTY_NOTICES.md +40 -0
  5. package/assets/pugi-mascot.ansi +15 -40
  6. package/assets/pugi-prozr2-mascot.ansi +9 -0
  7. package/bin/run.js +33 -1
  8. package/dist/commands/deploy.js +40 -40
  9. package/dist/commands/flatten.js +191 -0
  10. package/dist/commands/jobs-watch.js +201 -0
  11. package/dist/commands/jobs.js +42 -27
  12. package/dist/commands/retro.js +210 -0
  13. package/dist/commands/smoke.js +133 -0
  14. package/dist/core/agent-progress/cleanup.js +134 -0
  15. package/dist/core/agent-progress/schema.js +144 -0
  16. package/dist/core/agent-progress/writer.js +101 -0
  17. package/dist/core/agents/adaptive-router.js +330 -0
  18. package/dist/core/agents/query-decomposer.js +297 -0
  19. package/dist/core/agents/registry.js +3 -3
  20. package/dist/core/approvals/shortcut-resolver.js +98 -0
  21. package/dist/core/artifact-chain/dispatcher.js +148 -0
  22. package/dist/core/artifact-chain/exporter.js +164 -0
  23. package/dist/core/artifact-chain/state.js +243 -0
  24. package/dist/core/artifact-chain/steps.js +169 -0
  25. package/dist/core/ask-user/question.js +92 -0
  26. package/dist/core/audit/audit-trail.js +275 -0
  27. package/dist/core/auth/ensure-authenticated.js +129 -0
  28. package/dist/core/auth/env-provider.js +238 -0
  29. package/dist/core/auto-open-browser.js +4 -4
  30. package/dist/core/auto-update/channels.js +122 -0
  31. package/dist/core/auto-update/checker.js +241 -0
  32. package/dist/core/auto-update/state.js +235 -0
  33. package/dist/core/bare-mode/index.js +107 -0
  34. package/dist/core/bash/redirect.js +281 -0
  35. package/dist/core/bash-classifier.js +436 -40
  36. package/dist/core/checkpoint/resumer.js +149 -0
  37. package/dist/core/checkpoint/rewinder.js +291 -0
  38. package/dist/core/checkpoints/shadow-git.js +670 -0
  39. package/dist/core/citations/parser.js +109 -0
  40. package/dist/core/classifier/yolo-classifier.js +88 -0
  41. package/dist/core/codegraph/db.js +506 -0
  42. package/dist/core/codegraph/decision-store.js +248 -0
  43. package/dist/core/codegraph/detect-repo.js +459 -0
  44. package/dist/core/codegraph/install.js +134 -0
  45. package/dist/core/codegraph/offer-hook.js +220 -0
  46. package/dist/core/codegraph/parser.js +71 -0
  47. package/dist/core/codegraph/types.js +34 -0
  48. package/dist/core/compact/auto-trigger.js +96 -0
  49. package/dist/core/compact/buffer-rewriter.js +115 -0
  50. package/dist/core/compact/summarizer.js +208 -0
  51. package/dist/core/compact/token-counter.js +108 -0
  52. package/dist/core/consensus/anvil-fanout.js +25 -25
  53. package/dist/core/consensus/diff-capture.js +121 -12
  54. package/dist/core/consensus/rubric.js +21 -21
  55. package/dist/core/context/builder.js +6 -6
  56. package/dist/core/context/compaction-events.js +8 -8
  57. package/dist/core/context/compaction.js +31 -31
  58. package/dist/core/context/index.js +15 -8
  59. package/dist/core/context/invariants.js +51 -51
  60. package/dist/core/context/markdown-loader.js +28 -10
  61. package/dist/core/context/markdown-traverse.js +255 -0
  62. package/dist/core/context/pugiignore.js +41 -41
  63. package/dist/core/context/repo-skeleton.js +37 -37
  64. package/dist/core/context/tool-eviction.js +55 -0
  65. package/dist/core/context/watcher.js +32 -32
  66. package/dist/core/context/working-set.js +23 -23
  67. package/dist/core/coordinator/agent-tools.js +77 -0
  68. package/dist/core/coordinator/agent-toolset.js +65 -0
  69. package/dist/core/coordinator/fsm.js +73 -0
  70. package/dist/core/coordinator/mode-fsm.js +70 -0
  71. package/dist/core/cost/rate-card.js +129 -0
  72. package/dist/core/cost/tracker.js +221 -0
  73. package/dist/core/credentials.js +13 -13
  74. package/dist/core/cron/scheduler.js +138 -0
  75. package/dist/core/denial-tracking/index.js +8 -0
  76. package/dist/core/denial-tracking/state.js +264 -0
  77. package/dist/core/diagnostics/probe-runner.js +93 -0
  78. package/dist/core/diagnostics/probes/api.js +46 -0
  79. package/dist/core/diagnostics/probes/auth.js +93 -0
  80. package/dist/core/diagnostics/probes/bare-mode.js +42 -0
  81. package/dist/core/diagnostics/probes/cli-version.js +127 -0
  82. package/dist/core/diagnostics/probes/config.js +72 -0
  83. package/dist/core/diagnostics/probes/denial-tracking.js +57 -0
  84. package/dist/core/diagnostics/probes/disk.js +81 -0
  85. package/dist/core/diagnostics/probes/engine-live.js +46 -0
  86. package/dist/core/diagnostics/probes/git.js +65 -0
  87. package/dist/core/diagnostics/probes/hooks.js +118 -0
  88. package/dist/core/diagnostics/probes/mcp.js +75 -0
  89. package/dist/core/diagnostics/probes/node.js +59 -0
  90. package/dist/core/diagnostics/probes/pnpm.js +36 -0
  91. package/dist/core/diagnostics/probes/pugi-md.js +89 -0
  92. package/dist/core/diagnostics/probes/sandbox.js +72 -0
  93. package/dist/core/diagnostics/probes/session.js +74 -0
  94. package/dist/core/diagnostics/probes/status-snapshot.js +488 -0
  95. package/dist/core/diagnostics/probes/workspace.js +63 -0
  96. package/dist/core/diagnostics/types.js +70 -0
  97. package/dist/core/dispatch/cache-cleanup.js +197 -0
  98. package/dist/core/dispatch/cache-handoff.js +295 -0
  99. package/dist/core/edits/apply-patch-layer-e.js +189 -0
  100. package/dist/core/edits/dispatch.js +333 -7
  101. package/dist/core/edits/format-detector.js +260 -0
  102. package/dist/core/edits/format-matrix.js +26 -0
  103. package/dist/core/edits/fuzzy-ladder.js +650 -0
  104. package/dist/core/edits/index.js +5 -1
  105. package/dist/core/edits/journal.js +199 -0
  106. package/dist/core/edits/layer-a-apply.js +15 -15
  107. package/dist/core/edits/layer-a-fuzzy-apply.js +198 -0
  108. package/dist/core/edits/layer-b-apply.js +9 -9
  109. package/dist/core/edits/layer-c-apply.js +6 -6
  110. package/dist/core/edits/layer-d-ast.js +557 -14
  111. package/dist/core/edits/marker-parser.js +12 -12
  112. package/dist/core/edits/security-gate.js +27 -27
  113. package/dist/core/edits/verify-hook.js +273 -0
  114. package/dist/core/edits/worktree.js +322 -0
  115. package/dist/core/engine/anvil-client.js +214 -26
  116. package/dist/core/engine/auto-compact.js +247 -0
  117. package/dist/core/engine/budgets.js +220 -0
  118. package/dist/core/engine/compact-llm-summarizer.js +124 -0
  119. package/dist/core/engine/context-prefix.js +155 -0
  120. package/dist/core/engine/index.js +1 -1
  121. package/dist/core/engine/intensity.js +163 -0
  122. package/dist/core/engine/intent.js +260 -0
  123. package/dist/core/engine/native-pugi.js +1559 -227
  124. package/dist/core/engine/prompts.js +192 -16
  125. package/dist/core/engine/strip-internal-fields.js +124 -0
  126. package/dist/core/engine/tool-bridge.js +1887 -59
  127. package/dist/core/engine/verification-patterns.js +195 -0
  128. package/dist/core/evaluation/golden-dataset.js +293 -0
  129. package/dist/core/feedback/queue.js +177 -0
  130. package/dist/core/feedback/submitter.js +145 -0
  131. package/dist/core/file-cache.js +113 -1
  132. package/dist/core/flatten/flatten-repo.js +439 -0
  133. package/dist/core/format/osc8-link.js +28 -0
  134. package/dist/core/hook-chains.js +392 -0
  135. package/dist/core/hooks/citation-verify-hook.js +138 -0
  136. package/dist/core/hooks/citation-verify.js +112 -0
  137. package/dist/core/hooks/events.js +46 -0
  138. package/dist/core/hooks/index.js +15 -0
  139. package/dist/core/hooks/registry.js +216 -0
  140. package/dist/core/hooks/runner.js +236 -0
  141. package/dist/core/hooks/v2/event-emitter.js +115 -0
  142. package/dist/core/hooks/v2/executor.js +282 -0
  143. package/dist/core/hooks/v2/index.js +25 -0
  144. package/dist/core/hooks/v2/lifecycle.js +104 -0
  145. package/dist/core/hooks/v2/loader.js +216 -0
  146. package/dist/core/hooks/v2/matcher.js +125 -0
  147. package/dist/core/hooks/v2/trust.js +143 -0
  148. package/dist/core/hooks/v2/types.js +86 -0
  149. package/dist/core/hooks/worktree-events.js +158 -0
  150. package/dist/core/image/renderer.js +71 -0
  151. package/dist/core/init/detector.js +582 -0
  152. package/dist/core/init/template-renderer.js +242 -0
  153. package/dist/core/jobs/registry.js +18 -18
  154. package/dist/core/ledger/results-tsv.js +142 -0
  155. package/dist/core/log-discipline/stdout-redirect.js +51 -0
  156. package/dist/core/lsp/cache.js +105 -0
  157. package/dist/core/lsp/client.js +1229 -0
  158. package/dist/core/lsp/language-detect.js +66 -0
  159. package/dist/core/lsp/post-edit-diagnostics.js +171 -0
  160. package/dist/core/lsp/server-detect.js +173 -0
  161. package/dist/core/lsp/symbol-cache.js +162 -0
  162. package/dist/core/lsp/symbol-tools.js +664 -0
  163. package/dist/core/mcp/client.js +97 -28
  164. package/dist/core/mcp/http-server.js +553 -0
  165. package/dist/core/mcp/orchestrator-config.js +192 -0
  166. package/dist/core/mcp/orchestrator-tools.js +806 -0
  167. package/dist/core/mcp/permission.js +190 -0
  168. package/dist/core/mcp/registry.js +39 -17
  169. package/dist/core/mcp/server-tools.js +219 -0
  170. package/dist/core/mcp/server.js +397 -0
  171. package/dist/core/mcp/trust.js +10 -10
  172. package/dist/core/memory/dual-write.js +416 -0
  173. package/dist/core/memory/passive-extract.js +130 -0
  174. package/dist/core/memory/phase1-kinds.js +20 -0
  175. package/dist/core/memory/secret-scanner.js +304 -0
  176. package/dist/core/memory-sync/queue.js +170 -0
  177. package/dist/core/metrics/extract.js +113 -0
  178. package/dist/core/modes/roo-modes.js +68 -0
  179. package/dist/core/notes/notes-paths.js +113 -0
  180. package/dist/core/notes/notes-recorder.js +140 -0
  181. package/dist/core/notes/notes-writer.js +53 -0
  182. package/dist/core/notes/renderers.js +0 -0
  183. package/dist/core/notes/slug.js +105 -0
  184. package/dist/core/onboarding/ensure-initialized.js +133 -0
  185. package/dist/core/onboarding/marker.js +111 -0
  186. package/dist/core/onboarding/telemetry-state.js +108 -0
  187. package/dist/core/output-style/presets.js +176 -0
  188. package/dist/core/output-style/state.js +185 -0
  189. package/dist/core/path-security.js +287 -5
  190. package/dist/core/permission.js +82 -22
  191. package/dist/core/permissions/auto-classifier.js +124 -0
  192. package/dist/core/permissions/bash-parser.js +371 -0
  193. package/dist/core/permissions/circuit-breaker.js +83 -0
  194. package/dist/core/permissions/constrained-edit.js +91 -0
  195. package/dist/core/permissions/gate.js +278 -0
  196. package/dist/core/permissions/index.js +20 -0
  197. package/dist/core/permissions/mode.js +174 -0
  198. package/dist/core/permissions/network-egress.js +137 -0
  199. package/dist/core/permissions/state.js +241 -0
  200. package/dist/core/permissions/tool-class.js +107 -0
  201. package/dist/core/plan-mode/ui-state.js +51 -0
  202. package/dist/core/plans/plan-artifact.js +721 -0
  203. package/dist/core/policy-limits/etag-store.js +122 -0
  204. package/dist/core/prd-check/parser.js +215 -0
  205. package/dist/core/prd-check/reporter.js +127 -0
  206. package/dist/core/prd-check/session-review.js +557 -0
  207. package/dist/core/prd-check/verifiers.js +223 -0
  208. package/dist/core/prompt-cache/client-cache.js +99 -0
  209. package/dist/core/prompts/assembly.js +29 -0
  210. package/dist/core/prompts/registry.js +364 -0
  211. package/dist/core/pugi-gitignore.js +52 -0
  212. package/dist/core/pugi-md/cc-compat-rules.js +735 -0
  213. package/dist/core/pugi-md/context-injector.js +76 -0
  214. package/dist/core/pugi-md/walk-up.js +207 -0
  215. package/dist/core/python/uv-installer.js +270 -0
  216. package/dist/core/python/uv-resolver.js +83 -0
  217. package/dist/core/rate-limit/narrator.js +146 -0
  218. package/dist/core/recipes/cli-types.js +20 -0
  219. package/dist/core/recipes/loader.js +103 -0
  220. package/dist/core/recipes/runner.js +345 -0
  221. package/dist/core/recipes/schema.js +587 -0
  222. package/dist/core/release-notes/parser.js +241 -0
  223. package/dist/core/release-notes/state.js +116 -0
  224. package/dist/core/repl/ask.js +37 -37
  225. package/dist/core/repl/cancellation.js +26 -26
  226. package/dist/core/repl/cap-warning.js +4 -4
  227. package/dist/core/repl/clipboard-read.js +11 -11
  228. package/dist/core/repl/dispatch-fsm.js +12 -12
  229. package/dist/core/repl/engine-bridge.js +303 -0
  230. package/dist/core/repl/history-search.js +15 -15
  231. package/dist/core/repl/history.js +28 -18
  232. package/dist/core/repl/kill-ring.js +5 -5
  233. package/dist/core/repl/model-pricing.js +135 -0
  234. package/dist/core/repl/privacy-banner.js +22 -22
  235. package/dist/core/repl/session.js +2714 -228
  236. package/dist/core/repl/slash-commands.js +572 -40
  237. package/dist/core/repl/store/index.js +1 -1
  238. package/dist/core/repl/store/jsonl-log.js +22 -22
  239. package/dist/core/repl/store/lockfile.js +10 -10
  240. package/dist/core/repl/store/session-store.js +136 -107
  241. package/dist/core/repl/store/types.js +15 -15
  242. package/dist/core/repl/store/uuid-v7.js +12 -12
  243. package/dist/core/repl/tool-route.js +382 -0
  244. package/dist/core/repl/workspace-context.js +43 -21
  245. package/dist/core/repo-map/build.js +125 -0
  246. package/dist/core/repo-map/cache.js +185 -0
  247. package/dist/core/repo-map/extractor.js +254 -0
  248. package/dist/core/repo-map/formatter.js +145 -0
  249. package/dist/core/repo-map/page-rank.js +105 -0
  250. package/dist/core/repo-map/scanner.js +211 -0
  251. package/dist/core/retro/git-collector.js +251 -0
  252. package/dist/core/retro/health-card.js +25 -0
  253. package/dist/core/retro/metrics.js +342 -0
  254. package/dist/core/retro/narrative.js +249 -0
  255. package/dist/core/retro/plane-collector.js +274 -0
  256. package/dist/core/retro/pr-issue-link.js +65 -0
  257. package/dist/core/retro/types.js +16 -0
  258. package/dist/core/retry-budget/budget.js +284 -0
  259. package/dist/core/retry-budget/index.js +5 -0
  260. package/dist/core/retry-budget/retry-cap.js +74 -0
  261. package/dist/core/routing/lead-worker.js +43 -0
  262. package/dist/core/routing/pre-flight-estimator.js +108 -0
  263. package/dist/core/runs/run-tree.js +103 -0
  264. package/dist/core/sandboxing/adapter.js +29 -0
  265. package/dist/core/sandboxing/index.js +49 -0
  266. package/dist/core/sandboxing/none.js +19 -0
  267. package/dist/core/sandboxing/seatbelt.js +183 -0
  268. package/dist/core/security/injection-scanner.js +367 -0
  269. package/dist/core/security/output-filter.js +418 -0
  270. package/dist/core/session/env-file.js +105 -0
  271. package/dist/core/session/section-budgets.js +140 -0
  272. package/dist/core/session.js +119 -0
  273. package/dist/core/settings.js +378 -5
  274. package/dist/core/share/formatter.js +271 -0
  275. package/dist/core/share/redactor.js +221 -0
  276. package/dist/core/share/uploader.js +267 -0
  277. package/dist/core/skills/defaults.js +457 -0
  278. package/dist/core/skills/loader.js +22 -22
  279. package/dist/core/skills/sources.js +27 -27
  280. package/dist/core/smoke/headless-driver.js +174 -0
  281. package/dist/core/smoke/orchestrator.js +194 -0
  282. package/dist/core/smoke/runner.js +238 -0
  283. package/dist/core/smoke/scenario-parser.js +316 -0
  284. package/dist/core/statusline.js +99 -0
  285. package/dist/core/subagents/dispatcher-real.js +600 -0
  286. package/dist/core/subagents/dispatcher.js +146 -52
  287. package/dist/core/subagents/index.js +19 -6
  288. package/dist/core/subagents/isolation-matrix.js +213 -0
  289. package/dist/core/subagents/spawn.js +19 -4
  290. package/dist/core/telemetry/emitter.js +229 -0
  291. package/dist/core/telemetry/queue.js +251 -0
  292. package/dist/core/theme/context.js +91 -0
  293. package/dist/core/theme/presets.js +228 -0
  294. package/dist/core/theme/state.js +181 -0
  295. package/dist/core/todos/invariant.js +10 -0
  296. package/dist/core/todos/state.js +177 -0
  297. package/dist/core/tool-schema/compressor.js +89 -0
  298. package/dist/core/transport/version-interceptor.js +166 -0
  299. package/dist/core/trust.js +2 -2
  300. package/dist/core/tui/thinking-block.js +64 -0
  301. package/dist/core/vim/keymap.js +288 -0
  302. package/dist/core/vim/state.js +92 -0
  303. package/dist/core/watch-markers/marker-watcher.js +133 -0
  304. package/dist/core/worktree/include-parser.js +249 -0
  305. package/dist/core/worktree-manager/cleanup.js +123 -0
  306. package/dist/core/worktree-manager/manager.js +303 -0
  307. package/dist/index.js +36 -0
  308. package/dist/runtime/bootstrap.js +190 -0
  309. package/dist/runtime/cli.js +4536 -477
  310. package/dist/runtime/commands/agents.js +31 -31
  311. package/dist/runtime/commands/budget.js +5 -5
  312. package/dist/runtime/commands/cancel.js +231 -0
  313. package/dist/runtime/commands/chain.js +489 -0
  314. package/dist/runtime/commands/codegraph-status.js +227 -0
  315. package/dist/runtime/commands/compact.js +297 -0
  316. package/dist/runtime/commands/config.js +74 -40
  317. package/dist/runtime/commands/cost.js +199 -0
  318. package/dist/runtime/commands/delegate.js +312 -0
  319. package/dist/runtime/commands/dispatch.js +126 -0
  320. package/dist/runtime/commands/doctor.js +579 -0
  321. package/dist/runtime/commands/feedback.js +184 -0
  322. package/dist/runtime/commands/hooks.js +187 -0
  323. package/dist/runtime/commands/index-cmd.js +353 -0
  324. package/dist/runtime/commands/init.js +254 -0
  325. package/dist/runtime/commands/lsp.js +368 -0
  326. package/dist/runtime/commands/mcp.js +935 -0
  327. package/dist/runtime/commands/memory.js +582 -0
  328. package/dist/runtime/commands/model.js +237 -0
  329. package/dist/runtime/commands/onboarding.js +275 -0
  330. package/dist/runtime/commands/patch.js +128 -0
  331. package/dist/runtime/commands/permissions.js +112 -0
  332. package/dist/runtime/commands/plan.js +143 -0
  333. package/dist/runtime/commands/prd-check.js +285 -0
  334. package/dist/runtime/commands/privacy.js +17 -17
  335. package/dist/runtime/commands/recipe.js +325 -0
  336. package/dist/runtime/commands/redo-blob-store.js +92 -0
  337. package/dist/runtime/commands/redo.js +361 -0
  338. package/dist/runtime/commands/release-notes.js +229 -0
  339. package/dist/runtime/commands/repo-map.js +95 -0
  340. package/dist/runtime/commands/report.js +299 -0
  341. package/dist/runtime/commands/resume.js +118 -0
  342. package/dist/runtime/commands/review-consensus.js +68 -53
  343. package/dist/runtime/commands/rewind.js +333 -0
  344. package/dist/runtime/commands/roster.js +117 -0
  345. package/dist/runtime/commands/servers.js +236 -0
  346. package/dist/runtime/commands/sessions.js +163 -0
  347. package/dist/runtime/commands/share.js +316 -0
  348. package/dist/runtime/commands/skills.js +31 -31
  349. package/dist/runtime/commands/status.js +186 -0
  350. package/dist/runtime/commands/stickers.js +82 -0
  351. package/dist/runtime/commands/style.js +194 -0
  352. package/dist/runtime/commands/theme.js +196 -0
  353. package/dist/runtime/commands/undo.js +54 -22
  354. package/dist/runtime/commands/update.js +289 -0
  355. package/dist/runtime/commands/vim.js +140 -0
  356. package/dist/runtime/commands/worktree.js +177 -0
  357. package/dist/runtime/commands/worktrees.js +155 -0
  358. package/dist/runtime/deprecation-warning.js +69 -0
  359. package/dist/runtime/engine-exit-code.js +50 -0
  360. package/dist/runtime/headless-repl.js +195 -0
  361. package/dist/runtime/headless.js +548 -0
  362. package/dist/runtime/load-hooks-or-exit.js +71 -0
  363. package/dist/runtime/plan-decompose.js +531 -0
  364. package/dist/runtime/sigint-guard.js +272 -0
  365. package/dist/runtime/stream-renderer.js +195 -0
  366. package/dist/runtime/update-check.js +28 -28
  367. package/dist/runtime/version.js +65 -0
  368. package/dist/runtime/worktree-bootstrap.js +579 -0
  369. package/dist/skills/bundled/batch.js +617 -0
  370. package/dist/skills/bundled/index.js +45 -0
  371. package/dist/skills/bundled/loop.js +358 -0
  372. package/dist/skills/bundled/remember.js +383 -0
  373. package/dist/skills/bundled/simplify.js +289 -0
  374. package/dist/skills/bundled/skillify.js +373 -0
  375. package/dist/skills/bundled/stuck.js +558 -0
  376. package/dist/skills/bundled/verify.js +439 -0
  377. package/dist/testing/vcr.js +486 -0
  378. package/dist/tools/agent-tool.js +229 -0
  379. package/dist/tools/apply-patch.js +556 -0
  380. package/dist/tools/ask-user-question.js +337 -0
  381. package/dist/tools/ask-user.js +115 -0
  382. package/dist/tools/bash.js +624 -46
  383. package/dist/tools/brief.js +224 -0
  384. package/dist/tools/cron.js +433 -0
  385. package/dist/tools/enter-worktree.js +250 -0
  386. package/dist/tools/exit-worktree.js +147 -0
  387. package/dist/tools/file-tools.js +161 -44
  388. package/dist/tools/http-request.js +336 -0
  389. package/dist/tools/lsp-tools.js +565 -0
  390. package/dist/tools/mcp-tool.js +260 -0
  391. package/dist/tools/multi-edit.js +361 -0
  392. package/dist/tools/powershell.js +268 -0
  393. package/dist/tools/registry.js +142 -1
  394. package/dist/tools/server-tools.js +892 -0
  395. package/dist/tools/skill-tool.js +96 -0
  396. package/dist/tools/sleep.js +99 -0
  397. package/dist/tools/synthetic-output.js +133 -0
  398. package/dist/tools/tasks.js +208 -0
  399. package/dist/tools/todo-write.js +184 -0
  400. package/dist/tools/verify-plan-execution.js +295 -0
  401. package/dist/tools/web-fetch-injection-scanner.js +207 -0
  402. package/dist/tools/web-fetch.js +195 -10
  403. package/dist/tools/web-search.js +458 -0
  404. package/dist/tui/agent-progress-card.js +111 -0
  405. package/dist/tui/agent-tree.js +22 -1
  406. package/dist/tui/ask-modal.js +14 -14
  407. package/dist/tui/ask-user-question-chips.js +315 -0
  408. package/dist/tui/ask-user-question-prompt.js +203 -0
  409. package/dist/tui/compact-banner.js +81 -0
  410. package/dist/tui/conversation-pane.js +85 -11
  411. package/dist/tui/cost-table.js +111 -0
  412. package/dist/tui/device-flow.js +2 -2
  413. package/dist/tui/doctor-table.js +46 -0
  414. package/dist/tui/feedback-prompt.js +156 -0
  415. package/dist/tui/input-box.js +247 -32
  416. package/dist/tui/login-picker.js +3 -3
  417. package/dist/tui/markdown-render.js +6 -6
  418. package/dist/tui/multi-file-diff-approval.js +375 -0
  419. package/dist/tui/onboarding-wizard.js +240 -0
  420. package/dist/tui/permissions-picker.js +86 -0
  421. package/dist/tui/render.js +36 -1
  422. package/dist/tui/repl-render.js +405 -32
  423. package/dist/tui/repl-splash-art.js +16 -16
  424. package/dist/tui/repl-splash-mascot.js +48 -24
  425. package/dist/tui/repl-splash.js +22 -22
  426. package/dist/tui/repl.js +136 -43
  427. package/dist/tui/slash-palette.js +6 -6
  428. package/dist/tui/splash.js +2 -2
  429. package/dist/tui/status-bar.js +109 -31
  430. package/dist/tui/status-table.js +7 -0
  431. package/dist/tui/stickers-art.js +136 -0
  432. package/dist/tui/style-table.js +28 -0
  433. package/dist/tui/theme-table.js +29 -0
  434. package/dist/tui/thinking-spinner.js +123 -0
  435. package/dist/tui/tool-stream-pane.js +53 -4
  436. package/dist/tui/update-banner.js +27 -2
  437. package/dist/tui/vim-input.js +267 -0
  438. package/dist/tui/welcome-banner.js +107 -0
  439. package/dist/tui/welcome-data.js +293 -0
  440. package/dist/tui/workspace-context.js +2 -2
  441. package/docs/examples/codegraph.mcp.json +10 -0
  442. package/package.json +25 -7
  443. package/test/scenarios/codegen-create-file.scenario.txt +13 -0
  444. package/test/scenarios/compact-force.scenario.txt +12 -0
  445. package/test/scenarios/identity.scenario.txt +11 -0
  446. package/test/scenarios/persona-handoff.scenario.txt +12 -0
  447. package/test/scenarios/walkback.scenario.txt +12 -0
  448. package/dist/core/engine/compaction-hook.js +0 -154
@@ -0,0 +1,191 @@
1
+ /**
2
+ * `pugi flatten` — CLI surface for the rendergit-port flatten engine.
3
+ *
4
+ * The runner lives here (not in `runtime/cli.ts`) so the dispatch
5
+ * surface stays focused on argv routing. This module owns:
6
+ *
7
+ * - Parsing the command-local flags (`--mode`, `--max-file-size`,
8
+ * `--include`, `--exclude`, `--stdout`, `--open`, `--out`).
9
+ * - Routing to `flattenRepo` with a resolved option bag.
10
+ * - Forwarding the rendered text + summary through the unified
11
+ * `writeOutput` writer so `--json` mode works without a second
12
+ * code path.
13
+ *
14
+ * Ported from karpathy/rendergit (BSD-0). License compatible with
15
+ * Pugi's open-source posture.
16
+ */
17
+ import { resolve } from 'node:path';
18
+ import { DEFAULT_MAX_FILE_SIZE, flattenRepo, } from '../core/flatten/flatten-repo.js';
19
+ /**
20
+ * Entry point invoked by `runtime/cli.ts::dispatchFlatten`. Returns
21
+ * the desired process exit code so the dispatcher can set
22
+ * `process.exitCode` without a second round-trip.
23
+ */
24
+ export async function runFlattenCommand(ctx) {
25
+ const parsed = parseArgs(ctx.args);
26
+ if ('error' in parsed) {
27
+ ctx.writeOutput({ ok: false, error: parsed.error }, `pugi flatten: ${parsed.error}`);
28
+ return 2;
29
+ }
30
+ const options = {
31
+ cwd: parsed.cwd,
32
+ mode: parsed.mode,
33
+ stdout: parsed.stdout,
34
+ maxFileSize: parsed.maxFileSize,
35
+ include: parsed.include,
36
+ exclude: parsed.exclude,
37
+ open: parsed.open,
38
+ };
39
+ try {
40
+ const result = await flattenRepo(options);
41
+ if (parsed.stdout) {
42
+ // Always emit the rendered text to stdout. JSON mode wraps it
43
+ // in an envelope so scripted callers can demux the result from
44
+ // the summary line.
45
+ if (ctx.json) {
46
+ ctx.writeOutput({
47
+ ok: true,
48
+ mode: parsed.mode,
49
+ files: result.files.length,
50
+ skipped: result.skipped.length,
51
+ html: result.html,
52
+ }, result.html);
53
+ }
54
+ else {
55
+ process.stdout.write(result.html);
56
+ }
57
+ return 0;
58
+ }
59
+ const summary = `pugi flatten: wrote ${result.files.length} files (${result.skipped.length} skipped) to ${result.path ?? '<unknown>'}`;
60
+ ctx.writeOutput({
61
+ ok: true,
62
+ mode: parsed.mode,
63
+ path: result.path,
64
+ files: result.files.length,
65
+ skipped: result.skipped.length,
66
+ }, summary);
67
+ return 0;
68
+ }
69
+ catch (err) {
70
+ const msg = err instanceof Error ? err.message : String(err);
71
+ ctx.writeOutput({ ok: false, error: msg }, `pugi flatten: ${msg}`);
72
+ return 1;
73
+ }
74
+ }
75
+ function parseArgs(args) {
76
+ let cwd = process.cwd();
77
+ let mode = 'human';
78
+ let stdout = false;
79
+ let open = false;
80
+ let maxFileSize = DEFAULT_MAX_FILE_SIZE;
81
+ const include = [];
82
+ const exclude = [];
83
+ let positionalConsumed = false;
84
+ for (let i = 0; i < args.length; i += 1) {
85
+ const arg = args[i] ?? '';
86
+ if (arg === '--stdout') {
87
+ stdout = true;
88
+ continue;
89
+ }
90
+ if (arg === '--open') {
91
+ open = true;
92
+ continue;
93
+ }
94
+ if (arg === '--mode') {
95
+ const next = args[i + 1];
96
+ if (!next)
97
+ return { error: '--mode requires a value (human | llm)' };
98
+ const m = parseMode(next);
99
+ if (!m)
100
+ return { error: `--mode: unknown value "${next}" (expected human | llm)` };
101
+ mode = m;
102
+ i += 1;
103
+ continue;
104
+ }
105
+ if (arg.startsWith('--mode=')) {
106
+ const m = parseMode(arg.slice('--mode='.length));
107
+ if (!m)
108
+ return { error: `--mode: unknown value "${arg.slice('--mode='.length)}" (expected human | llm)` };
109
+ mode = m;
110
+ continue;
111
+ }
112
+ if (arg === '--max-file-size') {
113
+ const next = args[i + 1];
114
+ if (!next)
115
+ return { error: '--max-file-size requires a value (e.g. 200kb)' };
116
+ const n = parseSize(next);
117
+ if (n === undefined)
118
+ return { error: `--max-file-size: cannot parse "${next}"` };
119
+ maxFileSize = n;
120
+ i += 1;
121
+ continue;
122
+ }
123
+ if (arg.startsWith('--max-file-size=')) {
124
+ const v = arg.slice('--max-file-size='.length);
125
+ const n = parseSize(v);
126
+ if (n === undefined)
127
+ return { error: `--max-file-size: cannot parse "${v}"` };
128
+ maxFileSize = n;
129
+ continue;
130
+ }
131
+ if (arg === '--include') {
132
+ const next = args[i + 1];
133
+ if (!next)
134
+ return { error: '--include requires a pattern' };
135
+ include.push(next);
136
+ i += 1;
137
+ continue;
138
+ }
139
+ if (arg.startsWith('--include=')) {
140
+ include.push(arg.slice('--include='.length));
141
+ continue;
142
+ }
143
+ if (arg === '--exclude') {
144
+ const next = args[i + 1];
145
+ if (!next)
146
+ return { error: '--exclude requires a pattern' };
147
+ exclude.push(next);
148
+ i += 1;
149
+ continue;
150
+ }
151
+ if (arg.startsWith('--exclude=')) {
152
+ exclude.push(arg.slice('--exclude='.length));
153
+ continue;
154
+ }
155
+ if (arg.startsWith('--')) {
156
+ return { error: `unknown flag "${arg}"` };
157
+ }
158
+ // Positional: workspace path. Only the first non-flag wins; extras
159
+ // are an error so a typo (`pugi flatten . foo`) surfaces.
160
+ if (positionalConsumed) {
161
+ return { error: `unexpected positional argument "${arg}"` };
162
+ }
163
+ cwd = resolve(arg);
164
+ positionalConsumed = true;
165
+ }
166
+ return { cwd, mode, stdout, open, maxFileSize, include, exclude };
167
+ }
168
+ function parseMode(v) {
169
+ if (v === 'human' || v === 'llm')
170
+ return v;
171
+ return undefined;
172
+ }
173
+ /**
174
+ * Parse a size literal: bare number = bytes; `200kb` / `1mb` / `2gb`
175
+ * (case-insensitive, binary units — 1KB = 1024 bytes).
176
+ */
177
+ export function parseSize(raw) {
178
+ const trimmed = raw.trim().toLowerCase();
179
+ if (trimmed.length === 0)
180
+ return undefined;
181
+ const match = /^(\d+(?:\.\d+)?)\s*(b|kb|mb|gb)?$/.exec(trimmed);
182
+ if (!match)
183
+ return undefined;
184
+ const n = Number(match[1]);
185
+ if (!Number.isFinite(n) || n < 0)
186
+ return undefined;
187
+ const unit = match[2] ?? 'b';
188
+ const multiplier = unit === 'b' ? 1 : unit === 'kb' ? 1024 : unit === 'mb' ? 1024 * 1024 : 1024 * 1024 * 1024;
189
+ return Math.floor(n * multiplier);
190
+ }
191
+ //# sourceMappingURL=flatten.js.map
@@ -0,0 +1,201 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * `pugi jobs --watch` Ink TUI — live progress .
4
+ *
5
+ * Tails `~/.pugi/agent-progress/*.json` via chokidar and re-renders a
6
+ * grid of <AgentProgressCard> components. Mirrors the the upstream tool
7
+ * `/compact` layout pattern — one card per agent, sorted by status
8
+ * (running → completed → failed) then by lastUpdate descending so the
9
+ * freshest activity floats к the top.
10
+ *
11
+ * Lifecycle:
12
+ * 1. Resolve dir via resolveProgressDir() (env-aware).
13
+ * 2. Initial scan with readdirSync — populate the map.
14
+ * 3. chokidar.watch(dir, { ignoreInitial: true }) for add/change/unlink.
15
+ * 4. setInterval(1000) tick re-renders to keep elapsed labels live
16
+ * WITHOUT re-reading files.
17
+ * 5. SIGINT (Ctrl+C) triggers `app.unmount()` + process.exit(0).
18
+ *
19
+ * Layout: single column under 100 cols, two columns at 100+ cols
20
+ * (Ink's flexbox computes the responsive split automatically — we just
21
+ * set `flexDirection="row" flexWrap="wrap"` and bound each card к 50%
22
+ * width when stdout is wide enough).
23
+ *
24
+ * The TUI is opt-in (operator runs `pugi jobs --watch`); the bare
25
+ * `pugi jobs` continues to print the legacy job-registry table.
26
+ */
27
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
28
+ import { join } from 'node:path';
29
+ import chokidar from 'chokidar';
30
+ import { useEffect, useMemo, useState } from 'react';
31
+ import { Box, Text, render, useApp, useInput, useStdout } from 'ink';
32
+ import { resolveProgressDir } from '../core/agent-progress/writer.js';
33
+ import { runCleanup } from '../core/agent-progress/cleanup.js';
34
+ import { validateAgentProgress, } from '../core/agent-progress/schema.js';
35
+ import { AgentProgressCard } from '../tui/agent-progress-card.js';
36
+ /** Cleanup pass cadence inside the watcher. Cheap (readdir on a small
37
+ * dir); 60s is the operator-tested sweet spot — fast enough to feel
38
+ * live, slow enough к never burn CPU. */
39
+ const CLEANUP_INTERVAL_MS = 60_000;
40
+ const STATUS_RANK = {
41
+ running: 0,
42
+ completed: 1,
43
+ failed: 2,
44
+ };
45
+ /**
46
+ * Read + validate one progress file. Returns undefined on any failure
47
+ * — the watcher prefers к skip a malformed entry rather than crash.
48
+ * Exported for the spec.
49
+ */
50
+ export function readProgressFile(path) {
51
+ if (!existsSync(path))
52
+ return undefined;
53
+ try {
54
+ const body = readFileSync(path, 'utf8');
55
+ const parsed = JSON.parse(body);
56
+ const result = validateAgentProgress(parsed);
57
+ return result.ok ? result.value : undefined;
58
+ }
59
+ catch {
60
+ return undefined;
61
+ }
62
+ }
63
+ /**
64
+ * Sort progress entries for stable, operator-friendly display:
65
+ * 1. Running first.
66
+ * 2. Then by lastUpdate (most recent first).
67
+ * 3. Tiebreak on agentId for snapshot stability.
68
+ */
69
+ export function sortProgressEntries(entries) {
70
+ return [...entries].sort((a, b) => {
71
+ const rank = STATUS_RANK[a.status] - STATUS_RANK[b.status];
72
+ if (rank !== 0)
73
+ return rank;
74
+ const tsDiff = Date.parse(b.lastUpdate) - Date.parse(a.lastUpdate);
75
+ if (tsDiff !== 0)
76
+ return tsDiff;
77
+ return a.agentId.localeCompare(b.agentId);
78
+ });
79
+ }
80
+ export function JobsWatch(props) {
81
+ const { dir, nowEpochMs, staticMode = false } = props;
82
+ const resolvedDir = useMemo(() => resolveProgressDir(dir), [dir]);
83
+ const [agents, setAgents] = useState(() => initialScan(resolvedDir));
84
+ const [tick, setTick] = useState(0);
85
+ const { exit } = useApp();
86
+ const { stdout } = useStdout();
87
+ const cols = stdout?.columns ?? 80;
88
+ const twoColumns = cols >= 100;
89
+ useInput((_input, key) => {
90
+ if (key.escape || key.ctrl) {
91
+ // Ink's useInput passes ctrl=true for Ctrl+<x>; we exit on Ctrl+C
92
+ // (key.ctrl alone is too broad — actual key char arrives in `input`).
93
+ // Practically, raw mode passes Ctrl+C as SIGINT to the process so
94
+ // this is a belt-and-suspenders catch.
95
+ if (key.escape)
96
+ exit();
97
+ }
98
+ });
99
+ useEffect(() => {
100
+ if (staticMode)
101
+ return;
102
+ let watcher;
103
+ try {
104
+ watcher = chokidar.watch(resolvedDir, {
105
+ ignoreInitial: true,
106
+ depth: 0,
107
+ // The agent writer uses atomic rename — chokidar reports `add`
108
+ // when the final filename appears, never the *.tmp-* intermediate.
109
+ ignored: /\.tmp-/,
110
+ });
111
+ const onChange = (path) => {
112
+ if (!/\.json$/.test(path))
113
+ return;
114
+ const progress = readProgressFile(path);
115
+ if (!progress)
116
+ return;
117
+ setAgents((prev) => ({ ...prev, [progress.agentId]: progress }));
118
+ };
119
+ const onRemove = (path) => {
120
+ const match = /([^/\\]+)\.json$/.exec(path);
121
+ if (!match)
122
+ return;
123
+ const id = match[1];
124
+ if (!id)
125
+ return;
126
+ setAgents((prev) => {
127
+ if (!(id in prev))
128
+ return prev;
129
+ const next = { ...prev };
130
+ delete next[id];
131
+ return next;
132
+ });
133
+ };
134
+ watcher.on('add', onChange);
135
+ watcher.on('change', onChange);
136
+ watcher.on('unlink', onRemove);
137
+ }
138
+ catch {
139
+ // Watcher failures degrade gracefully — initial scan still rendered.
140
+ }
141
+ const interval = setInterval(() => setTick((t) => t + 1), 1000);
142
+ // Auto-cleanup completed/failed entries older than the TTL. The
143
+ // sweep moves them к `<dir>/archive/` so operators can still
144
+ // forensic; the watcher's chokidar `unlink` handler drops them
145
+ // from the live grid as the rename fires.
146
+ const cleanupInterval = setInterval(() => {
147
+ try {
148
+ runCleanup({ dir: resolvedDir });
149
+ }
150
+ catch {
151
+ // best-effort housekeeping; never crash the TUI
152
+ }
153
+ }, CLEANUP_INTERVAL_MS);
154
+ return () => {
155
+ clearInterval(interval);
156
+ clearInterval(cleanupInterval);
157
+ if (watcher) {
158
+ void watcher.close();
159
+ }
160
+ };
161
+ }, [resolvedDir, staticMode]);
162
+ const sorted = useMemo(() => sortProgressEntries(Object.values(agents)), [agents]);
163
+ const effectiveNow = nowEpochMs ?? Date.now() + tick * 0; // tick triggers re-render only
164
+ if (sorted.length === 0) {
165
+ return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsxs(Text, { dimColor: true, children: ["No agents broadcasting progress yet. Watching", ' ', _jsx(Text, { bold: true, children: resolvedDir }), " for `<id>.json` files\u2026"] }), _jsx(Text, { dimColor: true, children: "(Press Esc / Ctrl+C \u043A exit.)" })] }));
166
+ }
167
+ return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { bold: true, children: "pugi jobs --watch" }), _jsxs(Text, { dimColor: true, children: [' ', "\u00B7 ", sorted.length, " ", sorted.length === 1 ? 'agent' : 'agents', " \u00B7", ' ', resolvedDir] })] }), _jsx(Box, { flexDirection: "row", flexWrap: "wrap", children: sorted.map((progress) => (_jsx(Box, { width: twoColumns ? '50%' : '100%', flexDirection: "column", children: _jsx(AgentProgressCard, { progress: progress, nowEpochMs: effectiveNow }) }, progress.agentId))) }), _jsx(Text, { dimColor: true, children: "(Esc / Ctrl+C \u043A exit.)" })] }));
168
+ }
169
+ function initialScan(dir) {
170
+ const map = {};
171
+ if (!existsSync(dir))
172
+ return map;
173
+ let entries;
174
+ try {
175
+ entries = readdirSync(dir);
176
+ }
177
+ catch {
178
+ return map;
179
+ }
180
+ for (const name of entries) {
181
+ if (!name.endsWith('.json'))
182
+ continue;
183
+ if (/\.tmp-/.test(name))
184
+ continue;
185
+ const progress = readProgressFile(join(dir, name));
186
+ if (progress)
187
+ map[progress.agentId] = progress;
188
+ }
189
+ return map;
190
+ }
191
+ /**
192
+ * Entry-point for `pugi jobs --watch`. Mounts the Ink app and returns
193
+ * a Promise that resolves when the user exits (Ctrl+C / Esc).
194
+ */
195
+ export async function runJobsWatch(options = {}) {
196
+ return new Promise((resolve) => {
197
+ const app = render(_jsx(JobsWatch, { dir: options.dir }), { exitOnCtrlC: true });
198
+ void app.waitUntilExit().then(() => resolve(0));
199
+ });
200
+ }
201
+ //# sourceMappingURL=jobs-watch.js.map
@@ -1,21 +1,22 @@
1
1
  /**
2
- * `pugi jobs` command surface — Sprint α5.9 (ADR-0056 PR-PUGI-CLI-M1-GAP-J).
2
+ * `pugi jobs` command surface — Sprint .
3
3
  *
4
4
  * Subcommands:
5
- * pugi jobs list — table of all tracked jobs (or JSON envelope)
6
- * pugi jobs status <id> — full record + tail of overflow artifact
7
- * pugi jobs tail <id> — stream the overflow artifact
8
- * pugi jobs kill <id> — SIGTERM then SIGKILL after a grace
9
- * pugi jobs kill --all — kill every running job in this session
5
+ * pugi jobs list — table of all tracked jobs (or JSON envelope)
6
+ * pugi jobs status <id> — full record + tail of overflow artifact
7
+ * pugi jobs tail <id> — stream the overflow artifact
8
+ * pugi jobs kill <id> — SIGTERM then SIGKILL after a grace
9
+ * pugi jobs kill --all — kill every running job in this session
10
10
  *
11
11
  * Power-word voice rules (per Pugi brand guide):
12
- * - status names render as "on watch" (running), "shipped" (finished),
13
- * "stood down" (killed), "blocked" (failed), "lost" (abandoned).
14
- * - JSON envelopes keep the machine-friendly enum so consumers do
15
- * not have to map back.
12
+ * - status names render as "on watch" (running), "shipped" (finished),
13
+ * "stood down" (killed), "blocked" (failed), "lost" (abandoned).
14
+ * - JSON envelopes keep the machine-friendly enum so consumers do
15
+ * not have to map back.
16
16
  */
17
17
  import { existsSync, readFileSync } from 'node:fs';
18
18
  import { formatDuration, getJobRegistry, relativeAge, } from '../core/jobs/registry.js';
19
+ import { runJobsWatch } from './jobs-watch.js';
19
20
  const HUMAN_STATUS = {
20
21
  running: 'on watch',
21
22
  finished: 'shipped',
@@ -24,6 +25,19 @@ const HUMAN_STATUS = {
24
25
  abandoned: 'lost',
25
26
  };
26
27
  export async function runJobsCommand(args, flags, io, sessionId) {
28
+ // live progress : `pugi jobs --watch` mounts the live
29
+ // agent-progress TUI. The flag may sit anywhere in the arg list
30
+ // (`pugi jobs --watch` or `pugi jobs watch`) — both forms route к
31
+ // the watcher. JSON mode is incompatible (it would never return); we
32
+ // bail with a helpful error instead of silently swallowing the flag.
33
+ const wantsWatch = args.includes('--watch') || args[0] === 'watch';
34
+ if (wantsWatch) {
35
+ if (flags.json) {
36
+ io.writeError('pugi jobs --watch is interactive; --json is not supported.');
37
+ return 2;
38
+ }
39
+ return runJobsWatch();
40
+ }
27
41
  const sub = args[0] ?? 'list';
28
42
  switch (sub) {
29
43
  case 'list':
@@ -43,11 +57,12 @@ export async function runJobsCommand(args, flags, io, sessionId) {
43
57
  function usage() {
44
58
  return [
45
59
  'Usage:',
46
- ' pugi jobs list [--json] Table of background jobs.',
47
- ' pugi jobs status <id> [--json] Full record + tail of artifact.',
48
- ' pugi jobs tail <id> Stream the captured artifact.',
49
- ' pugi jobs kill <id> [--json] SIGTERM, escalate to SIGKILL.',
50
- ' pugi jobs kill --all [--json] Stand down every running job.',
60
+ ' pugi jobs list [--json] Table of background jobs.',
61
+ ' pugi jobs status <id> [--json] Full record + tail of artifact.',
62
+ ' pugi jobs tail <id> Stream the captured artifact.',
63
+ ' pugi jobs kill <id> [--json] SIGTERM, escalate to SIGKILL.',
64
+ ' pugi jobs kill --all [--json] Stand down every running job.',
65
+ ' pugi jobs --watch Live Ink TUI of agent progress.',
51
66
  ].join('\n');
52
67
  }
53
68
  async function runList(flags, io) {
@@ -91,20 +106,20 @@ async function runStatus(id, flags, io) {
91
106
  }
92
107
  const lines = [
93
108
  `Job ${entry.id}`,
94
- ` PID: ${entry.pid}`,
95
- ` Command: ${entry.command}`,
96
- ` Class: ${entry.bashClass}`,
97
- ` Status: ${HUMAN_STATUS[entry.status]} (${entry.status})`,
98
- ` CWD: ${entry.cwd}`,
99
- ` Started: ${entry.startedAt} (${relativeAge(entry.startedAt)} ago)`,
100
- ` Duration: ${formatDuration(entry.startedAt, entry.finishedAt)}`,
109
+ ` PID: ${entry.pid}`,
110
+ ` Command: ${entry.command}`,
111
+ ` Class: ${entry.bashClass}`,
112
+ ` Status: ${HUMAN_STATUS[entry.status]} (${entry.status})`,
113
+ ` CWD: ${entry.cwd}`,
114
+ ` Started: ${entry.startedAt} (${relativeAge(entry.startedAt)} ago)`,
115
+ ` Duration: ${formatDuration(entry.startedAt, entry.finishedAt)}`,
101
116
  ];
102
117
  if (entry.finishedAt)
103
- lines.push(` Finished: ${entry.finishedAt}`);
118
+ lines.push(` Finished: ${entry.finishedAt}`);
104
119
  if (entry.exitCode !== undefined)
105
- lines.push(` Exit code: ${entry.exitCode}`);
120
+ lines.push(` Exit code: ${entry.exitCode}`);
106
121
  if (entry.outputArtifactRef)
107
- lines.push(` Artifact: ${entry.outputArtifactRef}`);
122
+ lines.push(` Artifact: ${entry.outputArtifactRef}`);
108
123
  if (tail) {
109
124
  lines.push('', '--- output tail ---', tail);
110
125
  }
@@ -159,7 +174,7 @@ async function runKill(args, flags, io, sessionId) {
159
174
  }
160
175
  else {
161
176
  for (const result of results) {
162
- io.write(` ${result.id} ${result.killed ? 'stood down' : 'noop'} (${result.method})\n`);
177
+ io.write(` ${result.id} ${result.killed ? 'stood down' : 'noop'} (${result.method})\n`);
163
178
  }
164
179
  }
165
180
  return 0;
@@ -233,7 +248,7 @@ function renderTable(entries) {
233
248
  return rows
234
249
  .map((row) => row
235
250
  .map((cell, i) => cell.padEnd(widths[i] ?? cell.length))
236
- .join(' ')
251
+ .join(' ')
237
252
  .trimEnd())
238
253
  .join('\n');
239
254
  }