one-code-extension 0.4.0 → 0.5.0

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 (419) hide show
  1. package/README.md +219 -219
  2. package/agents/general-purpose.md +2 -2
  3. package/docs/guide/README.md +2 -1
  4. package/docs/guide/bring-your-claude-code-setup.md +60 -9
  5. package/docs/guide/configuration.md +48 -14
  6. package/docs/guide/differences-from-claude-code.md +32 -23
  7. package/docs/guide/doctor.md +20 -13
  8. package/docs/guide/hooks.md +18 -3
  9. package/docs/guide/installation.md +27 -4
  10. package/docs/guide/permissions-modes-and-auto-mode.md +225 -49
  11. package/docs/guide/providers-and-models.md +137 -54
  12. package/docs/guide/reference.md +27 -15
  13. package/docs/guide/sessions-and-context.md +69 -16
  14. package/docs/guide/skills-plugins-and-mcp.md +57 -20
  15. package/docs/guide/subagents-and-workflows.md +95 -29
  16. package/docs/guide/tasks-and-background-work.md +101 -26
  17. package/docs/guide/terminal-interface.md +24 -12
  18. package/docs/guide/tools.md +46 -5
  19. package/docs/guide/troubleshooting.md +13 -9
  20. package/docs/guide/windows.md +66 -34
  21. package/extensions/artifacts/gallery.ts +227 -0
  22. package/extensions/artifacts/index.ts +288 -0
  23. package/extensions/artifacts/store.ts +570 -0
  24. package/extensions/artifacts/viewer.ts +199 -0
  25. package/extensions/ask-user/description.ts +67 -0
  26. package/extensions/ask-user/dialogs.ts +80 -0
  27. package/extensions/ask-user/index.ts +37 -33
  28. package/extensions/ask-user/questions.ts +32 -7
  29. package/extensions/ask-user/widget.ts +45 -25
  30. package/extensions/auto-mode/actions.ts +6 -0
  31. package/extensions/auto-mode/cache.ts +88 -0
  32. package/extensions/auto-mode/classifier-prompt.ts +5 -4
  33. package/extensions/auto-mode/classifier.ts +290 -65
  34. package/extensions/auto-mode/config.ts +72 -20
  35. package/extensions/auto-mode/decision-log.ts +2 -0
  36. package/extensions/auto-mode/defaults.ts +1 -1
  37. package/extensions/auto-mode/denials.ts +123 -0
  38. package/extensions/auto-mode/git-checkout-programs.ts +187 -0
  39. package/extensions/auto-mode/git-status-meta.ts +159 -0
  40. package/extensions/auto-mode/history.ts +189 -0
  41. package/extensions/auto-mode/instructions.ts +58 -52
  42. package/extensions/auto-mode/model-select.ts +159 -134
  43. package/extensions/auto-mode/paths.ts +57 -5
  44. package/extensions/auto-mode/pause.ts +57 -2
  45. package/extensions/auto-mode/prompt.ts +37 -21
  46. package/extensions/auto-mode/read-only-options.ts +724 -0
  47. package/extensions/auto-mode/resolved-paths-meta.ts +133 -0
  48. package/extensions/auto-mode/rules.ts +18 -1
  49. package/extensions/auto-mode/safety-floor.ts +361 -18
  50. package/extensions/auto-mode/setup-run.ts +20 -14
  51. package/extensions/auto-mode/shell-analysis.ts +764 -490
  52. package/extensions/auto-mode/shell-parse.ts +885 -0
  53. package/extensions/auto-mode/system-note.ts +33 -0
  54. package/extensions/auto-mode/transcript.ts +80 -51
  55. package/extensions/background/cron.ts +515 -0
  56. package/extensions/background/index.ts +514 -236
  57. package/extensions/background/loop-fire.ts +136 -0
  58. package/extensions/background/loop-preamble.ts +59 -0
  59. package/extensions/background/loop-skill.ts +163 -0
  60. package/extensions/background/monitor-batch.ts +53 -0
  61. package/extensions/background/noop-fold.ts +128 -0
  62. package/extensions/background/switch-guard.ts +52 -0
  63. package/extensions/background/wakeup.ts +159 -55
  64. package/extensions/bash/background.ts +53 -17
  65. package/extensions/bash/child.ts +7 -0
  66. package/extensions/bash/description.ts +188 -0
  67. package/extensions/bash/guards.ts +15 -67
  68. package/extensions/bash/index.ts +88 -35
  69. package/extensions/branding/compaction-keep.ts +63 -0
  70. package/extensions/branding/declined.ts +22 -0
  71. package/extensions/branding/index.ts +133 -9
  72. package/extensions/branding/prompt-editor.ts +53 -6
  73. package/extensions/branding/queued-edit.ts +31 -0
  74. package/extensions/branding/replaced-builtins.ts +68 -0
  75. package/extensions/branding/startup.ts +33 -71
  76. package/extensions/btw/index.ts +229 -71
  77. package/extensions/btw/panel.ts +228 -100
  78. package/extensions/btw/prompt.ts +41 -4
  79. package/extensions/claude-compat/index.ts +7 -11
  80. package/extensions/claude-context/index.ts +446 -58
  81. package/extensions/compaction/cut.ts +157 -0
  82. package/extensions/compaction/index.ts +216 -75
  83. package/extensions/compaction/kept-thinking.ts +62 -0
  84. package/extensions/compaction/prompt.ts +15 -12
  85. package/extensions/context-budget/index.ts +24 -5
  86. package/extensions/context-management/index.ts +25 -0
  87. package/extensions/doctor/build.ts +59 -8
  88. package/extensions/doctor/builtins.ts +84 -0
  89. package/extensions/doctor/cli.ts +7 -1
  90. package/extensions/doctor/compat.ts +88 -23
  91. package/extensions/doctor/dependencies.ts +41 -5
  92. package/extensions/doctor/fix-prompt.ts +9 -2
  93. package/extensions/doctor/index.ts +102 -58
  94. package/extensions/doctor/models.ts +102 -63
  95. package/extensions/doctor/presets.ts +42 -27
  96. package/extensions/doctor/report.ts +19 -2
  97. package/extensions/doctor/viewer.ts +49 -27
  98. package/extensions/effort/index.ts +72 -19
  99. package/extensions/effort/settings.ts +21 -0
  100. package/extensions/effort/slider.ts +24 -20
  101. package/extensions/exit/index.ts +32 -1
  102. package/extensions/file-tracker/index.ts +337 -26
  103. package/extensions/file-tracker/replay.ts +96 -10
  104. package/extensions/file-tracker/restore.ts +63 -0
  105. package/extensions/file-tracker/results.ts +66 -0
  106. package/extensions/file-tracker/shell-reads.ts +211 -0
  107. package/extensions/file-tracker/tracker.ts +32 -15
  108. package/extensions/footer/footer-line.ts +45 -24
  109. package/extensions/footer/index.ts +47 -2
  110. package/extensions/footer/pr.ts +34 -5
  111. package/extensions/hooks/compaction.ts +7 -0
  112. package/extensions/hooks/executor.ts +32 -30
  113. package/extensions/hooks/index.ts +198 -31
  114. package/extensions/hooks/matcher.ts +3 -0
  115. package/extensions/hooks/protocol.ts +41 -3
  116. package/extensions/hooks/settings.ts +50 -19
  117. package/extensions/hooks/subagent-bridge.ts +2 -0
  118. package/extensions/hooks/trust.ts +13 -5
  119. package/extensions/idle-compact/index.ts +119 -0
  120. package/extensions/idle-compact/policy.ts +143 -0
  121. package/extensions/init/index.ts +11 -10
  122. package/extensions/init/prompt.ts +25 -32
  123. package/extensions/interrupted/index.ts +13 -1
  124. package/extensions/kept-thinking/index.ts +27 -0
  125. package/extensions/lib/agent-cron.ts +130 -0
  126. package/extensions/lib/agent-loader.ts +15 -1
  127. package/extensions/lib/agent-view.ts +85 -0
  128. package/extensions/lib/anthropic-payload.ts +82 -1
  129. package/extensions/lib/anthropic-server-call.ts +230 -0
  130. package/extensions/lib/anthropic-server-tools.ts +485 -0
  131. package/extensions/lib/app-launch.mjs +94 -0
  132. package/extensions/lib/argument-hints.ts +190 -0
  133. package/extensions/lib/atomic-write.ts +6 -2
  134. package/extensions/lib/auto-memory.ts +75 -0
  135. package/extensions/lib/bash-parser.ts +84 -0
  136. package/extensions/lib/btw-fork.ts +93 -0
  137. package/extensions/lib/child-extensions.ts +42 -0
  138. package/extensions/lib/child-writes.ts +45 -0
  139. package/extensions/lib/claude-context.ts +515 -100
  140. package/extensions/lib/claude-external-includes.ts +68 -0
  141. package/extensions/lib/claude-id.ts +22 -0
  142. package/extensions/lib/claude-rules.ts +323 -0
  143. package/extensions/lib/claude-settings.ts +76 -4
  144. package/extensions/lib/compaction-boundary.ts +36 -0
  145. package/extensions/lib/compaction-keep.mjs +83 -0
  146. package/extensions/lib/config-mode.ts +112 -0
  147. package/extensions/lib/consent-dialogs.ts +63 -0
  148. package/extensions/lib/consent-preview.ts +5 -1
  149. package/extensions/lib/consent-stores.ts +48 -0
  150. package/extensions/lib/context-facts.ts +78 -0
  151. package/extensions/lib/context-stack.ts +81 -0
  152. package/extensions/lib/deferred.ts +219 -25
  153. package/extensions/lib/dock-rows.ts +60 -0
  154. package/extensions/lib/empty-tool-result.ts +27 -0
  155. package/extensions/lib/environment-block.ts +76 -0
  156. package/extensions/lib/fetch-timeout.ts +24 -6
  157. package/extensions/{system-prompt → lib}/git-status.ts +51 -13
  158. package/extensions/lib/git.ts +75 -13
  159. package/extensions/lib/grammars/LICENSE-tree-sitter-bash +21 -0
  160. package/extensions/lib/grammars/README.md +2 -0
  161. package/extensions/lib/grammars/tree-sitter-bash.wasm +0 -0
  162. package/extensions/lib/guide-docs.ts +45 -0
  163. package/extensions/lib/headless-output.ts +46 -0
  164. package/extensions/lib/hook-gate.ts +7 -7
  165. package/extensions/lib/interrupt.ts +20 -4
  166. package/extensions/lib/key-input.ts +455 -0
  167. package/extensions/lib/keys.ts +14 -1
  168. package/extensions/lib/local-command.ts +47 -13
  169. package/extensions/lib/mcp-overrides.ts +1 -1
  170. package/extensions/lib/mcp-share.ts +46 -0
  171. package/extensions/lib/memory-content.ts +146 -0
  172. package/extensions/lib/memory-index.ts +18 -0
  173. package/extensions/lib/memory.ts +134 -123
  174. package/extensions/lib/model-catalog/huggingface.json +174 -0
  175. package/extensions/lib/model-catalog/models-dev.json +18297 -0
  176. package/extensions/lib/model-catalog/openrouter.json +5252 -0
  177. package/extensions/lib/model-catalog-data.ts +513 -0
  178. package/extensions/lib/model-catalog.ts +462 -0
  179. package/extensions/lib/model-choice-warnings.ts +137 -0
  180. package/extensions/lib/model-pairings.ts +152 -0
  181. package/extensions/{auto-mode → lib}/model-picker.ts +26 -43
  182. package/extensions/lib/model-policy.ts +112 -15
  183. package/extensions/lib/model-tier.ts +283 -355
  184. package/extensions/lib/model-unusable.ts +1 -1
  185. package/extensions/lib/newer-model.ts +100 -0
  186. package/extensions/lib/notices.ts +87 -0
  187. package/extensions/lib/notifications.ts +308 -64
  188. package/extensions/lib/one-code-settings.ts +74 -8
  189. package/extensions/lib/open-browser.ts +63 -0
  190. package/extensions/lib/openrouter-generation.ts +94 -0
  191. package/extensions/lib/operation-deadline.ts +30 -0
  192. package/extensions/lib/original-command.ts +4 -4
  193. package/extensions/lib/package-version.ts +1 -1
  194. package/extensions/lib/panel-focus.ts +134 -0
  195. package/extensions/lib/paths.ts +17 -2
  196. package/extensions/lib/permission-gate.ts +72 -6
  197. package/extensions/lib/persisted-output.ts +60 -8
  198. package/extensions/lib/pi-ai-estimate.ts +19 -3
  199. package/extensions/lib/pi-version.ts +21 -2
  200. package/extensions/lib/plan-mode-channels.ts +20 -5
  201. package/extensions/lib/plugins.ts +26 -17
  202. package/extensions/lib/powershell-parse-script.ts +208 -0
  203. package/extensions/lib/powershell-parser.ts +344 -0
  204. package/extensions/lib/process-tree.ts +131 -8
  205. package/extensions/lib/prompt-options.ts +82 -0
  206. package/extensions/lib/queued-delivery.ts +44 -0
  207. package/extensions/lib/reminders.ts +364 -58
  208. package/extensions/lib/replaced-builtins.mjs +199 -0
  209. package/extensions/lib/replay-call.ts +70 -0
  210. package/extensions/lib/request-replay.ts +439 -0
  211. package/extensions/lib/scratchpad.ts +81 -14
  212. package/extensions/lib/send-now-channel.ts +7 -0
  213. package/extensions/lib/session-model-tier.ts +51 -0
  214. package/extensions/lib/session-work.ts +64 -0
  215. package/extensions/lib/settings-channels.ts +4 -4
  216. package/extensions/lib/shell-exit-semantics.ts +170 -0
  217. package/extensions/lib/shell-quote.ts +11 -0
  218. package/extensions/lib/shell-result.ts +70 -0
  219. package/extensions/lib/shell-spawn.ts +70 -6
  220. package/extensions/lib/shell-tool.ts +75 -25
  221. package/extensions/lib/side-call-cache.ts +124 -0
  222. package/extensions/lib/side-call-run.ts +96 -0
  223. package/extensions/lib/side-call-usage.ts +38 -0
  224. package/extensions/lib/side-call.ts +13 -1
  225. package/extensions/lib/single-flight.ts +18 -0
  226. package/extensions/lib/skill-body.ts +42 -0
  227. package/extensions/lib/skill-scan.ts +63 -24
  228. package/extensions/lib/spill-file.ts +140 -0
  229. package/extensions/lib/subagent-handback.ts +113 -0
  230. package/extensions/lib/system-role.ts +156 -0
  231. package/extensions/lib/terminal-text.ts +114 -0
  232. package/extensions/lib/text-width.ts +47 -16
  233. package/extensions/lib/timer-ops.ts +20 -0
  234. package/extensions/lib/tool-additions.ts +149 -0
  235. package/extensions/lib/tool-call-corruption.ts +134 -0
  236. package/extensions/lib/tool-path.ts +66 -0
  237. package/extensions/lib/tool-variants.ts +69 -0
  238. package/extensions/lib/tui-render.ts +255 -27
  239. package/extensions/lib/turn-budget-layout.ts +143 -0
  240. package/extensions/lib/update-check.mjs +15 -2
  241. package/extensions/lib/usage-bus.ts +1 -1
  242. package/extensions/lib/user-denial.ts +38 -0
  243. package/extensions/lib/workspace-channel.ts +16 -0
  244. package/extensions/lib/worktree-channel.ts +31 -3
  245. package/extensions/lib/worktree-isolation.ts +40 -10
  246. package/extensions/lsp/client.ts +8 -9
  247. package/extensions/lsp/index.ts +70 -4
  248. package/extensions/lsp/keep-alive.ts +1 -1
  249. package/extensions/lsp/trust.ts +119 -0
  250. package/extensions/lsp/watcher.ts +1 -1
  251. package/extensions/mcp/announce.ts +87 -5
  252. package/extensions/mcp/client.ts +161 -48
  253. package/extensions/mcp/config.ts +132 -8
  254. package/extensions/mcp/discovery.ts +19 -0
  255. package/extensions/mcp/index.ts +209 -71
  256. package/extensions/mcp/oauth/browser.ts +38 -17
  257. package/extensions/mcp/oauth/flow.ts +25 -17
  258. package/extensions/mcp/oauth/provider.ts +14 -8
  259. package/extensions/mcp/oauth/store.ts +34 -16
  260. package/extensions/mcp/panel/keys.ts +12 -11
  261. package/extensions/mcp/panel/render.ts +9 -6
  262. package/extensions/mcp/schema.ts +104 -5
  263. package/extensions/mcp/trust.ts +151 -67
  264. package/extensions/memory/entries.ts +23 -14
  265. package/extensions/memory/index.ts +134 -28
  266. package/extensions/memory/open-external.ts +33 -18
  267. package/extensions/memory/panel.ts +135 -26
  268. package/extensions/newer-model/index.ts +31 -0
  269. package/extensions/notebook/description.ts +18 -0
  270. package/extensions/notebook/index.ts +6 -5
  271. package/extensions/notebook/notebook.ts +1 -1
  272. package/extensions/permissions/index.ts +1300 -381
  273. package/extensions/permissions/matcher.ts +425 -74
  274. package/extensions/permissions/modes.ts +6 -4
  275. package/extensions/permissions/panel/host.ts +130 -0
  276. package/extensions/permissions/panel/keys.ts +48 -0
  277. package/extensions/permissions/panel/render.ts +450 -0
  278. package/extensions/permissions/panel/state.ts +550 -0
  279. package/extensions/permissions/powershell-cmdlets.ts +198 -0
  280. package/extensions/permissions/powershell-paths.ts +197 -0
  281. package/extensions/permissions/powershell-rules.ts +207 -280
  282. package/extensions/permissions/powershell-tree.ts +557 -0
  283. package/extensions/permissions/project-trust.ts +27 -11
  284. package/extensions/permissions/protected-paths.ts +14 -2
  285. package/extensions/permissions/session-grant.ts +6 -0
  286. package/extensions/permissions/settings.ts +166 -31
  287. package/extensions/permissions/subagent-gate.ts +25 -0
  288. package/extensions/permissions/workspace.ts +78 -0
  289. package/extensions/plan-mode/index.ts +156 -69
  290. package/extensions/plan-mode/reminder.ts +89 -21
  291. package/extensions/plan-mode/texts.ts +177 -0
  292. package/extensions/plan-mode/viewer.ts +92 -27
  293. package/extensions/plugins/counts.ts +3 -3
  294. package/extensions/plugins/index.ts +61 -46
  295. package/extensions/plugins/install/install.ts +16 -0
  296. package/extensions/plugins/marketplace/sync.ts +9 -3
  297. package/extensions/plugins/marketplace/types.ts +3 -1
  298. package/extensions/plugins/panel/keys.ts +21 -24
  299. package/extensions/plugins/panel/render.ts +12 -6
  300. package/extensions/plugins/shell-expand.ts +107 -0
  301. package/extensions/plugins/template.ts +32 -15
  302. package/extensions/powershell/child.ts +7 -0
  303. package/extensions/powershell/description.ts +38 -6
  304. package/extensions/powershell/guards.ts +1 -1
  305. package/extensions/powershell/index.ts +12 -7
  306. package/extensions/recap/index.ts +65 -60
  307. package/extensions/recap/prompt.ts +2 -2
  308. package/extensions/recap/scheduler.ts +3 -5
  309. package/extensions/search-tools/grep-merge.ts +39 -0
  310. package/extensions/search-tools/index.ts +0 -0
  311. package/extensions/send-now/chord.ts +62 -0
  312. package/extensions/send-now/index.ts +133 -0
  313. package/extensions/session-title/index.ts +3 -0
  314. package/extensions/session-title/title.ts +4 -1
  315. package/extensions/skill/code-review.ts +97 -0
  316. package/extensions/skill/index.ts +421 -101
  317. package/extensions/skill/invoke.ts +128 -18
  318. package/extensions/skill/listing.ts +133 -9
  319. package/extensions/skill/panel/keys.ts +15 -16
  320. package/extensions/skill/panel/render.ts +5 -2
  321. package/extensions/skill/panel/state.ts +12 -1
  322. package/extensions/subagents/agent-args.ts +39 -0
  323. package/extensions/subagents/agent-description.ts +132 -0
  324. package/extensions/subagents/agents.ts +116 -23
  325. package/extensions/subagents/announce.ts +69 -0
  326. package/extensions/subagents/default-model.ts +2 -3
  327. package/extensions/subagents/delegation-steer.ts +4 -4
  328. package/extensions/subagents/fork-cache.ts +76 -0
  329. package/extensions/subagents/guide-agent.ts +189 -0
  330. package/extensions/subagents/hand-back-review.ts +3 -0
  331. package/extensions/subagents/index.ts +1493 -824
  332. package/extensions/subagents/live-runs.ts +26 -6
  333. package/extensions/subagents/model-select.ts +38 -25
  334. package/extensions/subagents/outcome.ts +2 -2
  335. package/extensions/subagents/panel-keys.ts +73 -31
  336. package/extensions/subagents/panel-render.ts +120 -96
  337. package/extensions/subagents/panel-widget.ts +60 -89
  338. package/extensions/subagents/runner.ts +108 -80
  339. package/extensions/subagents/runs.ts +39 -5
  340. package/extensions/subagents/send-to-main-tool.ts +1 -1
  341. package/extensions/subagents/session-turns.ts +32 -8
  342. package/extensions/subagents/shell-panel.ts +36 -178
  343. package/extensions/subagents/tasks-dialog.ts +170 -0
  344. package/extensions/subagents/viewport-mirror.ts +95 -0
  345. package/extensions/subagents/worktree.ts +57 -13
  346. package/extensions/system-prompt/environment.ts +19 -19
  347. package/extensions/system-prompt/idle-turn.ts +65 -0
  348. package/extensions/system-prompt/index.ts +131 -47
  349. package/extensions/system-prompt/template.ts +24 -50
  350. package/extensions/system-prompt/tiers/common.ts +23 -64
  351. package/extensions/system-prompt/tiers/frontier.ts +32 -11
  352. package/extensions/system-prompt/tiers/low.ts +67 -45
  353. package/extensions/system-prompt/tiers/mid.ts +96 -38
  354. package/extensions/system-reminder/index.ts +175 -13
  355. package/extensions/tasks/descriptions.ts +190 -0
  356. package/extensions/tasks/index.ts +120 -41
  357. package/extensions/tasks/store.ts +83 -16
  358. package/extensions/tool-call-corruption/child.ts +7 -0
  359. package/extensions/tool-call-corruption/index.ts +237 -0
  360. package/extensions/tool-search/announce.ts +16 -0
  361. package/extensions/tool-search/index.ts +189 -41
  362. package/extensions/tool-style/index.ts +68 -10
  363. package/extensions/tool-style/write-description.ts +40 -0
  364. package/extensions/tool-style/write-render.ts +237 -0
  365. package/extensions/turn-duration/index.ts +7 -3
  366. package/extensions/turn-duration/line.ts +47 -4
  367. package/extensions/web/backends.ts +6 -9
  368. package/extensions/web/description.ts +50 -0
  369. package/extensions/web/index.ts +118 -53
  370. package/extensions/web/native-call.ts +15 -0
  371. package/extensions/web/native-results.ts +41 -0
  372. package/extensions/web-fetch/description.ts +42 -0
  373. package/extensions/web-fetch/extract.ts +53 -6
  374. package/extensions/web-fetch/index.ts +125 -76
  375. package/extensions/web-fetch/page-content.ts +19 -0
  376. package/extensions/web-fetch/response.ts +49 -0
  377. package/extensions/web-fetch/summarize.ts +9 -10
  378. package/extensions/workflow/agent-session.ts +105 -18
  379. package/extensions/workflow/args.ts +24 -0
  380. package/extensions/workflow/description.ts +67 -0
  381. package/extensions/workflow/globals.ts +17 -3
  382. package/extensions/workflow/index.ts +145 -162
  383. package/extensions/workflow/records.ts +1 -0
  384. package/extensions/workflow/run-manager.ts +29 -6
  385. package/extensions/workflow/saved-workflows.ts +3 -2
  386. package/extensions/workflow/types.ts +22 -1
  387. package/extensions/workflow/viewer.ts +54 -24
  388. package/extensions/workflow/widget.ts +20 -0
  389. package/extensions/worktree/descriptions.ts +91 -0
  390. package/extensions/worktree/guards.ts +316 -54
  391. package/extensions/worktree/index.ts +121 -39
  392. package/extensions/worktree/powershell-guards.ts +167 -0
  393. package/extensions/worktree/rewrite.ts +14 -16
  394. package/package.json +19 -7
  395. package/skills/artifact-design/SKILL.md +85 -0
  396. package/skills/code-review/SKILL.md +20 -20
  397. package/skills/code-review/cells/arguments-and-flags.md +19 -0
  398. package/skills/code-review/cells/high-3x5-recall-verify.md +137 -0
  399. package/skills/code-review/cells/high-8-inline.md +122 -0
  400. package/skills/code-review/cells/low-1-pass-max4.md +27 -0
  401. package/skills/code-review/cells/low-1-pass-min-files-4.md +28 -0
  402. package/skills/code-review/cells/max-5x5-verify-sweep.md +162 -0
  403. package/skills/code-review/cells/medium-3x5-verify.md +132 -0
  404. package/skills/code-review/cells/minimal-prompt.md +32 -0
  405. package/skills/code-review/cells/xhigh-10-inline-sweep.md +149 -0
  406. package/skills/code-review/cells/xhigh-5x5-verify-sweep.md +162 -0
  407. package/skills/fewer-permission-prompts/SKILL.md +1 -1
  408. package/skills/loop/SKILL.md +11 -0
  409. package/skills/security-review/SKILL.md +2 -5
  410. package/skills/simplify/SKILL.md +7 -5
  411. package/skills/workflow-authoring/SKILL.md +143 -0
  412. package/themes/onecode-light.json +1 -1
  413. package/themes/onecode.json +1 -1
  414. package/types/app.d.ts +58 -0
  415. package/types/community-packages.d.ts +26 -1
  416. package/extensions/auto-mode/recoverability.ts +0 -229
  417. package/extensions/lib/capability-index.ts +0 -466
  418. package/extensions/lib/model-facts.generated.json +0 -2675
  419. package/extensions/lib/model-facts.ts +0 -162
