@pugi/cli 0.1.0-beta.9 → 0.1.0-beta.91

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 (411) hide show
  1. package/CHANGELOG.md +132 -0
  2. package/LICENSE +1 -1
  3. package/assets/pugi-prozr2-mascot.ansi +9 -0
  4. package/bin/run.js +33 -1
  5. package/dist/commands/deploy.js +40 -40
  6. package/dist/commands/flatten.js +191 -0
  7. package/dist/commands/jobs-watch.js +201 -0
  8. package/dist/commands/jobs.js +42 -27
  9. package/dist/commands/smoke.js +133 -0
  10. package/dist/core/agent-progress/cleanup.js +134 -0
  11. package/dist/core/agent-progress/schema.js +144 -0
  12. package/dist/core/agent-progress/writer.js +101 -0
  13. package/dist/core/agents/adaptive-router.js +330 -0
  14. package/dist/core/agents/query-decomposer.js +297 -0
  15. package/dist/core/agents/registry.js +3 -3
  16. package/dist/core/approvals/shortcut-resolver.js +98 -0
  17. package/dist/core/artifact-chain/dispatcher.js +148 -0
  18. package/dist/core/artifact-chain/exporter.js +164 -0
  19. package/dist/core/artifact-chain/state.js +243 -0
  20. package/dist/core/artifact-chain/steps.js +169 -0
  21. package/dist/core/ask-user/question.js +92 -0
  22. package/dist/core/audit/audit-trail.js +275 -0
  23. package/dist/core/auth/ensure-authenticated.js +129 -0
  24. package/dist/core/auth/env-provider.js +238 -0
  25. package/dist/core/auto-open-browser.js +4 -4
  26. package/dist/core/auto-update/channels.js +122 -0
  27. package/dist/core/auto-update/checker.js +241 -0
  28. package/dist/core/auto-update/state.js +235 -0
  29. package/dist/core/bare-mode/index.js +107 -0
  30. package/dist/core/bash/redirect.js +281 -0
  31. package/dist/core/bash-classifier.js +436 -40
  32. package/dist/core/checkpoint/resumer.js +149 -0
  33. package/dist/core/checkpoint/rewinder.js +291 -0
  34. package/dist/core/checkpoints/shadow-git.js +670 -0
  35. package/dist/core/citations/parser.js +109 -0
  36. package/dist/core/classifier/yolo-classifier.js +88 -0
  37. package/dist/core/codegraph/decision-store.js +248 -0
  38. package/dist/core/codegraph/detect-repo.js +459 -0
  39. package/dist/core/codegraph/install.js +134 -0
  40. package/dist/core/codegraph/offer-hook.js +220 -0
  41. package/dist/core/compact/auto-trigger.js +96 -0
  42. package/dist/core/compact/buffer-rewriter.js +115 -0
  43. package/dist/core/compact/summarizer.js +208 -0
  44. package/dist/core/compact/token-counter.js +108 -0
  45. package/dist/core/consensus/anvil-fanout.js +25 -25
  46. package/dist/core/consensus/diff-capture.js +121 -12
  47. package/dist/core/consensus/rubric.js +21 -21
  48. package/dist/core/context/builder.js +6 -6
  49. package/dist/core/context/compaction-events.js +8 -8
  50. package/dist/core/context/compaction.js +31 -31
  51. package/dist/core/context/index.js +15 -8
  52. package/dist/core/context/invariants.js +51 -51
  53. package/dist/core/context/markdown-loader.js +28 -10
  54. package/dist/core/context/markdown-traverse.js +255 -0
  55. package/dist/core/context/pugiignore.js +41 -41
  56. package/dist/core/context/repo-skeleton.js +37 -37
  57. package/dist/core/context/tool-eviction.js +55 -0
  58. package/dist/core/context/watcher.js +32 -32
  59. package/dist/core/context/working-set.js +23 -23
  60. package/dist/core/coordinator/agent-tools.js +77 -0
  61. package/dist/core/coordinator/agent-toolset.js +65 -0
  62. package/dist/core/coordinator/fsm.js +73 -0
  63. package/dist/core/coordinator/mode-fsm.js +70 -0
  64. package/dist/core/cost/rate-card.js +129 -0
  65. package/dist/core/cost/tracker.js +221 -0
  66. package/dist/core/credentials.js +13 -13
  67. package/dist/core/cron/scheduler.js +138 -0
  68. package/dist/core/denial-tracking/index.js +8 -0
  69. package/dist/core/denial-tracking/state.js +264 -0
  70. package/dist/core/diagnostics/probe-runner.js +93 -0
  71. package/dist/core/diagnostics/probes/api.js +46 -0
  72. package/dist/core/diagnostics/probes/auth.js +93 -0
  73. package/dist/core/diagnostics/probes/bare-mode.js +42 -0
  74. package/dist/core/diagnostics/probes/cli-version.js +127 -0
  75. package/dist/core/diagnostics/probes/config.js +72 -0
  76. package/dist/core/diagnostics/probes/denial-tracking.js +57 -0
  77. package/dist/core/diagnostics/probes/disk.js +81 -0
  78. package/dist/core/diagnostics/probes/engine-live.js +46 -0
  79. package/dist/core/diagnostics/probes/git.js +65 -0
  80. package/dist/core/diagnostics/probes/hooks.js +118 -0
  81. package/dist/core/diagnostics/probes/mcp.js +75 -0
  82. package/dist/core/diagnostics/probes/node.js +59 -0
  83. package/dist/core/diagnostics/probes/pnpm.js +36 -0
  84. package/dist/core/diagnostics/probes/pugi-md.js +89 -0
  85. package/dist/core/diagnostics/probes/sandbox.js +40 -0
  86. package/dist/core/diagnostics/probes/session.js +74 -0
  87. package/dist/core/diagnostics/probes/status-snapshot.js +488 -0
  88. package/dist/core/diagnostics/probes/workspace.js +63 -0
  89. package/dist/core/diagnostics/types.js +70 -0
  90. package/dist/core/dispatch/cache-cleanup.js +197 -0
  91. package/dist/core/dispatch/cache-handoff.js +295 -0
  92. package/dist/core/edits/apply-patch-layer-e.js +189 -0
  93. package/dist/core/edits/dispatch.js +333 -7
  94. package/dist/core/edits/format-detector.js +260 -0
  95. package/dist/core/edits/format-matrix.js +26 -0
  96. package/dist/core/edits/fuzzy-ladder.js +650 -0
  97. package/dist/core/edits/index.js +5 -1
  98. package/dist/core/edits/journal.js +199 -0
  99. package/dist/core/edits/layer-a-apply.js +15 -15
  100. package/dist/core/edits/layer-a-fuzzy-apply.js +198 -0
  101. package/dist/core/edits/layer-b-apply.js +9 -9
  102. package/dist/core/edits/layer-c-apply.js +6 -6
  103. package/dist/core/edits/layer-d-ast.js +557 -14
  104. package/dist/core/edits/marker-parser.js +12 -12
  105. package/dist/core/edits/security-gate.js +27 -27
  106. package/dist/core/edits/verify-hook.js +273 -0
  107. package/dist/core/edits/worktree.js +29 -29
  108. package/dist/core/engine/anvil-client.js +214 -26
  109. package/dist/core/engine/auto-compact.js +179 -0
  110. package/dist/core/engine/budgets.js +186 -0
  111. package/dist/core/engine/context-prefix.js +155 -0
  112. package/dist/core/engine/index.js +1 -1
  113. package/dist/core/engine/intensity.js +158 -0
  114. package/dist/core/engine/intent.js +260 -0
  115. package/dist/core/engine/native-pugi.js +1295 -227
  116. package/dist/core/engine/prompts.js +129 -19
  117. package/dist/core/engine/strip-internal-fields.js +124 -0
  118. package/dist/core/engine/tool-bridge.js +1792 -59
  119. package/dist/core/evaluation/golden-dataset.js +293 -0
  120. package/dist/core/feedback/queue.js +177 -0
  121. package/dist/core/feedback/submitter.js +145 -0
  122. package/dist/core/file-cache.js +113 -1
  123. package/dist/core/flatten/flatten-repo.js +439 -0
  124. package/dist/core/format/osc8-link.js +28 -0
  125. package/dist/core/hook-chains.js +392 -0
  126. package/dist/core/hooks/citation-verify-hook.js +138 -0
  127. package/dist/core/hooks/citation-verify.js +112 -0
  128. package/dist/core/hooks/events.js +46 -0
  129. package/dist/core/hooks/index.js +15 -0
  130. package/dist/core/hooks/registry.js +216 -0
  131. package/dist/core/hooks/runner.js +236 -0
  132. package/dist/core/hooks/v2/event-emitter.js +115 -0
  133. package/dist/core/hooks/v2/executor.js +282 -0
  134. package/dist/core/hooks/v2/index.js +25 -0
  135. package/dist/core/hooks/v2/lifecycle.js +104 -0
  136. package/dist/core/hooks/v2/loader.js +216 -0
  137. package/dist/core/hooks/v2/matcher.js +125 -0
  138. package/dist/core/hooks/v2/trust.js +143 -0
  139. package/dist/core/hooks/v2/types.js +86 -0
  140. package/dist/core/hooks/worktree-events.js +158 -0
  141. package/dist/core/image/renderer.js +71 -0
  142. package/dist/core/init/detector.js +582 -0
  143. package/dist/core/init/template-renderer.js +242 -0
  144. package/dist/core/jobs/registry.js +18 -18
  145. package/dist/core/ledger/results-tsv.js +142 -0
  146. package/dist/core/log-discipline/stdout-redirect.js +51 -0
  147. package/dist/core/lsp/cache.js +105 -0
  148. package/dist/core/lsp/client.js +551 -41
  149. package/dist/core/lsp/language-detect.js +66 -0
  150. package/dist/core/lsp/post-edit-diagnostics.js +171 -0
  151. package/dist/core/lsp/server-detect.js +173 -0
  152. package/dist/core/lsp/symbol-cache.js +162 -0
  153. package/dist/core/lsp/symbol-tools.js +664 -0
  154. package/dist/core/mcp/client.js +97 -28
  155. package/dist/core/mcp/http-server.js +553 -0
  156. package/dist/core/mcp/orchestrator-tools.js +662 -0
  157. package/dist/core/mcp/permission.js +190 -0
  158. package/dist/core/mcp/registry.js +39 -17
  159. package/dist/core/mcp/server-tools.js +219 -0
  160. package/dist/core/mcp/server.js +397 -0
  161. package/dist/core/mcp/trust.js +10 -10
  162. package/dist/core/memory/dual-write.js +416 -0
  163. package/dist/core/memory/passive-extract.js +130 -0
  164. package/dist/core/memory/phase1-kinds.js +20 -0
  165. package/dist/core/memory/secret-scanner.js +304 -0
  166. package/dist/core/memory-sync/queue.js +170 -0
  167. package/dist/core/metrics/extract.js +113 -0
  168. package/dist/core/modes/roo-modes.js +68 -0
  169. package/dist/core/onboarding/ensure-initialized.js +133 -0
  170. package/dist/core/onboarding/marker.js +111 -0
  171. package/dist/core/onboarding/telemetry-state.js +108 -0
  172. package/dist/core/output-style/presets.js +176 -0
  173. package/dist/core/output-style/state.js +185 -0
  174. package/dist/core/path-security.js +287 -5
  175. package/dist/core/permission.js +82 -22
  176. package/dist/core/permissions/auto-classifier.js +124 -0
  177. package/dist/core/permissions/bash-parser.js +371 -0
  178. package/dist/core/permissions/circuit-breaker.js +83 -0
  179. package/dist/core/permissions/constrained-edit.js +91 -0
  180. package/dist/core/permissions/gate.js +278 -0
  181. package/dist/core/permissions/index.js +20 -0
  182. package/dist/core/permissions/mode.js +174 -0
  183. package/dist/core/permissions/network-egress.js +137 -0
  184. package/dist/core/permissions/state.js +241 -0
  185. package/dist/core/permissions/tool-class.js +93 -0
  186. package/dist/core/plan-mode/ui-state.js +51 -0
  187. package/dist/core/plans/plan-artifact.js +721 -0
  188. package/dist/core/policy-limits/etag-store.js +122 -0
  189. package/dist/core/prd-check/parser.js +215 -0
  190. package/dist/core/prd-check/reporter.js +127 -0
  191. package/dist/core/prd-check/session-review.js +557 -0
  192. package/dist/core/prd-check/verifiers.js +223 -0
  193. package/dist/core/prompt-cache/client-cache.js +99 -0
  194. package/dist/core/prompts/assembly.js +29 -0
  195. package/dist/core/prompts/registry.js +364 -0
  196. package/dist/core/pugi-md/cc-compat-rules.js +735 -0
  197. package/dist/core/pugi-md/context-injector.js +76 -0
  198. package/dist/core/pugi-md/walk-up.js +207 -0
  199. package/dist/core/python/uv-installer.js +270 -0
  200. package/dist/core/python/uv-resolver.js +83 -0
  201. package/dist/core/rate-limit/narrator.js +146 -0
  202. package/dist/core/recipes/cli-types.js +20 -0
  203. package/dist/core/recipes/loader.js +103 -0
  204. package/dist/core/recipes/runner.js +345 -0
  205. package/dist/core/recipes/schema.js +587 -0
  206. package/dist/core/release-notes/parser.js +241 -0
  207. package/dist/core/release-notes/state.js +116 -0
  208. package/dist/core/repl/ask.js +37 -37
  209. package/dist/core/repl/cancellation.js +26 -26
  210. package/dist/core/repl/cap-warning.js +4 -4
  211. package/dist/core/repl/clipboard-read.js +11 -11
  212. package/dist/core/repl/dispatch-fsm.js +12 -12
  213. package/dist/core/repl/history-search.js +15 -15
  214. package/dist/core/repl/history.js +28 -18
  215. package/dist/core/repl/kill-ring.js +5 -5
  216. package/dist/core/repl/model-pricing.js +135 -0
  217. package/dist/core/repl/privacy-banner.js +22 -22
  218. package/dist/core/repl/session.js +2148 -217
  219. package/dist/core/repl/slash-commands.js +501 -41
  220. package/dist/core/repl/store/index.js +1 -1
  221. package/dist/core/repl/store/jsonl-log.js +22 -22
  222. package/dist/core/repl/store/lockfile.js +10 -10
  223. package/dist/core/repl/store/session-store.js +136 -107
  224. package/dist/core/repl/store/types.js +15 -15
  225. package/dist/core/repl/store/uuid-v7.js +12 -12
  226. package/dist/core/repl/workspace-context.js +43 -21
  227. package/dist/core/repo-map/build.js +125 -0
  228. package/dist/core/repo-map/cache.js +185 -0
  229. package/dist/core/repo-map/extractor.js +254 -0
  230. package/dist/core/repo-map/formatter.js +145 -0
  231. package/dist/core/repo-map/page-rank.js +105 -0
  232. package/dist/core/repo-map/scanner.js +211 -0
  233. package/dist/core/retry-budget/budget.js +284 -0
  234. package/dist/core/retry-budget/index.js +5 -0
  235. package/dist/core/retry-budget/retry-cap.js +74 -0
  236. package/dist/core/routing/lead-worker.js +43 -0
  237. package/dist/core/routing/pre-flight-estimator.js +108 -0
  238. package/dist/core/runs/run-tree.js +103 -0
  239. package/dist/core/security/injection-scanner.js +367 -0
  240. package/dist/core/security/output-filter.js +418 -0
  241. package/dist/core/session/env-file.js +105 -0
  242. package/dist/core/session/section-budgets.js +140 -0
  243. package/dist/core/session.js +92 -0
  244. package/dist/core/settings.js +324 -5
  245. package/dist/core/share/formatter.js +271 -0
  246. package/dist/core/share/redactor.js +221 -0
  247. package/dist/core/share/uploader.js +267 -0
  248. package/dist/core/skills/defaults.js +30 -30
  249. package/dist/core/skills/loader.js +22 -22
  250. package/dist/core/skills/sources.js +27 -27
  251. package/dist/core/smoke/headless-driver.js +174 -0
  252. package/dist/core/smoke/orchestrator.js +194 -0
  253. package/dist/core/smoke/runner.js +238 -0
  254. package/dist/core/smoke/scenario-parser.js +316 -0
  255. package/dist/core/statusline.js +99 -0
  256. package/dist/core/subagents/dispatcher-real.js +600 -0
  257. package/dist/core/subagents/dispatcher.js +132 -43
  258. package/dist/core/subagents/index.js +19 -6
  259. package/dist/core/subagents/isolation-matrix.js +213 -0
  260. package/dist/core/subagents/spawn.js +19 -4
  261. package/dist/core/telemetry/emitter.js +229 -0
  262. package/dist/core/telemetry/queue.js +251 -0
  263. package/dist/core/theme/context.js +91 -0
  264. package/dist/core/theme/presets.js +228 -0
  265. package/dist/core/theme/state.js +181 -0
  266. package/dist/core/todos/invariant.js +10 -0
  267. package/dist/core/todos/state.js +177 -0
  268. package/dist/core/tool-schema/compressor.js +89 -0
  269. package/dist/core/transport/version-interceptor.js +166 -0
  270. package/dist/core/trust.js +2 -2
  271. package/dist/core/tui/thinking-block.js +64 -0
  272. package/dist/core/vim/keymap.js +288 -0
  273. package/dist/core/vim/state.js +92 -0
  274. package/dist/core/watch-markers/marker-watcher.js +133 -0
  275. package/dist/core/worktree/include-parser.js +249 -0
  276. package/dist/core/worktree-manager/cleanup.js +123 -0
  277. package/dist/core/worktree-manager/manager.js +303 -0
  278. package/dist/index.js +36 -0
  279. package/dist/runtime/bootstrap.js +190 -0
  280. package/dist/runtime/cli.js +4185 -549
  281. package/dist/runtime/commands/agents.js +31 -31
  282. package/dist/runtime/commands/budget.js +5 -5
  283. package/dist/runtime/commands/cancel.js +231 -0
  284. package/dist/runtime/commands/chain.js +489 -0
  285. package/dist/runtime/commands/codegraph-status.js +227 -0
  286. package/dist/runtime/commands/compact.js +297 -0
  287. package/dist/runtime/commands/config.js +73 -39
  288. package/dist/runtime/commands/cost.js +199 -0
  289. package/dist/runtime/commands/delegate.js +27 -4
  290. package/dist/runtime/commands/dispatch.js +126 -0
  291. package/dist/runtime/commands/doctor.js +579 -0
  292. package/dist/runtime/commands/feedback.js +184 -0
  293. package/dist/runtime/commands/hooks.js +187 -0
  294. package/dist/runtime/commands/init.js +254 -0
  295. package/dist/runtime/commands/lsp.js +200 -38
  296. package/dist/runtime/commands/mcp.js +879 -0
  297. package/dist/runtime/commands/memory.js +582 -0
  298. package/dist/runtime/commands/model.js +237 -0
  299. package/dist/runtime/commands/onboarding.js +275 -0
  300. package/dist/runtime/commands/patch.js +12 -12
  301. package/dist/runtime/commands/permissions.js +112 -0
  302. package/dist/runtime/commands/plan.js +143 -0
  303. package/dist/runtime/commands/prd-check.js +285 -0
  304. package/dist/runtime/commands/privacy.js +17 -17
  305. package/dist/runtime/commands/recipe.js +325 -0
  306. package/dist/runtime/commands/redo-blob-store.js +92 -0
  307. package/dist/runtime/commands/redo.js +361 -0
  308. package/dist/runtime/commands/release-notes.js +229 -0
  309. package/dist/runtime/commands/repo-map.js +95 -0
  310. package/dist/runtime/commands/report.js +299 -0
  311. package/dist/runtime/commands/resume.js +118 -0
  312. package/dist/runtime/commands/review-consensus.js +68 -53
  313. package/dist/runtime/commands/rewind.js +333 -0
  314. package/dist/runtime/commands/roster.js +14 -14
  315. package/dist/runtime/commands/sessions.js +163 -0
  316. package/dist/runtime/commands/share.js +316 -0
  317. package/dist/runtime/commands/skills.js +31 -31
  318. package/dist/runtime/commands/status.js +186 -0
  319. package/dist/runtime/commands/stickers.js +82 -0
  320. package/dist/runtime/commands/style.js +194 -0
  321. package/dist/runtime/commands/theme.js +196 -0
  322. package/dist/runtime/commands/undo.js +54 -22
  323. package/dist/runtime/commands/update.js +289 -0
  324. package/dist/runtime/commands/vim.js +140 -0
  325. package/dist/runtime/commands/worktree.js +8 -8
  326. package/dist/runtime/commands/worktrees.js +155 -0
  327. package/dist/runtime/headless-repl.js +195 -0
  328. package/dist/runtime/headless.js +543 -0
  329. package/dist/runtime/load-hooks-or-exit.js +71 -0
  330. package/dist/runtime/plan-decompose.js +22 -22
  331. package/dist/runtime/sigint-guard.js +272 -0
  332. package/dist/runtime/update-check.js +28 -28
  333. package/dist/runtime/version.js +65 -0
  334. package/dist/runtime/worktree-bootstrap.js +579 -0
  335. package/dist/skills/bundled/batch.js +617 -0
  336. package/dist/skills/bundled/index.js +45 -0
  337. package/dist/skills/bundled/loop.js +358 -0
  338. package/dist/skills/bundled/remember.js +383 -0
  339. package/dist/skills/bundled/simplify.js +289 -0
  340. package/dist/skills/bundled/skillify.js +373 -0
  341. package/dist/skills/bundled/stuck.js +558 -0
  342. package/dist/skills/bundled/verify.js +439 -0
  343. package/dist/testing/vcr.js +486 -0
  344. package/dist/tools/agent-tool.js +229 -0
  345. package/dist/tools/apply-patch.js +89 -28
  346. package/dist/tools/ask-user-question.js +337 -0
  347. package/dist/tools/ask-user.js +115 -0
  348. package/dist/tools/bash.js +624 -46
  349. package/dist/tools/brief.js +224 -0
  350. package/dist/tools/cron.js +433 -0
  351. package/dist/tools/enter-worktree.js +250 -0
  352. package/dist/tools/exit-worktree.js +147 -0
  353. package/dist/tools/file-tools.js +161 -44
  354. package/dist/tools/lsp-tools.js +377 -1
  355. package/dist/tools/mcp-tool.js +260 -0
  356. package/dist/tools/multi-edit.js +361 -0
  357. package/dist/tools/powershell.js +268 -0
  358. package/dist/tools/registry.js +99 -4
  359. package/dist/tools/skill-tool.js +96 -0
  360. package/dist/tools/sleep.js +99 -0
  361. package/dist/tools/synthetic-output.js +133 -0
  362. package/dist/tools/tasks.js +208 -0
  363. package/dist/tools/todo-write.js +184 -0
  364. package/dist/tools/verify-plan-execution.js +295 -0
  365. package/dist/tools/web-fetch-injection-scanner.js +207 -0
  366. package/dist/tools/web-fetch.js +195 -10
  367. package/dist/tools/web-search.js +458 -0
  368. package/dist/tui/agent-progress-card.js +111 -0
  369. package/dist/tui/agent-tree.js +11 -1
  370. package/dist/tui/ask-modal.js +14 -14
  371. package/dist/tui/ask-user-question-chips.js +315 -0
  372. package/dist/tui/ask-user-question-prompt.js +203 -0
  373. package/dist/tui/compact-banner.js +81 -0
  374. package/dist/tui/conversation-pane.js +85 -11
  375. package/dist/tui/cost-table.js +111 -0
  376. package/dist/tui/device-flow.js +2 -2
  377. package/dist/tui/doctor-table.js +46 -0
  378. package/dist/tui/feedback-prompt.js +156 -0
  379. package/dist/tui/input-box.js +247 -32
  380. package/dist/tui/login-picker.js +3 -3
  381. package/dist/tui/markdown-render.js +6 -6
  382. package/dist/tui/multi-file-diff-approval.js +375 -0
  383. package/dist/tui/onboarding-wizard.js +240 -0
  384. package/dist/tui/permissions-picker.js +86 -0
  385. package/dist/tui/render.js +36 -1
  386. package/dist/tui/repl-render.js +176 -25
  387. package/dist/tui/repl-splash-art.js +16 -16
  388. package/dist/tui/repl-splash-mascot.js +48 -24
  389. package/dist/tui/repl-splash.js +22 -22
  390. package/dist/tui/repl.js +125 -45
  391. package/dist/tui/slash-palette.js +6 -6
  392. package/dist/tui/splash.js +2 -2
  393. package/dist/tui/status-bar.js +109 -31
  394. package/dist/tui/status-table.js +7 -0
  395. package/dist/tui/stickers-art.js +136 -0
  396. package/dist/tui/style-table.js +28 -0
  397. package/dist/tui/theme-table.js +29 -0
  398. package/dist/tui/thinking-spinner.js +123 -0
  399. package/dist/tui/tool-stream-pane.js +53 -4
  400. package/dist/tui/update-banner.js +27 -2
  401. package/dist/tui/vim-input.js +267 -0
  402. package/dist/tui/welcome-banner.js +107 -0
  403. package/dist/tui/welcome-data.js +293 -0
  404. package/dist/tui/workspace-context.js +2 -2
  405. package/package.json +31 -16
  406. package/test/scenarios/codegen-create-file.scenario.txt +13 -0
  407. package/test/scenarios/compact-force.scenario.txt +12 -0
  408. package/test/scenarios/identity.scenario.txt +12 -0
  409. package/test/scenarios/persona-handoff.scenario.txt +12 -0
  410. package/test/scenarios/walkback.scenario.txt +12 -0
  411. package/dist/core/engine/compaction-hook.js +0 -154
