@bastani/atomic 0.9.13 → 0.9.14-alpha.2

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 (762) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/README.md +3 -3
  3. package/dist/builtin/intercom/package.json +2 -2
  4. package/dist/builtin/mcp/package.json +3 -3
  5. package/dist/builtin/subagents/CHANGELOG.md +14 -0
  6. package/dist/builtin/subagents/README.md +6 -4
  7. package/dist/builtin/subagents/agents/code-simplifier.md +1 -1
  8. package/dist/builtin/subagents/agents/codebase-analyzer.md +1 -1
  9. package/dist/builtin/subagents/agents/codebase-locator.md +1 -1
  10. package/dist/builtin/subagents/agents/codebase-online-researcher.md +1 -1
  11. package/dist/builtin/subagents/agents/codebase-pattern-finder.md +1 -1
  12. package/dist/builtin/subagents/agents/codebase-research-analyzer.md +1 -1
  13. package/dist/builtin/subagents/agents/codebase-research-locator.md +1 -1
  14. package/dist/builtin/subagents/agents/debugger.md +1 -1
  15. package/dist/builtin/subagents/agents/worker.md +1 -1
  16. package/dist/builtin/subagents/package.json +6 -5
  17. package/dist/builtin/subagents/src/agents/agent-discovery.ts +17 -11
  18. package/dist/builtin/subagents/src/agents/agent-loaders.ts +115 -43
  19. package/dist/builtin/subagents/src/agents/agent-management-helpers.ts +10 -8
  20. package/dist/builtin/subagents/src/agents/agent-management.ts +8 -7
  21. package/dist/builtin/subagents/src/agents/agent-overrides.ts +2 -2
  22. package/dist/builtin/subagents/src/agents/agent-scope.ts +1 -1
  23. package/dist/builtin/subagents/src/agents/agent-selection.ts +1 -1
  24. package/dist/builtin/subagents/src/agents/agent-serializer.ts +24 -3
  25. package/dist/builtin/subagents/src/agents/agent-types.ts +3 -1
  26. package/dist/builtin/subagents/src/agents/agents.ts +7 -5
  27. package/dist/builtin/subagents/src/agents/frontmatter.ts +67 -22
  28. package/dist/builtin/subagents/src/agents/identity.ts +1 -1
  29. package/dist/builtin/subagents/src/agents/skills-paths.ts +1 -1
  30. package/dist/builtin/subagents/src/agents/skills.ts +64 -6
  31. package/dist/builtin/subagents/src/extension/config.ts +1 -1
  32. package/dist/builtin/subagents/src/extension/control-notices.ts +2 -2
  33. package/dist/builtin/subagents/src/extension/doctor.ts +15 -5
  34. package/dist/builtin/subagents/src/extension/fanout-child.ts +12 -12
  35. package/dist/builtin/subagents/src/extension/index.ts +23 -23
  36. package/dist/builtin/subagents/src/extension/notification-content.ts +1 -1
  37. package/dist/builtin/subagents/src/extension/schemas.ts +1 -1
  38. package/dist/builtin/subagents/src/extension/startup-maintenance.ts +3 -3
  39. package/dist/builtin/subagents/src/intercom/intercom-bridge.ts +3 -3
  40. package/dist/builtin/subagents/src/intercom/result-intercom.ts +1 -1
  41. package/dist/builtin/subagents/src/intercom/supervisor-authorization.ts +1 -1
  42. package/dist/builtin/subagents/src/runs/foreground/completion-notification.ts +2 -2
  43. package/dist/builtin/subagents/src/runs/foreground/execution-detach-reservations.ts +1 -1
  44. package/dist/builtin/subagents/src/runs/foreground/execution-intercom-detach.ts +3 -3
  45. package/dist/builtin/subagents/src/runs/foreground/execution-run-sync.ts +1 -1
  46. package/dist/builtin/subagents/src/runs/foreground/execution-updates.ts +2 -2
  47. package/dist/builtin/subagents/src/runs/foreground/execution-utils.ts +1 -1
  48. package/dist/builtin/subagents/src/runs/foreground/execution.ts +2 -2
  49. package/dist/builtin/subagents/src/runs/foreground/inprocess-run-sync.ts +27 -11
  50. package/dist/builtin/subagents/src/runs/foreground/notify.ts +3 -3
  51. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-context.ts +11 -11
  52. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-input.ts +3 -3
  53. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel-task.ts +15 -14
  54. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel.ts +19 -19
  55. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-runtime.ts +2 -2
  56. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-single.ts +14 -13
  57. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-status.ts +9 -9
  58. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-types.ts +7 -7
  59. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-worktree.ts +6 -6
  60. package/dist/builtin/subagents/src/runs/foreground/subagent-executor.ts +24 -23
  61. package/dist/builtin/subagents/src/runs/inprocess/control-registry.ts +1 -1
  62. package/dist/builtin/subagents/src/runs/inprocess/control-status.ts +3 -3
  63. package/dist/builtin/subagents/src/runs/inprocess/index.ts +3 -3
  64. package/dist/builtin/subagents/src/runs/inprocess/prompt-behavior.ts +17 -8
  65. package/dist/builtin/subagents/src/runs/inprocess/runner.ts +60 -12
  66. package/dist/builtin/subagents/src/runs/inprocess/runtime-support/nested-api.ts +8 -8
  67. package/dist/builtin/subagents/src/runs/inprocess/runtime-support/nested-control.ts +3 -3
  68. package/dist/builtin/subagents/src/runs/inprocess/runtime-support/nested-core.ts +4 -4
  69. package/dist/builtin/subagents/src/runs/inprocess/runtime-support/nested-projection.ts +4 -4
  70. package/dist/builtin/subagents/src/runs/inprocess/runtime-support/nested-registry.ts +5 -5
  71. package/dist/builtin/subagents/src/runs/inprocess/runtime-support/nested-rendering.ts +3 -3
  72. package/dist/builtin/subagents/src/runs/inprocess/runtime-support/nested-sanitize.ts +3 -3
  73. package/dist/builtin/subagents/src/runs/inprocess.ts +1 -1
  74. package/dist/builtin/subagents/src/runs/shared/long-running-guard.ts +1 -1
  75. package/dist/builtin/subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +1 -1
  76. package/dist/builtin/subagents/src/runs/shared/model-candidate-filter.ts +3 -3
  77. package/dist/builtin/subagents/src/runs/shared/model-fallback.ts +2 -2
  78. package/dist/builtin/subagents/src/runs/shared/parallel-utils.ts +1 -1
  79. package/dist/builtin/subagents/src/runs/shared/single-output.ts +1 -1
  80. package/dist/builtin/subagents/src/runs/shared/subagent-control.ts +1 -1
  81. package/dist/builtin/subagents/src/shared/artifacts.ts +2 -2
  82. package/dist/builtin/subagents/src/shared/event-jsonl-writer.ts +1 -1
  83. package/dist/builtin/subagents/src/shared/fast-mode.ts +1 -1
  84. package/dist/builtin/subagents/src/shared/formatters.ts +2 -2
  85. package/dist/builtin/subagents/src/shared/jsonl-writer.ts +1 -1
  86. package/dist/builtin/subagents/src/shared/model-resolution.ts +1 -1
  87. package/dist/builtin/subagents/src/shared/session-tokens.ts +1 -1
  88. package/dist/builtin/subagents/src/shared/settings.ts +4 -4
  89. package/dist/builtin/subagents/src/shared/status-format.ts +1 -1
  90. package/dist/builtin/subagents/src/shared/types-config.ts +16 -4
  91. package/dist/builtin/subagents/src/shared/types-depth.ts +1 -1
  92. package/dist/builtin/subagents/src/shared/types-nested.ts +1 -1
  93. package/dist/builtin/subagents/src/shared/types-output.ts +1 -1
  94. package/dist/builtin/subagents/src/shared/types-results.ts +1 -1
  95. package/dist/builtin/subagents/src/shared/types-runtime.ts +1 -1
  96. package/dist/builtin/subagents/src/shared/types.ts +6 -6
  97. package/dist/builtin/subagents/src/shared/utils.ts +3 -3
  98. package/dist/builtin/subagents/src/slash/prompt-template-bridge.ts +1 -1
  99. package/dist/builtin/subagents/src/slash/slash-bridge.ts +3 -3
  100. package/dist/builtin/subagents/src/slash/slash-commands.ts +6 -6
  101. package/dist/builtin/subagents/src/slash/slash-live-state.ts +3 -3
  102. package/dist/builtin/subagents/src/tui/render-event-formatting.ts +2 -2
  103. package/dist/builtin/subagents/src/tui/render-layout.ts +1 -1
  104. package/dist/builtin/subagents/src/tui/render-progress.ts +2 -2
  105. package/dist/builtin/subagents/src/tui/render-result-compact.ts +7 -7
  106. package/dist/builtin/subagents/src/tui/render-result.ts +10 -10
  107. package/dist/builtin/subagents/src/tui/render-stable-output.ts +1 -1
  108. package/dist/builtin/subagents/src/tui/render-status-progress.ts +5 -5
  109. package/dist/builtin/subagents/src/tui/render.ts +4 -4
  110. package/dist/builtin/web-access/package.json +2 -2
  111. package/dist/builtin/workflows/CHANGELOG.md +57 -0
  112. package/dist/builtin/workflows/README.md +39 -8
  113. package/dist/builtin/workflows/builtin/adversarial-verification-runner.ts +16 -5
  114. package/dist/builtin/workflows/builtin/adversarial-verification.ts +4 -0
  115. package/dist/builtin/workflows/builtin/classify-and-act.ts +4 -0
  116. package/dist/builtin/workflows/builtin/fan-out-and-synthesize.ts +4 -0
  117. package/dist/builtin/workflows/builtin/generate-and-filter-runner.ts +12 -4
  118. package/dist/builtin/workflows/builtin/generate-and-filter.ts +4 -0
  119. package/dist/builtin/workflows/builtin/goal-models.ts +8 -10
  120. package/dist/builtin/workflows/builtin/goal.ts +4 -0
  121. package/dist/builtin/workflows/builtin/index.d.ts +0 -4
  122. package/dist/builtin/workflows/builtin/loop-until-done-runner.ts +4 -2
  123. package/dist/builtin/workflows/builtin/loop-until-done.ts +4 -0
  124. package/dist/builtin/workflows/builtin/open-claude-design-live-protocol.ts +305 -0
  125. package/dist/builtin/workflows/builtin/open-claude-design-phases.ts +115 -171
  126. package/dist/builtin/workflows/builtin/open-claude-design-runner.ts +9 -25
  127. package/dist/builtin/workflows/builtin/open-claude-design-setup.ts +19 -86
  128. package/dist/builtin/workflows/builtin/open-claude-design-utils.ts +0 -6
  129. package/dist/builtin/workflows/builtin/open-claude-design.d.ts +0 -5
  130. package/dist/builtin/workflows/builtin/open-claude-design.ts +11 -15
  131. package/dist/builtin/workflows/builtin/ralph-models.ts +24 -29
  132. package/dist/builtin/workflows/builtin/ralph.ts +4 -0
  133. package/dist/builtin/workflows/builtin/tournament-runner.ts +6 -3
  134. package/dist/builtin/workflows/builtin/tournament.ts +4 -0
  135. package/dist/builtin/workflows/package.json +2 -2
  136. package/dist/builtin/workflows/skills/impeccable/SKILL.md +3 -3
  137. package/dist/builtin/workflows/skills/impeccable/agents/impeccable_asset_producer.toml +25 -31
  138. package/dist/builtin/workflows/skills/impeccable/agents/impeccable_documenter.toml +1 -0
  139. package/dist/builtin/workflows/skills/impeccable/agents/impeccable_finish_reviewer.toml +16 -10
  140. package/dist/builtin/workflows/skills/impeccable/agents/impeccable_manual_edit_applier.toml +2 -2
  141. package/dist/builtin/workflows/skills/impeccable/reference/android.md +6 -0
  142. package/dist/builtin/workflows/skills/impeccable/reference/animate.md +3 -0
  143. package/dist/builtin/workflows/skills/impeccable/reference/bolder.md +3 -1
  144. package/dist/builtin/workflows/skills/impeccable/reference/craft-floor.md +6 -1
  145. package/dist/builtin/workflows/skills/impeccable/reference/critique.md +18 -2
  146. package/dist/builtin/workflows/skills/impeccable/reference/degraded/asset-producer.md +24 -30
  147. package/dist/builtin/workflows/skills/impeccable/reference/degraded/documenter.md +1 -0
  148. package/dist/builtin/workflows/skills/impeccable/reference/degraded/finish-reviewer.md +16 -10
  149. package/dist/builtin/workflows/skills/impeccable/reference/degraded/manual-edit-applier.md +2 -2
  150. package/dist/builtin/workflows/skills/impeccable/reference/distill.md +1 -1
  151. package/dist/builtin/workflows/skills/impeccable/reference/doctor.md +1 -0
  152. package/dist/builtin/workflows/skills/impeccable/reference/document.md +1 -1
  153. package/dist/builtin/workflows/skills/impeccable/reference/extract.md +1 -1
  154. package/dist/builtin/workflows/skills/impeccable/reference/hooks.md +12 -6
  155. package/dist/builtin/workflows/skills/impeccable/reference/init.md +12 -3
  156. package/dist/builtin/workflows/skills/impeccable/reference/ios.md +6 -0
  157. package/dist/builtin/workflows/skills/impeccable/reference/live-setup.md +102 -0
  158. package/dist/builtin/workflows/skills/impeccable/reference/live.md +113 -521
  159. package/dist/builtin/workflows/skills/impeccable/reference/new-work.md +39 -26
  160. package/dist/builtin/workflows/skills/impeccable/reference/overdrive.md +1 -1
  161. package/dist/builtin/workflows/skills/impeccable/reference/polish.md +3 -3
  162. package/dist/builtin/workflows/skills/impeccable/reference/quieter.md +1 -1
  163. package/dist/builtin/workflows/skills/impeccable/reference/visualize.md +25 -11
  164. package/dist/builtin/workflows/skills/impeccable/scripts/concept-seed.mjs +332 -221
  165. package/dist/builtin/workflows/skills/impeccable/scripts/context-signals.mjs +10 -19
  166. package/dist/builtin/workflows/skills/impeccable/scripts/context.mjs +91 -38
  167. package/dist/builtin/workflows/skills/impeccable/scripts/critique-storage.mjs +19 -10
  168. package/dist/builtin/workflows/skills/impeccable/scripts/detector/browser/injected/index.mjs +56 -6
  169. package/dist/builtin/workflows/skills/impeccable/scripts/detector/cli/main.mjs +10 -16
  170. package/dist/builtin/workflows/skills/impeccable/scripts/detector/design-system.mjs +140 -2
  171. package/dist/builtin/workflows/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +1174 -694
  172. package/dist/builtin/workflows/skills/impeccable/scripts/detector/detect-antipatterns.mjs +1 -0
  173. package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/browser/detect-url.mjs +5 -1
  174. package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs +431 -45
  175. package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/static-html/css-cascade.mjs +10 -1
  176. package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/static-html/detect-html.mjs +47 -6
  177. package/dist/builtin/workflows/skills/impeccable/scripts/detector/node/file-system.mjs +23 -22
  178. package/dist/builtin/workflows/skills/impeccable/scripts/detector/registry/antipatterns.mjs +0 -10
  179. package/dist/builtin/workflows/skills/impeccable/scripts/detector/rules/checks.mjs +384 -384
  180. package/dist/builtin/workflows/skills/impeccable/scripts/detector/shared/color.mjs +466 -2
  181. package/dist/builtin/workflows/skills/impeccable/scripts/doctor.mjs +2 -0
  182. package/dist/builtin/workflows/skills/impeccable/scripts/embed-prompt.mjs +270 -0
  183. package/dist/builtin/workflows/skills/impeccable/scripts/generate-image.mjs +51 -6
  184. package/dist/builtin/workflows/skills/impeccable/scripts/hook-admin.mjs +70 -10
  185. package/dist/builtin/workflows/skills/impeccable/scripts/hook-lib.mjs +336 -90
  186. package/dist/builtin/workflows/skills/impeccable/scripts/lib/composition-catalog.mjs +38 -3
  187. package/dist/builtin/workflows/skills/impeccable/scripts/lib/concept-catalog.mjs +77 -11
  188. package/dist/builtin/workflows/skills/impeccable/scripts/lib/design-parser.mjs +102 -19
  189. package/dist/builtin/workflows/skills/impeccable/scripts/lib/impeccable-config.mjs +44 -59
  190. package/dist/builtin/workflows/skills/impeccable/scripts/lib/is-generated.mjs +3 -0
  191. package/dist/builtin/workflows/skills/impeccable/scripts/lib/open-system-browser.mjs +57 -0
  192. package/dist/builtin/workflows/skills/impeccable/scripts/lib/roll-selection.mjs +369 -0
  193. package/dist/builtin/workflows/skills/impeccable/scripts/lib/staleness-deep.mjs +31 -3
  194. package/dist/builtin/workflows/skills/impeccable/scripts/lib/staleness.mjs +73 -2
  195. package/dist/builtin/workflows/skills/impeccable/scripts/live/accept-css.mjs +617 -0
  196. package/dist/builtin/workflows/skills/impeccable/scripts/live/accept-verify.mjs +71 -0
  197. package/dist/builtin/workflows/skills/impeccable/scripts/live/browser-script-parts.mjs +29 -2
  198. package/dist/builtin/workflows/skills/impeccable/scripts/live/event-validation.mjs +54 -7
  199. package/dist/builtin/workflows/skills/impeccable/scripts/live/frameworks/astro.mjs +47 -0
  200. package/dist/builtin/workflows/skills/impeccable/scripts/live/frameworks/detect-utils.mjs +157 -0
  201. package/dist/builtin/workflows/skills/impeccable/scripts/live/frameworks/index.mjs +143 -0
  202. package/dist/builtin/workflows/skills/impeccable/scripts/live/frameworks/journal.mjs +205 -0
  203. package/dist/builtin/workflows/skills/impeccable/scripts/live/frameworks/nextjs.mjs +49 -0
  204. package/dist/builtin/workflows/skills/impeccable/scripts/live/frameworks/nuxt.mjs +170 -0
  205. package/dist/builtin/workflows/skills/impeccable/scripts/live/frameworks/script-src.mjs +26 -0
  206. package/dist/builtin/workflows/skills/impeccable/scripts/live/frameworks/static-html.mjs +26 -0
  207. package/dist/builtin/workflows/skills/impeccable/scripts/live/frameworks/sveltekit.mjs +71 -0
  208. package/dist/builtin/workflows/skills/impeccable/scripts/live/frameworks/tag-strategy.mjs +247 -0
  209. package/dist/builtin/workflows/skills/impeccable/scripts/live/frameworks/tanstack-start.mjs +70 -0
  210. package/dist/builtin/workflows/skills/impeccable/scripts/live/frameworks/vite-generic.mjs +42 -0
  211. package/dist/builtin/workflows/skills/impeccable/scripts/live/instructions.mjs +169 -0
  212. package/dist/builtin/workflows/skills/impeccable/scripts/live/roots.mjs +670 -0
  213. package/dist/builtin/workflows/skills/impeccable/scripts/live/session-store.mjs +232 -35
  214. package/dist/builtin/workflows/skills/impeccable/scripts/live/svelte-ast.mjs +969 -0
  215. package/dist/builtin/workflows/skills/impeccable/scripts/live/svelte-component.mjs +621 -74
  216. package/dist/builtin/workflows/skills/impeccable/scripts/live/sveltekit-adapter.mjs +66 -28
  217. package/dist/builtin/workflows/skills/impeccable/scripts/live/tanstack-adapter.mjs +12 -12
  218. package/dist/builtin/workflows/skills/impeccable/scripts/live/ui-surfaces.mjs +75 -0
  219. package/dist/builtin/workflows/skills/impeccable/scripts/live/vocabulary.mjs +135 -0
  220. package/dist/builtin/workflows/skills/impeccable/scripts/live-accept.mjs +23 -37
  221. package/dist/builtin/workflows/skills/impeccable/scripts/live-browser.js +945 -115
  222. package/dist/builtin/workflows/skills/impeccable/scripts/live-complete.mjs +33 -1
  223. package/dist/builtin/workflows/skills/impeccable/scripts/live-copy-edit-agent.mjs +132 -15
  224. package/dist/builtin/workflows/skills/impeccable/scripts/live-inject.mjs +173 -425
  225. package/dist/builtin/workflows/skills/impeccable/scripts/live-insert.mjs +2 -0
  226. package/dist/builtin/workflows/skills/impeccable/scripts/live-poll.mjs +16 -3
  227. package/dist/builtin/workflows/skills/impeccable/scripts/live-resume.mjs +39 -10
  228. package/dist/builtin/workflows/skills/impeccable/scripts/live-server.mjs +194 -27
  229. package/dist/builtin/workflows/skills/impeccable/scripts/live-status.mjs +10 -4
  230. package/dist/builtin/workflows/skills/impeccable/scripts/live-wrap.mjs +50 -31
  231. package/dist/builtin/workflows/skills/impeccable/scripts/live.mjs +91 -28
  232. package/dist/builtin/workflows/skills/impeccable/scripts/pin.mjs +8 -5
  233. package/dist/builtin/workflows/skills/impeccable/scripts/serve-question.mjs +759 -109
  234. package/dist/builtin/workflows/src/authoring/workflow.ts +9 -0
  235. package/dist/builtin/workflows/src/authoring.d.ts +3 -0
  236. package/dist/builtin/workflows/src/durable/completed-catalog.ts +23 -2
  237. package/dist/builtin/workflows/src/durable/dbos-backend.ts +30 -17
  238. package/dist/builtin/workflows/src/durable/dbos-envelope.ts +14 -0
  239. package/dist/builtin/workflows/src/durable/dbos-lifecycle.ts +60 -57
  240. package/dist/builtin/workflows/src/durable/dbos-process-owner.ts +87 -0
  241. package/dist/builtin/workflows/src/durable/dbos-registration-diagnostics.ts +113 -0
  242. package/dist/builtin/workflows/src/durable/factory.ts +11 -8
  243. package/dist/builtin/workflows/src/durable/tool-failure-checkpoint.ts +5 -0
  244. package/dist/builtin/workflows/src/durable/tool-primitive.ts +186 -20
  245. package/dist/builtin/workflows/src/durable/types.ts +4 -0
  246. package/dist/builtin/workflows/src/durable/workflow-heartbeat-anchor.ts +153 -0
  247. package/dist/builtin/workflows/src/engine/run-durable-stage-session.ts +28 -0
  248. package/dist/builtin/workflows/src/engine/run-tool-control-registry.ts +9 -1
  249. package/dist/builtin/workflows/src/engine/run.ts +1 -0
  250. package/dist/builtin/workflows/src/extension/adopt-session-run-state.ts +20 -0
  251. package/dist/builtin/workflows/src/extension/background-ui-adapter.ts +9 -30
  252. package/dist/builtin/workflows/src/extension/extension-factory.ts +3 -0
  253. package/dist/builtin/workflows/src/extension/extension-lifecycle.ts +28 -10
  254. package/dist/builtin/workflows/src/extension/extension-runtime-state.ts +138 -0
  255. package/dist/builtin/workflows/src/extension/index.bundle.mjs +3365 -1341
  256. package/dist/builtin/workflows/src/extension/workflow-heartbeat-delivery.ts +197 -0
  257. package/dist/builtin/workflows/src/extension/workflow-heartbeat-notice.ts +115 -0
  258. package/dist/builtin/workflows/src/extension/workflow-heartbeat-scheduler.ts +962 -0
  259. package/dist/builtin/workflows/src/extension/workflow-prompts.ts +4 -1
  260. package/dist/builtin/workflows/src/extension/workflow-schema.ts +29 -5
  261. package/dist/builtin/workflows/src/extension/workflow-tool-send.ts +32 -1
  262. package/dist/builtin/workflows/src/runs/background/cancellation-registry.ts +10 -1
  263. package/dist/builtin/workflows/src/runs/background/job-tracker.ts +10 -1
  264. package/dist/builtin/workflows/src/runs/foreground/executor-prompt-nodes.ts +16 -11
  265. package/dist/builtin/workflows/src/runs/foreground/stage-control-registry.ts +31 -1
  266. package/dist/builtin/workflows/src/runs/foreground/stage-runner-context.ts +41 -10
  267. package/dist/builtin/workflows/src/runs/foreground/stage-runner-messages.ts +48 -0
  268. package/dist/builtin/workflows/src/runs/foreground/stage-runner-output.ts +4 -1
  269. package/dist/builtin/workflows/src/runs/foreground/stage-runner-structured-output.ts +45 -12
  270. package/dist/builtin/workflows/src/sdk-surface.ts +9 -0
  271. package/dist/builtin/workflows/src/shared/authoring-contract-ui.d.ts +10 -0
  272. package/dist/builtin/workflows/src/shared/authoring-contract-ui.ts +10 -0
  273. package/dist/builtin/workflows/src/shared/graph-store-snapshot.ts +14 -2
  274. package/dist/builtin/workflows/src/shared/persistence-restore.ts +12 -0
  275. package/dist/builtin/workflows/src/shared/prompt-answer.ts +130 -0
  276. package/dist/builtin/workflows/src/shared/session-scoped-singleton.ts +98 -0
  277. package/dist/builtin/workflows/src/shared/stage-ui-broker.ts +9 -1
  278. package/dist/builtin/workflows/src/shared/store-factory.ts +9 -1
  279. package/dist/builtin/workflows/src/shared/store-public-types.ts +2 -1
  280. package/dist/builtin/workflows/src/shared/store-tool-node-methods.ts +7 -0
  281. package/dist/builtin/workflows/src/shared/store-types.ts +18 -1
  282. package/dist/builtin/workflows/src/shared/tool-payload-bounds.ts +576 -0
  283. package/dist/builtin/workflows/src/shared/workflow-authoring-types.d.ts +1 -0
  284. package/dist/builtin/workflows/src/shared/workflow-authoring-types.ts +1 -0
  285. package/dist/builtin/workflows/src/shared/workflow-heartbeat-contract.d.ts +21 -0
  286. package/dist/builtin/workflows/src/shared/workflow-heartbeat-contract.ts +25 -0
  287. package/dist/builtin/workflows/src/tui/graph-theme.ts +8 -1
  288. package/dist/builtin/workflows/src/tui/graph-view-constants.ts +11 -0
  289. package/dist/builtin/workflows/src/tui/graph-view-input.ts +100 -5
  290. package/dist/builtin/workflows/src/tui/graph-view-layout.ts +42 -11
  291. package/dist/builtin/workflows/src/tui/graph-view-render-helpers.ts +55 -6
  292. package/dist/builtin/workflows/src/tui/graph-view-render.ts +71 -6
  293. package/dist/builtin/workflows/src/tui/graph-view-state.ts +43 -0
  294. package/dist/builtin/workflows/src/tui/keybindings-adapter.ts +2 -0
  295. package/dist/builtin/workflows/src/tui/node-card.ts +5 -1
  296. package/dist/builtin/workflows/src/tui/stage-chat-view-archive-history.ts +11 -2
  297. package/dist/builtin/workflows/src/tui/stage-chat-view.ts +36 -10
  298. package/dist/builtin/workflows/src/tui/switcher.ts +11 -4
  299. package/dist/builtin/workflows/src/tui/tool-detail.ts +348 -0
  300. package/dist/builtin/workflows/src/tui/workflow-status.ts +5 -2
  301. package/dist/cli/args.d.ts +1 -0
  302. package/dist/cli/args.d.ts.map +1 -1
  303. package/dist/cli/args.js +11 -0
  304. package/dist/cli/args.js.map +1 -1
  305. package/dist/cli/auth-check.d.ts +1 -1
  306. package/dist/cli/auth-check.js.map +1 -1
  307. package/dist/cli/credential-print.d.ts +1 -1
  308. package/dist/cli/credential-print.js.map +1 -1
  309. package/dist/cli/list-models.d.ts +1 -1
  310. package/dist/cli/list-models.js.map +1 -1
  311. package/dist/cli/startup-ui.d.ts +9 -0
  312. package/dist/cli/startup-ui.d.ts.map +1 -1
  313. package/dist/cli/startup-ui.js +7 -1
  314. package/dist/cli/startup-ui.js.map +1 -1
  315. package/dist/core/agent-session-custom-message-commit.js +2 -2
  316. package/dist/core/agent-session-custom-message-commit.js.map +1 -1
  317. package/dist/core/agent-session-export.d.ts +6 -1
  318. package/dist/core/agent-session-export.d.ts.map +1 -1
  319. package/dist/core/agent-session-export.js +6 -3
  320. package/dist/core/agent-session-export.js.map +1 -1
  321. package/dist/core/agent-session-extension-bindings.d.ts.map +1 -1
  322. package/dist/core/agent-session-extension-bindings.js +6 -4
  323. package/dist/core/agent-session-extension-bindings.js.map +1 -1
  324. package/dist/core/agent-session-methods.d.ts +5 -2
  325. package/dist/core/agent-session-methods.d.ts.map +1 -1
  326. package/dist/core/agent-session-methods.js.map +1 -1
  327. package/dist/core/agent-session-prompt.d.ts +12 -1
  328. package/dist/core/agent-session-prompt.d.ts.map +1 -1
  329. package/dist/core/agent-session-prompt.js +31 -10
  330. package/dist/core/agent-session-prompt.js.map +1 -1
  331. package/dist/core/agent-session-runtime-auth.js.map +1 -1
  332. package/dist/core/agent-session-services.d.ts +1 -1
  333. package/dist/core/agent-session-services.js.map +1 -1
  334. package/dist/core/agent-session-skill-block.d.ts +1 -0
  335. package/dist/core/agent-session-skill-block.d.ts.map +1 -1
  336. package/dist/core/agent-session-skill-block.js +18 -2
  337. package/dist/core/agent-session-skill-block.js.map +1 -1
  338. package/dist/core/agent-session-state.d.ts.map +1 -1
  339. package/dist/core/agent-session-state.js +2 -1
  340. package/dist/core/agent-session-state.js.map +1 -1
  341. package/dist/core/agent-session-types.d.ts +2 -1
  342. package/dist/core/agent-session-types.d.ts.map +1 -1
  343. package/dist/core/agent-session-types.js.map +1 -1
  344. package/dist/core/agent-session.d.ts +1 -1
  345. package/dist/core/agent-session.js.map +1 -1
  346. package/dist/core/atomic-guide-command.js +2 -2
  347. package/dist/core/atomic-guide-command.js.map +1 -1
  348. package/dist/core/builtin-packages.d.ts.map +1 -1
  349. package/dist/core/builtin-packages.js +0 -6
  350. package/dist/core/builtin-packages.js.map +1 -1
  351. package/dist/core/cloudflare-gateway-binding.d.ts +11 -0
  352. package/dist/core/cloudflare-gateway-binding.d.ts.map +1 -0
  353. package/dist/core/cloudflare-gateway-binding.js +11 -0
  354. package/dist/core/cloudflare-gateway-binding.js.map +1 -0
  355. package/dist/core/codex-fast-mode-transport.d.ts +12 -0
  356. package/dist/core/codex-fast-mode-transport.d.ts.map +1 -0
  357. package/dist/core/codex-fast-mode-transport.js +130 -0
  358. package/dist/core/codex-fast-mode-transport.js.map +1 -0
  359. package/dist/core/codex-fast-mode.d.ts +20 -6
  360. package/dist/core/codex-fast-mode.d.ts.map +1 -1
  361. package/dist/core/codex-fast-mode.js +111 -3
  362. package/dist/core/codex-fast-mode.js.map +1 -1
  363. package/dist/core/diagnostics.d.ts +4 -0
  364. package/dist/core/diagnostics.d.ts.map +1 -1
  365. package/dist/core/diagnostics.js.map +1 -1
  366. package/dist/core/event-bus.d.ts +12 -0
  367. package/dist/core/event-bus.d.ts.map +1 -1
  368. package/dist/core/event-bus.js +22 -0
  369. package/dist/core/event-bus.js.map +1 -1
  370. package/dist/core/experimental.d.ts +25 -0
  371. package/dist/core/experimental.d.ts.map +1 -1
  372. package/dist/core/experimental.js +24 -0
  373. package/dist/core/experimental.js.map +1 -1
  374. package/dist/core/export-html/template-js/tree-filter-render.js +4 -3
  375. package/dist/core/export-html/template.js +4 -3
  376. package/dist/core/extension-session-state.d.ts +28 -0
  377. package/dist/core/extension-session-state.d.ts.map +1 -0
  378. package/dist/core/extension-session-state.js +55 -0
  379. package/dist/core/extension-session-state.js.map +1 -0
  380. package/dist/core/extensions/api-types.d.ts +6 -0
  381. package/dist/core/extensions/api-types.d.ts.map +1 -1
  382. package/dist/core/extensions/api-types.js.map +1 -1
  383. package/dist/core/extensions/context-types.d.ts +4 -0
  384. package/dist/core/extensions/context-types.d.ts.map +1 -1
  385. package/dist/core/extensions/context-types.js.map +1 -1
  386. package/dist/core/extensions/index.d.ts +1 -0
  387. package/dist/core/extensions/index.d.ts.map +1 -1
  388. package/dist/core/extensions/index.js +1 -0
  389. package/dist/core/extensions/index.js.map +1 -1
  390. package/dist/core/extensions/loader-api.d.ts +1 -1
  391. package/dist/core/extensions/loader-api.d.ts.map +1 -1
  392. package/dist/core/extensions/loader-api.js +16 -10
  393. package/dist/core/extensions/loader-api.js.map +1 -1
  394. package/dist/core/extensions/loader-virtual-modules.d.ts.map +1 -1
  395. package/dist/core/extensions/loader-virtual-modules.js +12 -1
  396. package/dist/core/extensions/loader-virtual-modules.js.map +1 -1
  397. package/dist/core/extensions/runner-context.d.ts +2 -0
  398. package/dist/core/extensions/runner-context.d.ts.map +1 -1
  399. package/dist/core/extensions/runner-context.js +8 -0
  400. package/dist/core/extensions/runner-context.js.map +1 -1
  401. package/dist/core/extensions/runner.d.ts +1 -0
  402. package/dist/core/extensions/runner.d.ts.map +1 -1
  403. package/dist/core/extensions/runner.js +3 -0
  404. package/dist/core/extensions/runner.js.map +1 -1
  405. package/dist/core/extensions/runtime-types.d.ts +3 -0
  406. package/dist/core/extensions/runtime-types.d.ts.map +1 -1
  407. package/dist/core/extensions/runtime-types.js.map +1 -1
  408. package/dist/core/extensions/ui-types.d.ts +26 -0
  409. package/dist/core/extensions/ui-types.d.ts.map +1 -1
  410. package/dist/core/extensions/ui-types.js +17 -1
  411. package/dist/core/extensions/ui-types.js.map +1 -1
  412. package/dist/core/http-dispatcher.d.ts.map +1 -1
  413. package/dist/core/http-dispatcher.js +5 -0
  414. package/dist/core/http-dispatcher.js.map +1 -1
  415. package/dist/core/keybindings.d.ts +24 -0
  416. package/dist/core/keybindings.d.ts.map +1 -1
  417. package/dist/core/keybindings.js +6 -0
  418. package/dist/core/keybindings.js.map +1 -1
  419. package/dist/core/model-config.d.ts +5 -0
  420. package/dist/core/model-config.d.ts.map +1 -1
  421. package/dist/core/model-config.js +1 -0
  422. package/dist/core/model-config.js.map +1 -1
  423. package/dist/core/model-registry.d.ts +1 -1
  424. package/dist/core/model-registry.js.map +1 -1
  425. package/dist/core/model-resolver-cli.d.ts +1 -1
  426. package/dist/core/model-resolver-cli.js.map +1 -1
  427. package/dist/core/model-resolver-defaults.js +3 -3
  428. package/dist/core/model-resolver-defaults.js.map +1 -1
  429. package/dist/core/model-resolver-initial.d.ts +1 -1
  430. package/dist/core/model-resolver-initial.js.map +1 -1
  431. package/dist/core/model-resolver-scope.d.ts +1 -1
  432. package/dist/core/model-resolver-scope.js.map +1 -1
  433. package/dist/core/model-runtime.d.ts +54 -0
  434. package/dist/core/model-runtime.d.ts.map +1 -1
  435. package/dist/core/model-runtime.js +96 -13
  436. package/dist/core/model-runtime.js.map +1 -1
  437. package/dist/core/oauth-login.js.map +1 -1
  438. package/dist/core/project-trust.d.ts +10 -0
  439. package/dist/core/project-trust.d.ts.map +1 -1
  440. package/dist/core/project-trust.js +12 -0
  441. package/dist/core/project-trust.js.map +1 -1
  442. package/dist/core/resource-loader-assets.d.ts.map +1 -1
  443. package/dist/core/resource-loader-assets.js +14 -5
  444. package/dist/core/resource-loader-assets.js.map +1 -1
  445. package/dist/core/resource-loader-core.d.ts +3 -0
  446. package/dist/core/resource-loader-core.d.ts.map +1 -1
  447. package/dist/core/resource-loader-core.js +5 -0
  448. package/dist/core/resource-loader-core.js.map +1 -1
  449. package/dist/core/resource-loader-internals.d.ts +2 -0
  450. package/dist/core/resource-loader-internals.d.ts.map +1 -1
  451. package/dist/core/resource-loader-internals.js.map +1 -1
  452. package/dist/core/resource-loader-reload.d.ts.map +1 -1
  453. package/dist/core/resource-loader-reload.js +2 -0
  454. package/dist/core/resource-loader-reload.js.map +1 -1
  455. package/dist/core/resource-loader-types.d.ts +2 -0
  456. package/dist/core/resource-loader-types.d.ts.map +1 -1
  457. package/dist/core/resource-loader-types.js.map +1 -1
  458. package/dist/core/resource-loader.d.ts +2 -0
  459. package/dist/core/resource-loader.d.ts.map +1 -1
  460. package/dist/core/resource-loader.js +1 -0
  461. package/dist/core/resource-loader.js.map +1 -1
  462. package/dist/core/sdk-types.d.ts +7 -6
  463. package/dist/core/sdk-types.d.ts.map +1 -1
  464. package/dist/core/sdk-types.js.map +1 -1
  465. package/dist/core/sdk.d.ts.map +1 -1
  466. package/dist/core/sdk.js +17 -6
  467. package/dist/core/sdk.js.map +1 -1
  468. package/dist/core/session-manager-core.d.ts +7 -1
  469. package/dist/core/session-manager-core.d.ts.map +1 -1
  470. package/dist/core/session-manager-core.js +11 -2
  471. package/dist/core/session-manager-core.js.map +1 -1
  472. package/dist/core/session-manager-entries.d.ts +2 -2
  473. package/dist/core/session-manager-entries.d.ts.map +1 -1
  474. package/dist/core/session-manager-entries.js +6 -4
  475. package/dist/core/session-manager-entries.js.map +1 -1
  476. package/dist/core/session-manager-list.d.ts.map +1 -1
  477. package/dist/core/session-manager-list.js +5 -1
  478. package/dist/core/session-manager-list.js.map +1 -1
  479. package/dist/core/session-manager-types.d.ts +25 -2
  480. package/dist/core/session-manager-types.d.ts.map +1 -1
  481. package/dist/core/session-manager-types.js.map +1 -1
  482. package/dist/core/session-manager.d.ts +1 -1
  483. package/dist/core/session-manager.d.ts.map +1 -1
  484. package/dist/core/session-manager.js.map +1 -1
  485. package/dist/core/settings-manager-basic-accessors.d.ts +1 -0
  486. package/dist/core/settings-manager-basic-accessors.d.ts.map +1 -1
  487. package/dist/core/settings-manager-basic-accessors.js +8 -0
  488. package/dist/core/settings-manager-basic-accessors.js.map +1 -1
  489. package/dist/core/settings-manager-ui-accessors.d.ts +3 -1
  490. package/dist/core/settings-manager-ui-accessors.d.ts.map +1 -1
  491. package/dist/core/settings-manager-ui-accessors.js +9 -0
  492. package/dist/core/settings-manager-ui-accessors.js.map +1 -1
  493. package/dist/core/settings-manager.d.ts +1 -1
  494. package/dist/core/settings-manager.d.ts.map +1 -1
  495. package/dist/core/settings-manager.js.map +1 -1
  496. package/dist/core/settings-types.d.ts +4 -0
  497. package/dist/core/settings-types.d.ts.map +1 -1
  498. package/dist/core/settings-types.js.map +1 -1
  499. package/dist/core/skill-catalog.d.ts +35 -0
  500. package/dist/core/skill-catalog.d.ts.map +1 -0
  501. package/dist/core/skill-catalog.js +264 -0
  502. package/dist/core/skill-catalog.js.map +1 -0
  503. package/dist/core/skills-async.d.ts.map +1 -1
  504. package/dist/core/skills-async.js +12 -6
  505. package/dist/core/skills-async.js.map +1 -1
  506. package/dist/core/skills.d.ts +2 -0
  507. package/dist/core/skills.d.ts.map +1 -1
  508. package/dist/core/skills.js +8 -5
  509. package/dist/core/skills.js.map +1 -1
  510. package/dist/core/slash-commands.d.ts.map +1 -1
  511. package/dist/core/slash-commands.js +1 -5
  512. package/dist/core/slash-commands.js.map +1 -1
  513. package/dist/core/system-prompt.js +2 -2
  514. package/dist/core/system-prompt.js.map +1 -1
  515. package/dist/core/tools/ask-user-question/ask-user-question.d.ts +25 -2
  516. package/dist/core/tools/ask-user-question/ask-user-question.d.ts.map +1 -1
  517. package/dist/core/tools/ask-user-question/ask-user-question.js +47 -18
  518. package/dist/core/tools/ask-user-question/ask-user-question.js.map +1 -1
  519. package/dist/core/tools/ask-user-question/view/components/multi-select-view.d.ts.map +1 -1
  520. package/dist/core/tools/ask-user-question/view/components/multi-select-view.js +5 -2
  521. package/dist/core/tools/ask-user-question/view/components/multi-select-view.js.map +1 -1
  522. package/dist/core/tools/ask-user-question/view/components/submit-picker.d.ts.map +1 -1
  523. package/dist/core/tools/ask-user-question/view/components/submit-picker.js +3 -1
  524. package/dist/core/tools/ask-user-question/view/components/submit-picker.js.map +1 -1
  525. package/dist/core/tools/ask-user-question/view/components/wrapping-select.d.ts.map +1 -1
  526. package/dist/core/tools/ask-user-question/view/components/wrapping-select.js +8 -1
  527. package/dist/core/tools/ask-user-question/view/components/wrapping-select.js.map +1 -1
  528. package/dist/core/tools/bash.d.ts.map +1 -1
  529. package/dist/core/tools/bash.js +2 -0
  530. package/dist/core/tools/bash.js.map +1 -1
  531. package/dist/core/tools/edit.d.ts.map +1 -1
  532. package/dist/core/tools/edit.js +2 -0
  533. package/dist/core/tools/edit.js.map +1 -1
  534. package/dist/core/tools/find.d.ts.map +1 -1
  535. package/dist/core/tools/find.js +3 -1
  536. package/dist/core/tools/find.js.map +1 -1
  537. package/dist/core/tools/grep.js +1 -1
  538. package/dist/core/tools/grep.js.map +1 -1
  539. package/dist/core/tools/hashline-engine/format.d.ts +2 -0
  540. package/dist/core/tools/hashline-engine/format.d.ts.map +1 -1
  541. package/dist/core/tools/hashline-engine/format.js +4 -2
  542. package/dist/core/tools/hashline-engine/format.js.map +1 -1
  543. package/dist/core/tools/hashline-engine/messages.d.ts +2 -0
  544. package/dist/core/tools/hashline-engine/messages.d.ts.map +1 -1
  545. package/dist/core/tools/hashline-engine/messages.js +4 -2
  546. package/dist/core/tools/hashline-engine/messages.js.map +1 -1
  547. package/dist/core/tools/hashline-engine/parser.d.ts.map +1 -1
  548. package/dist/core/tools/hashline-engine/parser.js +16 -4
  549. package/dist/core/tools/hashline-engine/parser.js.map +1 -1
  550. package/dist/core/tools/hashline-engine/tokenizer.d.ts.map +1 -1
  551. package/dist/core/tools/hashline-engine/tokenizer.js +37 -27
  552. package/dist/core/tools/hashline-engine/tokenizer.js.map +1 -1
  553. package/dist/core/tools/hashline.d.ts.map +1 -1
  554. package/dist/core/tools/hashline.js +8 -2
  555. package/dist/core/tools/hashline.js.map +1 -1
  556. package/dist/core/tools/ls.d.ts.map +1 -1
  557. package/dist/core/tools/ls.js +2 -0
  558. package/dist/core/tools/ls.js.map +1 -1
  559. package/dist/core/tools/read.d.ts.map +1 -1
  560. package/dist/core/tools/read.js +8 -1
  561. package/dist/core/tools/read.js.map +1 -1
  562. package/dist/core/tools/search.d.ts.map +1 -1
  563. package/dist/core/tools/search.js +2 -0
  564. package/dist/core/tools/search.js.map +1 -1
  565. package/dist/core/tools/todos.d.ts +3 -12
  566. package/dist/core/tools/todos.d.ts.map +1 -1
  567. package/dist/core/tools/todos.js +19 -4
  568. package/dist/core/tools/todos.js.map +1 -1
  569. package/dist/core/tools/write.d.ts.map +1 -1
  570. package/dist/core/tools/write.js +2 -0
  571. package/dist/core/tools/write.js.map +1 -1
  572. package/dist/index-extensions.d.ts +1 -1
  573. package/dist/index-extensions.d.ts.map +1 -1
  574. package/dist/index-extensions.js +1 -1
  575. package/dist/index-extensions.js.map +1 -1
  576. package/dist/index.d.ts +8 -5
  577. package/dist/index.d.ts.map +1 -1
  578. package/dist/index.js +6 -2
  579. package/dist/index.js.map +1 -1
  580. package/dist/main-runtime-api-key.d.ts +1 -1
  581. package/dist/main-runtime-api-key.js.map +1 -1
  582. package/dist/main-session-options.d.ts +1 -1
  583. package/dist/main-session-options.js.map +1 -1
  584. package/dist/main.d.ts.map +1 -1
  585. package/dist/main.js +10 -2
  586. package/dist/main.js.map +1 -1
  587. package/dist/modes/interactive/components/chat-session-host-rendering.js +1 -1
  588. package/dist/modes/interactive/components/chat-session-host-rendering.js.map +1 -1
  589. package/dist/modes/interactive/components/chat-session-host-state.d.ts +8 -0
  590. package/dist/modes/interactive/components/chat-session-host-state.d.ts.map +1 -1
  591. package/dist/modes/interactive/components/chat-session-host-state.js +8 -0
  592. package/dist/modes/interactive/components/chat-session-host-state.js.map +1 -1
  593. package/dist/modes/interactive/components/chat-session-host.d.ts +26 -0
  594. package/dist/modes/interactive/components/chat-session-host.d.ts.map +1 -1
  595. package/dist/modes/interactive/components/chat-session-host.js +38 -0
  596. package/dist/modes/interactive/components/chat-session-host.js.map +1 -1
  597. package/dist/modes/interactive/components/chat-transcript.d.ts +37 -0
  598. package/dist/modes/interactive/components/chat-transcript.d.ts.map +1 -1
  599. package/dist/modes/interactive/components/chat-transcript.js +54 -1
  600. package/dist/modes/interactive/components/chat-transcript.js.map +1 -1
  601. package/dist/modes/interactive/components/fast-mode-selector.js +1 -1
  602. package/dist/modes/interactive/components/fast-mode-selector.js.map +1 -1
  603. package/dist/modes/interactive/components/model-selector.d.ts +1 -1
  604. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  605. package/dist/modes/interactive/components/model-selector.js +2 -1
  606. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  607. package/dist/modes/interactive/components/oauth-selector.d.ts +1 -1
  608. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  609. package/dist/modes/interactive/components/reserved-bottom-overlay.d.ts +95 -0
  610. package/dist/modes/interactive/components/reserved-bottom-overlay.d.ts.map +1 -0
  611. package/dist/modes/interactive/components/reserved-bottom-overlay.js +234 -0
  612. package/dist/modes/interactive/components/reserved-bottom-overlay.js.map +1 -0
  613. package/dist/modes/interactive/components/session-selector-search.d.ts +4 -0
  614. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
  615. package/dist/modes/interactive/components/session-selector-search.js +4 -0
  616. package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  617. package/dist/modes/interactive/components/settings-selector-handlers.d.ts.map +1 -1
  618. package/dist/modes/interactive/components/settings-selector-handlers.js +3 -0
  619. package/dist/modes/interactive/components/settings-selector-handlers.js.map +1 -1
  620. package/dist/modes/interactive/components/settings-selector-items.d.ts.map +1 -1
  621. package/dist/modes/interactive/components/settings-selector-items.js +7 -0
  622. package/dist/modes/interactive/components/settings-selector-items.js.map +1 -1
  623. package/dist/modes/interactive/components/settings-selector-types.d.ts +3 -1
  624. package/dist/modes/interactive/components/settings-selector-types.d.ts.map +1 -1
  625. package/dist/modes/interactive/components/settings-selector-types.js.map +1 -1
  626. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  627. package/dist/modes/interactive/components/tool-execution.js +12 -1
  628. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  629. package/dist/modes/interactive/interactive-auth-login.js.map +1 -1
  630. package/dist/modes/interactive/interactive-auth-routing.js.map +1 -1
  631. package/dist/modes/interactive/interactive-autocomplete.js +5 -4
  632. package/dist/modes/interactive/interactive-autocomplete.js.map +1 -1
  633. package/dist/modes/interactive/interactive-bash-compact.d.ts.map +1 -1
  634. package/dist/modes/interactive/interactive-bash-compact.js +2 -2
  635. package/dist/modes/interactive/interactive-bash-compact.js.map +1 -1
  636. package/dist/modes/interactive/interactive-extension-custom-ui.js +94 -6
  637. package/dist/modes/interactive/interactive-extension-custom-ui.js.map +1 -1
  638. package/dist/modes/interactive/interactive-mode-base.d.ts +41 -3
  639. package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
  640. package/dist/modes/interactive/interactive-mode-base.js +80 -11
  641. package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
  642. package/dist/modes/interactive/interactive-mode-surface.d.ts +9 -1
  643. package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
  644. package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
  645. package/dist/modes/interactive/interactive-mode-types.d.ts +2 -0
  646. package/dist/modes/interactive/interactive-mode-types.d.ts.map +1 -1
  647. package/dist/modes/interactive/interactive-mode-types.js.map +1 -1
  648. package/dist/modes/interactive/interactive-model-catalog-startup.d.ts +8 -1
  649. package/dist/modes/interactive/interactive-model-catalog-startup.d.ts.map +1 -1
  650. package/dist/modes/interactive/interactive-model-catalog-startup.js +13 -3
  651. package/dist/modes/interactive/interactive-model-catalog-startup.js.map +1 -1
  652. package/dist/modes/interactive/interactive-model-routing.js +3 -4
  653. package/dist/modes/interactive/interactive-model-routing.js.map +1 -1
  654. package/dist/modes/interactive/interactive-render-chat.js +6 -0
  655. package/dist/modes/interactive/interactive-render-chat.js.map +1 -1
  656. package/dist/modes/interactive/interactive-resource-disclosure.js +2 -2
  657. package/dist/modes/interactive/interactive-resource-disclosure.js.map +1 -1
  658. package/dist/modes/interactive/interactive-selectors.js +7 -3
  659. package/dist/modes/interactive/interactive-selectors.js.map +1 -1
  660. package/dist/modes/interactive/interactive-session-runtime.js +7 -1
  661. package/dist/modes/interactive/interactive-session-runtime.js.map +1 -1
  662. package/dist/modes/interactive/interactive-slash-commands.js +2 -2
  663. package/dist/modes/interactive/interactive-slash-commands.js.map +1 -1
  664. package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
  665. package/dist/modes/interactive/interactive-startup.js +34 -9
  666. package/dist/modes/interactive/interactive-startup.js.map +1 -1
  667. package/dist/modes/interactive/interactive-tui.d.ts +21 -1
  668. package/dist/modes/interactive/interactive-tui.d.ts.map +1 -1
  669. package/dist/modes/interactive/interactive-tui.js +140 -38
  670. package/dist/modes/interactive/interactive-tui.js.map +1 -1
  671. package/dist/modes/interactive/model-catalog-refresh.d.ts +17 -0
  672. package/dist/modes/interactive/model-catalog-refresh.d.ts.map +1 -0
  673. package/dist/modes/interactive/model-catalog-refresh.js +84 -0
  674. package/dist/modes/interactive/model-catalog-refresh.js.map +1 -0
  675. package/dist/modes/interactive/theme/dark.json +2 -0
  676. package/dist/modes/interactive/theme/light.json +2 -0
  677. package/dist/modes/interactive/theme/theme-class.d.ts +12 -3
  678. package/dist/modes/interactive/theme/theme-class.d.ts.map +1 -1
  679. package/dist/modes/interactive/theme/theme-class.js +6 -1
  680. package/dist/modes/interactive/theme/theme-class.js.map +1 -1
  681. package/dist/modes/interactive/theme/theme-controller.d.ts +10 -2
  682. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  683. package/dist/modes/interactive/theme/theme-controller.js +23 -10
  684. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  685. package/dist/modes/interactive/theme/theme-loading.d.ts.map +1 -1
  686. package/dist/modes/interactive/theme/theme-loading.js +1 -0
  687. package/dist/modes/interactive/theme/theme-loading.js.map +1 -1
  688. package/dist/modes/interactive/theme/theme-schema.d.ts +8 -0
  689. package/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -1
  690. package/dist/modes/interactive/theme/theme-schema.js +3 -1
  691. package/dist/modes/interactive/theme/theme-schema.js.map +1 -1
  692. package/dist/modes/interactive/theme/theme-schema.json +9 -1
  693. package/dist/modes/interactive-engine/engine-custom-ui.d.ts +2 -0
  694. package/dist/modes/interactive-engine/engine-custom-ui.d.ts.map +1 -1
  695. package/dist/modes/interactive-engine/engine-custom-ui.js +1 -0
  696. package/dist/modes/interactive-engine/engine-custom-ui.js.map +1 -1
  697. package/dist/modes/interactive-engine/protocol.d.ts +1 -0
  698. package/dist/modes/interactive-engine/protocol.d.ts.map +1 -1
  699. package/dist/modes/interactive-engine/protocol.js +1 -0
  700. package/dist/modes/interactive-engine/protocol.js.map +1 -1
  701. package/dist/modes/interactive-engine/remote-component.d.ts +3 -1
  702. package/dist/modes/interactive-engine/remote-component.d.ts.map +1 -1
  703. package/dist/modes/interactive-engine/remote-component.js +3 -2
  704. package/dist/modes/interactive-engine/remote-component.js.map +1 -1
  705. package/dist/modes/json-event.d.ts +6 -1
  706. package/dist/modes/json-event.d.ts.map +1 -1
  707. package/dist/modes/json-event.js +17 -2
  708. package/dist/modes/json-event.js.map +1 -1
  709. package/dist/modes/rpc/rpc-client.js.map +1 -1
  710. package/dist/modes/rpc/rpc-command-handler.d.ts.map +1 -1
  711. package/dist/modes/rpc/rpc-command-handler.js +5 -4
  712. package/dist/modes/rpc/rpc-command-handler.js.map +1 -1
  713. package/dist/modes/rpc/rpc-provider-auth.js.map +1 -1
  714. package/dist/modes/rpc/rpc-responses.js.map +1 -1
  715. package/dist/modes/rpc/rpc-types.d.ts +1 -1
  716. package/dist/modes/rpc/rpc-types.js.map +1 -1
  717. package/dist/package-manager-cli.js.map +1 -1
  718. package/dist/server/create-harness.d.ts.map +1 -1
  719. package/dist/server/create-harness.js +11 -0
  720. package/dist/server/create-harness.js.map +1 -1
  721. package/dist/utils/abort.d.ts +9 -0
  722. package/dist/utils/abort.d.ts.map +1 -0
  723. package/dist/utils/abort.js +19 -0
  724. package/dist/utils/abort.js.map +1 -0
  725. package/dist/utils/tools-manager.d.ts +16 -1
  726. package/dist/utils/tools-manager.d.ts.map +1 -1
  727. package/dist/utils/tools-manager.js +19 -19
  728. package/dist/utils/tools-manager.js.map +1 -1
  729. package/docs/custom-provider.md +9 -8
  730. package/docs/development.md +0 -1
  731. package/docs/docs.json +0 -1
  732. package/docs/environment-variables.md +3 -0
  733. package/docs/extensions.md +100 -2
  734. package/docs/json.md +3 -1
  735. package/docs/keybindings.md +8 -3
  736. package/docs/models/artificial-analysis-index.md +2 -2
  737. package/docs/models/model-selection.md +32 -23
  738. package/docs/models/pareto-efficiency.md +25 -24
  739. package/docs/providers.md +95 -2
  740. package/docs/quickstart.md +4 -2
  741. package/docs/rpc.md +21 -7
  742. package/docs/sdk.md +26 -1
  743. package/docs/session-format.md +5 -2
  744. package/docs/settings.md +34 -3
  745. package/docs/skills.md +16 -1
  746. package/docs/terminal-setup.md +15 -2
  747. package/docs/themes.md +22 -4
  748. package/docs/tools.md +3 -1
  749. package/docs/tui.md +2 -0
  750. package/docs/usage.md +5 -4
  751. package/docs/workflows.md +96 -19
  752. package/npm-shrinkwrap.json +211 -232
  753. package/package.json +8 -8
  754. package/dist/builtin/i-have-adhd/CHANGELOG.md +0 -30
  755. package/dist/builtin/i-have-adhd/LICENSE +0 -21
  756. package/dist/builtin/i-have-adhd/README.md +0 -18
  757. package/dist/builtin/i-have-adhd/index.ts +0 -238
  758. package/dist/builtin/i-have-adhd/package.json +0 -56
  759. package/dist/builtin/i-have-adhd/skills/i-have-adhd/SKILL.md +0 -140
  760. package/dist/builtin/workflows/builtin/open-claude-design-feedback.ts +0 -359
  761. package/dist/builtin/workflows/skills/impeccable/scripts/live/ui-core.mjs +0 -180
  762. package/docs/i-have-adhd.md +0 -36
