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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (445) hide show
  1. package/CHANGELOG.md +132 -0
  2. package/LICENSE +1 -1
  3. package/README.md +53 -11
  4. package/assets/pugi-prozr2-mascot.ansi +9 -0
  5. package/bin/run.js +33 -1
  6. package/dist/commands/deploy.js +40 -40
  7. package/dist/commands/flatten.js +191 -0
  8. package/dist/commands/jobs-watch.js +201 -0
  9. package/dist/commands/jobs.js +42 -27
  10. package/dist/commands/retro.js +210 -0
  11. package/dist/commands/smoke.js +133 -0
  12. package/dist/core/agent-progress/cleanup.js +134 -0
  13. package/dist/core/agent-progress/schema.js +144 -0
  14. package/dist/core/agent-progress/writer.js +101 -0
  15. package/dist/core/agents/adaptive-router.js +330 -0
  16. package/dist/core/agents/query-decomposer.js +297 -0
  17. package/dist/core/agents/registry.js +3 -3
  18. package/dist/core/approvals/shortcut-resolver.js +98 -0
  19. package/dist/core/artifact-chain/dispatcher.js +148 -0
  20. package/dist/core/artifact-chain/exporter.js +164 -0
  21. package/dist/core/artifact-chain/state.js +243 -0
  22. package/dist/core/artifact-chain/steps.js +169 -0
  23. package/dist/core/ask-user/question.js +92 -0
  24. package/dist/core/audit/audit-trail.js +275 -0
  25. package/dist/core/auth/ensure-authenticated.js +129 -0
  26. package/dist/core/auth/env-provider.js +238 -0
  27. package/dist/core/auto-open-browser.js +4 -4
  28. package/dist/core/auto-update/channels.js +122 -0
  29. package/dist/core/auto-update/checker.js +241 -0
  30. package/dist/core/auto-update/state.js +235 -0
  31. package/dist/core/bare-mode/index.js +107 -0
  32. package/dist/core/bash/redirect.js +281 -0
  33. package/dist/core/bash-classifier.js +436 -40
  34. package/dist/core/checkpoint/resumer.js +149 -0
  35. package/dist/core/checkpoint/rewinder.js +291 -0
  36. package/dist/core/checkpoints/shadow-git.js +670 -0
  37. package/dist/core/citations/parser.js +109 -0
  38. package/dist/core/classifier/yolo-classifier.js +88 -0
  39. package/dist/core/codegraph/db.js +506 -0
  40. package/dist/core/codegraph/decision-store.js +248 -0
  41. package/dist/core/codegraph/detect-repo.js +459 -0
  42. package/dist/core/codegraph/install.js +134 -0
  43. package/dist/core/codegraph/offer-hook.js +220 -0
  44. package/dist/core/codegraph/parser.js +71 -0
  45. package/dist/core/codegraph/types.js +34 -0
  46. package/dist/core/compact/auto-trigger.js +96 -0
  47. package/dist/core/compact/buffer-rewriter.js +115 -0
  48. package/dist/core/compact/summarizer.js +208 -0
  49. package/dist/core/compact/token-counter.js +108 -0
  50. package/dist/core/consensus/anvil-fanout.js +25 -25
  51. package/dist/core/consensus/diff-capture.js +121 -12
  52. package/dist/core/consensus/rubric.js +21 -21
  53. package/dist/core/context/builder.js +6 -6
  54. package/dist/core/context/compaction-events.js +8 -8
  55. package/dist/core/context/compaction.js +31 -31
  56. package/dist/core/context/index.js +15 -8
  57. package/dist/core/context/invariants.js +51 -51
  58. package/dist/core/context/markdown-loader.js +28 -10
  59. package/dist/core/context/markdown-traverse.js +255 -0
  60. package/dist/core/context/pugiignore.js +41 -41
  61. package/dist/core/context/repo-skeleton.js +37 -37
  62. package/dist/core/context/tool-eviction.js +55 -0
  63. package/dist/core/context/watcher.js +32 -32
  64. package/dist/core/context/working-set.js +23 -23
  65. package/dist/core/coordinator/agent-tools.js +77 -0
  66. package/dist/core/coordinator/agent-toolset.js +65 -0
  67. package/dist/core/coordinator/fsm.js +73 -0
  68. package/dist/core/coordinator/mode-fsm.js +70 -0
  69. package/dist/core/cost/rate-card.js +129 -0
  70. package/dist/core/cost/tracker.js +221 -0
  71. package/dist/core/credentials.js +13 -13
  72. package/dist/core/cron/scheduler.js +138 -0
  73. package/dist/core/denial-tracking/index.js +8 -0
  74. package/dist/core/denial-tracking/state.js +264 -0
  75. package/dist/core/diagnostics/probe-runner.js +93 -0
  76. package/dist/core/diagnostics/probes/api.js +46 -0
  77. package/dist/core/diagnostics/probes/auth.js +93 -0
  78. package/dist/core/diagnostics/probes/bare-mode.js +42 -0
  79. package/dist/core/diagnostics/probes/cli-version.js +127 -0
  80. package/dist/core/diagnostics/probes/config.js +72 -0
  81. package/dist/core/diagnostics/probes/denial-tracking.js +57 -0
  82. package/dist/core/diagnostics/probes/disk.js +81 -0
  83. package/dist/core/diagnostics/probes/engine-live.js +46 -0
  84. package/dist/core/diagnostics/probes/git.js +65 -0
  85. package/dist/core/diagnostics/probes/hooks.js +118 -0
  86. package/dist/core/diagnostics/probes/mcp.js +75 -0
  87. package/dist/core/diagnostics/probes/node.js +59 -0
  88. package/dist/core/diagnostics/probes/pnpm.js +36 -0
  89. package/dist/core/diagnostics/probes/pugi-md.js +89 -0
  90. package/dist/core/diagnostics/probes/sandbox.js +72 -0
  91. package/dist/core/diagnostics/probes/session.js +74 -0
  92. package/dist/core/diagnostics/probes/status-snapshot.js +488 -0
  93. package/dist/core/diagnostics/probes/workspace.js +63 -0
  94. package/dist/core/diagnostics/types.js +70 -0
  95. package/dist/core/dispatch/cache-cleanup.js +197 -0
  96. package/dist/core/dispatch/cache-handoff.js +295 -0
  97. package/dist/core/edits/apply-patch-layer-e.js +189 -0
  98. package/dist/core/edits/dispatch.js +333 -7
  99. package/dist/core/edits/format-detector.js +260 -0
  100. package/dist/core/edits/format-matrix.js +26 -0
  101. package/dist/core/edits/fuzzy-ladder.js +650 -0
  102. package/dist/core/edits/index.js +5 -1
  103. package/dist/core/edits/journal.js +199 -0
  104. package/dist/core/edits/layer-a-apply.js +15 -15
  105. package/dist/core/edits/layer-a-fuzzy-apply.js +198 -0
  106. package/dist/core/edits/layer-b-apply.js +9 -9
  107. package/dist/core/edits/layer-c-apply.js +6 -6
  108. package/dist/core/edits/layer-d-ast.js +557 -14
  109. package/dist/core/edits/marker-parser.js +12 -12
  110. package/dist/core/edits/security-gate.js +27 -27
  111. package/dist/core/edits/verify-hook.js +273 -0
  112. package/dist/core/edits/worktree.js +29 -29
  113. package/dist/core/engine/anvil-client.js +214 -26
  114. package/dist/core/engine/auto-compact.js +247 -0
  115. package/dist/core/engine/budgets.js +220 -0
  116. package/dist/core/engine/compact-llm-summarizer.js +124 -0
  117. package/dist/core/engine/context-prefix.js +155 -0
  118. package/dist/core/engine/index.js +1 -1
  119. package/dist/core/engine/intensity.js +163 -0
  120. package/dist/core/engine/intent.js +260 -0
  121. package/dist/core/engine/native-pugi.js +1559 -227
  122. package/dist/core/engine/prompts.js +187 -19
  123. package/dist/core/engine/strip-internal-fields.js +124 -0
  124. package/dist/core/engine/tool-bridge.js +1887 -59
  125. package/dist/core/engine/verification-patterns.js +195 -0
  126. package/dist/core/evaluation/golden-dataset.js +293 -0
  127. package/dist/core/feedback/queue.js +177 -0
  128. package/dist/core/feedback/submitter.js +145 -0
  129. package/dist/core/file-cache.js +113 -1
  130. package/dist/core/flatten/flatten-repo.js +439 -0
  131. package/dist/core/format/osc8-link.js +28 -0
  132. package/dist/core/hook-chains.js +392 -0
  133. package/dist/core/hooks/citation-verify-hook.js +138 -0
  134. package/dist/core/hooks/citation-verify.js +112 -0
  135. package/dist/core/hooks/events.js +46 -0
  136. package/dist/core/hooks/index.js +15 -0
  137. package/dist/core/hooks/registry.js +216 -0
  138. package/dist/core/hooks/runner.js +236 -0
  139. package/dist/core/hooks/v2/event-emitter.js +115 -0
  140. package/dist/core/hooks/v2/executor.js +282 -0
  141. package/dist/core/hooks/v2/index.js +25 -0
  142. package/dist/core/hooks/v2/lifecycle.js +104 -0
  143. package/dist/core/hooks/v2/loader.js +216 -0
  144. package/dist/core/hooks/v2/matcher.js +125 -0
  145. package/dist/core/hooks/v2/trust.js +143 -0
  146. package/dist/core/hooks/v2/types.js +86 -0
  147. package/dist/core/hooks/worktree-events.js +158 -0
  148. package/dist/core/image/renderer.js +71 -0
  149. package/dist/core/init/detector.js +582 -0
  150. package/dist/core/init/template-renderer.js +242 -0
  151. package/dist/core/jobs/registry.js +18 -18
  152. package/dist/core/ledger/results-tsv.js +142 -0
  153. package/dist/core/log-discipline/stdout-redirect.js +51 -0
  154. package/dist/core/lsp/cache.js +105 -0
  155. package/dist/core/lsp/client.js +551 -41
  156. package/dist/core/lsp/language-detect.js +66 -0
  157. package/dist/core/lsp/post-edit-diagnostics.js +171 -0
  158. package/dist/core/lsp/server-detect.js +173 -0
  159. package/dist/core/lsp/symbol-cache.js +162 -0
  160. package/dist/core/lsp/symbol-tools.js +664 -0
  161. package/dist/core/mcp/client.js +97 -28
  162. package/dist/core/mcp/http-server.js +553 -0
  163. package/dist/core/mcp/orchestrator-config.js +192 -0
  164. package/dist/core/mcp/orchestrator-tools.js +806 -0
  165. package/dist/core/mcp/permission.js +190 -0
  166. package/dist/core/mcp/registry.js +39 -17
  167. package/dist/core/mcp/server-tools.js +219 -0
  168. package/dist/core/mcp/server.js +397 -0
  169. package/dist/core/mcp/trust.js +10 -10
  170. package/dist/core/memory/dual-write.js +416 -0
  171. package/dist/core/memory/passive-extract.js +130 -0
  172. package/dist/core/memory/phase1-kinds.js +20 -0
  173. package/dist/core/memory/secret-scanner.js +304 -0
  174. package/dist/core/memory-sync/queue.js +170 -0
  175. package/dist/core/metrics/extract.js +113 -0
  176. package/dist/core/modes/roo-modes.js +68 -0
  177. package/dist/core/notes/notes-paths.js +113 -0
  178. package/dist/core/notes/notes-recorder.js +140 -0
  179. package/dist/core/notes/notes-writer.js +53 -0
  180. package/dist/core/notes/renderers.js +0 -0
  181. package/dist/core/notes/slug.js +105 -0
  182. package/dist/core/onboarding/ensure-initialized.js +133 -0
  183. package/dist/core/onboarding/marker.js +111 -0
  184. package/dist/core/onboarding/telemetry-state.js +108 -0
  185. package/dist/core/output-style/presets.js +176 -0
  186. package/dist/core/output-style/state.js +185 -0
  187. package/dist/core/path-security.js +287 -5
  188. package/dist/core/permission.js +82 -22
  189. package/dist/core/permissions/auto-classifier.js +124 -0
  190. package/dist/core/permissions/bash-parser.js +371 -0
  191. package/dist/core/permissions/circuit-breaker.js +83 -0
  192. package/dist/core/permissions/constrained-edit.js +91 -0
  193. package/dist/core/permissions/gate.js +278 -0
  194. package/dist/core/permissions/index.js +20 -0
  195. package/dist/core/permissions/mode.js +174 -0
  196. package/dist/core/permissions/network-egress.js +137 -0
  197. package/dist/core/permissions/state.js +241 -0
  198. package/dist/core/permissions/tool-class.js +107 -0
  199. package/dist/core/plan-mode/ui-state.js +51 -0
  200. package/dist/core/plans/plan-artifact.js +721 -0
  201. package/dist/core/policy-limits/etag-store.js +122 -0
  202. package/dist/core/prd-check/parser.js +215 -0
  203. package/dist/core/prd-check/reporter.js +127 -0
  204. package/dist/core/prd-check/session-review.js +557 -0
  205. package/dist/core/prd-check/verifiers.js +223 -0
  206. package/dist/core/prompt-cache/client-cache.js +99 -0
  207. package/dist/core/prompts/assembly.js +29 -0
  208. package/dist/core/prompts/registry.js +364 -0
  209. package/dist/core/pugi-gitignore.js +52 -0
  210. package/dist/core/pugi-md/cc-compat-rules.js +735 -0
  211. package/dist/core/pugi-md/context-injector.js +76 -0
  212. package/dist/core/pugi-md/walk-up.js +207 -0
  213. package/dist/core/python/uv-installer.js +270 -0
  214. package/dist/core/python/uv-resolver.js +83 -0
  215. package/dist/core/rate-limit/narrator.js +146 -0
  216. package/dist/core/recipes/cli-types.js +20 -0
  217. package/dist/core/recipes/loader.js +103 -0
  218. package/dist/core/recipes/runner.js +345 -0
  219. package/dist/core/recipes/schema.js +587 -0
  220. package/dist/core/release-notes/parser.js +241 -0
  221. package/dist/core/release-notes/state.js +116 -0
  222. package/dist/core/repl/ask.js +37 -37
  223. package/dist/core/repl/cancellation.js +26 -26
  224. package/dist/core/repl/cap-warning.js +4 -4
  225. package/dist/core/repl/clipboard-read.js +11 -11
  226. package/dist/core/repl/dispatch-fsm.js +12 -12
  227. package/dist/core/repl/engine-bridge.js +303 -0
  228. package/dist/core/repl/history-search.js +15 -15
  229. package/dist/core/repl/history.js +28 -18
  230. package/dist/core/repl/kill-ring.js +5 -5
  231. package/dist/core/repl/model-pricing.js +135 -0
  232. package/dist/core/repl/privacy-banner.js +22 -22
  233. package/dist/core/repl/session.js +2690 -229
  234. package/dist/core/repl/slash-commands.js +540 -41
  235. package/dist/core/repl/store/index.js +1 -1
  236. package/dist/core/repl/store/jsonl-log.js +22 -22
  237. package/dist/core/repl/store/lockfile.js +10 -10
  238. package/dist/core/repl/store/session-store.js +136 -107
  239. package/dist/core/repl/store/types.js +15 -15
  240. package/dist/core/repl/store/uuid-v7.js +12 -12
  241. package/dist/core/repl/tool-route.js +382 -0
  242. package/dist/core/repl/workspace-context.js +43 -21
  243. package/dist/core/repo-map/build.js +125 -0
  244. package/dist/core/repo-map/cache.js +185 -0
  245. package/dist/core/repo-map/extractor.js +254 -0
  246. package/dist/core/repo-map/formatter.js +145 -0
  247. package/dist/core/repo-map/page-rank.js +105 -0
  248. package/dist/core/repo-map/scanner.js +211 -0
  249. package/dist/core/retro/git-collector.js +251 -0
  250. package/dist/core/retro/health-card.js +25 -0
  251. package/dist/core/retro/metrics.js +342 -0
  252. package/dist/core/retro/narrative.js +249 -0
  253. package/dist/core/retro/plane-collector.js +274 -0
  254. package/dist/core/retro/pr-issue-link.js +65 -0
  255. package/dist/core/retro/types.js +16 -0
  256. package/dist/core/retry-budget/budget.js +284 -0
  257. package/dist/core/retry-budget/index.js +5 -0
  258. package/dist/core/retry-budget/retry-cap.js +74 -0
  259. package/dist/core/routing/lead-worker.js +43 -0
  260. package/dist/core/routing/pre-flight-estimator.js +108 -0
  261. package/dist/core/runs/run-tree.js +103 -0
  262. package/dist/core/sandboxing/adapter.js +29 -0
  263. package/dist/core/sandboxing/index.js +49 -0
  264. package/dist/core/sandboxing/none.js +19 -0
  265. package/dist/core/sandboxing/seatbelt.js +183 -0
  266. package/dist/core/security/injection-scanner.js +367 -0
  267. package/dist/core/security/output-filter.js +418 -0
  268. package/dist/core/session/env-file.js +105 -0
  269. package/dist/core/session/section-budgets.js +140 -0
  270. package/dist/core/session.js +119 -0
  271. package/dist/core/settings.js +378 -5
  272. package/dist/core/share/formatter.js +271 -0
  273. package/dist/core/share/redactor.js +221 -0
  274. package/dist/core/share/uploader.js +267 -0
  275. package/dist/core/skills/defaults.js +30 -30
  276. package/dist/core/skills/loader.js +22 -22
  277. package/dist/core/skills/sources.js +27 -27
  278. package/dist/core/smoke/headless-driver.js +174 -0
  279. package/dist/core/smoke/orchestrator.js +194 -0
  280. package/dist/core/smoke/runner.js +238 -0
  281. package/dist/core/smoke/scenario-parser.js +316 -0
  282. package/dist/core/statusline.js +99 -0
  283. package/dist/core/subagents/dispatcher-real.js +600 -0
  284. package/dist/core/subagents/dispatcher.js +146 -52
  285. package/dist/core/subagents/index.js +19 -6
  286. package/dist/core/subagents/isolation-matrix.js +213 -0
  287. package/dist/core/subagents/spawn.js +19 -4
  288. package/dist/core/telemetry/emitter.js +229 -0
  289. package/dist/core/telemetry/queue.js +251 -0
  290. package/dist/core/theme/context.js +91 -0
  291. package/dist/core/theme/presets.js +228 -0
  292. package/dist/core/theme/state.js +181 -0
  293. package/dist/core/todos/invariant.js +10 -0
  294. package/dist/core/todos/state.js +177 -0
  295. package/dist/core/tool-schema/compressor.js +89 -0
  296. package/dist/core/transport/version-interceptor.js +166 -0
  297. package/dist/core/trust.js +2 -2
  298. package/dist/core/tui/thinking-block.js +64 -0
  299. package/dist/core/vim/keymap.js +288 -0
  300. package/dist/core/vim/state.js +92 -0
  301. package/dist/core/watch-markers/marker-watcher.js +133 -0
  302. package/dist/core/worktree/include-parser.js +249 -0
  303. package/dist/core/worktree-manager/cleanup.js +123 -0
  304. package/dist/core/worktree-manager/manager.js +303 -0
  305. package/dist/index.js +36 -0
  306. package/dist/runtime/bootstrap.js +190 -0
  307. package/dist/runtime/cli.js +4345 -561
  308. package/dist/runtime/commands/agents.js +31 -31
  309. package/dist/runtime/commands/budget.js +5 -5
  310. package/dist/runtime/commands/cancel.js +231 -0
  311. package/dist/runtime/commands/chain.js +489 -0
  312. package/dist/runtime/commands/codegraph-status.js +227 -0
  313. package/dist/runtime/commands/compact.js +297 -0
  314. package/dist/runtime/commands/config.js +74 -40
  315. package/dist/runtime/commands/cost.js +199 -0
  316. package/dist/runtime/commands/delegate.js +27 -4
  317. package/dist/runtime/commands/dispatch.js +126 -0
  318. package/dist/runtime/commands/doctor.js +579 -0
  319. package/dist/runtime/commands/feedback.js +184 -0
  320. package/dist/runtime/commands/hooks.js +187 -0
  321. package/dist/runtime/commands/index-cmd.js +353 -0
  322. package/dist/runtime/commands/init.js +254 -0
  323. package/dist/runtime/commands/lsp.js +200 -38
  324. package/dist/runtime/commands/mcp.js +935 -0
  325. package/dist/runtime/commands/memory.js +582 -0
  326. package/dist/runtime/commands/model.js +237 -0
  327. package/dist/runtime/commands/onboarding.js +275 -0
  328. package/dist/runtime/commands/patch.js +12 -12
  329. package/dist/runtime/commands/permissions.js +112 -0
  330. package/dist/runtime/commands/plan.js +143 -0
  331. package/dist/runtime/commands/prd-check.js +285 -0
  332. package/dist/runtime/commands/privacy.js +17 -17
  333. package/dist/runtime/commands/recipe.js +325 -0
  334. package/dist/runtime/commands/redo-blob-store.js +92 -0
  335. package/dist/runtime/commands/redo.js +361 -0
  336. package/dist/runtime/commands/release-notes.js +229 -0
  337. package/dist/runtime/commands/repo-map.js +95 -0
  338. package/dist/runtime/commands/report.js +299 -0
  339. package/dist/runtime/commands/resume.js +118 -0
  340. package/dist/runtime/commands/review-consensus.js +68 -53
  341. package/dist/runtime/commands/rewind.js +333 -0
  342. package/dist/runtime/commands/roster.js +14 -14
  343. package/dist/runtime/commands/servers.js +236 -0
  344. package/dist/runtime/commands/sessions.js +163 -0
  345. package/dist/runtime/commands/share.js +316 -0
  346. package/dist/runtime/commands/skills.js +31 -31
  347. package/dist/runtime/commands/status.js +186 -0
  348. package/dist/runtime/commands/stickers.js +82 -0
  349. package/dist/runtime/commands/style.js +194 -0
  350. package/dist/runtime/commands/theme.js +196 -0
  351. package/dist/runtime/commands/undo.js +54 -22
  352. package/dist/runtime/commands/update.js +289 -0
  353. package/dist/runtime/commands/vim.js +140 -0
  354. package/dist/runtime/commands/worktree.js +8 -8
  355. package/dist/runtime/commands/worktrees.js +155 -0
  356. package/dist/runtime/deprecation-warning.js +69 -0
  357. package/dist/runtime/engine-exit-code.js +50 -0
  358. package/dist/runtime/headless-repl.js +195 -0
  359. package/dist/runtime/headless.js +548 -0
  360. package/dist/runtime/load-hooks-or-exit.js +71 -0
  361. package/dist/runtime/plan-decompose.js +22 -22
  362. package/dist/runtime/sigint-guard.js +272 -0
  363. package/dist/runtime/stream-renderer.js +195 -0
  364. package/dist/runtime/update-check.js +28 -28
  365. package/dist/runtime/version.js +65 -0
  366. package/dist/runtime/worktree-bootstrap.js +579 -0
  367. package/dist/skills/bundled/batch.js +617 -0
  368. package/dist/skills/bundled/index.js +45 -0
  369. package/dist/skills/bundled/loop.js +358 -0
  370. package/dist/skills/bundled/remember.js +383 -0
  371. package/dist/skills/bundled/simplify.js +289 -0
  372. package/dist/skills/bundled/skillify.js +373 -0
  373. package/dist/skills/bundled/stuck.js +558 -0
  374. package/dist/skills/bundled/verify.js +439 -0
  375. package/dist/testing/vcr.js +486 -0
  376. package/dist/tools/agent-tool.js +229 -0
  377. package/dist/tools/apply-patch.js +89 -28
  378. package/dist/tools/ask-user-question.js +337 -0
  379. package/dist/tools/ask-user.js +115 -0
  380. package/dist/tools/bash.js +624 -46
  381. package/dist/tools/brief.js +224 -0
  382. package/dist/tools/cron.js +433 -0
  383. package/dist/tools/enter-worktree.js +250 -0
  384. package/dist/tools/exit-worktree.js +147 -0
  385. package/dist/tools/file-tools.js +161 -44
  386. package/dist/tools/http-request.js +336 -0
  387. package/dist/tools/lsp-tools.js +377 -1
  388. package/dist/tools/mcp-tool.js +260 -0
  389. package/dist/tools/multi-edit.js +361 -0
  390. package/dist/tools/powershell.js +268 -0
  391. package/dist/tools/registry.js +120 -5
  392. package/dist/tools/server-tools.js +892 -0
  393. package/dist/tools/skill-tool.js +96 -0
  394. package/dist/tools/sleep.js +99 -0
  395. package/dist/tools/synthetic-output.js +133 -0
  396. package/dist/tools/tasks.js +208 -0
  397. package/dist/tools/todo-write.js +184 -0
  398. package/dist/tools/verify-plan-execution.js +295 -0
  399. package/dist/tools/web-fetch-injection-scanner.js +207 -0
  400. package/dist/tools/web-fetch.js +195 -10
  401. package/dist/tools/web-search.js +458 -0
  402. package/dist/tui/agent-progress-card.js +111 -0
  403. package/dist/tui/agent-tree.js +22 -1
  404. package/dist/tui/ask-modal.js +14 -14
  405. package/dist/tui/ask-user-question-chips.js +315 -0
  406. package/dist/tui/ask-user-question-prompt.js +203 -0
  407. package/dist/tui/compact-banner.js +81 -0
  408. package/dist/tui/conversation-pane.js +85 -11
  409. package/dist/tui/cost-table.js +111 -0
  410. package/dist/tui/device-flow.js +2 -2
  411. package/dist/tui/doctor-table.js +46 -0
  412. package/dist/tui/feedback-prompt.js +156 -0
  413. package/dist/tui/input-box.js +247 -32
  414. package/dist/tui/login-picker.js +3 -3
  415. package/dist/tui/markdown-render.js +6 -6
  416. package/dist/tui/multi-file-diff-approval.js +375 -0
  417. package/dist/tui/onboarding-wizard.js +240 -0
  418. package/dist/tui/permissions-picker.js +86 -0
  419. package/dist/tui/render.js +36 -1
  420. package/dist/tui/repl-render.js +239 -25
  421. package/dist/tui/repl-splash-art.js +16 -16
  422. package/dist/tui/repl-splash-mascot.js +48 -24
  423. package/dist/tui/repl-splash.js +22 -22
  424. package/dist/tui/repl.js +125 -45
  425. package/dist/tui/slash-palette.js +6 -6
  426. package/dist/tui/splash.js +2 -2
  427. package/dist/tui/status-bar.js +109 -31
  428. package/dist/tui/status-table.js +7 -0
  429. package/dist/tui/stickers-art.js +136 -0
  430. package/dist/tui/style-table.js +28 -0
  431. package/dist/tui/theme-table.js +29 -0
  432. package/dist/tui/thinking-spinner.js +123 -0
  433. package/dist/tui/tool-stream-pane.js +53 -4
  434. package/dist/tui/update-banner.js +27 -2
  435. package/dist/tui/vim-input.js +267 -0
  436. package/dist/tui/welcome-banner.js +107 -0
  437. package/dist/tui/welcome-data.js +293 -0
  438. package/dist/tui/workspace-context.js +2 -2
  439. package/package.json +21 -5
  440. package/test/scenarios/codegen-create-file.scenario.txt +13 -0
  441. package/test/scenarios/compact-force.scenario.txt +12 -0
  442. package/test/scenarios/identity.scenario.txt +11 -0
  443. package/test/scenarios/persona-handoff.scenario.txt +12 -0
  444. package/test/scenarios/walkback.scenario.txt +12 -0
  445. package/dist/core/engine/compaction-hook.js +0 -154