@@ -0,0 +1,439 @@
1
+ /**
2
+ * `pugi verify` — post-execution claim verification.
3
+ *
4
+ * Bundled skill, batch 2 (backlog). The operator runs `pugi verify
5
+ * <claims.json>` after an agent or batch reports "done"; the skill
6
+ * walks the claim list, runs each assertion, and prints a
7
+ * pass/fail ledger. This is the anti-fake-dispatch primitive — Hiroshi
8
+ * can promise "tic-tac-toe shipped, snake.html written, tests added"
9
+ * but `pugi verify` is the only thing that can prove it.
10
+ *
11
+ * # Claim shapes
12
+ *
13
+ * - `file_exists` — `target` is a path. Pass when the file exists +
14
+ * is non-empty (a 0-byte placeholder is a fake).
15
+ * - `grep_match` — `target` is a path, `expected` is a literal
16
+ * substring OR `/regex/flags`. Pass when at least
17
+ * one match is found.
18
+ * - `cmd_zero_exit`— `target` is a command line (one program + args,
19
+ * no shell metacharacters). Pass when the process
20
+ * exits 0 inside a 30-second wall clock.
21
+ *
22
+ * # Output
23
+ *
24
+ * - Human-readable table with `[ok]` / `[FAIL]` per claim.
25
+ * - JSON envelope on `--json`.
26
+ *
27
+ * # Exit codes
28
+ *
29
+ * - 0 — every claim passed (or `--strict` was off + only soft fails).
30
+ * - 1 — at least one claim failed.
31
+ * - 2 — CLI / input error (missing file, bad JSON, malformed claim).
32
+ *
33
+ * # Strict mode
34
+ *
35
+ * `--strict` (default ON) treats ANY failure as the exit-code-1 trigger.
36
+ * `--no-strict` flips to "report-only" — useful when the operator wants
37
+ * the ledger printed for analysis but is iterating on a known-broken
38
+ * snapshot and does not want the wrapper script to bail.
39
+ *
40
+ * # Provenance
41
+ *
42
+ * Inspired by the external bundled-skills pattern (intel from
43
+ * leak-research memos, independent implementation TS). No upstream code reused.
44
+ */
45
+ import { spawnSync } from 'node:child_process';
46
+ import { existsSync, readFileSync, statSync } from 'node:fs';
47
+ import { isAbsolute, resolve } from 'node:path';
48
+ const DEFAULT_CMD_TIMEOUT_MS = 30_000;
49
+ function parseFlags(args) {
50
+ const flags = {
51
+ json: false,
52
+ strict: true,
53
+ claimsPath: null,
54
+ };
55
+ for (let i = 0; i < args.length; i += 1) {
56
+ const arg = args[i];
57
+ if (arg === undefined)
58
+ continue;
59
+ if (arg === '--json') {
60
+ flags.json = true;
61
+ continue;
62
+ }
63
+ if (arg === '--strict') {
64
+ flags.strict = true;
65
+ continue;
66
+ }
67
+ if (arg === '--no-strict') {
68
+ flags.strict = false;
69
+ continue;
70
+ }
71
+ if (arg === '--help' || arg === '-h') {
72
+ return { flags, error: 'help' };
73
+ }
74
+ if (arg.startsWith('--')) {
75
+ return { flags, error: `unknown flag: ${arg}` };
76
+ }
77
+ if (flags.claimsPath === null) {
78
+ flags.claimsPath = arg;
79
+ continue;
80
+ }
81
+ return { flags, error: `unexpected positional argument: ${arg}` };
82
+ }
83
+ return { flags, error: null };
84
+ }
85
+ /**
86
+ * Parse a JSON document into a typed claim list. The grammar is
87
+ * intentionally strict — any unknown `kind`, missing field, or extra
88
+ * top-level type produces a parse error so the operator does not get
89
+ * a silent green check for a malformed claim.
90
+ *
91
+ * Public for test coverage.
92
+ */
93
+ export function parseClaimsDocument(raw) {
94
+ let json;
95
+ try {
96
+ json = JSON.parse(raw);
97
+ }
98
+ catch (err) {
99
+ const message = err instanceof Error ? err.message : String(err);
100
+ return { ok: false, error: `invalid JSON: ${message}` };
101
+ }
102
+ const items = Array.isArray(json)
103
+ ? json
104
+ : isPlainObject(json) && Array.isArray(json.claims)
105
+ ? json.claims
106
+ : [];
107
+ if (!Array.isArray(items)) {
108
+ return { ok: false, error: 'top-level value must be an array or { claims: [...] }' };
109
+ }
110
+ if (items.length === 0) {
111
+ return { ok: false, error: 'claims list is empty' };
112
+ }
113
+ const claims = [];
114
+ for (let i = 0; i < items.length; i += 1) {
115
+ const item = items[i];
116
+ if (!isPlainObject(item)) {
117
+ return { ok: false, error: `claims[${i}] must be an object` };
118
+ }
119
+ const claim = item.claim;
120
+ const kind = item.kind;
121
+ const target = item.target;
122
+ const expected = item.expected;
123
+ if (typeof claim !== 'string' || claim.length === 0) {
124
+ return { ok: false, error: `claims[${i}].claim must be a non-empty string` };
125
+ }
126
+ if (kind !== 'file_exists' &&
127
+ kind !== 'grep_match' &&
128
+ kind !== 'cmd_zero_exit') {
129
+ return {
130
+ ok: false,
131
+ error: `claims[${i}].kind must be one of file_exists | grep_match | cmd_zero_exit`,
132
+ };
133
+ }
134
+ if (typeof target !== 'string' || target.length === 0) {
135
+ return { ok: false, error: `claims[${i}].target must be a non-empty string` };
136
+ }
137
+ if (kind === 'grep_match') {
138
+ if (typeof expected !== 'string' || expected.length === 0) {
139
+ return {
140
+ ok: false,
141
+ error: `claims[${i}].expected required for grep_match (substring or /regex/)`,
142
+ };
143
+ }
144
+ }
145
+ if (kind === 'cmd_zero_exit') {
146
+ // Reject shell metacharacters so we cannot accidentally
147
+ // open an injection seam — the runner uses spawnSync without a
148
+ // shell, but a heavy quote in the target string still indicates
149
+ // operator intent we should refuse.
150
+ if (/[;&|`$<>]/.test(target)) {
151
+ return {
152
+ ok: false,
153
+ error: `claims[${i}].target rejects shell metacharacters (; & | $\` < >)`,
154
+ };
155
+ }
156
+ }
157
+ const built = {
158
+ claim,
159
+ kind,
160
+ target,
161
+ ...(typeof expected === 'string' ? { expected } : {}),
162
+ };
163
+ claims.push(built);
164
+ }
165
+ return { ok: true, claims };
166
+ }
167
+ function isPlainObject(value) {
168
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
169
+ }
170
+ /**
171
+ * Resolve a claim target to an absolute path. Public so tests can pin
172
+ * the resolution without spinning up a fake filesystem.
173
+ */
174
+ export function resolveTargetPath(target, cwd) {
175
+ return isAbsolute(target) ? target : resolve(cwd, target);
176
+ }
177
+ function evaluateFileExists(claim, resolvePath) {
178
+ const path = resolvePath(claim.target);
179
+ if (!existsSync(path)) {
180
+ return { ok: false, detail: `missing: ${path}` };
181
+ }
182
+ try {
183
+ const stats = statSync(path);
184
+ if (!stats.isFile()) {
185
+ return { ok: false, detail: `not a regular file: ${path}` };
186
+ }
187
+ if (stats.size === 0) {
188
+ return { ok: false, detail: `empty file (0 bytes): ${path}` };
189
+ }
190
+ return { ok: true, detail: `present, ${stats.size} bytes: ${path}` };
191
+ }
192
+ catch (err) {
193
+ const message = err instanceof Error ? err.message : String(err);
194
+ return { ok: false, detail: `stat failed for ${path}: ${message}` };
195
+ }
196
+ }
197
+ function evaluateGrepMatch(claim, resolvePath) {
198
+ const path = resolvePath(claim.target);
199
+ if (!existsSync(path)) {
200
+ return { ok: false, detail: `missing: ${path}` };
201
+ }
202
+ if (claim.expected === undefined) {
203
+ return { ok: false, detail: `expected pattern is required for grep_match` };
204
+ }
205
+ let body;
206
+ try {
207
+ body = readFileSync(path, 'utf8');
208
+ }
209
+ catch (err) {
210
+ const message = err instanceof Error ? err.message : String(err);
211
+ return { ok: false, detail: `read failed for ${path}: ${message}` };
212
+ }
213
+ const regex = parseExpectedPattern(claim.expected);
214
+ if (regex === null) {
215
+ return {
216
+ ok: false,
217
+ detail: `invalid expected pattern: ${claim.expected}`,
218
+ };
219
+ }
220
+ if (typeof regex === 'string') {
221
+ return body.includes(regex)
222
+ ? { ok: true, detail: `substring matched in ${path}` }
223
+ : { ok: false, detail: `substring '${regex}' not found in ${path}` };
224
+ }
225
+ return regex.test(body)
226
+ ? { ok: true, detail: `regex matched in ${path}` }
227
+ : { ok: false, detail: `regex ${String(regex)} not found in ${path}` };
228
+ }
229
+ /**
230
+ * Parse the `expected` field. `/pattern/flags` → RegExp; anything else
231
+ * is a literal substring. Returns `null` on a malformed regex syntax.
232
+ * Public so the test suite can exercise the surface directly.
233
+ */
234
+ export function parseExpectedPattern(expected) {
235
+ const trimmed = expected;
236
+ // Detect /pattern/flags shape; the pattern must end with the same
237
+ // slash and only allow a small flag set so a bare path with slashes
238
+ // does NOT get mistaken for a regex.
239
+ if (trimmed.length >= 2 &&
240
+ trimmed.startsWith('/') &&
241
+ /\/[gimsuy]*$/.test(trimmed.slice(1))) {
242
+ const lastSlash = trimmed.lastIndexOf('/');
243
+ const pattern = trimmed.slice(1, lastSlash);
244
+ const flags = trimmed.slice(lastSlash + 1);
245
+ try {
246
+ return new RegExp(pattern, flags);
247
+ }
248
+ catch {
249
+ return null;
250
+ }
251
+ }
252
+ return trimmed;
253
+ }
254
+ function evaluateCmdZeroExit(claim, ctx) {
255
+ const tokens = tokenizeCommand(claim.target);
256
+ if (tokens.length === 0) {
257
+ return { ok: false, detail: 'empty command' };
258
+ }
259
+ const runCommand = ctx.runCommand ?? defaultRunCommand;
260
+ const result = runCommand(tokens, {
261
+ cwd: ctx.cwd,
262
+ env: ctx.env,
263
+ timeoutMs: DEFAULT_CMD_TIMEOUT_MS,
264
+ });
265
+ if (result.exitCode === 0) {
266
+ return { ok: true, detail: `exit 0 (${tokens.join(' ')})` };
267
+ }
268
+ const head = (result.stderr || result.stdout).split('\n', 1)[0] ?? '';
269
+ return {
270
+ ok: false,
271
+ detail: `exit ${result.exitCode ?? 'null'} (${tokens.join(' ')}) — ${head.slice(0, 200)}`,
272
+ };
273
+ }
274
+ /**
275
+ * Naive whitespace + quoted-string tokenizer. Sufficient for the
276
+ * cmd_zero_exit surface (operators commonly hand us `pnpm typecheck`
277
+ * or `node -e "..."`); rejects shell metas at parse time so the
278
+ * lexer never needs to handle pipes or redirects.
279
+ *
280
+ * Public for test coverage of edge cases like quoted args with spaces.
281
+ */
282
+ export function tokenizeCommand(input) {
283
+ const out = [];
284
+ let cur = '';
285
+ let quote = null;
286
+ for (let i = 0; i < input.length; i += 1) {
287
+ const ch = input.charAt(i);
288
+ if (quote !== null) {
289
+ if (ch === quote) {
290
+ quote = null;
291
+ continue;
292
+ }
293
+ cur += ch;
294
+ continue;
295
+ }
296
+ if (ch === '"' || ch === "'") {
297
+ quote = ch;
298
+ continue;
299
+ }
300
+ if (ch === ' ' || ch === '\t') {
301
+ if (cur !== '') {
302
+ out.push(cur);
303
+ cur = '';
304
+ }
305
+ continue;
306
+ }
307
+ cur += ch;
308
+ }
309
+ if (cur !== '')
310
+ out.push(cur);
311
+ return out;
312
+ }
313
+ function defaultRunCommand(args, ctx) {
314
+ const [bin, ...rest] = args;
315
+ if (bin === undefined) {
316
+ return { exitCode: null, stdout: '', stderr: 'empty command' };
317
+ }
318
+ try {
319
+ const result = spawnSync(bin, rest, {
320
+ cwd: ctx.cwd,
321
+ env: ctx.env,
322
+ encoding: 'utf8',
323
+ timeout: ctx.timeoutMs,
324
+ maxBuffer: 8 * 1024 * 1024,
325
+ });
326
+ return {
327
+ exitCode: result.status,
328
+ stdout: result.stdout ?? '',
329
+ stderr: result.stderr ?? '',
330
+ };
331
+ }
332
+ catch (err) {
333
+ const message = err instanceof Error ? err.message : String(err);
334
+ return { exitCode: null, stdout: '', stderr: message };
335
+ }
336
+ }
337
+ function renderHumanReport(result, strict) {
338
+ const lines = [];
339
+ lines.push(`pugi verify — ${result.results.length} claim(s)`);
340
+ lines.push(`passed: ${result.passed} failed: ${result.failed.length} strict: ${strict ? 'on' : 'off'}`);
341
+ lines.push('');
342
+ for (const r of result.results) {
343
+ const tag = r.ok ? '[ok] ' : '[FAIL]';
344
+ lines.push(`${tag} ${r.claim.claim} (${r.claim.kind})`);
345
+ lines.push(` ${r.detail}`);
346
+ }
347
+ return lines.join('\n');
348
+ }
349
+ export async function runVerifyCommand(args, ctx) {
350
+ const { flags, error } = parseFlags(args);
351
+ if (error === 'help') {
352
+ ctx.writeOutput({ ok: true, command: 'verify', usage: VERIFY_USAGE }, VERIFY_USAGE);
353
+ return { results: [], passed: 0, failed: [], exitCode: 0 };
354
+ }
355
+ if (error !== null) {
356
+ ctx.writeOutput({ ok: false, command: 'verify', error }, `pugi verify: ${error}`);
357
+ return { results: [], passed: 0, failed: [], exitCode: 2 };
358
+ }
359
+ if (flags.claimsPath === null) {
360
+ const msg = 'claims path is required';
361
+ ctx.writeOutput({ ok: false, command: 'verify', error: msg }, `pugi verify: ${msg}\n\n${VERIFY_USAGE}`);
362
+ return { results: [], passed: 0, failed: [], exitCode: 2 };
363
+ }
364
+ const claimsPath = isAbsolute(flags.claimsPath)
365
+ ? flags.claimsPath
366
+ : resolve(ctx.cwd, flags.claimsPath);
367
+ if (!existsSync(claimsPath)) {
368
+ const msg = `claims file not found: ${claimsPath}`;
369
+ ctx.writeOutput({ ok: false, command: 'verify', error: msg }, `pugi verify: ${msg}`);
370
+ return { results: [], passed: 0, failed: [], exitCode: 2 };
371
+ }
372
+ let raw;
373
+ try {
374
+ raw = readFileSync(claimsPath, 'utf8');
375
+ }
376
+ catch (err) {
377
+ const message = err instanceof Error ? err.message : String(err);
378
+ ctx.writeOutput({ ok: false, command: 'verify', error: message }, `pugi verify: cannot read ${claimsPath}: ${message}`);
379
+ return { results: [], passed: 0, failed: [], exitCode: 2 };
380
+ }
381
+ const parsed = parseClaimsDocument(raw);
382
+ if (!parsed.ok) {
383
+ ctx.writeOutput({ ok: false, command: 'verify', error: parsed.error }, `pugi verify: ${parsed.error}`);
384
+ return { results: [], passed: 0, failed: [], exitCode: 2 };
385
+ }
386
+ const resolvePath = ctx.resolvePath
387
+ ?? ((t) => resolveTargetPath(t, ctx.cwd));
388
+ const results = [];
389
+ for (const claim of parsed.claims) {
390
+ const startedAt = Date.now();
391
+ let outcome;
392
+ if (claim.kind === 'file_exists') {
393
+ outcome = evaluateFileExists(claim, resolvePath);
394
+ }
395
+ else if (claim.kind === 'grep_match') {
396
+ outcome = evaluateGrepMatch(claim, resolvePath);
397
+ }
398
+ else {
399
+ outcome = evaluateCmdZeroExit(claim, ctx);
400
+ }
401
+ const durationMs = Date.now() - startedAt;
402
+ results.push({
403
+ claim,
404
+ ok: outcome.ok,
405
+ detail: outcome.detail,
406
+ durationMs,
407
+ });
408
+ }
409
+ const failed = results.filter((r) => !r.ok);
410
+ const passed = results.length - failed.length;
411
+ const exitCode = flags.strict && failed.length > 0 ? 1 : 0;
412
+ const result = { results, passed, failed, exitCode };
413
+ ctx.writeOutput({ ok: true, command: 'verify', result }, renderHumanReport(result, flags.strict));
414
+ return result;
415
+ }
416
+ const VERIFY_USAGE = [
417
+ 'pugi verify — post-execution claim verification.',
418
+ '',
419
+ 'Usage:',
420
+ ' pugi verify <claims.json> [--json] [--strict | --no-strict]',
421
+ '',
422
+ 'Flags:',
423
+ ' --json Emit a JSON envelope instead of human text.',
424
+ ' --strict Any failed claim → exit 1 (default).',
425
+ ' --no-strict Print the ledger but always exit 0 on hard claim failures.',
426
+ '',
427
+ 'Claim shapes (kind):',
428
+ ' file_exists target = path (pass when file present + non-empty)',
429
+ ' grep_match target = path expected = substring or /regex/flags',
430
+ ' cmd_zero_exit target = command line (no shell metas)',
431
+ '',
432
+ 'Sample claims.json:',
433
+ ' [',
434
+ ' { "claim": "snake.html shipped", "kind": "file_exists", "target": "snake.html" },',
435
+ ' { "claim": "Hiroshi authored", "kind": "grep_match", "target": "CHANGELOG.md", "expected": "Hiroshi" },',
436
+ ' { "claim": "types compile", "kind": "cmd_zero_exit", "target": "pnpm typecheck" }',
437
+ ' ]',
438
+ ].join('\n');
439
+ //# sourceMappingURL=verify.js.map