@@ -0,0 +1,969 @@
1
+ /**
2
+ * AST-based Svelte scaffolding for live component previews.
3
+ *
4
+ * The scaffolder turns the selected block of a route's markup into a detached
5
+ * preview component whose dynamic values arrive as props. The old
6
+ * implementation matched `{...}` with a regex, which flattened control-flow
7
+ * blocks ({#each}, {#if}) into scalar text props and shipped structurally
8
+ * wrong previews. This module uses the app's own svelte compiler
9
+ * (parse with modern: true) and replaces only expressions that are FREE,
10
+ * i.e. reference identifiers not bound by an enclosing template scope:
11
+ *
12
+ * {#each stages as stage, i} stages -> collection prop (array)
13
+ * <span>{stage.label}</span> bound -> left verbatim
14
+ * {/each}
15
+ * <p>{footerNote}</p> free -> text prop (string)
16
+ *
17
+ * Constructs that cannot work in a detached component (component tags whose
18
+ * imports live in the route file, bind:/use: directives, await blocks,
19
+ * render tags) mark the analysis unsupported; the caller falls back to
20
+ * source-preview mode, which keeps the markup inside the route file where
21
+ * those references still resolve. A wrong preview is worse than a plain one.
22
+ *
23
+ * The compiler is resolved from the APP's node_modules, never bundled: the
24
+ * preview must be parsed by the same svelte version that will compile it.
25
+ */
26
+
27
+ import { createRequire } from 'node:module';
28
+ import path from 'node:path';
29
+
30
+ const HANDLER_ATTR_RE = /^on[a-z]/;
31
+
32
+ /**
33
+ * Resolve the app's svelte compiler synchronously (svelte 5 ships a CJS
34
+ * compiler build, so createRequire works and the accept/scaffold pipeline
35
+ * stays synchronous). Returns { parse, compile, VERSION } or null.
36
+ */
37
+ export function loadSvelteCompiler(appRoot) {
38
+ try {
39
+ const req = createRequire(path.join(appRoot, 'package.json'));
40
+ const mod = req('svelte/compiler');
41
+ if (typeof mod.parse !== 'function') return null;
42
+ const major = parseInt(String(mod.VERSION || '0'), 10);
43
+ if (major < 5) return null; // detached mount() previews are svelte 5 only
44
+ return { parse: mod.parse, compile: mod.compile, VERSION: mod.VERSION };
45
+ } catch {
46
+ return null;
47
+ }
48
+ }
49
+
50
+ // ---------------------------------------------------------------------------
51
+ // ESTree helpers
52
+ // ---------------------------------------------------------------------------
53
+
54
+ /**
55
+ * Collect the root identifiers an ESTree expression reads. Walks generically;
56
+ * skips non-computed member properties and non-computed/non-shorthand object
57
+ * keys, which are names, not references.
58
+ */
59
+ export function collectRootIdentifiers(node, out = new Set()) {
60
+ if (!node || typeof node !== 'object') return out;
61
+ if (Array.isArray(node)) {
62
+ for (const item of node) collectRootIdentifiers(item, out);
63
+ return out;
64
+ }
65
+ switch (node.type) {
66
+ case 'Identifier':
67
+ out.add(node.name);
68
+ return out;
69
+ case 'MemberExpression':
70
+ collectRootIdentifiers(node.object, out);
71
+ if (node.computed) collectRootIdentifiers(node.property, out);
72
+ return out;
73
+ case 'Property':
74
+ if (node.computed) collectRootIdentifiers(node.key, out);
75
+ collectRootIdentifiers(node.value, out);
76
+ return out;
77
+ case 'ArrowFunctionExpression':
78
+ case 'FunctionExpression': {
79
+ // Params shadow outer names inside the body.
80
+ const bound = new Set();
81
+ for (const param of node.params || []) collectPatternNames(param, bound);
82
+ const inner = collectRootIdentifiers(node.body, new Set());
83
+ for (const name of inner) if (!bound.has(name)) out.add(name);
84
+ return out;
85
+ }
86
+ default: {
87
+ for (const key of Object.keys(node)) {
88
+ if (key === 'type' || key === 'start' || key === 'end' || key === 'loc' || key === 'range' || key === 'parent') continue;
89
+ collectRootIdentifiers(node[key], out);
90
+ }
91
+ return out;
92
+ }
93
+ }
94
+ }
95
+
96
+ /** Collect names bound by a destructuring pattern (each contexts, const tags). */
97
+ export function collectPatternNames(pattern, out = new Set()) {
98
+ if (!pattern || typeof pattern !== 'object') return out;
99
+ switch (pattern.type) {
100
+ case 'Identifier':
101
+ out.add(pattern.name);
102
+ return out;
103
+ case 'ObjectPattern':
104
+ for (const prop of pattern.properties || []) {
105
+ if (prop.type === 'RestElement') collectPatternNames(prop.argument, out);
106
+ else collectPatternNames(prop.value, out);
107
+ }
108
+ return out;
109
+ case 'ArrayPattern':
110
+ for (const el of pattern.elements || []) if (el) collectPatternNames(el, out);
111
+ return out;
112
+ case 'AssignmentPattern':
113
+ collectPatternNames(pattern.left, out);
114
+ return out;
115
+ case 'RestElement':
116
+ collectPatternNames(pattern.argument, out);
117
+ return out;
118
+ default:
119
+ return out;
120
+ }
121
+ }
122
+
123
+ // ---------------------------------------------------------------------------
124
+ // Template analysis
125
+ // ---------------------------------------------------------------------------
126
+
127
+ class Analysis {
128
+ constructor(source) {
129
+ this.source = source;
130
+ this.replacements = []; // { start, end, prop } source ranges to swap
131
+ this.contract = []; // [{ prop, expr, kind, ... }]
132
+ this.byExpr = new Map(); // expr text -> contract entry
133
+ this.usedNames = new Set();
134
+ this.unsupported = null;
135
+ }
136
+
137
+ fail(reason) {
138
+ if (!this.unsupported) this.unsupported = reason;
139
+ }
140
+
141
+ propFor(exprText, kind, extra = {}) {
142
+ const existing = this.byExpr.get(exprText);
143
+ if (existing) return existing;
144
+ const base = derivePropName(exprText);
145
+ let name = base;
146
+ let n = 2;
147
+ while (this.usedNames.has(name)) name = `${base}${n++}`;
148
+ this.usedNames.add(name);
149
+ const entry = { prop: name, expr: exprText, kind, ...extra };
150
+ this.byExpr.set(exprText, entry);
151
+ this.contract.push(entry);
152
+ return entry;
153
+ }
154
+ }
155
+
156
+ // A derived prop name lands in `let { <name> } = $props()`; a reserved word
157
+ // there is a syntax error the session only hits at import time.
158
+ const RESERVED_PROP_NAMES = new Set([
159
+ 'await', 'break', 'case', 'catch', 'class', 'const', 'continue', 'debugger',
160
+ 'default', 'delete', 'do', 'else', 'enum', 'export', 'extends', 'false',
161
+ 'finally', 'for', 'function', 'if', 'implements', 'import', 'in',
162
+ 'instanceof', 'interface', 'let', 'new', 'null', 'package', 'private',
163
+ 'protected', 'public', 'return', 'static', 'super', 'switch', 'this',
164
+ 'throw', 'true', 'try', 'typeof', 'undefined', 'var', 'void', 'while',
165
+ 'with', 'yield',
166
+ ]);
167
+
168
+ export function derivePropName(expr) {
169
+ const tail = String(expr).match(/(?:\.|\[["']?)([A-Za-z_$][\w$]*)["']?\]?\s*$/);
170
+ const candidate = (tail && tail[1])
171
+ || (String(expr).match(/^([A-Za-z_$][\w$]*)$/) || [])[1]
172
+ || 'value';
173
+ return RESERVED_PROP_NAMES.has(candidate) ? `${candidate}Value` : candidate;
174
+ }
175
+
176
+ function exprText(source, node) {
177
+ return source.slice(node.start, node.end);
178
+ }
179
+
180
+ // Identifiers that resolve in ANY module scope. They are neither hydratable
181
+ // props nor evidence of route coupling, so they count as neither free nor
182
+ // bound: `{Math.round(x)}` must not mint a prop named `round`, and
183
+ // `{fmt(stage.label)}` must not pass as global-only.
184
+ const GLOBAL_IDENTIFIERS = new Set([
185
+ 'Math', 'JSON', 'Date', 'Intl', 'Number', 'String', 'Boolean', 'Array',
186
+ 'Object', 'Map', 'Set', 'Promise', 'RegExp', 'NaN', 'Infinity', 'undefined',
187
+ 'isNaN', 'isFinite', 'parseInt', 'parseFloat', 'encodeURIComponent',
188
+ 'decodeURIComponent', 'console', 'window', 'document', 'navigator',
189
+ 'location', 'structuredClone', 'crypto',
190
+ ]);
191
+
192
+ function classifyRoots(node, scopes) {
193
+ const roots = collectRootIdentifiers(node);
194
+ let bound = 0;
195
+ let free = 0;
196
+ for (const name of roots) {
197
+ if (GLOBAL_IDENTIFIERS.has(name)) continue;
198
+ if (scopes.some((scope) => scope.has(name))) bound++;
199
+ else free++;
200
+ }
201
+ return { bound, free };
202
+ }
203
+
204
+ function isFree(node, scopes) {
205
+ const { bound, free } = classifyRoots(node, scopes);
206
+ return free > 0 && bound === 0;
207
+ }
208
+
209
+ /**
210
+ * An expression mixing loop-bound and outer free identifiers (e.g.
211
+ * `{fmt(stage.label)}` where `fmt` lives in the route script) can neither
212
+ * become a prop (the bound part varies per item) nor survive detachment
213
+ * verbatim (the free name is undeclared in the preview and throws at mount,
214
+ * past the compile gate, because globals make it legal to the compiler).
215
+ * Source-preview mode is the only correct home for it.
216
+ */
217
+ function failOnMixedExpression(node, scopes, analysis, source) {
218
+ const { bound, free } = classifyRoots(node, scopes);
219
+ if (bound > 0 && free > 0) {
220
+ analysis.fail(`expression mixing loop and outer identifiers ({${exprText(source, node).slice(0, 60)}}) requires source-preview mode`);
221
+ return true;
222
+ }
223
+ return false;
224
+ }
225
+
226
+ /**
227
+ * Analyze a parsed template fragment. `scopes` is a stack of Sets of bound
228
+ * names; the outermost call passes an empty stack.
229
+ */
230
+ function analyzeFragment(fragment, analysis, scopes) {
231
+ if (!fragment || !Array.isArray(fragment.nodes)) return;
232
+ // ConstTag declarations bind for the whole fragment.
233
+ const fragmentScope = new Set();
234
+ const nextScopes = [...scopes, fragmentScope];
235
+ for (const node of fragment.nodes) {
236
+ if (node.type === 'ConstTag' && node.declaration) {
237
+ for (const decl of node.declaration.declarations || []) {
238
+ collectPatternNames(decl.id, fragmentScope);
239
+ }
240
+ }
241
+ }
242
+ for (const node of fragment.nodes) analyzeNode(node, analysis, nextScopes);
243
+ }
244
+
245
+ function analyzeNode(node, analysis, scopes) {
246
+ if (!node || analysis.unsupported) return;
247
+ switch (node.type) {
248
+ case 'Text':
249
+ case 'Comment':
250
+ return;
251
+ case 'ExpressionTag': {
252
+ if (failOnMixedExpression(node.expression, scopes, analysis, analysis.source)) return;
253
+ if (isFree(node.expression, scopes)) {
254
+ const text = exprText(analysis.source, node.expression);
255
+ const entry = analysis.propFor(text, 'text');
256
+ // node.start/end include the braces; keep them, swap the inside.
257
+ analysis.replacements.push({ start: node.expression.start, end: node.expression.end, prop: entry.prop });
258
+ }
259
+ return;
260
+ }
261
+ case 'HtmlTag': {
262
+ if (failOnMixedExpression(node.expression, scopes, analysis, analysis.source)) return;
263
+ if (isFree(node.expression, scopes)) {
264
+ const text = exprText(analysis.source, node.expression);
265
+ const entry = analysis.propFor(text, 'raw');
266
+ analysis.replacements.push({ start: node.expression.start, end: node.expression.end, prop: entry.prop });
267
+ }
268
+ return;
269
+ }
270
+ case 'ConstTag': {
271
+ // Its expression may read free names; leave them: the declaration
272
+ // travels with the markup and stays valid only if its inputs do.
273
+ if (node.declaration) {
274
+ for (const decl of node.declaration.declarations || []) {
275
+ if (decl.init && failOnMixedExpression(decl.init, scopes, analysis, analysis.source)) return;
276
+ if (decl.init && isFree(decl.init, scopes)) {
277
+ const text = exprText(analysis.source, decl.init);
278
+ const entry = analysis.propFor(text, 'text');
279
+ analysis.replacements.push({ start: decl.init.start, end: decl.init.end, prop: entry.prop });
280
+ }
281
+ }
282
+ }
283
+ return;
284
+ }
285
+ case 'EachBlock': {
286
+ if (failOnMixedExpression(node.expression, scopes, analysis, analysis.source)) return;
287
+ if (isFree(node.expression, scopes)) {
288
+ const text = exprText(analysis.source, node.expression);
289
+ const item = describeEachItem(node, analysis.source);
290
+ // Keyed each: the key must evaluate to a distinct value per hydrated
291
+ // item or Svelte throws each_key_duplicate at mount. A key that is a
292
+ // plain member of the item (the common `(item.id)` shape) gets a
293
+ // synthetic per-index value injected by the browser (keyField).
294
+ // Anything else cannot be hydrated safely; source-preview mode keeps
295
+ // it correct.
296
+ if (node.key) {
297
+ const keyInfo = classifyEachKey(node);
298
+ if (keyInfo.unsupported) {
299
+ analysis.fail(keyInfo.unsupported);
300
+ return;
301
+ }
302
+ if (keyInfo.keyField) {
303
+ if (item.textSlots.some((slot) => slot.key === keyInfo.keyField)) {
304
+ // The key doubles as a displayed slot; a synthetic value would
305
+ // change visible text, and the displayed text may not be
306
+ // unique. Not previewable in a detached component.
307
+ analysis.fail('each key that is also a displayed field requires source-preview mode');
308
+ return;
309
+ }
310
+ item.keyField = keyInfo.keyField;
311
+ }
312
+ }
313
+ const entry = analysis.propFor(text, 'collection', { item });
314
+ analysis.replacements.push({ start: node.expression.start, end: node.expression.end, prop: entry.prop });
315
+ }
316
+ const bound = new Set();
317
+ if (node.context) collectPatternNames(node.context, bound);
318
+ if (node.index) bound.add(node.index);
319
+ analyzeFragment(node.body, analysis, [...scopes, bound]);
320
+ if (node.fallback) analyzeFragment(node.fallback, analysis, scopes);
321
+ return;
322
+ }
323
+ case 'IfBlock': {
324
+ if (failOnMixedExpression(node.test, scopes, analysis, analysis.source)) return;
325
+ if (isFree(node.test, scopes)) {
326
+ const text = exprText(analysis.source, node.test);
327
+ // The browser hydrates a free condition from what the live page
328
+ // currently shows: when the consequent's root element is present
329
+ // under the picked element, the condition is on.
330
+ const entry = analysis.propFor(text, 'condition', {
331
+ probe: describeElementProbe(node.consequent),
332
+ });
333
+ analysis.replacements.push({ start: node.test.start, end: node.test.end, prop: entry.prop });
334
+ }
335
+ analyzeFragment(node.consequent, analysis, scopes);
336
+ if (node.alternate) analyzeFragment(node.alternate, analysis, scopes);
337
+ return;
338
+ }
339
+ case 'KeyBlock': {
340
+ if (failOnMixedExpression(node.expression, scopes, analysis, analysis.source)) return;
341
+ if (isFree(node.expression, scopes)) {
342
+ const text = exprText(analysis.source, node.expression);
343
+ const entry = analysis.propFor(text, 'text');
344
+ analysis.replacements.push({ start: node.expression.start, end: node.expression.end, prop: entry.prop });
345
+ }
346
+ analyzeFragment(node.fragment, analysis, scopes);
347
+ return;
348
+ }
349
+ case 'SnippetBlock': {
350
+ const bound = new Set();
351
+ for (const param of node.parameters || []) collectPatternNames(param, bound);
352
+ // The snippet's own name becomes available to render tags in this file.
353
+ analyzeFragment(node.body, analysis, [...scopes, bound]);
354
+ return;
355
+ }
356
+ case 'RegularElement':
357
+ case 'SlotElement':
358
+ case 'TitleElement': {
359
+ if (node.name === 'script') {
360
+ // An inline script inside the selected block carries route-scoped
361
+ // code; running it a second time from a detached preview is wrong.
362
+ analysis.fail('inline script element requires source-preview mode');
363
+ return;
364
+ }
365
+ analyzeAttributes(node, analysis, scopes);
366
+ if (!analysis.unsupported) analyzeFragment(node.fragment, analysis, scopes);
367
+ return;
368
+ }
369
+ case 'SvelteElement':
370
+ case 'SvelteFragment':
371
+ case 'SvelteBoundary': {
372
+ analyzeAttributes(node, analysis, scopes);
373
+ if (!analysis.unsupported) analyzeFragment(node.fragment, analysis, scopes);
374
+ return;
375
+ }
376
+ case 'Component':
377
+ case 'SvelteComponent':
378
+ case 'SvelteSelf':
379
+ // The component's import lives in the route file; a detached preview
380
+ // cannot resolve it. Source-preview mode keeps it working.
381
+ analysis.fail(`component tag <${node.name || 'Component'}> requires source-preview mode`);
382
+ return;
383
+ case 'RenderTag':
384
+ analysis.fail('render tag requires source-preview mode');
385
+ return;
386
+ case 'AwaitBlock':
387
+ analysis.fail('await block requires source-preview mode');
388
+ return;
389
+ case 'SvelteHead':
390
+ case 'SvelteWindow':
391
+ case 'SvelteDocument':
392
+ case 'SvelteBody':
393
+ analysis.fail(`${node.type} requires source-preview mode`);
394
+ return;
395
+ default: {
396
+ if (node.fragment) analyzeFragment(node.fragment, analysis, scopes);
397
+ return;
398
+ }
399
+ }
400
+ }
401
+
402
+ function analyzeAttributes(node, analysis, scopes) {
403
+ for (const attr of node.attributes || []) {
404
+ switch (attr.type) {
405
+ case 'Attribute': {
406
+ if (attr.value === true) break;
407
+ const parts = Array.isArray(attr.value) ? attr.value : [attr.value];
408
+ for (const part of parts) {
409
+ if (!part || part.type !== 'ExpressionTag') continue;
410
+ if (failOnMixedExpression(part.expression, scopes, analysis, analysis.source)) return;
411
+ if (!isFree(part.expression, scopes)) continue;
412
+ const text = exprText(analysis.source, part.expression);
413
+ const kind = HANDLER_ATTR_RE.test(attr.name) ? 'handler' : 'text';
414
+ const entry = analysis.propFor(text, kind);
415
+ analysis.replacements.push({ start: part.expression.start, end: part.expression.end, prop: entry.prop });
416
+ }
417
+ break;
418
+ }
419
+ case 'ClassDirective': {
420
+ const expr = attr.expression;
421
+ if (expr && failOnMixedExpression(expr, scopes, analysis, analysis.source)) return;
422
+ if (expr && isFree(expr, scopes)) {
423
+ const text = exprText(analysis.source, expr);
424
+ // The directive's class name is literal, so the live DOM answers
425
+ // the condition directly: the class is either present or not.
426
+ const entry = analysis.propFor(text, 'condition', {
427
+ probe: { className: attr.name },
428
+ });
429
+ analysis.replacements.push({ start: expr.start, end: expr.end, prop: entry.prop });
430
+ }
431
+ break;
432
+ }
433
+ case 'StyleDirective': {
434
+ // Unlike ClassDirective, a style directive stores its value in
435
+ // attribute shape: `true` for the shorthand, else an array of parts.
436
+ const parts = attr.value === true ? [] : (Array.isArray(attr.value) ? attr.value : [attr.value]);
437
+ for (const part of parts) {
438
+ if (part?.type === 'ExpressionTag'
439
+ && failOnMixedExpression(part.expression, scopes, analysis, analysis.source)) {
440
+ return;
441
+ }
442
+ }
443
+ const dynamic = parts.some((part) => part?.type === 'ExpressionTag' && isFree(part.expression, scopes));
444
+ const shorthandFree = attr.value === true && isFree({ type: 'Identifier', name: attr.name }, scopes);
445
+ if (dynamic || shorthandFree) {
446
+ // style:opacity={x} carries a css VALUE, not a boolean, and the
447
+ // computed value on the live element is not reliably recoverable in
448
+ // the shape the expression produced. A falsified style is worse
449
+ // than an HMR-resetting preview.
450
+ analysis.fail(`style:${attr.name} with a dynamic value requires source-preview mode`);
451
+ }
452
+ break;
453
+ }
454
+ case 'BindDirective':
455
+ analysis.fail(`bind:${attr.name} requires source-preview mode`);
456
+ return;
457
+ case 'UseDirective':
458
+ analysis.fail(`use:${attr.name} requires source-preview mode`);
459
+ return;
460
+ case 'AnimateDirective':
461
+ case 'TransitionDirective':
462
+ // Motion directives reference route-scoped or svelte/transition
463
+ // imports; a detached preview cannot resolve them.
464
+ analysis.fail(`${attr.type} requires source-preview mode`);
465
+ return;
466
+ case 'OnDirective': {
467
+ // Legacy on:click syntax; treat like handler attributes.
468
+ const expr = attr.expression;
469
+ if (expr && failOnMixedExpression(expr, scopes, analysis, analysis.source)) return;
470
+ if (expr && isFree(expr, scopes)) {
471
+ const text = exprText(analysis.source, expr);
472
+ const entry = analysis.propFor(text, 'handler');
473
+ analysis.replacements.push({ start: expr.start, end: expr.end, prop: entry.prop });
474
+ }
475
+ break;
476
+ }
477
+ case 'SpreadAttribute':
478
+ analysis.fail('spread attribute requires source-preview mode');
479
+ return;
480
+ default:
481
+ break;
482
+ }
483
+ }
484
+ }
485
+
486
+ /**
487
+ * Describe the repeating item of an each block for browser-side hydration:
488
+ * the item's root element (tag + static classes, used to count live
489
+ * iterations) and the ordered text slots that reference loop bindings.
490
+ */
491
+ function describeEachItem(node, source) {
492
+ const body = node.body;
493
+ const rootEl = (body?.nodes || []).find((n) => n.type === 'RegularElement');
494
+
495
+ const textSlots = [];
496
+ const staticTexts = [];
497
+ let nestedUnsupported = false;
498
+ const collectStatics = (fragment) => {
499
+ for (const child of fragment?.nodes || []) {
500
+ if (child.type === 'Text') {
501
+ const trimmed = String(child.data || '').trim();
502
+ if (trimmed) staticTexts.push(trimmed);
503
+ } else if (child.type === 'IfBlock') {
504
+ collectStatics(child.consequent);
505
+ if (child.alternate) collectStatics(child.alternate);
506
+ } else if (child.type === 'EachBlock') {
507
+ collectStatics(child.body);
508
+ } else if (child.fragment) {
509
+ collectStatics(child.fragment);
510
+ }
511
+ }
512
+ };
513
+ collectStatics(body);
514
+ const attrSlots = [];
515
+ // The hydration item is a SHALLOW object whose string fields are the exact
516
+ // property names the markup accesses, filled from the rendered page. That
517
+ // model supports one item access per slot, optionally wrapped in a global
518
+ // transform ({Math.round(r.score)} hydrates `score`). Shapes it cannot
519
+ // represent split two ways: CRASHY ones would throw at mount time against a
520
+ // shallow item (deep paths like r.meta.label, method calls like r.format())
521
+ // and force the source-preview fallback; LOSSY ones render wrong but safe
522
+ // (bare {r}, multi-access expressions that would double their text) and
523
+ // also fall back in text position, where the damage is visible.
524
+ const boundAs = (name, scopeInfos) => {
525
+ for (let i = scopeInfos.length - 1; i >= 0; i--) {
526
+ const info = scopeInfos[i];
527
+ if (info.indexName === name) return 'index';
528
+ if (info.itemName === name) return 'item';
529
+ if (info.names.has(name)) return 'field';
530
+ }
531
+ return null;
532
+ };
533
+ const slotKeysOf = (expression, scopeInfos) => {
534
+ const keys = new Set();
535
+ let crashy = false;
536
+ let lossy = false;
537
+ let touches = false;
538
+ const visit = (node, ctx) => {
539
+ if (!node || typeof node !== 'object' || crashy) return;
540
+ if (Array.isArray(node)) {
541
+ for (const item of node) visit(item, {});
542
+ return;
543
+ }
544
+ switch (node.type) {
545
+ case 'Identifier': {
546
+ const kind = boundAs(node.name, scopeInfos);
547
+ if (!kind) return;
548
+ touches = true;
549
+ if (kind === 'index') return; // the runtime each provides it
550
+ if (kind === 'item') { lossy = true; return; } // bare item reference
551
+ if (ctx.callee) { crashy = true; return; } // field() on a hydrated string
552
+ keys.add(node.name); // destructured context field
553
+ return;
554
+ }
555
+ case 'MemberExpression': {
556
+ if (
557
+ !node.computed
558
+ && node.object?.type === 'Identifier'
559
+ && boundAs(node.object.name, scopeInfos) === 'item'
560
+ && node.property?.type === 'Identifier'
561
+ ) {
562
+ touches = true;
563
+ // item.a.b or item.method(): a shallow string field throws here.
564
+ if (ctx.memberObject || ctx.callee) { crashy = true; return; }
565
+ keys.add(node.property.name);
566
+ return;
567
+ }
568
+ visit(node.object, { memberObject: true });
569
+ if (node.computed) visit(node.property, {});
570
+ return;
571
+ }
572
+ case 'CallExpression':
573
+ visit(node.callee, { callee: true });
574
+ for (const arg of node.arguments || []) visit(arg, {});
575
+ return;
576
+ case 'ArrowFunctionExpression':
577
+ case 'FunctionExpression': {
578
+ // Closures cannot hydrate; only lossy when they capture the item.
579
+ const roots = collectRootIdentifiers(node);
580
+ if ([...roots].some((name) => boundAs(name, scopeInfos))) { touches = true; lossy = true; }
581
+ return;
582
+ }
583
+ case 'Property':
584
+ if (node.computed) visit(node.key, {});
585
+ visit(node.value, {});
586
+ return;
587
+ default: {
588
+ for (const key of Object.keys(node)) {
589
+ if (key === 'type' || key === 'start' || key === 'end' || key === 'loc' || key === 'range' || key === 'parent') continue;
590
+ visit(node[key], {});
591
+ }
592
+ }
593
+ }
594
+ };
595
+ visit(expression, {});
596
+ if (crashy) return { crashy: true };
597
+ if (lossy || keys.size > 1) return { lossy: true };
598
+ if (!touches || keys.size === 0) return { skip: true };
599
+ return { key: [...keys][0] };
600
+ };
601
+ const staticClassesOf = (el) => {
602
+ const classes = [];
603
+ for (const attr of el?.attributes || []) {
604
+ if (attr.type === 'Attribute' && attr.name === 'class' && Array.isArray(attr.value)) {
605
+ for (const part of attr.value) {
606
+ if (part.type === 'Text') classes.push(...part.data.split(/\s+/).filter(Boolean));
607
+ }
608
+ }
609
+ }
610
+ return classes;
611
+ };
612
+ const scopeInfoOf = (eachNode) => {
613
+ const names = new Set();
614
+ if (eachNode.context) collectPatternNames(eachNode.context, names);
615
+ return {
616
+ names,
617
+ itemName: eachNode.context?.type === 'Identifier' ? eachNode.context.name : null,
618
+ indexName: eachNode.index || null,
619
+ };
620
+ };
621
+ const walkForSlots = (fragment, scopeInfos) => {
622
+ for (const child of fragment?.nodes || []) {
623
+ if (child.type === 'ExpressionTag') {
624
+ const slot = slotKeysOf(child.expression, scopeInfos);
625
+ if (slot.crashy || slot.lossy) { nestedUnsupported = true; continue; }
626
+ if (slot.skip) continue;
627
+ textSlots.push({ key: slot.key, expr: exprText(source, child.expression) });
628
+ } else if (child.type === 'RegularElement' || child.type === 'SvelteElement') {
629
+ // Bound values in ATTRIBUTES (href={link.href}, src={item.img}) are
630
+ // part of the item too: the browser reads the rendered attribute off
631
+ // the live element, so the preview does not mount with empty links.
632
+ // Only a single-expression attribute hydrates exactly; a mixed value
633
+ // ("card {r.status}") stays unhydrated because the rendered attribute
634
+ // is not separable into its parts, which was the prior behavior.
635
+ for (const attr of child.attributes || []) {
636
+ if (attr.type !== 'Attribute' || attr.value === true) continue;
637
+ if (HANDLER_ATTR_RE.test(attr.name)) continue; // functions cannot hydrate
638
+ const parts = Array.isArray(attr.value) ? attr.value : [attr.value];
639
+ const exprParts = parts.filter((part) => part?.type === 'ExpressionTag');
640
+ for (const part of exprParts) {
641
+ const slot = slotKeysOf(part.expression, scopeInfos);
642
+ if (slot.crashy) { nestedUnsupported = true; continue; }
643
+ if (slot.skip || slot.lossy) continue;
644
+ if (parts.length !== 1) continue; // mixed static+dynamic value
645
+ attrSlots.push({
646
+ key: slot.key,
647
+ expr: exprText(source, part.expression),
648
+ attr: attr.name,
649
+ tag: child.name || null,
650
+ classes: staticClassesOf(child),
651
+ });
652
+ }
653
+ }
654
+ walkForSlots(child.fragment, scopeInfos);
655
+ continue;
656
+ } else if (child.type === 'EachBlock') {
657
+ const roots = collectRootIdentifiers(child.expression);
658
+ const boundNested = [...roots].some((name) => boundAs(name, scopeInfos));
659
+ if (boundNested) nestedUnsupported = true; // nested per-item arrays: no hydration plan yet
660
+ walkForSlots(child.body, [...scopeInfos, scopeInfoOf(child)]);
661
+ } else if (child.type === 'IfBlock') {
662
+ walkForSlots(child.consequent, scopeInfos);
663
+ if (child.alternate) walkForSlots(child.alternate, scopeInfos);
664
+ } else if (child.fragment) {
665
+ walkForSlots(child.fragment, scopeInfos);
666
+ }
667
+ }
668
+ };
669
+ walkForSlots(body, [scopeInfoOf(node)]);
670
+
671
+ const staticClasses = [];
672
+ for (const attr of rootEl?.attributes || []) {
673
+ if (attr.type === 'Attribute' && attr.name === 'class' && Array.isArray(attr.value)) {
674
+ for (const part of attr.value) {
675
+ if (part.type === 'Text') staticClasses.push(...part.data.split(/\s+/).filter(Boolean));
676
+ }
677
+ }
678
+ }
679
+
680
+ return {
681
+ rootTag: rootEl?.name || null,
682
+ rootClasses: staticClasses,
683
+ textSlots,
684
+ attrSlots,
685
+ staticTexts,
686
+ nestedUnsupported,
687
+ };
688
+ }
689
+
690
+ /**
691
+ * Classify a keyed each block's key expression:
692
+ * { keyField } member of the loop item (e.g. `(expense.id)` when the
693
+ * context binds `expense`): browser injects a unique
694
+ * per-index value under that field.
695
+ * {} key is the whole loop item or the index: already
696
+ * distinct per iteration, nothing to inject.
697
+ * { unsupported } free or complex keys: cannot hydrate distinct values.
698
+ */
699
+ function classifyEachKey(node) {
700
+ const bound = new Set();
701
+ if (node.context) collectPatternNames(node.context, bound);
702
+ if (node.index) bound.add(node.index);
703
+ const key = node.key;
704
+ const roots = collectRootIdentifiers(key);
705
+ const usesLoopBinding = [...roots].some((name) => bound.has(name));
706
+ if (!usesLoopBinding) {
707
+ // A key that ignores the loop item is constant across iterations:
708
+ // guaranteed duplicate keys at mount.
709
+ return { unsupported: 'each key not derived from the loop item requires source-preview mode' };
710
+ }
711
+ if (key.type === 'Identifier' && bound.has(key.name)) return {};
712
+ if (
713
+ key.type === 'MemberExpression'
714
+ && !key.computed
715
+ && key.object?.type === 'Identifier'
716
+ && bound.has(key.object.name)
717
+ && key.property?.type === 'Identifier'
718
+ ) {
719
+ return { keyField: key.property.name };
720
+ }
721
+ return { unsupported: 'complex each key requires source-preview mode' };
722
+ }
723
+
724
+ /**
725
+ * Describe a fragment's root element for browser presence probing:
726
+ * { tag, classes } of the first RegularElement, or null for text-only
727
+ * fragments (which cannot be probed reliably).
728
+ */
729
+ function describeElementProbe(fragment) {
730
+ const rootEl = (fragment?.nodes || []).find((n) => n.type === 'RegularElement');
731
+ if (!rootEl) return null;
732
+ const classes = [];
733
+ for (const attr of rootEl.attributes || []) {
734
+ if (attr.type === 'Attribute' && attr.name === 'class' && Array.isArray(attr.value)) {
735
+ for (const part of attr.value) {
736
+ if (part.type === 'Text') classes.push(...part.data.split(/\s+/).filter(Boolean));
737
+ }
738
+ }
739
+ }
740
+ return { tag: rootEl.name, classes };
741
+ }
742
+
743
+ // ---------------------------------------------------------------------------
744
+ // Public API
745
+ // ---------------------------------------------------------------------------
746
+
747
+ /**
748
+ * Analyze a markup block and produce the prop-substituted scaffold markup and
749
+ * the v2 prop contract. Returns { ok: false, reason } when the block needs
750
+ * source-preview mode (parse failure or unsupported construct).
751
+ */
752
+ export function analyzeSvelteMarkup(markup, parse) {
753
+ const source = String(markup || '');
754
+ let ast;
755
+ try {
756
+ ast = parse(source, { modern: true });
757
+ } catch (err) {
758
+ return { ok: false, reason: `svelte parse failed: ${err.message}` };
759
+ }
760
+ if (ast.instance || ast.module) {
761
+ return { ok: false, reason: 'selected block contains a script tag' };
762
+ }
763
+ const analysis = new Analysis(source);
764
+ analyzeFragment(ast.fragment, analysis, []);
765
+ if (analysis.unsupported) {
766
+ return { ok: false, reason: analysis.unsupported };
767
+ }
768
+ for (const entry of analysis.contract) {
769
+ if (entry.kind === 'collection' && entry.item?.nestedUnsupported) {
770
+ return { ok: false, reason: 'per-item content (nested blocks or expressions) this preview cannot hydrate requires source-preview mode' };
771
+ }
772
+ }
773
+
774
+ const markupWithProps = applyReplacements(source, analysis.replacements);
775
+ return {
776
+ ok: true,
777
+ markupWithProps,
778
+ contract: analysis.contract.map((entry) => ({
779
+ prop: entry.prop,
780
+ expr: entry.expr,
781
+ kind: entry.kind,
782
+ // Kept for backward compatibility with v1 consumers (fake e2e agent,
783
+ // text-only restore paths).
784
+ placeholder: `{${entry.expr}}`,
785
+ ...(entry.item ? { item: entry.item } : {}),
786
+ ...(entry.probe ? { probe: entry.probe } : {}),
787
+ })),
788
+ };
789
+ }
790
+
791
+ function applyReplacements(source, replacements) {
792
+ const sorted = [...replacements].sort((a, b) => b.start - a.start);
793
+ let out = source;
794
+ for (const { start, end, prop } of sorted) {
795
+ out = out.slice(0, start) + prop + out.slice(end);
796
+ }
797
+ return out;
798
+ }
799
+
800
+ /**
801
+ * Restore a variant's markup back to route-source form: every free
802
+ * identifier that matches a contract prop is replaced by its original
803
+ * expression. AST-based so `{#each stages as stage}` restores to
804
+ * `{#each data.stages as stage}` even though the prop appears without braces.
805
+ */
806
+ export function restoreSvelteMarkup(markup, contract, parse) {
807
+ const source = String(markup || '');
808
+ const byProp = new Map();
809
+ for (const entry of contract || []) byProp.set(entry.prop, entry.expr);
810
+ if (byProp.size === 0) return { ok: true, markup: source };
811
+
812
+ let ast;
813
+ try {
814
+ ast = parse(source, { modern: true });
815
+ } catch (err) {
816
+ return { ok: false, reason: `variant parse failed: ${err.message}` };
817
+ }
818
+
819
+ const replacements = [];
820
+ const visitExpr = (expression, scopes) => {
821
+ if (!expression) return;
822
+ collectFreeIdentifierRanges(expression, scopes, (name, start, end) => {
823
+ const original = byProp.get(name);
824
+ if (original != null && original !== name) replacements.push({ start, end, prop: original });
825
+ });
826
+ };
827
+
828
+ const walk = (fragment, scopes) => {
829
+ const fragmentScope = new Set();
830
+ const nextScopes = [...scopes, fragmentScope];
831
+ for (const node of fragment?.nodes || []) {
832
+ if (node.type === 'ConstTag' && node.declaration) {
833
+ for (const decl of node.declaration.declarations || []) collectPatternNames(decl.id, fragmentScope);
834
+ }
835
+ }
836
+ for (const node of fragment?.nodes || []) {
837
+ switch (node?.type) {
838
+ case 'ExpressionTag':
839
+ case 'HtmlTag':
840
+ visitExpr(node.expression, nextScopes);
841
+ break;
842
+ case 'ConstTag':
843
+ for (const decl of node.declaration?.declarations || []) visitExpr(decl.init, nextScopes);
844
+ break;
845
+ case 'EachBlock': {
846
+ visitExpr(node.expression, nextScopes);
847
+ const bound = new Set();
848
+ if (node.context) collectPatternNames(node.context, bound);
849
+ if (node.index) bound.add(node.index);
850
+ // The key evaluates per item, so the loop context and index are in
851
+ // scope there. Visiting it with outer scopes only let a contract
852
+ // prop that shares a loop binding's name rewrite the key.
853
+ if (node.key) visitExpr(node.key, [...nextScopes, bound]);
854
+ walk(node.body, [...nextScopes, bound]);
855
+ if (node.fallback) walk(node.fallback, nextScopes);
856
+ break;
857
+ }
858
+ case 'IfBlock':
859
+ visitExpr(node.test, nextScopes);
860
+ walk(node.consequent, nextScopes);
861
+ if (node.alternate) walk(node.alternate, nextScopes);
862
+ break;
863
+ case 'KeyBlock':
864
+ visitExpr(node.expression, nextScopes);
865
+ walk(node.fragment, nextScopes);
866
+ break;
867
+ case 'SnippetBlock': {
868
+ const bound = new Set();
869
+ for (const param of node.parameters || []) collectPatternNames(param, bound);
870
+ walk(node.body, [...nextScopes, bound]);
871
+ break;
872
+ }
873
+ default: {
874
+ for (const attr of node?.attributes || []) {
875
+ if (attr.type === 'Attribute' && Array.isArray(attr.value)) {
876
+ for (const part of attr.value) {
877
+ if (part?.type === 'ExpressionTag') visitExpr(part.expression, nextScopes);
878
+ }
879
+ } else if (attr.expression) {
880
+ visitExpr(attr.expression, nextScopes);
881
+ }
882
+ }
883
+ if (node?.fragment) walk(node.fragment, nextScopes);
884
+ }
885
+ }
886
+ }
887
+ };
888
+ walk(ast.fragment, []);
889
+
890
+ return { ok: true, markup: applyReplacements(source, replacements) };
891
+ }
892
+
893
+ /**
894
+ * Report [name, start, end] for every free root identifier READ in an
895
+ * expression (skips member properties, object keys, shadowed names).
896
+ */
897
+ function collectFreeIdentifierRanges(node, scopes, emit) {
898
+ const visit = (n, localBound) => {
899
+ if (!n || typeof n !== 'object') return;
900
+ if (Array.isArray(n)) { for (const item of n) visit(item, localBound); return; }
901
+ switch (n.type) {
902
+ case 'Identifier': {
903
+ const bound = localBound.has(n.name) || scopes.some((s) => s.has(n.name));
904
+ if (!bound) emit(n.name, n.start, n.end);
905
+ return;
906
+ }
907
+ case 'MemberExpression':
908
+ visit(n.object, localBound);
909
+ if (n.computed) visit(n.property, localBound);
910
+ return;
911
+ case 'Property':
912
+ if (n.computed) visit(n.key, localBound);
913
+ visit(n.value, localBound);
914
+ return;
915
+ case 'ArrowFunctionExpression':
916
+ case 'FunctionExpression': {
917
+ const inner = new Set(localBound);
918
+ for (const param of n.params || []) collectPatternNames(param, inner);
919
+ visit(n.body, inner);
920
+ return;
921
+ }
922
+ default:
923
+ for (const key of Object.keys(n)) {
924
+ if (key === 'type' || key === 'start' || key === 'end' || key === 'loc' || key === 'range' || key === 'parent') continue;
925
+ visit(n[key], localBound);
926
+ }
927
+ }
928
+ };
929
+ visit(node, new Set());
930
+ }
931
+
932
+ /**
933
+ * Build the preview component's script block from a v2 contract, with
934
+ * defaults that keep an unhydrated mount rendering instead of crashing.
935
+ */
936
+ // `/** @type {...} */` directly before a destructuring declaration is also
937
+ // JSDoc's cast syntax, and Svelte 5.50+ re-emits the annotation in cast form
938
+ // onto the template's own declaration: `var /** @type {...} */ (h1) = root()`.
939
+ // That is a syntax error, so the browser's dynamic import of the variant dies
940
+ // with "Unexpected token '('" and nothing renders. `@typedef` carries the same
941
+ // shape without being a cast. Keep it a typedef;
942
+ // tests/live-svelte-props-script.test.mjs compiles what these builders emit
943
+ // and parses the result.
944
+ export function buildPropsScriptV2(contract) {
945
+ if (!contract || contract.length === 0) {
946
+ return '<script>\n /** @typedef {Record<string, never>} Props */\n let {} = $props();\n</script>\n';
947
+ }
948
+ const defaults = {
949
+ text: "''",
950
+ raw: "''",
951
+ condition: 'false',
952
+ collection: '[]',
953
+ handler: '() => {}',
954
+ };
955
+ const types = {
956
+ text: 'string',
957
+ raw: 'string',
958
+ condition: 'boolean',
959
+ collection: 'Array<Record<string, unknown>>',
960
+ handler: '() => void',
961
+ };
962
+ const names = contract
963
+ .map((c) => `${c.prop} = ${defaults[c.kind] ?? "''"}`)
964
+ .join(', ');
965
+ const typeFields = contract
966
+ .map((c) => ` ${c.prop}?: ${types[c.kind] ?? 'string'};`)
967
+ .join('\n');
968
+ return `<script>\n /** @typedef {{\n${typeFields}\n }} Props */\n let { ${names} } = $props();\n</script>\n`;
969
+ }