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

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 (409) 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 +1731 -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/enter-worktree.js +250 -0
  351. package/dist/tools/exit-worktree.js +147 -0
  352. package/dist/tools/file-tools.js +161 -44
  353. package/dist/tools/lsp-tools.js +377 -1
  354. package/dist/tools/mcp-tool.js +260 -0
  355. package/dist/tools/multi-edit.js +361 -0
  356. package/dist/tools/powershell.js +268 -0
  357. package/dist/tools/registry.js +86 -4
  358. package/dist/tools/skill-tool.js +96 -0
  359. package/dist/tools/sleep.js +99 -0
  360. package/dist/tools/synthetic-output.js +133 -0
  361. package/dist/tools/tasks.js +208 -0
  362. package/dist/tools/todo-write.js +184 -0
  363. package/dist/tools/verify-plan-execution.js +295 -0
  364. package/dist/tools/web-fetch-injection-scanner.js +207 -0
  365. package/dist/tools/web-fetch.js +195 -10
  366. package/dist/tools/web-search.js +458 -0
  367. package/dist/tui/agent-progress-card.js +111 -0
  368. package/dist/tui/agent-tree.js +11 -1
  369. package/dist/tui/ask-modal.js +14 -14
  370. package/dist/tui/ask-user-question-chips.js +315 -0
  371. package/dist/tui/ask-user-question-prompt.js +203 -0
  372. package/dist/tui/compact-banner.js +81 -0
  373. package/dist/tui/conversation-pane.js +85 -11
  374. package/dist/tui/cost-table.js +111 -0
  375. package/dist/tui/device-flow.js +2 -2
  376. package/dist/tui/doctor-table.js +46 -0
  377. package/dist/tui/feedback-prompt.js +156 -0
  378. package/dist/tui/input-box.js +247 -32
  379. package/dist/tui/login-picker.js +3 -3
  380. package/dist/tui/markdown-render.js +6 -6
  381. package/dist/tui/onboarding-wizard.js +240 -0
  382. package/dist/tui/permissions-picker.js +86 -0
  383. package/dist/tui/render.js +36 -1
  384. package/dist/tui/repl-render.js +176 -25
  385. package/dist/tui/repl-splash-art.js +16 -16
  386. package/dist/tui/repl-splash-mascot.js +48 -24
  387. package/dist/tui/repl-splash.js +22 -22
  388. package/dist/tui/repl.js +125 -45
  389. package/dist/tui/slash-palette.js +6 -6
  390. package/dist/tui/splash.js +2 -2
  391. package/dist/tui/status-bar.js +109 -31
  392. package/dist/tui/status-table.js +7 -0
  393. package/dist/tui/stickers-art.js +136 -0
  394. package/dist/tui/style-table.js +28 -0
  395. package/dist/tui/theme-table.js +29 -0
  396. package/dist/tui/thinking-spinner.js +123 -0
  397. package/dist/tui/tool-stream-pane.js +53 -4
  398. package/dist/tui/update-banner.js +27 -2
  399. package/dist/tui/vim-input.js +267 -0
  400. package/dist/tui/welcome-banner.js +107 -0
  401. package/dist/tui/welcome-data.js +293 -0
  402. package/dist/tui/workspace-context.js +2 -2
  403. package/package.json +31 -16
  404. package/test/scenarios/codegen-create-file.scenario.txt +13 -0
  405. package/test/scenarios/compact-force.scenario.txt +12 -0
  406. package/test/scenarios/identity.scenario.txt +12 -0
  407. package/test/scenarios/persona-handoff.scenario.txt +12 -0
  408. package/test/scenarios/walkback.scenario.txt +12 -0
  409. package/dist/core/engine/compaction-hook.js +0 -154
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Watch-mode inline marker scanner — Aider AI?/AI! pattern.
3
+ *
4
+ * Watches a directory tree via chokidar (already в deps — used by
5
+ * VS Code и most JS file-watchers). When a file changes, scans the
6
+ * delta для inline markers и emits structured events. Pugi-flavoured
7
+ * marker pair:
8
+ *
9
+ * // PUGI? → operator asks Pugi a question right here
10
+ * // PUGI! → operator instructs Pugi to act right here
11
+ *
12
+ * Also accepts Aider-compatible `// AI?` / `// AI!` for muscle-memory
13
+ * parity. Block comments and `# PUGI?` (Python / shell) are recognised
14
+ * too — language is detected from extension, NOT parsed properly. The
15
+ * goal is opportunistic ergonomics, not a precise parser.
16
+ *
17
+ * No tool dispatch happens here — this module emits events; downstream
18
+ * code (engine integration follow-up) decides what to do.
19
+ */
20
+ import chokidar from 'chokidar';
21
+ import { readFile } from 'node:fs/promises';
22
+ import { EventEmitter } from 'node:events';
23
+ import path from 'node:path';
24
+ const DEFAULT_IGNORED = [
25
+ '**/node_modules/**',
26
+ '**/.git/**',
27
+ '**/dist/**',
28
+ '**/build/**',
29
+ '**/coverage/**',
30
+ '**/.next/**',
31
+ '**/.pugi/**',
32
+ ];
33
+ const DEFAULT_MAX_FILE_BYTES = 256 * 1024;
34
+ // Recognises `// PUGI?`, `# PUGI!`, `/* AI? ... */`, `<!-- PUGI! ... -->` and equivalents.
35
+ // Capture group 1 = comment prefix, 2 = tag (PUGI | AI), 3 = symbol (? | !), 4 = trailing text.
36
+ const MARKER_RE = /(?:\/\/|#|\/\*|<!--)\s*(PUGI|AI)([?!])\s*([^\n*-]*?)(?:\*\/|-->|$)/g;
37
+ export class MarkerWatcher extends EventEmitter {
38
+ options;
39
+ watcher = null;
40
+ maxFileBytes;
41
+ constructor(options = {}) {
42
+ super();
43
+ this.options = options;
44
+ this.maxFileBytes = options.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES;
45
+ }
46
+ /**
47
+ * Start watching `patterns`. Multiple calls without close() throw —
48
+ * one instance, one active watcher.
49
+ */
50
+ start(patterns) {
51
+ if (this.watcher) {
52
+ throw new Error('MarkerWatcher already started — call close() first');
53
+ }
54
+ const ignored = [...(this.options.ignored ?? DEFAULT_IGNORED)];
55
+ const opts = {
56
+ ignored,
57
+ ignoreInitial: this.options.ignoreInitial ?? true,
58
+ persistent: true,
59
+ };
60
+ if (this.options.cwd !== undefined) {
61
+ opts.cwd = this.options.cwd;
62
+ }
63
+ this.watcher = chokidar.watch(patterns, opts);
64
+ this.watcher.on('add', p => void this.scan(p));
65
+ this.watcher.on('change', p => void this.scan(p));
66
+ this.watcher.on('error', err => this.emit('error', err));
67
+ }
68
+ /** Stop watching и release file handles. Safe to call multiple times. */
69
+ async close() {
70
+ if (!this.watcher)
71
+ return;
72
+ await this.watcher.close();
73
+ this.watcher = null;
74
+ }
75
+ /**
76
+ * Scan a single file synchronously — bypasses the watcher entirely.
77
+ * Useful для one-shot scans / tests / initial-load passes.
78
+ */
79
+ async scanOnce(file) {
80
+ return this.collectFromFile(file);
81
+ }
82
+ async scan(file) {
83
+ const hits = await this.collectFromFile(file);
84
+ for (const hit of hits) {
85
+ this.emit('marker', hit);
86
+ }
87
+ }
88
+ async collectFromFile(file) {
89
+ let content;
90
+ // chokidar emits paths relative to its `cwd` option when set. Resolve
91
+ // so readFile doesn't fall back to the process CWD и miss the file.
92
+ const resolved = this.options.cwd && !path.isAbsolute(file)
93
+ ? path.join(this.options.cwd, file)
94
+ : file;
95
+ try {
96
+ const buf = await readFile(resolved);
97
+ if (buf.byteLength > this.maxFileBytes)
98
+ return [];
99
+ content = buf.toString('utf8');
100
+ }
101
+ catch (err) {
102
+ // File deleted between event and read, permissions, etc.
103
+ this.emit('error', err);
104
+ return [];
105
+ }
106
+ const hits = [];
107
+ const lines = content.split('\n');
108
+ for (let i = 0; i < lines.length; i += 1) {
109
+ const lineText = lines[i] ?? '';
110
+ MARKER_RE.lastIndex = 0;
111
+ let match;
112
+ while ((match = MARKER_RE.exec(lineText)) !== null) {
113
+ const tag = match[1] ?? 'PUGI';
114
+ const symbol = match[2] ?? '?';
115
+ const text = (match[3] ?? '').trim();
116
+ hits.push({
117
+ file,
118
+ line: i + 1,
119
+ kind: symbol === '!' ? 'instruction' : 'question',
120
+ tag,
121
+ text,
122
+ });
123
+ }
124
+ }
125
+ return hits;
126
+ }
127
+ }
128
+ /** Standalone scan helper для callers that don't want a long-lived watcher. */
129
+ export async function scanFileForMarkers(file, options = {}) {
130
+ const watcher = new MarkerWatcher({ maxFileBytes: options.maxFileBytes });
131
+ return watcher.scanOnce(file);
132
+ }
133
+ //# sourceMappingURL=marker-watcher.js.map
@@ -0,0 +1,249 @@
1
+ /**
2
+ * `.worktreeinclude` parser - PUGI-487.
3
+ *
4
+ * The `.worktreeinclude` file lives at the repository root and carries
5
+ * gitignore-syntax patterns. Files that:
6
+ *
7
+ * 1. Match at least one pattern in `.worktreeinclude`, AND
8
+ * 2. Are git-ignored (untracked-and-ignored OR explicitly ignored),
9
+ *
10
+ * get COPIED into a fresh `pugi --worktree <name>` tree right after
11
+ * `git worktree add` finishes. Tracked files are NEVER copied because
12
+ * git already brings them along on its own, and double-writing would
13
+ * corrupt the worktree index.
14
+ *
15
+ * Why a separate include file instead of `.gitignore` negation
16
+ * patterns?
17
+ *
18
+ * - The common case is "I have an untracked `.env` with API keys that
19
+ * every parallel session needs". Listing it in `.gitignore` with
20
+ * a negation would force-add it to the repo, defeating the point.
21
+ * - Operators want a single-file, copy-pasteable manifest of WHAT
22
+ * leaves the main tree, not a derived view across `.gitignore`
23
+ * semantics.
24
+ *
25
+ * Pattern grammar (subset of gitignore):
26
+ *
27
+ * - Lines starting with `#` are comments. Blank lines are skipped.
28
+ * - Trailing `/` means directory-only and applies recursively to
29
+ * every file under the directory.
30
+ * - Leading `!` is a negation pattern that REMOVES matches from
31
+ * prior includes. Multiple negations are processed in order.
32
+ * - `*` matches any character except `/`.
33
+ * - `**` matches any number of path segments.
34
+ * - `?` matches a single non-`/` character.
35
+ * - Patterns with NO `/` match anywhere in the tree (e.g. `.env`
36
+ * matches both `./.env` and `./apps/foo/.env`).
37
+ * - Patterns starting with `/` are anchored to the repository root.
38
+ *
39
+ * Brand voice: ASCII only, no emoji, no banned words.
40
+ */
41
+ import { spawnSync } from 'node:child_process';
42
+ import { existsSync, readFileSync, statSync } from 'node:fs';
43
+ import { resolve, sep, posix } from 'node:path';
44
+ /** Default file name. */
45
+ export const WORKTREE_INCLUDE_FILENAME = '.worktreeinclude';
46
+ /**
47
+ * Parse the textual contents of a `.worktreeinclude` file into a rule
48
+ * list. Pure function - does not touch the filesystem. Exposed for
49
+ * spec coverage and the cleanup/dry-run path.
50
+ */
51
+ export function parseWorktreeIncludeText(text, source = WORKTREE_INCLUDE_FILENAME) {
52
+ const rules = [];
53
+ const lines = text.split(/\r?\n/);
54
+ for (const raw of lines) {
55
+ const line = raw.trim();
56
+ if (line.length === 0)
57
+ continue;
58
+ if (line.startsWith('#'))
59
+ continue;
60
+ let body = line;
61
+ let negate = false;
62
+ if (body.startsWith('!')) {
63
+ negate = true;
64
+ body = body.slice(1);
65
+ }
66
+ if (body.length === 0)
67
+ continue;
68
+ let directoryOnly = false;
69
+ if (body.endsWith('/')) {
70
+ directoryOnly = true;
71
+ body = body.slice(0, -1);
72
+ }
73
+ let anchored = false;
74
+ if (body.startsWith('/')) {
75
+ anchored = true;
76
+ body = body.slice(1);
77
+ }
78
+ else if (body.includes('/')) {
79
+ // a non-leading slash also anchors per gitignore semantics
80
+ anchored = true;
81
+ }
82
+ if (body.length === 0)
83
+ continue;
84
+ rules.push({
85
+ raw: line,
86
+ pattern: body,
87
+ negate,
88
+ directoryOnly,
89
+ anchored,
90
+ });
91
+ }
92
+ return { rules, source };
93
+ }
94
+ /**
95
+ * Load + parse `.worktreeinclude` from a repository root. Returns an
96
+ * empty rule set when the file is absent or unreadable - a missing
97
+ * include file is the normal case (no extras to copy).
98
+ */
99
+ export function loadWorktreeInclude(repoRoot) {
100
+ const path = resolve(repoRoot, WORKTREE_INCLUDE_FILENAME);
101
+ if (!existsSync(path)) {
102
+ return { rules: [], source: path };
103
+ }
104
+ try {
105
+ const text = readFileSync(path, 'utf8');
106
+ return parseWorktreeIncludeText(text, path);
107
+ }
108
+ catch {
109
+ return { rules: [], source: path };
110
+ }
111
+ }
112
+ const REGEX_ESCAPE = /[.+^${}()|[\]\\]/;
113
+ /**
114
+ * Convert a gitignore-style glob pattern into a regex source string.
115
+ * Subset implementation: covers `*`, `**`, `?`, and escapes the rest.
116
+ *
117
+ * Uses index-based scanning so `**` is detected and consumed before a
118
+ * single `*` substitution could eat the doubled form.
119
+ */
120
+ function globToRegexSource(pattern) {
121
+ let out = '';
122
+ for (let i = 0; i < pattern.length; i += 1) {
123
+ const ch = pattern.charAt(i);
124
+ if (ch === '*') {
125
+ if (pattern.charAt(i + 1) === '*') {
126
+ out += '.*';
127
+ i += 1;
128
+ continue;
129
+ }
130
+ out += '[^/]*';
131
+ continue;
132
+ }
133
+ if (ch === '?') {
134
+ out += '[^/]';
135
+ continue;
136
+ }
137
+ if (REGEX_ESCAPE.test(ch)) {
138
+ out += '\\' + ch;
139
+ continue;
140
+ }
141
+ out += ch;
142
+ }
143
+ return out;
144
+ }
145
+ /**
146
+ * Decide whether `relPath` (a forward-slash, no-leading-slash path
147
+ * relative to the repo root) is matched by the given rule list. The
148
+ * last matching rule wins so a negation after an include drops the
149
+ * entry and an include after a negation re-adds it.
150
+ */
151
+ export function matchesWorktreeInclude(relPath, rules, isDirectory = false) {
152
+ const normalized = relPath.replace(/\\+/g, '/');
153
+ let matched = false;
154
+ for (const rule of rules) {
155
+ if (rule.directoryOnly && !isDirectory) {
156
+ // directory-only rule still matches files UNDER the dir (handled
157
+ // below). Falls through to the file-match attempt.
158
+ }
159
+ const source = buildRegex(rule);
160
+ const re = new RegExp('^' + source + '$');
161
+ if (re.test(normalized)) {
162
+ matched = !rule.negate;
163
+ continue;
164
+ }
165
+ if (rule.directoryOnly) {
166
+ const reUnder = new RegExp('^' + source + '/.*$');
167
+ if (reUnder.test(normalized)) {
168
+ matched = !rule.negate;
169
+ }
170
+ }
171
+ }
172
+ return matched;
173
+ }
174
+ function buildRegex(rule) {
175
+ const body = globToRegexSource(rule.pattern);
176
+ if (rule.anchored) {
177
+ return body;
178
+ }
179
+ // Unanchored pattern matches anywhere in the tree. Allow a
180
+ // segment-aligned match by accepting either start-of-string or a
181
+ // `/` boundary before the pattern body.
182
+ return '(?:.*/)?' + body;
183
+ }
184
+ /**
185
+ * Walk `repoRoot` and return every git-ignored file path that matches
186
+ * the include rules. Tracked files are excluded because they ride
187
+ * along with git automatically.
188
+ *
189
+ * Implementation note: rather than re-implement gitignore evaluation
190
+ * the default lister shells out to
191
+ * `git ls-files --others --ignored --exclude-standard` to get the
192
+ * authoritative ignored-untracked list. Tracked files never appear in
193
+ * that output, so the result is exactly the safe-to-copy candidate
194
+ * pool.
195
+ */
196
+ export function collectWorktreeIncludeFiles(repoRoot, rules, options = {}) {
197
+ if (rules.length === 0)
198
+ return [];
199
+ const lister = options.listIgnored ?? defaultListIgnored;
200
+ const stat = options.isDirectory ?? defaultIsDirectory;
201
+ const candidates = lister(resolve(repoRoot));
202
+ const out = [];
203
+ for (const candidate of candidates) {
204
+ const rel = candidate.replace(/\\+/g, '/').replace(/^\.\//, '');
205
+ if (rel.length === 0)
206
+ continue;
207
+ if (rel.startsWith('.pugi/') || rel.startsWith('.claude/')) {
208
+ // Never copy Pugi or .claude state into the worktree. Those
209
+ // dirs are owned by the runtime and the include file should
210
+ // not be able to leak audit logs or stale session state.
211
+ continue;
212
+ }
213
+ const absPath = resolve(repoRoot, rel);
214
+ const isDir = stat(absPath);
215
+ if (matchesWorktreeInclude(rel, rules, isDir)) {
216
+ out.push(rel);
217
+ }
218
+ }
219
+ return out;
220
+ }
221
+ function defaultListIgnored(repoRoot) {
222
+ // `-z` emits NUL-separated paths, the only safe form when filenames
223
+ // may contain spaces or newlines.
224
+ const result = spawnSync('git', ['ls-files', '--others', '--ignored', '--exclude-standard', '-z'], {
225
+ cwd: repoRoot,
226
+ encoding: 'buffer',
227
+ shell: false,
228
+ maxBuffer: 64 * 1024 * 1024,
229
+ });
230
+ if (result.status !== 0 || !result.stdout)
231
+ return [];
232
+ const text = result.stdout.toString('utf8');
233
+ return text.split('\u0000').filter((s) => s.length > 0);
234
+ }
235
+ function defaultIsDirectory(absPath) {
236
+ try {
237
+ return statSync(absPath).isDirectory();
238
+ }
239
+ catch {
240
+ return false;
241
+ }
242
+ }
243
+ /** Cross-platform path-join in posix form (for matching semantics). */
244
+ export function joinRel(parent, child) {
245
+ return posix.join(parent.replace(/\\+/g, '/'), child);
246
+ }
247
+ /** Re-export the system separator so consumers do not have to import it. */
248
+ export const PATH_SEP = sep;
249
+ //# sourceMappingURL=include-parser.js.map
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Stale-worktree sweep — .
3
+ *
4
+ * Pairs with `WorktreeManager` to find worktrees whose agent has either:
5
+ *
6
+ * 1. No corresponding progress JSON under `.pugi/agent-progress/` (the
7
+ * writer never wrote one, OR the file was archived away), OR
8
+ * 2. A progress JSON whose `status` is `completed` or `failed` (the
9
+ * agent finished — the worktree is no longer load-bearing).
10
+ *
11
+ * Crashed agents (status `running` with a stale lastUpdate) are NOT
12
+ * swept; the leak-research contract says we LEAVE worktrees of crashed
13
+ * agents in place for forensics. The operator can `pugi worktrees
14
+ * cleanup <id>` manually after the post-mortem.
15
+ *
16
+ * Implementation notes:
17
+ *
18
+ * - The cleanup is read-then-write: list the manager state, classify
19
+ * each entry, then call `manager.cleanup()` per stale id. Errors per
20
+ * entry never abort the loop — they accumulate in the report.
21
+ * - The progress directory we look at is the SAME `.pugi/agent-progress/`
22
+ * root the writer uses (resolved via the writer's env-aware helper).
23
+ * - `runStaleCleanup` is the only public entry point. The internal
24
+ * classifier is exported as `classifyStale` for spec coverage.
25
+ *
26
+ * Brand voice: ASCII only, no emoji, no banned words.
27
+ */
28
+ import { existsSync, readFileSync } from 'node:fs';
29
+ import { join } from 'node:path';
30
+ import { resolveProgressDir } from '../agent-progress/writer.js';
31
+ import { validateAgentProgress } from '../agent-progress/schema.js';
32
+ import { WorktreeManager, } from './manager.js';
33
+ /**
34
+ * Classify a single worktree listing against the on-disk progress JSON.
35
+ * Pure-ish — only reads from the progress file when one exists. Exposed
36
+ * for the spec; production callers go through `runStaleCleanup`.
37
+ */
38
+ export function classifyStale(listing, progressDir, options = {}) {
39
+ const grace = options.crashedGraceMs ?? 30 * 60 * 1000;
40
+ const now = options.now ?? Date.now;
41
+ const progressPath = join(progressDir, `${listing.agentId}.json`);
42
+ if (!existsSync(progressPath)) {
43
+ return 'orphan_no_progress';
44
+ }
45
+ let raw;
46
+ try {
47
+ raw = readFileSync(progressPath, 'utf8');
48
+ }
49
+ catch {
50
+ // Unreadable progress file — treat as orphan so the operator can
51
+ // see it in the cleanup report. We never act on it silently.
52
+ return 'orphan_no_progress';
53
+ }
54
+ let parsed;
55
+ try {
56
+ parsed = JSON.parse(raw);
57
+ }
58
+ catch {
59
+ return 'orphan_no_progress';
60
+ }
61
+ const validation = validateAgentProgress(parsed);
62
+ if (!validation.ok)
63
+ return 'orphan_no_progress';
64
+ const progress = validation.value;
65
+ if (progress.status === 'completed')
66
+ return 'stale_completed';
67
+ if (progress.status === 'failed')
68
+ return 'stale_failed';
69
+ // status === 'running' — check for crashed (stale lastUpdate)
70
+ const lastTs = Date.parse(progress.lastUpdate);
71
+ if (Number.isFinite(lastTs) && now() - lastTs > grace) {
72
+ return 'crashed_running';
73
+ }
74
+ return 'active';
75
+ }
76
+ /**
77
+ * Run a single stale-worktree sweep. Removes only `stale_completed`,
78
+ * `stale_failed`, and `orphan_no_progress` entries. Crashed-running
79
+ * entries are LEFT IN PLACE per the L23 forensics contract, but they
80
+ * appear in the report so the operator can act on them manually.
81
+ */
82
+ export function runStaleCleanup(managerOpts, options = {}) {
83
+ const manager = new WorktreeManager(managerOpts);
84
+ const report = {
85
+ scanned: 0,
86
+ classified: [],
87
+ removed: [],
88
+ preserved: [],
89
+ errors: [],
90
+ };
91
+ const listResult = manager.list();
92
+ if (!listResult.ok) {
93
+ report.errors.push({ agentId: '', detail: `list failed: ${listResult.detail}` });
94
+ return report;
95
+ }
96
+ const progressDir = options.progressDir ?? resolveProgressDir();
97
+ const listings = listResult.value;
98
+ report.scanned = listings.length;
99
+ for (const entry of listings) {
100
+ const cls = classifyStale(entry, progressDir, options);
101
+ report.classified.push({ agentId: entry.agentId, path: entry.path, class: cls });
102
+ if (cls === 'active' || cls === 'crashed_running') {
103
+ report.preserved.push({ agentId: entry.agentId, reason: cls });
104
+ continue;
105
+ }
106
+ if (options.dryRun) {
107
+ // Dry-run reports the classification only — no cleanup, no remove.
108
+ continue;
109
+ }
110
+ const cleanup = manager.cleanup(entry.agentId);
111
+ if (cleanup.ok) {
112
+ report.removed.push(entry.path);
113
+ }
114
+ else {
115
+ report.errors.push({
116
+ agentId: entry.agentId,
117
+ detail: `${cleanup.reason}: ${cleanup.detail}`,
118
+ });
119
+ }
120
+ }
121
+ return report;
122
+ }
123
+ //# sourceMappingURL=cleanup.js.map