@@ -0,0 +1,353 @@
1
+ /**
2
+ * `pugi index` - local symbol index CLI surface.
3
+ *
4
+ * Operator entry point for the Pugi-native symbol index living at
5
+ * `.pugi/codegraph.db`. Four subcommands today, all wired against the
6
+ * scaffold DB layer in `core/codegraph/db.ts`:
7
+ *
8
+ * - `pugi index` - full (re)index of the workspace.
9
+ * Today: opens the DB, runs the
10
+ * v1 migration, and reports the
11
+ * stub parser state. PR L1
12
+ * replaces this with a real
13
+ * tree-sitter walk.
14
+ * - `pugi index --watch` - start the file watcher. Not
15
+ * implemented in this PR; exits
16
+ * with rc=3 + a pointer at
17
+ * PR L2 which ships chokidar
18
+ * + 2s debounce.
19
+ * - `pugi index search <query>` - FTS5 query against
20
+ * `symbols_fts`. Works on top
21
+ * of an empty index too -
22
+ * returns zero matches.
23
+ * - `pugi index definition <symbol>` - exact-name lookup. Same shape
24
+ * as `--search`.
25
+ * - `pugi index callers <symbol>` - reverse-edge query. Empty
26
+ * today because the stub
27
+ * parser emits no edges.
28
+ *
29
+ * The command is intentionally narrow - every information surface
30
+ * (count, freshness, language coverage) routes through the existing
31
+ * `/codegraph-status` slash that already ships in `runtime/commands/
32
+ * codegraph-status.ts`. This file owns the indexing verbs; status
33
+ * lives over there.
34
+ *
35
+ * Exit codes:
36
+ * 0 - success / "nothing to do" idempotent path
37
+ * 1 - runtime failure (db error, IO error)
38
+ * 2 - invalid CLI args (unknown subcommand, missing required positional)
39
+ * 3 - not implemented yet (parser stub, watcher) - pointer in stderr
40
+ */
41
+ import { resolve } from 'node:path';
42
+ import { closeIndex, countSymbols, findCallers, findDefinition, openIndex, resolveIndexPath, searchSymbols, } from '../../core/codegraph/db.js';
43
+ import { INDEXED_LANGUAGES } from '../../core/codegraph/types.js';
44
+ /**
45
+ * Single entry-point. Returns the process exit code; the caller in
46
+ * `runtime/cli.ts` propagates it via `process.exitCode` (mirrors the
47
+ * `dispatchFlatten` pattern).
48
+ */
49
+ export async function runIndexCommand(args, ctx) {
50
+ const sub = parseArgs(args);
51
+ switch (sub.kind) {
52
+ case 'help':
53
+ return printHelp(ctx);
54
+ case 'unknown':
55
+ return printUnknown(ctx, sub.raw);
56
+ case 'reindex':
57
+ return runReindex(ctx, sub.watch);
58
+ case 'search':
59
+ return runSearch(ctx, sub.query);
60
+ case 'definition':
61
+ return runDefinition(ctx, sub.symbol);
62
+ case 'callers':
63
+ return runCallers(ctx, sub.symbol);
64
+ }
65
+ }
66
+ /**
67
+ * Parse the argv tail (everything after `pugi index`). Pure - exported
68
+ * for the spec to pin canonical shapes.
69
+ */
70
+ export function parseArgs(args) {
71
+ if (args.length === 0) {
72
+ return { kind: 'reindex', watch: false };
73
+ }
74
+ const [head, ...rest] = args;
75
+ if (!head)
76
+ return { kind: 'reindex', watch: false };
77
+ if (head === '--help' || head === '-h' || head === 'help') {
78
+ return { kind: 'help' };
79
+ }
80
+ if (head === '--watch' || head === '-w') {
81
+ return { kind: 'reindex', watch: true };
82
+ }
83
+ if (head === 'search') {
84
+ const query = rest.join(' ').trim();
85
+ if (query.length === 0)
86
+ return { kind: 'unknown', raw: 'search (missing query)' };
87
+ return { kind: 'search', query };
88
+ }
89
+ if (head === 'definition') {
90
+ const symbol = rest.join(' ').trim();
91
+ if (symbol.length === 0)
92
+ return { kind: 'unknown', raw: 'definition (missing symbol)' };
93
+ return { kind: 'definition', symbol };
94
+ }
95
+ if (head === 'callers') {
96
+ const symbol = rest.join(' ').trim();
97
+ if (symbol.length === 0)
98
+ return { kind: 'unknown', raw: 'callers (missing symbol)' };
99
+ return { kind: 'callers', symbol };
100
+ }
101
+ return { kind: 'unknown', raw: head };
102
+ }
103
+ function printHelp(ctx) {
104
+ ctx.writeOutput({ command: 'index', sub: 'help', subcommands: ['search', 'definition', 'callers'] }, [
105
+ 'pugi index - local symbol index (CodeGraph-style).',
106
+ '',
107
+ 'Usage:',
108
+ ' pugi index Re-index the workspace.',
109
+ ' pugi index --watch Start file watcher (PR L2, not yet wired).',
110
+ ' pugi index search <query> FTS5 search across symbol names.',
111
+ ' pugi index definition <symbol> Find the definition of <symbol>.',
112
+ ' pugi index callers <symbol> List call sites referencing <symbol>.',
113
+ '',
114
+ `Languages (v1): ${INDEXED_LANGUAGES.join(', ')}.`,
115
+ 'Storage: .pugi/codegraph.db (gitignored, regenerable).',
116
+ 'Design memo: docs/research/2026-06-05-pugi-index-codegraph-design.md',
117
+ ].join('\n'));
118
+ return 0;
119
+ }
120
+ function printUnknown(ctx, raw) {
121
+ ctx.writeOutput({ command: 'index', error: 'unknown-subcommand', got: raw }, `pugi index: unknown subcommand "${raw}". Allowed: search, definition, callers, --watch, --help.`);
122
+ return 2;
123
+ }
124
+ function runReindex(ctx, watch) {
125
+ if (watch) {
126
+ ctx.writeOutput({
127
+ command: 'index',
128
+ sub: 'reindex',
129
+ watch: true,
130
+ status: 'not-implemented',
131
+ followup: 'PR L2',
132
+ }, [
133
+ 'pugi index --watch: file watcher not implemented in this scaffold PR.',
134
+ 'Tracked in follow-up PR L2 (chokidar + 2s debounce + incremental).',
135
+ ].join('\n'));
136
+ return 3;
137
+ }
138
+ let db = null;
139
+ try {
140
+ db = openIndex(ctx.workspaceRoot);
141
+ const symCount = countSymbols(db);
142
+ ctx.writeOutput({
143
+ command: 'index',
144
+ sub: 'reindex',
145
+ watch: false,
146
+ status: 'scaffold-ready',
147
+ followup: 'PR L1',
148
+ dbPath: db.dbPath,
149
+ schemaVersion: db.version,
150
+ symbolCount: symCount,
151
+ }, [
152
+ `Index DB ready at ${db.dbPath} (schema v${db.version}).`,
153
+ `Indexed symbols: ${symCount}.`,
154
+ 'Parser is stubbed in this PR. Real tree-sitter extraction lands in PR L1.',
155
+ ].join('\n'));
156
+ return 0;
157
+ }
158
+ catch (err) {
159
+ const message = err instanceof Error ? err.message : String(err);
160
+ ctx.writeOutput({ command: 'index', sub: 'reindex', error: 'db_error', message }, `pugi index failed: ${message}`);
161
+ return 1;
162
+ }
163
+ finally {
164
+ if (db)
165
+ closeIndex(db);
166
+ }
167
+ }
168
+ function runSearch(ctx, query) {
169
+ let db = null;
170
+ try {
171
+ db = openIndex(ctx.workspaceRoot);
172
+ const results = searchSymbols(db, query, { limit: 50 });
173
+ ctx.writeOutput({
174
+ command: 'index',
175
+ sub: 'search',
176
+ query,
177
+ matches: results.length,
178
+ results: results.map(serializeSearchResult),
179
+ }, renderSearchText(query, results, db.dbPath));
180
+ return 0;
181
+ }
182
+ catch (err) {
183
+ const message = err instanceof Error ? err.message : String(err);
184
+ ctx.writeOutput({ command: 'index', sub: 'search', error: 'query_failed', message }, `pugi index search failed: ${message}`);
185
+ return 1;
186
+ }
187
+ finally {
188
+ if (db)
189
+ closeIndex(db);
190
+ }
191
+ }
192
+ function runDefinition(ctx, symbol) {
193
+ let db = null;
194
+ try {
195
+ db = openIndex(ctx.workspaceRoot);
196
+ const result = findDefinition(db, symbol);
197
+ ctx.writeOutput({
198
+ command: 'index',
199
+ sub: 'definition',
200
+ symbol,
201
+ result: serializeDefinitionResult(result),
202
+ }, renderDefinitionText(symbol, result));
203
+ return result.kind === 'found' ? 0 : 0;
204
+ }
205
+ catch (err) {
206
+ const message = err instanceof Error ? err.message : String(err);
207
+ ctx.writeOutput({ command: 'index', sub: 'definition', error: 'query_failed', message }, `pugi index definition failed: ${message}`);
208
+ return 1;
209
+ }
210
+ finally {
211
+ if (db)
212
+ closeIndex(db);
213
+ }
214
+ }
215
+ function runCallers(ctx, symbol) {
216
+ let db = null;
217
+ try {
218
+ db = openIndex(ctx.workspaceRoot);
219
+ const def = findDefinition(db, symbol);
220
+ if (def.kind !== 'found' || def.definition.id === undefined) {
221
+ ctx.writeOutput({
222
+ command: 'index',
223
+ sub: 'callers',
224
+ symbol,
225
+ matches: 0,
226
+ note: 'definition_not_found',
227
+ }, `pugi index callers: no definition known for "${symbol}". Run \`pugi index\` first or check the spelling.`);
228
+ return 0;
229
+ }
230
+ const callers = findCallers(db, def.definition.id);
231
+ ctx.writeOutput({
232
+ command: 'index',
233
+ sub: 'callers',
234
+ symbol,
235
+ definitionId: def.definition.id,
236
+ matches: callers.length,
237
+ callers: callers.map(serializeCallerResult),
238
+ }, renderCallersText(symbol, callers));
239
+ return 0;
240
+ }
241
+ catch (err) {
242
+ const message = err instanceof Error ? err.message : String(err);
243
+ ctx.writeOutput({ command: 'index', sub: 'callers', error: 'query_failed', message }, `pugi index callers failed: ${message}`);
244
+ return 1;
245
+ }
246
+ finally {
247
+ if (db)
248
+ closeIndex(db);
249
+ }
250
+ }
251
+ function serializeSearchResult(r) {
252
+ return {
253
+ name: r.symbol.name,
254
+ kind: r.symbol.kind,
255
+ file: r.symbol.file,
256
+ line: r.symbol.line,
257
+ col: r.symbol.column,
258
+ scope: r.symbol.scope,
259
+ signature: r.symbol.signature ?? null,
260
+ rank: r.rank,
261
+ };
262
+ }
263
+ function serializeDefinitionResult(r) {
264
+ if (r.kind === 'not_found')
265
+ return { found: false, name: r.name };
266
+ return {
267
+ found: true,
268
+ definition: serializeSymbol(r.definition),
269
+ disambiguations: r.disambiguations.map(serializeSymbol),
270
+ };
271
+ }
272
+ function serializeCallerResult(c) {
273
+ return {
274
+ name: c.caller.name,
275
+ kind: c.caller.kind,
276
+ file: c.caller.file,
277
+ line: c.caller.line,
278
+ col: c.caller.column,
279
+ scope: c.caller.scope,
280
+ edgeKind: c.edge.kind,
281
+ };
282
+ }
283
+ function serializeSymbol(s) {
284
+ return {
285
+ id: s.id,
286
+ name: s.name,
287
+ kind: s.kind,
288
+ file: s.file,
289
+ line: s.line,
290
+ col: s.column,
291
+ scope: s.scope,
292
+ signature: s.signature ?? null,
293
+ };
294
+ }
295
+ function renderSearchText(query, results, dbPath) {
296
+ if (results.length === 0) {
297
+ return [
298
+ `pugi index search "${query}" - 0 matches.`,
299
+ `Index DB: ${dbPath}`,
300
+ 'Hint: the parser stub does not extract symbols yet. PR L1 wires real tree-sitter extraction.',
301
+ ].join('\n');
302
+ }
303
+ const lines = [
304
+ `pugi index search "${query}" - ${results.length} matches:`,
305
+ '',
306
+ ];
307
+ for (const r of results) {
308
+ lines.push(` ${r.symbol.name} [${r.symbol.kind}] ${r.symbol.file}:${r.symbol.line} rank=${r.rank.toFixed(2)}`);
309
+ }
310
+ return lines.join('\n');
311
+ }
312
+ function renderDefinitionText(symbol, result) {
313
+ if (result.kind === 'not_found') {
314
+ return [
315
+ `pugi index definition "${symbol}" - not found.`,
316
+ 'Hint: PR L1 wires the parser; until then the index is empty unless seeded by tests.',
317
+ ].join('\n');
318
+ }
319
+ const d = result.definition;
320
+ const head = ` ${d.name} [${d.kind}] ${d.file}:${d.line}`;
321
+ if (result.disambiguations.length === 0)
322
+ return head;
323
+ return [
324
+ head,
325
+ `Also found in ${result.disambiguations.length} other locations:`,
326
+ ...result.disambiguations.map((s) => ` - ${s.file}:${s.line} [${s.kind}]`),
327
+ ].join('\n');
328
+ }
329
+ function renderCallersText(symbol, callers) {
330
+ if (callers.length === 0) {
331
+ return `pugi index callers "${symbol}" - 0 call sites.`;
332
+ }
333
+ const lines = [
334
+ `pugi index callers "${symbol}" - ${callers.length} call sites:`,
335
+ '',
336
+ ];
337
+ for (const c of callers) {
338
+ lines.push(` ${c.caller.name} ${c.caller.file}:${c.caller.line} edge=${c.edge.kind}`);
339
+ }
340
+ return lines.join('\n');
341
+ }
342
+ /**
343
+ * Resolve the absolute workspace root from a relative input. Exported so
344
+ * the cli.ts dispatcher can call this once and pass an already-absolute
345
+ * path to the context. Pure - no IO.
346
+ */
347
+ export function resolveWorkspaceRoot(input) {
348
+ return resolve(input);
349
+ }
350
+ // Re-export `resolveIndexPath` from db.ts for callers that want to know
351
+ // where the DB lives without opening it (e.g. `pugi doctor`).
352
+ export { resolveIndexPath };
353
+ //# sourceMappingURL=index-cmd.js.map
@@ -0,0 +1,254 @@
1
+ /**
2
+ * `pugi init` codebase scan → PUGI.md auto-gen (backlog #82).
3
+ *
4
+ * Extends the existing `init()` scaffold with a project-aware PUGI.md
5
+ * generator. Runs AFTER `scaffoldPugiWorkspace` so the `.pugi/` workspace
6
+ * exists for the `init-report.json` write.
7
+ *
8
+ * Flow:
9
+ *
10
+ * 1. Detect existing PUGI.md. If present without `--force`, refuse
11
+ * with `refused_existing`.
12
+ * 2. Run `detectWorkspace` against cwd.
13
+ * 3. Render PUGI.md content for the requested style.
14
+ * 4. Confirm with the operator unless `--yes` / `--json` / `--force`.
15
+ * 5. Write `<cwd>/PUGI.md` atomically (tmp + rename, fallback к
16
+ * direct write on EXDEV — happens когда tmp lives на a different
17
+ * volume).
18
+ * 6. Write `.pugi/init-report.json` (mode 0o600) with the raw
19
+ * detection payload for re-runs / auditing.
20
+ * 7. Emit a JSON envelope describing the outcome.
21
+ */
22
+ import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync, } from 'node:fs';
23
+ import { tmpdir } from 'node:os';
24
+ import { dirname, join, resolve } from 'node:path';
25
+ import { createInterface } from 'node:readline';
26
+ import { detectWorkspace } from '../../core/init/detector.js';
27
+ import { renderPugiMd, STYLE_WORD_CAPS, } from '../../core/init/template-renderer.js';
28
+ export const DEFAULT_PUGI_MD_STYLE = 'standard';
29
+ /** Entry point invoked by `cli.ts::init`. */
30
+ export async function runInitScanCommand(args, ctx) {
31
+ const cwd = resolve(ctx.cwd);
32
+ const pugiMdPath = join(cwd, 'PUGI.md');
33
+ const reportPath = join(cwd, '.pugi', 'init-report.json');
34
+ // `args` is currently consumed only via flags. Keep the parameter to
35
+ // mirror every other command surface so we can grow positional args
36
+ // (e.g. an explicit target path) without breaking the call site.
37
+ void args;
38
+ try {
39
+ if (existsSync(pugiMdPath) && !ctx.force) {
40
+ const envelope = {
41
+ command: 'init-scan',
42
+ status: 'refused_existing',
43
+ pugiMdPath,
44
+ reportPath,
45
+ style: ctx.style,
46
+ message: 'PUGI.md already exists. Re-run with --force to overwrite, or edit by hand.',
47
+ };
48
+ ctx.writeOutput(envelope, formatHuman(envelope));
49
+ return envelope;
50
+ }
51
+ const detection = detectWorkspace(cwd);
52
+ const rendered = renderPugiMd(detection, { style: ctx.style, now: ctx.now });
53
+ const shouldConfirm = !ctx.yes && !ctx.json && !ctx.force;
54
+ if (shouldConfirm) {
55
+ const confirm = ctx.confirm ?? defaultConfirm;
56
+ const ok = await confirm(`Write PUGI.md at ${pugiMdPath} (${rendered.wordCount} words, style: ${ctx.style})? [y/N] `);
57
+ if (!ok) {
58
+ const envelope = {
59
+ command: 'init-scan',
60
+ status: 'aborted',
61
+ pugiMdPath,
62
+ reportPath,
63
+ style: ctx.style,
64
+ message: 'Aborted by operator before write.',
65
+ };
66
+ ctx.writeOutput(envelope, formatHuman(envelope));
67
+ return envelope;
68
+ }
69
+ }
70
+ atomicWrite(pugiMdPath, rendered.content);
71
+ writeReport(reportPath, detection, rendered.wordCount, ctx.style);
72
+ const envelope = {
73
+ command: 'init-scan',
74
+ status: 'written',
75
+ pugiMdPath,
76
+ reportPath,
77
+ detection,
78
+ wordCount: rendered.wordCount,
79
+ style: ctx.style,
80
+ };
81
+ ctx.writeOutput(envelope, formatHuman(envelope));
82
+ return envelope;
83
+ }
84
+ catch (error) {
85
+ const message = error instanceof Error ? error.message : String(error);
86
+ const envelope = {
87
+ command: 'init-scan',
88
+ status: 'error',
89
+ pugiMdPath,
90
+ reportPath,
91
+ style: ctx.style,
92
+ message,
93
+ };
94
+ ctx.writeOutput(envelope, formatHuman(envelope));
95
+ return envelope;
96
+ }
97
+ }
98
+ /* ------------------------------------------------------------------ */
99
+ /* Atomic write */
100
+ /* ------------------------------------------------------------------ */
101
+ function atomicWrite(targetPath, content) {
102
+ const dir = dirname(targetPath);
103
+ mkdirSync(dir, { recursive: true });
104
+ const tmpName = `.pugi-md-${process.pid}-${Date.now()}.tmp`;
105
+ const tmpPath = join(tmpdir(), tmpName);
106
+ try {
107
+ writeFileSync(tmpPath, content, { encoding: 'utf8', mode: 0o644 });
108
+ renameSync(tmpPath, targetPath);
109
+ return;
110
+ }
111
+ catch (error) {
112
+ // EXDEV — cross-device link: tmpdir lives on a different volume
113
+ // than the workspace. Retry with the tmpfile inside the workspace.
114
+ cleanupTmp(tmpPath);
115
+ const code = error.code;
116
+ if (code !== 'EXDEV') {
117
+ // Fall through to the in-dir fallback for any rename failure so
118
+ // we keep the contract: PUGI.md is either fully written or not
119
+ // written. The direct writeFileSync at the end is the final
120
+ // safety net.
121
+ }
122
+ const localTmpPath = join(dir, `.pugi-md-${process.pid}-${Date.now()}.tmp`);
123
+ try {
124
+ writeFileSync(localTmpPath, content, { encoding: 'utf8', mode: 0o644 });
125
+ renameSync(localTmpPath, targetPath);
126
+ return;
127
+ }
128
+ catch {
129
+ cleanupTmp(localTmpPath);
130
+ }
131
+ // Final fallback — direct write. We sacrifice the atomicity guarantee
132
+ // here but keep behavioural correctness when both the tmp + in-dir
133
+ // strategies fail (rare; usually FS quirks).
134
+ writeFileSync(targetPath, content, { encoding: 'utf8', mode: 0o644 });
135
+ }
136
+ }
137
+ function cleanupTmp(path) {
138
+ try {
139
+ unlinkSync(path);
140
+ }
141
+ catch {
142
+ // best effort
143
+ }
144
+ }
145
+ function writeReport(reportPath, detection, wordCount, style) {
146
+ mkdirSync(dirname(reportPath), { recursive: true });
147
+ const payload = {
148
+ generatedAt: new Date().toISOString(),
149
+ style,
150
+ wordCap: STYLE_WORD_CAPS[style],
151
+ wordCount,
152
+ detection,
153
+ };
154
+ writeFileSync(reportPath, JSON.stringify(payload, null, 2), {
155
+ encoding: 'utf8',
156
+ mode: 0o600,
157
+ });
158
+ try {
159
+ chmodSync(reportPath, 0o600);
160
+ }
161
+ catch {
162
+ // Some filesystems (FAT, NTFS over CIFS) reject chmod; the mode
163
+ // option on writeFileSync is the primary guard. Best-effort here.
164
+ }
165
+ }
166
+ /* ------------------------------------------------------------------ */
167
+ /* Confirm prompt */
168
+ /* ------------------------------------------------------------------ */
169
+ async function defaultConfirm(question) {
170
+ if (process.stdin.isTTY !== true) {
171
+ return true;
172
+ }
173
+ const rl = createInterface({
174
+ input: process.stdin,
175
+ output: process.stderr,
176
+ });
177
+ return new Promise((resolveAnswer) => {
178
+ let settled = false;
179
+ const settle = (value) => {
180
+ if (settled)
181
+ return;
182
+ settled = true;
183
+ rl.close();
184
+ resolveAnswer(value);
185
+ };
186
+ rl.once('close', () => settle(false));
187
+ rl.question(question, (answer) => {
188
+ settle(/^y(es)?$/i.test(answer.trim()));
189
+ });
190
+ });
191
+ }
192
+ /* ------------------------------------------------------------------ */
193
+ /* Human-readable formatting */
194
+ /* ------------------------------------------------------------------ */
195
+ function formatHuman(env) {
196
+ switch (env.status) {
197
+ case 'written':
198
+ return [
199
+ `PUGI.md written to ${env.pugiMdPath}`,
200
+ ` Style: ${env.style}`,
201
+ ` Word count: ${env.wordCount ?? 0}`,
202
+ ` Report: ${env.reportPath}`,
203
+ ].join('\n');
204
+ case 'refused_existing':
205
+ return env.message ?? 'PUGI.md already exists. Use --force to overwrite.';
206
+ case 'aborted':
207
+ return env.message ?? 'Aborted.';
208
+ case 'error':
209
+ return `pugi init scan failed: ${env.message ?? 'unknown error'}`;
210
+ default:
211
+ return 'pugi init scan complete.';
212
+ }
213
+ }
214
+ /* ------------------------------------------------------------------ */
215
+ /* Helpers consumed by cli.ts */
216
+ /* ------------------------------------------------------------------ */
217
+ /** Parse `--style=<minimal|standard|detailed>` (or `--style minimal`). */
218
+ export function parseInitStyle(args) {
219
+ for (let i = 0; i < args.length; i += 1) {
220
+ const arg = args[i];
221
+ if (typeof arg !== 'string')
222
+ continue;
223
+ if (arg.startsWith('--style=')) {
224
+ const value = arg.slice('--style='.length);
225
+ const parsed = coerceStyle(value);
226
+ if (parsed)
227
+ return parsed;
228
+ }
229
+ else if (arg === '--style') {
230
+ const next = args[i + 1];
231
+ if (typeof next === 'string') {
232
+ const parsed = coerceStyle(next);
233
+ if (parsed)
234
+ return parsed;
235
+ }
236
+ }
237
+ }
238
+ return DEFAULT_PUGI_MD_STYLE;
239
+ }
240
+ function coerceStyle(value) {
241
+ if (value === 'minimal' || value === 'standard' || value === 'detailed')
242
+ return value;
243
+ return null;
244
+ }
245
+ /** Test surface: read back the on-disk report. */
246
+ export function readInitReport(reportPath) {
247
+ try {
248
+ return JSON.parse(readFileSync(reportPath, 'utf8'));
249
+ }
250
+ catch {
251
+ return null;
252
+ }
253
+ }
254
+ //# sourceMappingURL=init.js.map