@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,229 @@
1
+ /**
2
+ * `agent` tool — β2 S3 .
3
+ *
4
+ * Exposes the subagent spawn primitive as a first-class tool call so
5
+ * the root Pugi persona (or any orchestrator-capable parent loop) can
6
+ * delegate a brief to a specialist child via the standard tool-use
7
+ * grammar instead of via the legacy `<pugi-delegate>` XML sidechannel.
8
+ *
9
+ * Grammar:
10
+ *
11
+ * {
12
+ * "role": "coder" | "verifier" | "reviewer" | "researcher" | ...,
13
+ * "brief": "one-paragraph task description",
14
+ * "isolation": "worktree" | "shared_fs" | "auto" // optional, default "auto"
15
+ * }
16
+ *
17
+ * Returns a JSON envelope:
18
+ *
19
+ * {
20
+ * "ok": true,
21
+ * "taskId": "subagent-<uuid>",
22
+ * "role": "coder",
23
+ * "personaSlug": "dev",
24
+ * "status": "shipped" | "blocked" | "failed",
25
+ * "summary": "...",
26
+ * "filesChanged": ["src/...", "src/..."],
27
+ * "toolCallCount": N,
28
+ * "tokensIn": N,
29
+ * "tokensOut": N,
30
+ * "durationMs": N,
31
+ * "worktreePath": "/path/.pugi/worktrees/<uuid>" // only when worktree isolation used
32
+ * }
33
+ *
34
+ * Why expose this as a tool rather than baking it into the engine
35
+ * loop directly:
36
+ *
37
+ * - The model's existing tool-use grammar is what every modern Anvil
38
+ * provider speaks natively. Wrapping delegation as a tool means the
39
+ * model can decide WHEN to spawn a child the same way it decides
40
+ * when to read/edit/bash — no special-case prompt engineering.
41
+ * - The `agent` tool is gated by the isolation-matrix capability map
42
+ * (only `orchestrator`-class roles see it in their tools schema).
43
+ * A coder/reviewer/verifier cannot recursively spawn grandchildren
44
+ * because they never see the `agent` tool in the first place.
45
+ * - The audit log threads cleanly: parent's `tool_call: agent(...)`
46
+ * pairs with the child's `subagent.spawned/tool_call/completed`
47
+ * events, and a single SSE replay yields the full tree.
48
+ */
49
+ import { z } from 'zod';
50
+ import { randomUUID } from 'node:crypto';
51
+ import { relative as relativePath } from 'node:path';
52
+ import { spawnSubagentWithOutcome } from '../core/subagents/spawn.js';
53
+ import { inheritCacheContext } from '../core/dispatch/cache-handoff.js';
54
+ /**
55
+ * Argument schema. `isolation: 'auto'` defers to the role-default
56
+ * isolation tier (set by `isolationForRole` in dispatcher.ts). The
57
+ * explicit `worktree` opt-in forces worktree isolation even for roles
58
+ * whose default is `shared_fs_serialized`; `shared_fs` does the
59
+ * inverse (forces shared-fs even for roles whose default is `worktree`).
60
+ *
61
+ * The role enum mirrors the SDK's SubagentRole — keep both in lockstep.
62
+ *
63
+ * Leak P0 L2 : `z.strictObject` rejects ANY additional or
64
+ * aliased fields at parse time. Matches the the standard file-edit grammar /
65
+ * FileWriteTool posture (). The model-facing JSON
66
+ * schema already declares `additionalProperties: false`; the strict
67
+ * Zod variant is defense-in-depth — if the bridge ever bypasses the
68
+ * model-side gate (raw test fixture, internal dispatch), the runtime
69
+ * still refuses unknown keys instead of silently dropping them.
70
+ */
71
+ export const agentToolArgsSchema = z.strictObject({
72
+ role: z.enum([
73
+ 'orchestrator',
74
+ 'architect',
75
+ 'coder',
76
+ 'verifier',
77
+ 'reviewer',
78
+ 'researcher',
79
+ 'release',
80
+ 'devops',
81
+ 'design_qa',
82
+ ]).describe('SubagentRole — selects persona + isolation tier.'),
83
+ brief: z
84
+ .string()
85
+ .min(1, 'brief must not be empty')
86
+ .max(8000, 'brief must be ≤ 8000 chars')
87
+ .describe('One-paragraph task description forwarded to the child as the user prompt. '
88
+ + 'Be concrete: include filenames, expected behavior, and acceptance criteria.'),
89
+ isolation: z
90
+ .enum(['worktree', 'shared_fs', 'auto'])
91
+ .optional()
92
+ .describe('Optional override. `worktree` forces a scratch git worktree for write isolation; '
93
+ + '`shared_fs` forces same-tree execution; `auto` (default) defers to the role tier.'),
94
+ });
95
+ /**
96
+ * Dispatch a subagent via the `agent` tool. Returns the JSON envelope
97
+ * the executor wraps into the tool result frame. Throws when the
98
+ * arguments fail schema validation — the executor catches and feeds
99
+ * the message back to the model so it can correct itself.
100
+ */
101
+ export async function agentTool(args, ctx) {
102
+ const validated = agentToolArgsSchema.parse(args);
103
+ if (!ctx.engineClient) {
104
+ // Hard refusal: the `agent` tool is real-backend-only. Surfacing a
105
+ // structured envelope (instead of throwing) lets the model decide
106
+ // whether to abandon the delegation or to fall back to in-process
107
+ // work. Throwing here would terminate the parent loop on a tool
108
+ // error frame, which is the wrong UX when the issue is config.
109
+ return {
110
+ ok: false,
111
+ taskId: `subagent-rejected-${randomUUID()}`,
112
+ role: validated.role,
113
+ personaSlug: '',
114
+ status: 'failed',
115
+ summary: 'agent tool unavailable: no engine client wired through the parent dispatch. '
116
+ + 'Run pugi via the standard CLI entrypoints; the in-memory test harness does '
117
+ + 'not currently support real subagent spawn.',
118
+ filesChanged: [],
119
+ toolCallCount: 0,
120
+ tokensIn: 0,
121
+ tokensOut: 0,
122
+ durationMs: 0,
123
+ };
124
+ }
125
+ // β2 S10 pre-flight (best-effort): refuse the spawn if the child's
126
+ // role-default token budget exceeds the parent's remaining budget.
127
+ // The check is conservative — it uses the child's DEFAULT envelope
128
+ // because we do not know the actual run cost ahead of time. Roles
129
+ // can downscale via SubagentTask.budget overrides; this gate just
130
+ // catches the gross case (parent has 5k left, child default 80k).
131
+ if (ctx.parentBudgetRemaining?.tokens !== undefined) {
132
+ const { budgetForRole } = await import('../core/subagents/dispatcher.js');
133
+ const childDefault = budgetForRole(validated.role, undefined);
134
+ if (childDefault.tokens > ctx.parentBudgetRemaining.tokens) {
135
+ return {
136
+ ok: false,
137
+ taskId: `subagent-budget-refused-${randomUUID()}`,
138
+ role: validated.role,
139
+ personaSlug: '',
140
+ status: 'blocked',
141
+ summary: `agent spawn refused: child '${validated.role}' default budget is ${childDefault.tokens} tokens `
142
+ + `but parent has only ${ctx.parentBudgetRemaining.tokens} tokens remaining. `
143
+ + 'Tighten the child task budget or finish the parent first.',
144
+ filesChanged: [],
145
+ toolCallCount: 0,
146
+ tokensIn: 0,
147
+ tokensOut: 0,
148
+ durationMs: 0,
149
+ };
150
+ }
151
+ }
152
+ const task = {
153
+ id: `subagent-${randomUUID()}`,
154
+ role: validated.role,
155
+ prompt: validated.brief,
156
+ // `auto` permission mode matches the parent loop's default; the
157
+ // isolation-matrix capability gate provides the load-bearing
158
+ // restriction layer regardless of permissionMode.
159
+ permissionMode: 'auto',
160
+ };
161
+ // L10 : synthesize a prompt-cache inheritance handle for
162
+ // the child before we dispatch. The handle is persisted under
163
+ // `.pugi/cache-refs/<childAgentId>.json` so:
164
+ // - The child engine loop's first turn (dispatcher-real.ts) can
165
+ // forward parent_cache_id onto Anvil — provider-dependent honour
166
+ // (Anthropic cache_control breakpoints today; OpenAI/Gemini
167
+ // silently ignore until Anvil grows per-provider adapters).
168
+ // - Operators can introspect via `pugi dispatch list-cache-refs`.
169
+ // - `pugi dispatch clear-cache-refs --older-than 1h` can GC after
170
+ // a long session.
171
+ // Failure to persist must NOT block the dispatch — the handle is a
172
+ // best-effort optimisation; if disk is full or the workspace root is
173
+ // read-only, we degrade silently to a cache-miss dispatch.
174
+ try {
175
+ inheritCacheContext(ctx.session.id, task.id, {
176
+ workspaceRoot: ctx.session.root,
177
+ ...(ctx.now ? { now: ctx.now } : {}),
178
+ });
179
+ }
180
+ catch {
181
+ // Silent degrade: cache inheritance is forward-compat, not load-bearing.
182
+ }
183
+ const useWorktree = validated.isolation === 'worktree'
184
+ ? true
185
+ : validated.isolation === 'shared_fs'
186
+ ? false
187
+ : undefined; // 'auto' → defer to role default
188
+ const outcome = await spawnSubagentWithOutcome(task, ctx.session, {
189
+ engineClient: ctx.engineClient,
190
+ ...(useWorktree !== undefined ? { useWorktreeIsolation: useWorktree } : {}),
191
+ });
192
+ const envelope = {
193
+ // `ok` = subagent did not crash. Both `shipped` (real work) and
194
+ // `replied` (text-only completion, added) count as
195
+ // non-crash outcomes; the caller can branch on the explicit
196
+ // `status` field below if it needs to distinguish them.
197
+ ok: outcome.result.status === 'shipped' || outcome.result.status === 'replied',
198
+ taskId: outcome.result.taskId,
199
+ role: outcome.result.role,
200
+ personaSlug: outcome.result.personaSlug,
201
+ status: outcome.result.status,
202
+ summary: outcome.result.summary,
203
+ filesChanged: outcome.result.filesChanged,
204
+ toolCallCount: outcome.result.toolCallCount,
205
+ tokensIn: outcome.result.tokensIn,
206
+ tokensOut: outcome.result.tokensOut,
207
+ durationMs: outcome.result.durationMs,
208
+ };
209
+ if (outcome.worktreeHandle) {
210
+ // β2a r2 (Codex P1): emit the worktree path RELATIVE to
211
+ // the parent session's workspace root. The envelope is JSON-stringified
212
+ // into the parent loop's tool_result frame and from there flows to the
213
+ // provider on every subsequent assistant turn — shipping the absolute
214
+ // path (`/Users/<operator>/Web/.../.pugi/worktrees/<uuid>`) leaks the
215
+ // operator's home directory to the upstream provider on every spawn.
216
+ //
217
+ // The composeSummary path (dispatcher-real.ts §β2a r1) already scrubs
218
+ // the summary text via the same `relative()` wrapping; this is the
219
+ // matching fix for the structured envelope field that r1 missed.
220
+ // The relative form (`.pugi/worktrees/<uuid>`) is enough for the
221
+ // operator's local `pugi worktree promote/drop` commands which run
222
+ // resolved against ctx.session.root anyway.
223
+ const relPath = relativePath(ctx.session.root, outcome.worktreeHandle.path)
224
+ || outcome.worktreeHandle.path;
225
+ envelope.worktreePath = relPath;
226
+ }
227
+ return envelope;
228
+ }
229
+ //# sourceMappingURL=agent-tool.js.map
@@ -1,22 +1,22 @@
1
1
  /**
2
- * apply_patch tool — α7.7 Phase 1.
2
+ * apply_patch tool — Phase 1.
3
3
  *
4
4
  * Accepts a unified diff (the format produced by `git diff` and
5
5
  * consumed by `git apply`) and lands it atomically into the workspace.
6
- * This is the third edit primitive alongside the α6.6 4-layer diff
6
+ * This is the third edit primitive alongside the 4-layer diff
7
7
  * escalation: where the layers escalate from minimal `oldString`/
8
8
  * `newString` blocks up to full-file rewrites, apply_patch covers the
9
9
  * unified-diff dialect that OpenAI Codex and most external tools emit.
10
10
  *
11
11
  * Why we have both:
12
12
  *
13
- * - The 4-layer escalation maximises model-side success rate on
14
- * conversational edits (Claude / Gemini / OpenAI all have a
15
- * preferred dialect that maps onto one of the layers).
16
- * - apply_patch is the "external tools speak this" path. A model
17
- * emits a single unified diff (the format `git diff` produces),
18
- * and we run it through `git apply` with the same security gate
19
- * the layers use.
13
+ * - The 4-layer escalation maximises model-side success rate on
14
+ * conversational edits (Claude / Gemini / OpenAI all have a
15
+ * preferred dialect that maps onto one of the layers).
16
+ * - apply_patch is the "external tools speak this" path. A model
17
+ * emits a single unified diff (the format `git diff` produces),
18
+ * and we run it through `git apply` with the same security gate
19
+ * the layers use.
20
20
  *
21
21
  * Security: every file mentioned in the patch goes through the same
22
22
  * `applySecurityGate` chokepoint as the layers (see
@@ -55,7 +55,7 @@ import { recordToolCall, recordToolResult, recordFileMutation } from '../core/se
55
55
  * touched paths feeds the security gate — EVERY file goes through
56
56
  * `applySecurityGate` before we trust `git apply` to do anything.
57
57
  *
58
- * Security (R1 fix 2026-05-26, PR #413 r1): git emits C-style quoted
58
+ * Security (R1 fix, PR r1): git emits C-style quoted
59
59
  * path headers when a path contains "unusual" bytes (high bits, control
60
60
  * chars, double-quote, backslash) and `core.quotePath` is true (the
61
61
  * default). The literal header looks like
@@ -140,11 +140,11 @@ function stripQuotedHalf(after, prefix) {
140
140
  * (default) git writes paths with high-bit / control / quote bytes as
141
141
  * C-string escapes inside double quotes:
142
142
  *
143
- * `"\.env"` -> `.env` (backslash before . is just a literal)
144
- * `"a\"b"` -> `a"b` (escaped double-quote)
145
- * `"a\\b"` -> `a\b` (escaped backslash)
146
- * `"a\tb"` -> `a` + TAB + `b`
147
- * `"a\341\210\264"` -> `a` + UTF-8 bytes 0xe1 0x88 0xb4
143
+ * `"\.env"` -> `.env` (backslash before . is just a literal)
144
+ * `"a\"b"` -> `a"b` (escaped double-quote)
145
+ * `"a\\b"` -> `a\b` (escaped backslash)
146
+ * `"a\tb"` -> `a` + TAB + `b`
147
+ * `"a\341\210\264"` -> `a` + UTF-8 bytes 0xe1 0x88 0xb4
148
148
  *
149
149
  * Accepts a path that is EITHER already unquoted (passed through) OR an
150
150
  * inner string previously stripped of its surrounding quotes. The
@@ -261,6 +261,25 @@ export function applyPatch(ctx, patch, opts = {}) {
261
261
  recordToolResult(ctx.session, toolCallId, 'error', 'empty_patch');
262
262
  return result;
263
263
  }
264
+ // β7 L4: pre-flight conflict-marker check. A patch that still carries
265
+ // unresolved `<<<<<<<`/`=======`/`>>>>>>>` lines is almost always
266
+ // operator error (copy-pasted a half-resolved merge instead of the
267
+ // clean diff). `git apply` would reject it with a confusing
268
+ // "corrupt patch" message; the dedicated reason makes the failure
269
+ // obvious. We only check at body line starts so a legitimate diff
270
+ // that adds a string literal containing `<<<<<<<` for tests still
271
+ // applies.
272
+ if (containsConflictMarkers(patch)) {
273
+ const result = {
274
+ ok: false,
275
+ filesChanged: [],
276
+ reason: 'conflict_markers',
277
+ detail: 'patch body contains unresolved git conflict markers (<<<<<<<, =======, >>>>>>>). ' +
278
+ 'Resolve the conflict first or use --3way with --base=<sha> to defer to git.',
279
+ };
280
+ recordToolResult(ctx.session, toolCallId, 'error', 'conflict_markers');
281
+ return result;
282
+ }
264
283
  const paths = extractPatchPaths(patch);
265
284
  if (paths.length === 0) {
266
285
  const result = {
@@ -272,12 +291,12 @@ export function applyPatch(ctx, patch, opts = {}) {
272
291
  recordToolResult(ctx.session, toolCallId, 'error', 'invalid_patch');
273
292
  return result;
274
293
  }
275
- // SECURITY GATE — reuse the α6.6 chokepoint. Every path in the patch
294
+ // SECURITY GATE — reuse the chokepoint. Every path in the patch
276
295
  // is validated against:
277
- // 1. workspace containment (no ../../ escapes)
278
- // 2. protected-file basenames (.env, *.pem, id_rsa, etc.)
279
- // 3. symlink escape (an in-workspace symlink pointing to /etc/hosts
280
- // or a protected basename gets rejected here)
296
+ // 1. workspace containment (no ../../ escapes)
297
+ // 2. protected-file basenames (.env, *.pem, id_rsa, etc.)
298
+ // 3. symlink escape (an in-workspace symlink pointing to /etc/hosts
299
+ // or a protected basename gets rejected here)
281
300
  for (const file of paths) {
282
301
  const gate = applySecurityGate(file, { cwd: ctx.root, toolName: 'layer-c' });
283
302
  if (!gate.ok) {
@@ -349,7 +368,7 @@ export function applyPatch(ctx, patch, opts = {}) {
349
368
  recordToolResult(ctx.session, toolCallId, 'success', `dry-run ok, ${paths.length} files`);
350
369
  return result;
351
370
  }
352
- // R1 fix (2026-05-26, PR #413 r1, Fix 6): snapshot which paths exist
371
+ // R1 fix (2026-05-26, PR r1, Fix 6): snapshot which paths exist
353
372
  // BEFORE the apply so rollbackFiles can decide between
354
373
  // `git checkout -- <file>` (for files that existed) and `fs.rmSync`
355
374
  // (for files the patch was creating that may have been half-written
@@ -409,16 +428,16 @@ export function applyPatch(ctx, patch, opts = {}) {
409
428
  * only on the rare path where `git apply` fails AFTER `git apply --check`
410
429
  * passed.
411
430
  *
412
- * R1 fix (2026-05-26, PR #413 r1, Fix 6): a multi-file patch that
431
+ * R1 fix (2026-05-26, PR r1, Fix 6): a multi-file patch that
413
432
  * creates new files leaves them on disk when `git apply` fails partway —
414
433
  * `git checkout -- <file>` does NOT delete a path that was never tracked
415
434
  * (the file was created by the failed apply). We split paths into two
416
435
  * groups using the pre-apply snapshot:
417
436
  *
418
- * - existed-before -> `git checkout -- <file>` restores tracked content.
419
- * - created-by-apply -> `fs.rmSync(file, { force: true })` removes the
420
- * half-written file so the workspace ends up identical to its
421
- * pre-apply state.
437
+ * - existed-before -> `git checkout -- <file>` restores tracked content.
438
+ * - created-by-apply -> `fs.rmSync(file, { force: true })` removes the
439
+ * half-written file so the workspace ends up identical to its
440
+ * pre-apply state.
422
441
  *
423
442
  * This keeps the dispatcher's invariant: a tool result of `ok: false`
424
443
  * means the workspace is unchanged.
@@ -470,7 +489,7 @@ function rollbackFiles(cwd, paths, preExisting) {
470
489
  return { ok: true };
471
490
  }
472
491
  function runGit(args, cwd, stdin) {
473
- // R1 fix (2026-05-26, PR #413 r1, P2 #13): force the English C locale
492
+ // R1 fix (2026-05-26, PR r1, P2 #13): force the English C locale
474
493
  // for the git child process. The `already_applied` reason-coding
475
494
  // below greps stderr for the literal English string
476
495
  // "already exists in working directory"; on a host where git was
@@ -486,10 +505,52 @@ function runGit(args, cwd, stdin) {
486
505
  env: { ...process.env, LANG: 'C', LC_ALL: 'C' },
487
506
  });
488
507
  }
508
+ /**
509
+ * β7 L4: detect unresolved git conflict markers in a patch body.
510
+ *
511
+ * Conflict markers in a unified diff are a sign of operator error —
512
+ * someone copy-pasted a half-merged file instead of the clean diff.
513
+ * `git apply` would reject the patch with a confusing parse error
514
+ * ("corrupt patch at line N"). We check at the START of body lines so
515
+ * a legitimate diff that adds a string literal containing `<<<<<<<`
516
+ * (rare but legitimate for tests) still applies.
517
+ *
518
+ * Conflict marker bytes in a unified diff body look like:
519
+ *
520
+ * +<<<<<<< HEAD
521
+ * +=======
522
+ * +>>>>>>> branch
523
+ *
524
+ * The `+` prefix is the unified-diff line-add marker. We strip it
525
+ * before the marker check; without the strip, an INVERSE diff that
526
+ * REMOVES a real conflict marker (legitimate cleanup commit) would be
527
+ * a false positive.
528
+ *
529
+ * Returns true when ANY conflict marker is detected.
530
+ */
531
+ export function containsConflictMarkers(patch) {
532
+ for (const line of patch.split('\n')) {
533
+ // Only inspect body lines (start with `+` or `-` — the diff add/del
534
+ // markers). Header lines (`diff --git`, `+++`, `---`, `@@`) are
535
+ // skipped because the marker tokens cannot appear in those positions.
536
+ if (!(line.startsWith('+') || line.startsWith('-')))
537
+ continue;
538
+ // Skip diff header lines (`+++ b/foo` / `--- a/foo`).
539
+ if (line.startsWith('+++') || line.startsWith('---'))
540
+ continue;
541
+ const body = line.slice(1);
542
+ if (body.startsWith('<<<<<<<') ||
543
+ body.startsWith('>>>>>>>') ||
544
+ body === '=======') {
545
+ return true;
546
+ }
547
+ }
548
+ return false;
549
+ }
489
550
  /**
490
551
  * Test-only surface for the apply-patch heuristics. Specs poke
491
552
  * `extractPatchPaths` directly to assert on the path-parsing layer
492
553
  * without paying for a real git invocation.
493
554
  */
494
- export const __test__ = { extractPatchPaths, runGit, unquoteGitPath };
555
+ export const __test__ = { extractPatchPaths, runGit, unquoteGitPath, containsConflictMarkers };
495
556
  //# sourceMappingURL=apply-patch.js.map