@@ -8,13 +8,13 @@ import type { Api, Model } from "@earendil-works/pi-ai";
8
8
  * `/doctor` is the checkup, as in Claude Code, with the harness's measured
9
9
  * report attached to the prompt; `/doctor report` shows that report alone, and
10
10
  * bare `/doctor` falls back to it when no model can run — the first-session
11
- * state ("no provider is ready") this command exists for. docs/decisions/doctor.md.
11
+ * state ("no provider is ready") this command exists for. working-docs/decisions/doctor.md.
12
12
  *
13
13
  * /doctor the checkup: the report goes to the model inside Claude Code's
14
14
  * doctor prompt, adapted (falls back to the report when no model can run)
15
15
  * /doctor report the measured report alone (a scrollable panel in the TUI, plain text elsewhere)
16
16
  * /doctor presets the three model presets for this provider
17
- * /doctor preset <name> apply one: main model, subagent default, classifier
17
+ * /doctor preset <name> apply one: main model and subagent default
18
18
  *
19
19
  * `onecode doctor` (the app's CLI subcommand) prints the same report without a
20
20
  * session — see cli.ts. Thin wiring: every check lives in the pure modules.
@@ -23,18 +23,23 @@ import type { Api, Model } from "@earendil-works/pi-ai";
23
23
  import * as os from "node:os";
24
24
  import { join } from "node:path";
25
25
  import {
26
+ CONFIG_DIR_NAME,
26
27
  type ExtensionAPI,
27
28
  type ExtensionCommandContext,
28
29
  type ExtensionContext,
29
30
  getAgentDir,
31
+ SettingsManager,
30
32
  VERSION as PI_VERSION,
31
33
  } from "@earendil-works/pi-coding-agent";
32
34
  import { loadAutoModeConfig, persistClassifierModel } from "../auto-mode/config.ts";
33
- import { configuredCapabilityKey, loadCapabilitySnapshot, refreshCapabilitySnapshot, snapshotIsStale } from "../lib/capability-index.ts";
35
+ import { catalogRefreshDue, readCatalogRefreshEnabled, refreshModelCatalog } from "../lib/model-catalog-data.ts";
36
+ import { BUILTIN_PROVIDER_POLICIES } from "../lib/model-policy.ts";
34
37
  import { MODEL_UNUSABLE_CHANNEL, type ModelUnusableEvent, withoutUnusable } from "../lib/model-unusable.ts";
35
38
  import { MCP_STATUS_CHANNEL, MCP_STATUS_REQUEST_CHANNEL, type McpStatusEvent } from "../lib/mcp-status.ts";
36
- import { sessionOutlivesTurn } from "../lib/notifications.ts";
39
+ import { canShowCustomUi, notifyOrPrint } from "../lib/headless-output.ts";
40
+ import { createUserMessageSender, sessionOutlivesTurn } from "../lib/notifications.ts";
37
41
  import { modelSpec } from "../lib/model-policy.ts";
42
+ import { sessionModelTier } from "../lib/session-model-tier.ts";
38
43
  import { oneCodeProjectSettingsPath, oneCodeSettingsPath } from "../lib/one-code-settings.ts";
39
44
  import { oneCodeStateDir } from "../lib/paths.ts";
40
45
  import { CLASSIFIER_SETTING_CHANGED_CHANNEL, SUBAGENT_DEFAULT_CHANGED_CHANNEL } from "../lib/settings-channels.ts";
@@ -42,16 +47,25 @@ import { boundedDockHeight, safeThemeBold, safeThemePaint, truncateLine } from "
42
47
  import { PERMISSION_STATUS_CHANNEL, type PermissionStatus } from "../permissions/modes.ts";
43
48
  import { persistSubagentModel } from "../subagents/default-model.ts";
44
49
  import { buildDoctorReport, oneCodeVersion } from "./build.ts";
50
+ import { installKind, keepView, replacedBuiltinsView } from "./builtins.ts";
45
51
  import { doctorFixPrompt } from "./fix-prompt.ts";
46
52
  import { computePresets, describePresetChanges, findPreset, PRESET_NAMES, presetsSection } from "./presets.ts";
47
53
  import { type DoctorReport, renderDoctorReport, renderDoctorText, renderSection } from "./report.ts";
48
54
  import { lookupLatestVersion } from "./update-lookup.ts";
49
- import { applyDoctorKey, decodeDoctorKey, renderDoctorViewer, visibleBodyRows } from "./viewer.ts";
55
+ import { applyDoctorKey, decodeDoctorKey, type DoctorViewerState, renderDoctorViewer, visibleBodyRows } from "./viewer.ts";
56
+ import { announceArgumentHint, extendingCompletions } from "../lib/argument-hints.ts";
57
+ import { announceLocalCommand } from "../lib/local-command.ts";
58
+ import { registeredMcpServers } from "../mcp/config.ts";
59
+ import { configMode } from "../lib/config-mode.ts";
60
+ import { promptCommandText } from "../skill/invoke.ts";
61
+ import { panelUi } from "../lib/panel-focus.ts";
50
62
 
51
63
  /** Rows the panel may take; the terminal's own height caps it (boundedDockHeight). */
52
64
  export const DOCTOR_PANEL_MAX_HEIGHT = 40;
53
65
 
54
66
  export default function doctorExtension(pi: ExtensionAPI) {
67
+ const requestTier = sessionModelTier(pi);
68
+ const sendUserMessage = createUserMessageSender(pi);
55
69
  // Models the account refused this session (lib/model-unusable.ts): the report
56
70
  // and presets must not recommend a model the session has just learned to avoid.
57
71
  const unusableModels = new Set<string>();
@@ -78,56 +92,78 @@ export default function doctorExtension(pi: ExtensionAPI) {
78
92
  return snapshot;
79
93
  };
80
94
 
81
- const install = (): "app" | "pi-package" => (process.env.CC_VERSION ? "app" : "pi-package");
82
-
83
- // The Artificial Analysis snapshot behind the measured capability floor
84
- // (lib/capability-index.ts): refreshed at most daily, only from a session
85
- // that outlives the turn, never awaited in session_start (findings §15, §19),
86
- // inert once the session is shutting down. A failure is logged once.
95
+ // The public model catalogs behind the tiers (lib/model-catalog-data.ts):
96
+ // refreshed at most daily, only from a session that outlives the turn, never
97
+ // awaited in session_start (findings §15, §19), inert once the session is
98
+ // shutting down (session_shutdown cancels a fetch in flight), off with
99
+ // `refreshModelCatalog: false`. A failure is logged once, the copy on disk
100
+ // (or the bundled one) keeps serving, and the next try waits a day. The
101
+ // start-up check reads only the files' stamps; this extension never parses
102
+ // the catalogs unless it refreshes or reports. Request surfaces keep their
103
+ // frozen tier until session_start/model_select; automatic model selection
104
+ // uses the refreshed catalog immediately.
87
105
  let shuttingDown = false;
88
106
  let refreshWarned = false;
89
- const refreshCapability = async (ctx: ExtensionContext, home: string): Promise<void> => {
90
- const outcome = await refreshCapabilitySnapshot({ key: configuredCapabilityKey(home), stateDir: oneCodeStateDir(process.env, home) });
107
+ let refreshAbort = new AbortController();
108
+ const refreshCatalog = async (ctx: ExtensionContext, home: string): Promise<void> => {
109
+ if (!readCatalogRefreshEnabled(oneCodeSettingsPath(home))) return;
110
+ const outcome = await refreshModelCatalog({
111
+ stateDir: oneCodeStateDir(process.env, home),
112
+ piProviders: Object.keys(BUILTIN_PROVIDER_POLICIES),
113
+ signal: refreshAbort.signal,
114
+ });
91
115
  if (outcome.status === "failed" && !refreshWarned && !shuttingDown) {
92
116
  refreshWarned = true;
93
117
  try {
94
- ctx.ui.notify(`Capability scores not refreshed: ${outcome.error}. Automatic picks keep using the last snapshot, if any.`, "warning");
118
+ notifyOrPrint(ctx, `Model catalogs not refreshed: ${outcome.error}. Model tiers keep using the copy on disk.`, "warning");
95
119
  } catch {
96
120
  // A UI hiccup must not fail the report that awaits this refresh.
97
121
  }
98
122
  }
99
123
  };
100
124
  pi.on("session_start", (_event, ctx) => {
125
+ if (refreshAbort.signal.aborted) refreshAbort = new AbortController();
101
126
  const home = os.homedir();
102
- if (!sessionOutlivesTurn(ctx.mode) || !configuredCapabilityKey(home)) return;
103
- if (!snapshotIsStale(loadCapabilitySnapshot(oneCodeStateDir(process.env, home)))) return;
104
- void refreshCapability(ctx, home).catch(() => {});
127
+ if (!sessionOutlivesTurn(ctx.mode) || !readCatalogRefreshEnabled(oneCodeSettingsPath(home))) return;
128
+ if (!catalogRefreshDue(oneCodeStateDir(process.env, home))) return;
129
+ void refreshCatalog(ctx, home).catch(() => {});
105
130
  });
106
131
  pi.on("session_shutdown", () => {
107
132
  shuttingDown = true;
133
+ refreshAbort.abort(new Error("the session ended"));
108
134
  });
109
135
 
110
136
  const gather = async (ctx: ExtensionContext, options: { network: boolean }): Promise<DoctorReport> => {
111
137
  const home = os.homedir();
112
138
  const version = oneCodeVersion();
113
- // Two unrelated endpoints (npm registry, Artificial Analysis): overlap them.
114
- // The snapshot refresh is a no-op when fresh or keyless, bounded by FETCH_TIMEOUT_MS.
139
+ // Unrelated endpoints (npm registry, the model catalogs): overlap them.
140
+ // The catalog refresh is a no-op when fresh or turned off, bounded by its fetch timeout.
115
141
  const [latest] = options.network
116
- ? await Promise.all([lookupLatestVersion({ install: install(), current: version, env: process.env }), refreshCapability(ctx, home)])
142
+ ? await Promise.all([lookupLatestVersion({ install: installKind(), current: version, env: process.env }), refreshCatalog(ctx, home)])
117
143
  : [undefined];
144
+ // One read of pi's settings serves both views; made inside their own
145
+ // try, since a malformed settings file throws.
146
+ const piPaths = { agentDir: getAgentDir(), cwd: ctx.cwd };
147
+ let manager: SettingsManager | undefined;
148
+ const piSettings = () => (manager ??= SettingsManager.create(ctx.cwd, piPaths.agentDir));
118
149
  return buildDoctorReport({
119
150
  env: {
120
151
  cwd: ctx.cwd,
121
152
  home,
122
153
  agentDir: getAgentDir(),
123
154
  stateDir: oneCodeStateDir(process.env, home),
155
+ configMode: configMode(),
124
156
  env: process.env,
125
157
  platform: process.platform,
126
158
  arch: process.arch,
127
159
  nodeVersion: process.versions.node,
128
160
  oneCodeVersion: version,
129
- install: install(),
161
+ install: installKind(),
130
162
  piVersion: PI_VERSION,
163
+ replacedBuiltins: replacedBuiltinsView(PI_VERSION, piSettings, piPaths),
164
+ compactionKeep: keepView(piSettings, piPaths, ctx.model ? `${ctx.model.provider}/${ctx.model.id}` : undefined),
165
+ piConfigDirName: CONFIG_DIR_NAME,
166
+ registeredMcpServers: registeredMcpServers(pi),
131
167
  latest,
132
168
  },
133
169
  registry: {
@@ -138,6 +174,7 @@ export default function doctorExtension(pi: ExtensionAPI) {
138
174
  },
139
175
  session: {
140
176
  model: ctx.model,
177
+ promptTier: requestTier(),
141
178
  modelSource: ctx.model ? "session" : "none",
142
179
  thinkingLevel: ctx.thinkingLevel,
143
180
  permission: permission
@@ -148,32 +185,33 @@ export default function doctorExtension(pi: ExtensionAPI) {
148
185
  });
149
186
  };
150
187
 
151
- const sendFix = (ctx: ExtensionContext, report: DoctorReport): boolean => {
188
+ const sendFix = async (ctx: ExtensionCommandContext, report: DoctorReport): Promise<boolean> => {
152
189
  if (!ctx.model) {
153
- ctx.ui.notify("No model is available, so the checkup cannot run. Connect a provider with /login first; the report already lists what to fix.", "warning");
190
+ notifyOrPrint(ctx, "No model is available, so the checkup cannot run. Connect a provider with /login first; the report already lists what to fix.", "warning");
154
191
  return false;
155
192
  }
156
193
  const home = os.homedir();
157
194
  const prompt = doctorFixPrompt({
158
195
  reportText: renderDoctorText(report, 100),
159
- install: install(),
196
+ install: installKind(),
160
197
  oneCodeVersion: oneCodeVersion(),
161
198
  sessionsDir: join(getAgentDir(), "sessions"),
162
199
  sessionDir: ctx.sessionManager.getSessionDir(),
163
200
  oneCodeSettingsPath: oneCodeSettingsPath(home),
164
201
  oneCodeProjectSettingsPath: oneCodeProjectSettingsPath(ctx.cwd, home),
165
202
  decisionLogEnabled: loadAutoModeConfig(home).logDecisions,
203
+ independent: configMode() === "independent",
166
204
  });
167
- pi.sendUserMessage(prompt, { deliverAs: "followUp" });
205
+ await sendUserMessage(ctx, promptCommandText("doctor", "", prompt));
168
206
  return true;
169
207
  };
170
208
 
171
209
  const showPanel = async (ctx: ExtensionCommandContext, report: DoctorReport): Promise<void> => {
172
210
  let wantFix = false;
173
- await ctx.ui.custom<null>((tui, theme, _keybindings, done) => {
211
+ await panelUi(pi.events, ctx.ui).custom<null>((tui, theme, _keybindings, done) => {
174
212
  const paint = safeThemePaint(theme);
175
213
  const bold = safeThemeBold(theme);
176
- const state = { offset: 0 };
214
+ const state: DoctorViewerState = { offset: 0 };
177
215
  let cache: { width: number; lines: string[] } | undefined;
178
216
  const body = (width: number) => {
179
217
  if (cache?.width === width) return cache;
@@ -191,7 +229,7 @@ export default function doctorExtension(pi: ExtensionAPI) {
191
229
  const key = decodeDoctorKey(data);
192
230
  if (!key) return;
193
231
  const termRows = (tui as { terminal?: { rows?: number } }).terminal?.rows ?? DOCTOR_PANEL_MAX_HEIGHT;
194
- const visible = visibleBodyRows(boundedDockHeight(termRows, DOCTOR_PANEL_MAX_HEIGHT));
232
+ const visible = state.visibleRows ?? visibleBodyRows(boundedDockHeight(termRows, DOCTOR_PANEL_MAX_HEIGHT));
195
233
  const effect = applyDoctorKey(state, key, cache?.lines.length ?? 0, visible);
196
234
  if (effect?.kind === "fix") {
197
235
  wantFix = true;
@@ -209,84 +247,86 @@ export default function doctorExtension(pi: ExtensionAPI) {
209
247
  },
210
248
  };
211
249
  });
212
- if (wantFix) sendFix(ctx, report);
250
+ if (wantFix) await sendFix(ctx, report);
213
251
  };
214
252
 
215
- const applyPreset = async (name: string, ctx: ExtensionCommandContext): Promise<void> => {
253
+ const notifyLocalResult = (args: string, ctx: ExtensionCommandContext, stdout: string, type: "info" | "warning" | "error"): void => {
254
+ announceLocalCommand(pi, { name: "doctor", args, stdout });
255
+ notifyOrPrint(ctx, stdout, type);
256
+ };
257
+
258
+ /** The preset's result, for the caller to notify and report as the command's stdout. */
259
+ const applyPreset = async (name: string, ctx: ExtensionCommandContext): Promise<{ text: string; type: "info" | "warning" | "error" }> => {
216
260
  const available = usableModels(ctx);
217
261
  const { presets, unavailable } = computePresets(available, ctx.model);
218
262
  if (unavailable === "no-model") {
219
- ctx.ui.notify("No model is available — connect a provider with /login first.", "warning");
220
- return;
263
+ return { text: "No model is available — connect a provider with /login first.", type: "warning" };
221
264
  }
222
265
  if (unavailable === "no-priced-models") {
223
- ctx.ui.notify("No priced models on this provider, so tiers cannot be told apart and no preset can be applied. Pick models by hand with /model, /subagent and /auto-mode model.", "warning");
224
- return;
266
+ return { text: "No priced models on this provider, so tiers cannot be told apart and no preset can be applied. Pick models by hand with /model or /subagent.", type: "warning" };
225
267
  }
226
268
  const preset = findPreset(presets, name);
227
269
  if (!preset) {
228
- ctx.ui.notify(`Unknown preset "${name}". Choose one of: ${PRESET_NAMES.join(", ")} (see /doctor presets).`, "error");
229
- return;
270
+ return { text: `Unknown preset "${name}". Choose one of: ${PRESET_NAMES.join(", ")} (see /doctor presets).`, type: "error" };
230
271
  }
231
272
  const home = os.homedir();
232
273
  const mainSwitched = !ctx.model || modelSpec(ctx.model) !== modelSpec(preset.main);
233
274
  if (mainSwitched && !(await pi.setModel(preset.main))) {
234
- ctx.ui.notify(`Could not switch the main model to ${modelSpec(preset.main)}; nothing was changed.`, "error");
235
- return;
275
+ return { text: `Could not switch the main model to ${modelSpec(preset.main)}; nothing was changed.`, type: "error" };
236
276
  }
237
277
  try {
238
278
  persistSubagentModel(preset.subagents.setting === "inherit" ? "inherit" : undefined, home);
279
+ // Every preset returns the classifier to the automatic choice.
239
280
  persistClassifierModel(undefined, home);
240
281
  } catch (error) {
241
282
  const switched = mainSwitched ? ` The main model was already switched to ${modelSpec(preset.main)}; /model switches it back.` : "";
242
- ctx.ui.notify(`Could not save settings: ${error instanceof Error ? error.message : String(error)}.${switched}`, "error");
243
- return;
283
+ return { text: `Could not save settings: ${error instanceof Error ? error.message : String(error)}.${switched}`, type: "error" };
244
284
  }
245
285
  pi.events.emit(SUBAGENT_DEFAULT_CHANGED_CHANNEL, {});
246
286
  pi.events.emit(CLASSIFIER_SETTING_CHANGED_CHANNEL, {});
247
- ctx.ui.notify(
248
- [
287
+ return {
288
+ text: [
249
289
  `Applied the ${preset.label} preset:`,
250
290
  ...describePresetChanges(preset, mainSwitched).map((line) => ` ${line}`),
251
291
  "Saved to ~/.onecode/settings.json; the main model is remembered as pi's default.",
252
292
  ].join("\n"),
253
- "info",
254
- );
293
+ type: "info",
294
+ };
255
295
  };
256
296
 
257
297
  /** The subcommands, with the one-line explanation the completion menu shows next to each. */
258
298
  const SUBCOMMANDS: Array<{ value: string; description: string }> = [
259
299
  { value: "report", description: "Show the measured setup report: providers, the model each role gets, imported Claude Code config, MCP servers, dependencies" },
260
300
  { value: "presets", description: "List the economical / balanced / maximum-quality model presets for this provider, with the models each would pick" },
261
- { value: "preset economical", description: "Apply: one cheap model for the main session, subagents and the classifier" },
262
- { value: "preset balanced", description: "Apply: a capable main model, cheaper automatic picks for subagents and the classifier" },
301
+ { value: "preset economical", description: "Apply: one cheap model for the main session and subagents; automatic classifier" },
302
+ { value: "preset balanced", description: "Apply: a capable main model with automatic subagents and classifier" },
263
303
  { value: "preset quality", description: "Apply: the strongest model for the main session and its subagents" },
264
304
  ];
265
305
 
306
+ announceArgumentHint(pi, "doctor", "[report|presets|preset <name>]");
266
307
  pi.registerCommand("doctor", {
267
308
  description:
268
309
  "Health-check your setup and fix what's wrong (Claude Code's checkup, run by the model). Subcommands: report (the measured report only), presets, preset <economical|balanced|quality>",
269
- getArgumentCompletions: (prefix) => {
270
- const typed = prefix.trim().toLowerCase();
271
- return SUBCOMMANDS.filter((option) => option.value.startsWith(typed)).map((option) => ({ value: option.value, label: option.value, description: option.description }));
272
- },
310
+ getArgumentCompletions: (prefix) =>
311
+ extendingCompletions(prefix, SUBCOMMANDS.map((option) => ({ value: option.value, label: option.value, description: option.description }))),
273
312
  handler: async (args, ctx) => {
274
313
  const [verb, ...rest] = args.trim().split(/\s+/).filter(Boolean);
275
314
  if (verb === "preset") {
276
315
  if (rest.length === 0) {
277
- ctx.ui.notify(`Which preset? /doctor preset <${PRESET_NAMES.join("|")}> — /doctor presets shows what each would pick.`, "warning");
316
+ notifyLocalResult(args, ctx, `Which preset? /doctor preset <${PRESET_NAMES.join("|")}> — /doctor presets shows what each would pick.`, "warning");
278
317
  return;
279
318
  }
280
- await applyPreset(rest.join(" "), ctx);
319
+ const result = await applyPreset(rest.join(" "), ctx);
320
+ notifyLocalResult(args, ctx, result.text, result.type);
281
321
  return;
282
322
  }
283
323
  if (verb === "presets") {
284
324
  const section = presetsSection(computePresets(usableModels(ctx), ctx.model), ctx.model);
285
- ctx.ui.notify(renderSection(section, { width: 100 }).join("\n"), "info");
325
+ notifyLocalResult(args, ctx, renderSection(section, { width: 100 }).join("\n"), "info");
286
326
  return;
287
327
  }
288
328
  if (verb && verb !== "report") {
289
- ctx.ui.notify(`Unknown /doctor argument "${verb}". Use /doctor, /doctor report, /doctor presets, or /doctor preset <name>.`, "error");
329
+ notifyLocalResult(args, ctx, `Unknown /doctor argument "${verb}". Use /doctor, /doctor report, /doctor presets, or /doctor preset <name>.`, "error");
290
330
  return;
291
331
  }
292
332
  // Bare `/doctor` is the checkup (Claude Code parity). Without a model it
@@ -295,15 +335,19 @@ export default function doctorExtension(pi: ExtensionAPI) {
295
335
  const checkup = verb === undefined;
296
336
  const report = await gather(ctx, { network: !checkup });
297
337
  if (checkup && ctx.model) {
298
- sendFix(ctx, report);
338
+ await sendFix(ctx, report);
299
339
  return;
300
340
  }
301
- if (checkup) ctx.ui.notify("No model is available, so the checkup cannot run; showing the setup report instead. Connect a provider with /login, then rerun /doctor.", "warning");
302
- if (ctx.hasUI && ctx.mode === "tui") {
341
+ const warning = checkup ? "No model is available, so the checkup cannot run; showing the setup report instead. Connect a provider with /login, then rerun /doctor." : "";
342
+ const stdout = renderDoctorText(report, 100);
343
+ // The panel can submit the checkup prompt; queue its local result first.
344
+ announceLocalCommand(pi, { name: "doctor", args, stdout: warning ? `${warning}\n${stdout}` : stdout });
345
+ if (warning) notifyOrPrint(ctx, warning, "warning");
346
+ if (canShowCustomUi(ctx)) {
303
347
  await showPanel(ctx, report);
304
348
  return;
305
349
  }
306
- ctx.ui.notify(renderDoctorText(report, 100), report.ready ? "info" : "warning");
350
+ notifyOrPrint(ctx, stdout, report.ready ? "info" : "warning");
307
351
  },
308
352
  });
309
353
  }