@agent-native/core 0.98.17 → 0.99.1

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 (583) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +25 -0
  3. package/corpus/core/docs/content/actions.mdx +1 -1
  4. package/corpus/core/docs/content/authentication.mdx +1 -1
  5. package/corpus/core/docs/content/dispatch.mdx +3 -3
  6. package/corpus/core/docs/content/external-agents.mdx +30 -19
  7. package/corpus/core/docs/content/locales/ar-SA/actions.mdx +1 -1
  8. package/corpus/core/docs/content/locales/ar-SA/authentication.mdx +1 -1
  9. package/corpus/core/docs/content/locales/ar-SA/dispatch.mdx +3 -3
  10. package/corpus/core/docs/content/locales/ar-SA/external-agents.mdx +23 -19
  11. package/corpus/core/docs/content/locales/ar-SA/mcp-clients.mdx +31 -3
  12. package/corpus/core/docs/content/locales/ar-SA/mcp-protocol.mdx +29 -15
  13. package/corpus/core/docs/content/locales/ar-SA/plan-plugin.mdx +3 -3
  14. package/corpus/core/docs/content/locales/ar-SA/server.mdx +2 -2
  15. package/corpus/core/docs/content/locales/ar-SA/skills-guide.mdx +1 -1
  16. package/corpus/core/docs/content/locales/ar-SA/template-assets.mdx +1 -1
  17. package/corpus/core/docs/content/locales/ar-SA/template-dispatch.mdx +2 -2
  18. package/corpus/core/docs/content/locales/ar-SA/template-plan.mdx +3 -3
  19. package/corpus/core/docs/content/locales/de-DE/actions.mdx +1 -1
  20. package/corpus/core/docs/content/locales/de-DE/authentication.mdx +1 -1
  21. package/corpus/core/docs/content/locales/de-DE/dispatch.mdx +3 -3
  22. package/corpus/core/docs/content/locales/de-DE/external-agents.mdx +23 -19
  23. package/corpus/core/docs/content/locales/de-DE/mcp-clients.mdx +37 -3
  24. package/corpus/core/docs/content/locales/de-DE/mcp-protocol.mdx +29 -15
  25. package/corpus/core/docs/content/locales/de-DE/plan-plugin.mdx +3 -3
  26. package/corpus/core/docs/content/locales/de-DE/server.mdx +2 -2
  27. package/corpus/core/docs/content/locales/de-DE/skills-guide.mdx +1 -1
  28. package/corpus/core/docs/content/locales/de-DE/template-assets.mdx +1 -1
  29. package/corpus/core/docs/content/locales/de-DE/template-dispatch.mdx +2 -2
  30. package/corpus/core/docs/content/locales/de-DE/template-plan.mdx +3 -3
  31. package/corpus/core/docs/content/locales/es-ES/actions.mdx +1 -1
  32. package/corpus/core/docs/content/locales/es-ES/authentication.mdx +1 -1
  33. package/corpus/core/docs/content/locales/es-ES/dispatch.mdx +3 -3
  34. package/corpus/core/docs/content/locales/es-ES/external-agents.mdx +32 -19
  35. package/corpus/core/docs/content/locales/es-ES/mcp-clients.mdx +17 -3
  36. package/corpus/core/docs/content/locales/es-ES/mcp-protocol.mdx +38 -15
  37. package/corpus/core/docs/content/locales/es-ES/plan-plugin.mdx +3 -3
  38. package/corpus/core/docs/content/locales/es-ES/server.mdx +2 -2
  39. package/corpus/core/docs/content/locales/es-ES/skills-guide.mdx +1 -1
  40. package/corpus/core/docs/content/locales/es-ES/template-assets.mdx +1 -1
  41. package/corpus/core/docs/content/locales/es-ES/template-dispatch.mdx +2 -2
  42. package/corpus/core/docs/content/locales/es-ES/template-plan.mdx +3 -3
  43. package/corpus/core/docs/content/locales/fr-FR/actions.mdx +1 -1
  44. package/corpus/core/docs/content/locales/fr-FR/authentication.mdx +1 -1
  45. package/corpus/core/docs/content/locales/fr-FR/dispatch.mdx +3 -3
  46. package/corpus/core/docs/content/locales/fr-FR/external-agents.mdx +23 -19
  47. package/corpus/core/docs/content/locales/fr-FR/mcp-clients.mdx +17 -3
  48. package/corpus/core/docs/content/locales/fr-FR/mcp-protocol.mdx +29 -15
  49. package/corpus/core/docs/content/locales/fr-FR/plan-plugin.mdx +3 -3
  50. package/corpus/core/docs/content/locales/fr-FR/server.mdx +2 -2
  51. package/corpus/core/docs/content/locales/fr-FR/skills-guide.mdx +1 -1
  52. package/corpus/core/docs/content/locales/fr-FR/template-assets.mdx +1 -1
  53. package/corpus/core/docs/content/locales/fr-FR/template-dispatch.mdx +2 -2
  54. package/corpus/core/docs/content/locales/fr-FR/template-plan.mdx +3 -3
  55. package/corpus/core/docs/content/locales/hi-IN/actions.mdx +1 -1
  56. package/corpus/core/docs/content/locales/hi-IN/authentication.mdx +1 -1
  57. package/corpus/core/docs/content/locales/hi-IN/dispatch.mdx +3 -3
  58. package/corpus/core/docs/content/locales/hi-IN/external-agents.mdx +31 -19
  59. package/corpus/core/docs/content/locales/hi-IN/mcp-clients.mdx +17 -3
  60. package/corpus/core/docs/content/locales/hi-IN/mcp-protocol.mdx +36 -15
  61. package/corpus/core/docs/content/locales/hi-IN/plan-plugin.mdx +3 -3
  62. package/corpus/core/docs/content/locales/hi-IN/server.mdx +2 -2
  63. package/corpus/core/docs/content/locales/hi-IN/skills-guide.mdx +1 -1
  64. package/corpus/core/docs/content/locales/hi-IN/template-assets.mdx +1 -1
  65. package/corpus/core/docs/content/locales/hi-IN/template-dispatch.mdx +2 -2
  66. package/corpus/core/docs/content/locales/hi-IN/template-plan.mdx +3 -3
  67. package/corpus/core/docs/content/locales/ja-JP/actions.mdx +1 -1
  68. package/corpus/core/docs/content/locales/ja-JP/authentication.mdx +1 -1
  69. package/corpus/core/docs/content/locales/ja-JP/dispatch.mdx +3 -3
  70. package/corpus/core/docs/content/locales/ja-JP/external-agents.mdx +23 -19
  71. package/corpus/core/docs/content/locales/ja-JP/mcp-clients.mdx +34 -3
  72. package/corpus/core/docs/content/locales/ja-JP/mcp-protocol.mdx +29 -15
  73. package/corpus/core/docs/content/locales/ja-JP/plan-plugin.mdx +3 -3
  74. package/corpus/core/docs/content/locales/ja-JP/server.mdx +2 -2
  75. package/corpus/core/docs/content/locales/ja-JP/skills-guide.mdx +1 -1
  76. package/corpus/core/docs/content/locales/ja-JP/template-assets.mdx +1 -1
  77. package/corpus/core/docs/content/locales/ja-JP/template-dispatch.mdx +2 -2
  78. package/corpus/core/docs/content/locales/ja-JP/template-plan.mdx +3 -3
  79. package/corpus/core/docs/content/locales/ko-KR/actions.mdx +1 -1
  80. package/corpus/core/docs/content/locales/ko-KR/authentication.mdx +1 -1
  81. package/corpus/core/docs/content/locales/ko-KR/dispatch.mdx +3 -3
  82. package/corpus/core/docs/content/locales/ko-KR/external-agents.mdx +30 -19
  83. package/corpus/core/docs/content/locales/ko-KR/mcp-clients.mdx +33 -3
  84. package/corpus/core/docs/content/locales/ko-KR/mcp-protocol.mdx +36 -15
  85. package/corpus/core/docs/content/locales/ko-KR/plan-plugin.mdx +3 -3
  86. package/corpus/core/docs/content/locales/ko-KR/server.mdx +2 -2
  87. package/corpus/core/docs/content/locales/ko-KR/skills-guide.mdx +1 -1
  88. package/corpus/core/docs/content/locales/ko-KR/template-assets.mdx +1 -1
  89. package/corpus/core/docs/content/locales/ko-KR/template-dispatch.mdx +2 -2
  90. package/corpus/core/docs/content/locales/ko-KR/template-plan.mdx +3 -3
  91. package/corpus/core/docs/content/locales/pt-BR/actions.mdx +1 -1
  92. package/corpus/core/docs/content/locales/pt-BR/authentication.mdx +1 -1
  93. package/corpus/core/docs/content/locales/pt-BR/dispatch.mdx +3 -3
  94. package/corpus/core/docs/content/locales/pt-BR/external-agents.mdx +32 -19
  95. package/corpus/core/docs/content/locales/pt-BR/mcp-clients.mdx +34 -3
  96. package/corpus/core/docs/content/locales/pt-BR/mcp-protocol.mdx +32 -15
  97. package/corpus/core/docs/content/locales/pt-BR/plan-plugin.mdx +3 -3
  98. package/corpus/core/docs/content/locales/pt-BR/server.mdx +2 -2
  99. package/corpus/core/docs/content/locales/pt-BR/skills-guide.mdx +1 -1
  100. package/corpus/core/docs/content/locales/pt-BR/template-assets.mdx +1 -1
  101. package/corpus/core/docs/content/locales/pt-BR/template-dispatch.mdx +2 -2
  102. package/corpus/core/docs/content/locales/pt-BR/template-plan.mdx +3 -3
  103. package/corpus/core/docs/content/locales/zh-CN/actions.mdx +1 -1
  104. package/corpus/core/docs/content/locales/zh-CN/authentication.mdx +1 -1
  105. package/corpus/core/docs/content/locales/zh-CN/dispatch.mdx +3 -3
  106. package/corpus/core/docs/content/locales/zh-CN/external-agents.mdx +23 -19
  107. package/corpus/core/docs/content/locales/zh-CN/mcp-clients.mdx +28 -3
  108. package/corpus/core/docs/content/locales/zh-CN/mcp-protocol.mdx +29 -15
  109. package/corpus/core/docs/content/locales/zh-CN/plan-plugin.mdx +3 -3
  110. package/corpus/core/docs/content/locales/zh-CN/server.mdx +2 -2
  111. package/corpus/core/docs/content/locales/zh-CN/skills-guide.mdx +1 -1
  112. package/corpus/core/docs/content/locales/zh-CN/template-assets.mdx +1 -1
  113. package/corpus/core/docs/content/locales/zh-CN/template-dispatch.mdx +2 -2
  114. package/corpus/core/docs/content/locales/zh-CN/template-plan.mdx +3 -3
  115. package/corpus/core/docs/content/locales/zh-TW/actions.mdx +1 -1
  116. package/corpus/core/docs/content/locales/zh-TW/authentication.mdx +1 -1
  117. package/corpus/core/docs/content/locales/zh-TW/dispatch.mdx +3 -3
  118. package/corpus/core/docs/content/locales/zh-TW/external-agents.mdx +23 -19
  119. package/corpus/core/docs/content/locales/zh-TW/mcp-clients.mdx +28 -3
  120. package/corpus/core/docs/content/locales/zh-TW/mcp-protocol.mdx +30 -15
  121. package/corpus/core/docs/content/locales/zh-TW/plan-plugin.mdx +3 -3
  122. package/corpus/core/docs/content/locales/zh-TW/server.mdx +2 -2
  123. package/corpus/core/docs/content/locales/zh-TW/skills-guide.mdx +1 -1
  124. package/corpus/core/docs/content/locales/zh-TW/template-assets.mdx +1 -1
  125. package/corpus/core/docs/content/locales/zh-TW/template-dispatch.mdx +2 -2
  126. package/corpus/core/docs/content/locales/zh-TW/template-plan.mdx +3 -3
  127. package/corpus/core/docs/content/mcp-clients.mdx +31 -4
  128. package/corpus/core/docs/content/mcp-protocol.mdx +35 -15
  129. package/corpus/core/docs/content/plan-plugin.mdx +3 -3
  130. package/corpus/core/docs/content/server.mdx +2 -2
  131. package/corpus/core/docs/content/skills-guide.mdx +1 -1
  132. package/corpus/core/docs/content/template-assets.mdx +1 -1
  133. package/corpus/core/docs/content/template-dispatch.mdx +2 -2
  134. package/corpus/core/docs/content/template-plan.mdx +3 -3
  135. package/corpus/core/package.json +1 -1
  136. package/corpus/core/src/a2a/client.ts +3 -0
  137. package/corpus/core/src/a2a/handlers.ts +95 -7
  138. package/corpus/core/src/agent/production-agent.ts +21 -0
  139. package/corpus/core/src/cli/connect.ts +50 -24
  140. package/corpus/core/src/cli/mcp-config-writers.ts +10 -0
  141. package/corpus/core/src/cli/mcp.ts +5 -5
  142. package/corpus/core/src/cli/pr-visual-recap-workflow.ts +1 -1
  143. package/corpus/core/src/cli/skills-content/assets-skill.ts +1 -1
  144. package/corpus/core/src/cli/skills-content/design-exploration-skill.ts +1 -1
  145. package/corpus/core/src/cli/skills-content/help.ts +1 -1
  146. package/corpus/core/src/cli/skills-content/plan-setup-auth.ts +1 -1
  147. package/corpus/core/src/cli/skills-content/visual-plan-skill.ts +1 -1
  148. package/corpus/core/src/cli/skills-content/visual-recap-skill.ts +2 -2
  149. package/corpus/core/src/cli/skills.ts +23 -12
  150. package/corpus/core/src/client/analytics.ts +13 -0
  151. package/corpus/core/src/client/resources/McpIntegrationDialog.tsx +5 -0
  152. package/corpus/core/src/client/resources/mcp-integration-catalog.ts +17 -0
  153. package/corpus/core/src/embedding/agent.ts +8 -6
  154. package/corpus/core/src/localization/default-messages.ts +7 -0
  155. package/corpus/core/src/mcp/ask-app-inline-tasks.ts +125 -0
  156. package/corpus/core/src/mcp/build-server.ts +65 -3
  157. package/corpus/core/src/mcp/builtin-tools.ts +186 -22
  158. package/corpus/core/src/mcp/connect-route.ts +17 -14
  159. package/corpus/core/src/mcp/oauth-route.ts +38 -13
  160. package/corpus/core/src/mcp/route-paths.ts +34 -0
  161. package/corpus/core/src/mcp/server.ts +21 -10
  162. package/corpus/core/src/mcp/stdio.ts +34 -16
  163. package/corpus/core/src/mcp/workspace-resolve.ts +2 -1
  164. package/corpus/core/src/mcp-client/manager.ts +5 -3
  165. package/corpus/core/src/mcp-client/remote-store.ts +10 -10
  166. package/corpus/core/src/server/agent-chat/action-filters-a2a.ts +13 -0
  167. package/corpus/core/src/server/agent-chat-plugin.ts +42 -9
  168. package/corpus/core/src/server/agent-teams.ts +17 -0
  169. package/corpus/core/src/server/auth.ts +22 -6
  170. package/corpus/core/src/server/core-routes-plugin.ts +30 -24
  171. package/corpus/core/src/server/csrf.ts +17 -0
  172. package/corpus/core/src/server/framework-request-handler.ts +8 -2
  173. package/corpus/core/src/server/google-oauth.ts +12 -2
  174. package/corpus/core/src/server/http-response-telemetry.ts +6 -1
  175. package/corpus/core/src/server/recap-image-route.ts +3 -3
  176. package/corpus/core/src/server/security-headers.ts +7 -1
  177. package/corpus/core/src/server/ssr-handler.ts +2 -0
  178. package/corpus/core/src/shared/cache-control.ts +6 -4
  179. package/corpus/core/src/templates/default/.agents/skills/security/SKILL.md +10 -0
  180. package/corpus/core/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +15 -6
  181. package/corpus/core/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +16 -10
  182. package/corpus/core/src/templates/workspace-core/.agents/skills/performance/SKILL.md +20 -1
  183. package/corpus/core/src/templates/workspace-core/.agents/skills/security/SKILL.md +10 -0
  184. package/corpus/templates/analytics/.agents/skills/security/SKILL.md +10 -0
  185. package/corpus/templates/analytics/app/assets/replay-cursor.svg +17 -0
  186. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +4 -3
  187. package/corpus/templates/analytics/app/global.css +71 -4
  188. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/DashboardFilterBar.tsx +32 -4
  189. package/corpus/templates/analytics/app/pages/monitoring/errors/IssueDetail.tsx +1 -1
  190. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +49 -11
  191. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +4 -6
  192. package/corpus/templates/analytics/changelog/2026-07-13-all-time-dashboard-filters-no-longer-send-invalid-dates-to-b.md +6 -0
  193. package/corpus/templates/analytics/changelog/2026-07-13-daily-dashboard-emails-recover-more-reliably-from-serverless.md +6 -0
  194. package/corpus/templates/analytics/changelog/2026-07-13-error-issue-titles-wrap-instead-of-overflowing.md +6 -0
  195. package/corpus/templates/analytics/changelog/2026-07-13-saving-a-new-dashboard-view-no-longer-fails-with-a-server-er.md +6 -0
  196. package/corpus/templates/analytics/changelog/2026-07-13-session-replay-cursors-stay-hidden-until-their-first-recorde.md +6 -0
  197. package/corpus/templates/analytics/changelog/2026-07-13-session-replay-links-now-support-cmd-click-and-middle-click-.md +6 -0
  198. package/corpus/templates/analytics/changelog/2026-07-13-session-replays-keep-a-visible-mac-style-cursor-over-the-vis.md +6 -0
  199. package/corpus/templates/analytics/server/jobs/dashboard-report.ts +21 -2
  200. package/corpus/templates/analytics/server/lib/dashboard-report-subscriptions.ts +57 -1
  201. package/corpus/templates/analytics/server/lib/dashboard-report.ts +266 -28
  202. package/corpus/templates/analytics/server/lib/dashboards-store.ts +43 -4
  203. package/corpus/templates/analytics/server/lib/error-capture.ts +24 -5
  204. package/corpus/templates/analytics/server/plugins/agent-chat.ts +5 -0
  205. package/corpus/templates/analytics/server/routes/[...page].get.ts +0 -2
  206. package/corpus/templates/assets/.agents/skills/security/SKILL.md +10 -0
  207. package/corpus/templates/assets/agent-native.app-skill.json +1 -1
  208. package/corpus/templates/brain/.agents/skills/security/SKILL.md +10 -0
  209. package/corpus/templates/calendar/.agents/skills/security/SKILL.md +10 -0
  210. package/corpus/templates/calendar/AGENTS.md +2 -1
  211. package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +0 -19
  212. package/corpus/templates/calendar/app/lib/attendee-local-time.ts +14 -5
  213. package/corpus/templates/calendar/changelog/2026-07-13-your-local-time-now-follows-your-browser-timezone-and-event-.md +6 -0
  214. package/corpus/templates/chat/.agents/skills/security/SKILL.md +10 -0
  215. package/corpus/templates/clips/.agents/skills/recording/SKILL.md +7 -2
  216. package/corpus/templates/clips/.agents/skills/security/SKILL.md +10 -0
  217. package/corpus/templates/clips/AGENTS.md +7 -0
  218. package/corpus/templates/clips/actions/list-meetings.ts +19 -4
  219. package/corpus/templates/clips/actions/start-meeting-recording.ts +7 -1
  220. package/corpus/templates/clips/app/components/library/recording-card.tsx +27 -26
  221. package/corpus/templates/clips/app/components/library/space-card.tsx +4 -6
  222. package/corpus/templates/clips/app/components/meetings/transcript-bubbles.tsx +75 -78
  223. package/corpus/templates/clips/app/components/recorder/confetti-canvas.tsx +18 -1
  224. package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +6 -12
  225. package/corpus/templates/clips/app/components/recorder/recording-toolbar.tsx +19 -2
  226. package/corpus/templates/clips/app/lib/camera-composite.ts +70 -10
  227. package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +1 -1
  228. package/corpus/templates/clips/app/routes/record.tsx +5 -25
  229. package/corpus/templates/clips/changelog/2026-07-13-clips-desktop-now-requires-macos-13-for-native-capture.md +6 -0
  230. package/corpus/templates/clips/changelog/2026-07-13-clips-hide-solo-meeting-reminders.md +6 -0
  231. package/corpus/templates/clips/changelog/2026-07-13-clips-now-removes-duplicate-mic-and-system-transcript-turns-.md +6 -0
  232. package/corpus/templates/clips/changelog/2026-07-13-desktop-recordings-run-cooler-and-quieter-live-transcription.md +6 -0
  233. package/corpus/templates/clips/changelog/2026-07-13-meeting-recordings-now-stop-after-a-calendar-meeting-ends-an.md +6 -0
  234. package/corpus/templates/clips/changelog/2026-07-13-meeting-transcripts-now-use-a-clean-agent-chat-style-reading.md +6 -0
  235. package/corpus/templates/clips/changelog/2026-07-13-screen-recordings-use-less-processing-power-during-longer-ca.md +6 -0
  236. package/corpus/templates/clips/chrome-extension/src/background.ts +5 -3
  237. package/corpus/templates/clips/chrome-extension/src/offscreen.ts +17 -14
  238. package/corpus/templates/clips/chrome-extension/src/overlay.ts +8 -2
  239. package/corpus/templates/clips/desktop/README.md +3 -0
  240. package/corpus/templates/clips/desktop/src/hooks/useMeetingTranscription.ts +9 -0
  241. package/corpus/templates/clips/desktop/src/lib/recorder.ts +8 -2
  242. package/corpus/templates/clips/desktop/src/lib/silence-events.ts +1 -0
  243. package/corpus/templates/clips/desktop/src/lib/transcription-capture.ts +5 -0
  244. package/corpus/templates/clips/desktop/src/lib/transcription-engine.ts +134 -5
  245. package/corpus/templates/clips/desktop/src/lib/upload-video-stream.ts +28 -0
  246. package/corpus/templates/clips/desktop/src/overlays/flow-bar.tsx +10 -3
  247. package/corpus/templates/clips/desktop/src/overlays/meeting-notification.tsx +42 -9
  248. package/corpus/templates/clips/desktop/src/overlays/recording-pill.tsx +10 -2
  249. package/corpus/templates/clips/desktop/src-tauri/Cargo.toml +6 -1
  250. package/corpus/templates/clips/desktop/src-tauri/src/notifications.rs +77 -1
  251. package/corpus/templates/clips/desktop/src-tauri/src/silence_detector.rs +104 -25
  252. package/corpus/templates/clips/desktop/src-tauri/src/system_audio.rs +4 -0
  253. package/corpus/templates/clips/desktop/src-tauri/src/whisper_speech.rs +287 -32
  254. package/corpus/templates/clips/desktop/src-tauri/tauri.conf.json +1 -1
  255. package/corpus/templates/clips/server/lib/calendar-event-classification.ts +28 -0
  256. package/corpus/templates/clips/server/routes/[...page].get.ts +1 -59
  257. package/corpus/templates/clips/shared/recording-capture.ts +37 -0
  258. package/corpus/templates/content/.agents/skills/security/SKILL.md +10 -0
  259. package/corpus/templates/content/agent-native.app-skill.json +1 -1
  260. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +18 -16
  261. package/corpus/templates/content/server/routes/[...page].get.ts +1 -15
  262. package/corpus/templates/design/.agents/skills/security/SKILL.md +10 -0
  263. package/corpus/templates/design/actions/connect-assets-mcp.ts +1 -1
  264. package/corpus/templates/design/agent-native.app-skill.json +1 -1
  265. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +88 -12
  266. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +1 -0
  267. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +4 -1
  268. package/corpus/templates/design/changelog/2026-07-13-adding-shapes-preserves-canvas-background.md +6 -0
  269. package/corpus/templates/design/changelog/2026-07-13-clicking-quickly-between-overlapping-elements-no-longer-bounc.md +6 -0
  270. package/corpus/templates/design/server/plugins/assets-mcp.ts +1 -1
  271. package/corpus/templates/design/server/routes/[...page].get.ts +0 -2
  272. package/corpus/templates/dispatch/.agents/skills/security/SKILL.md +10 -0
  273. package/corpus/templates/forms/.agents/skills/security/SKILL.md +10 -0
  274. package/corpus/templates/macros/.agents/skills/security/SKILL.md +10 -0
  275. package/corpus/templates/mail/.agents/skills/security/SKILL.md +10 -0
  276. package/corpus/templates/plan/.agents/skills/security/SKILL.md +10 -0
  277. package/corpus/templates/plan/.agents/skills/visual-plan/SKILL.md +1 -1
  278. package/corpus/templates/plan/.agents/skills/visual-recap/SKILL.md +2 -2
  279. package/corpus/templates/plan/agent-native.app-skill.json +1 -1
  280. package/corpus/templates/plan/app/lib/plan-local-bridge.ts +6 -1
  281. package/corpus/templates/plan/app/pages/PlansPage.tsx +15 -6
  282. package/corpus/templates/plan/changelog/2026-07-13-fixed-local-plan-previews-continuously-flickering-while-revi.md +6 -0
  283. package/corpus/templates/plan/server/routes/[...page].get.ts +0 -2
  284. package/corpus/templates/slides/.agents/skills/security/SKILL.md +10 -0
  285. package/dist/a2a/client.d.ts +2 -0
  286. package/dist/a2a/client.d.ts.map +1 -1
  287. package/dist/a2a/client.js +2 -0
  288. package/dist/a2a/client.js.map +1 -1
  289. package/dist/a2a/handlers.d.ts.map +1 -1
  290. package/dist/a2a/handlers.js +84 -7
  291. package/dist/a2a/handlers.js.map +1 -1
  292. package/dist/agent/production-agent.d.ts +9 -0
  293. package/dist/agent/production-agent.d.ts.map +1 -1
  294. package/dist/agent/production-agent.js +12 -0
  295. package/dist/agent/production-agent.js.map +1 -1
  296. package/dist/cli/connect.d.ts +2 -2
  297. package/dist/cli/connect.d.ts.map +1 -1
  298. package/dist/cli/connect.js +45 -23
  299. package/dist/cli/connect.js.map +1 -1
  300. package/dist/cli/mcp-config-writers.d.ts.map +1 -1
  301. package/dist/cli/mcp-config-writers.js +7 -0
  302. package/dist/cli/mcp-config-writers.js.map +1 -1
  303. package/dist/cli/mcp.js +5 -3
  304. package/dist/cli/mcp.js.map +1 -1
  305. package/dist/cli/pr-visual-recap-workflow.d.ts +1 -1
  306. package/dist/cli/pr-visual-recap-workflow.d.ts.map +1 -1
  307. package/dist/cli/pr-visual-recap-workflow.js +1 -1
  308. package/dist/cli/pr-visual-recap-workflow.js.map +1 -1
  309. package/dist/cli/skills-content/assets-skill.d.ts +1 -1
  310. package/dist/cli/skills-content/assets-skill.d.ts.map +1 -1
  311. package/dist/cli/skills-content/assets-skill.js +1 -1
  312. package/dist/cli/skills-content/assets-skill.js.map +1 -1
  313. package/dist/cli/skills-content/design-exploration-skill.d.ts +1 -1
  314. package/dist/cli/skills-content/design-exploration-skill.d.ts.map +1 -1
  315. package/dist/cli/skills-content/design-exploration-skill.js +1 -1
  316. package/dist/cli/skills-content/design-exploration-skill.js.map +1 -1
  317. package/dist/cli/skills-content/help.d.ts +1 -1
  318. package/dist/cli/skills-content/help.d.ts.map +1 -1
  319. package/dist/cli/skills-content/help.js +1 -1
  320. package/dist/cli/skills-content/help.js.map +1 -1
  321. package/dist/cli/skills-content/plan-setup-auth.d.ts +1 -1
  322. package/dist/cli/skills-content/plan-setup-auth.d.ts.map +1 -1
  323. package/dist/cli/skills-content/plan-setup-auth.js +1 -1
  324. package/dist/cli/skills-content/plan-setup-auth.js.map +1 -1
  325. package/dist/cli/skills-content/visual-plan-skill.d.ts +1 -1
  326. package/dist/cli/skills-content/visual-plan-skill.d.ts.map +1 -1
  327. package/dist/cli/skills-content/visual-plan-skill.js +1 -1
  328. package/dist/cli/skills-content/visual-plan-skill.js.map +1 -1
  329. package/dist/cli/skills-content/visual-recap-skill.d.ts +1 -1
  330. package/dist/cli/skills-content/visual-recap-skill.d.ts.map +1 -1
  331. package/dist/cli/skills-content/visual-recap-skill.js +2 -2
  332. package/dist/cli/skills-content/visual-recap-skill.js.map +1 -1
  333. package/dist/cli/skills.d.ts.map +1 -1
  334. package/dist/cli/skills.js +16 -12
  335. package/dist/cli/skills.js.map +1 -1
  336. package/dist/client/analytics.d.ts.map +1 -1
  337. package/dist/client/analytics.js +11 -0
  338. package/dist/client/analytics.js.map +1 -1
  339. package/dist/client/resources/McpIntegrationDialog.d.ts.map +1 -1
  340. package/dist/client/resources/McpIntegrationDialog.js +1 -1
  341. package/dist/client/resources/McpIntegrationDialog.js.map +1 -1
  342. package/dist/client/resources/mcp-integration-catalog.d.ts +1 -0
  343. package/dist/client/resources/mcp-integration-catalog.d.ts.map +1 -1
  344. package/dist/client/resources/mcp-integration-catalog.js +14 -0
  345. package/dist/client/resources/mcp-integration-catalog.js.map +1 -1
  346. package/dist/collab/awareness.d.ts +2 -2
  347. package/dist/collab/awareness.d.ts.map +1 -1
  348. package/dist/collab/routes.d.ts +1 -1
  349. package/dist/collab/struct-routes.d.ts +1 -1
  350. package/dist/embedding/agent.d.ts.map +1 -1
  351. package/dist/embedding/agent.js +6 -7
  352. package/dist/embedding/agent.js.map +1 -1
  353. package/dist/localization/default-messages.d.ts +5 -0
  354. package/dist/localization/default-messages.d.ts.map +1 -1
  355. package/dist/localization/default-messages.js +5 -0
  356. package/dist/localization/default-messages.js.map +1 -1
  357. package/dist/mcp/ask-app-inline-tasks.d.ts +47 -0
  358. package/dist/mcp/ask-app-inline-tasks.d.ts.map +1 -0
  359. package/dist/mcp/ask-app-inline-tasks.js +87 -0
  360. package/dist/mcp/ask-app-inline-tasks.js.map +1 -0
  361. package/dist/mcp/build-server.d.ts.map +1 -1
  362. package/dist/mcp/build-server.js +56 -3
  363. package/dist/mcp/build-server.js.map +1 -1
  364. package/dist/mcp/builtin-tools.d.ts.map +1 -1
  365. package/dist/mcp/builtin-tools.js +141 -21
  366. package/dist/mcp/builtin-tools.js.map +1 -1
  367. package/dist/mcp/connect-route.d.ts +12 -10
  368. package/dist/mcp/connect-route.d.ts.map +1 -1
  369. package/dist/mcp/connect-route.js +17 -14
  370. package/dist/mcp/connect-route.js.map +1 -1
  371. package/dist/mcp/oauth-route.d.ts +1 -1
  372. package/dist/mcp/oauth-route.d.ts.map +1 -1
  373. package/dist/mcp/oauth-route.js +30 -13
  374. package/dist/mcp/oauth-route.js.map +1 -1
  375. package/dist/mcp/route-paths.d.ts +13 -0
  376. package/dist/mcp/route-paths.d.ts.map +1 -0
  377. package/dist/mcp/route-paths.js +27 -0
  378. package/dist/mcp/route-paths.js.map +1 -0
  379. package/dist/mcp/server.d.ts +2 -1
  380. package/dist/mcp/server.d.ts.map +1 -1
  381. package/dist/mcp/server.js +14 -6
  382. package/dist/mcp/server.js.map +1 -1
  383. package/dist/mcp/stdio.d.ts +7 -6
  384. package/dist/mcp/stdio.d.ts.map +1 -1
  385. package/dist/mcp/stdio.js +27 -15
  386. package/dist/mcp/stdio.js.map +1 -1
  387. package/dist/mcp/workspace-resolve.d.ts +2 -1
  388. package/dist/mcp/workspace-resolve.d.ts.map +1 -1
  389. package/dist/mcp/workspace-resolve.js +2 -1
  390. package/dist/mcp/workspace-resolve.js.map +1 -1
  391. package/dist/mcp-client/manager.js +6 -3
  392. package/dist/mcp-client/manager.js.map +1 -1
  393. package/dist/mcp-client/remote-store.js +5 -7
  394. package/dist/mcp-client/remote-store.js.map +1 -1
  395. package/dist/notifications/routes.d.ts +3 -3
  396. package/dist/progress/routes.d.ts +1 -1
  397. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  398. package/dist/resources/handlers.d.ts +2 -2
  399. package/dist/server/agent-chat/action-filters-a2a.d.ts.map +1 -1
  400. package/dist/server/agent-chat/action-filters-a2a.js +11 -1
  401. package/dist/server/agent-chat/action-filters-a2a.js.map +1 -1
  402. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  403. package/dist/server/agent-chat-plugin.js +43 -11
  404. package/dist/server/agent-chat-plugin.js.map +1 -1
  405. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  406. package/dist/server/agent-teams.d.ts.map +1 -1
  407. package/dist/server/agent-teams.js +15 -1
  408. package/dist/server/agent-teams.js.map +1 -1
  409. package/dist/server/auth.d.ts.map +1 -1
  410. package/dist/server/auth.js +16 -6
  411. package/dist/server/auth.js.map +1 -1
  412. package/dist/server/core-routes-plugin.d.ts +4 -3
  413. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  414. package/dist/server/core-routes-plugin.js +20 -15
  415. package/dist/server/core-routes-plugin.js.map +1 -1
  416. package/dist/server/csrf.d.ts.map +1 -1
  417. package/dist/server/csrf.js +11 -0
  418. package/dist/server/csrf.js.map +1 -1
  419. package/dist/server/framework-request-handler.d.ts.map +1 -1
  420. package/dist/server/framework-request-handler.js +8 -2
  421. package/dist/server/framework-request-handler.js.map +1 -1
  422. package/dist/server/google-oauth.d.ts +2 -0
  423. package/dist/server/google-oauth.d.ts.map +1 -1
  424. package/dist/server/google-oauth.js +11 -2
  425. package/dist/server/google-oauth.js.map +1 -1
  426. package/dist/server/http-response-telemetry.d.ts.map +1 -1
  427. package/dist/server/http-response-telemetry.js +4 -1
  428. package/dist/server/http-response-telemetry.js.map +1 -1
  429. package/dist/server/recap-image-route.js +3 -3
  430. package/dist/server/recap-image-route.js.map +1 -1
  431. package/dist/server/security-headers.d.ts.map +1 -1
  432. package/dist/server/security-headers.js +4 -1
  433. package/dist/server/security-headers.js.map +1 -1
  434. package/dist/server/ssr-handler.d.ts.map +1 -1
  435. package/dist/server/ssr-handler.js +3 -1
  436. package/dist/server/ssr-handler.js.map +1 -1
  437. package/dist/shared/cache-control.d.ts +7 -6
  438. package/dist/shared/cache-control.d.ts.map +1 -1
  439. package/dist/shared/cache-control.js +4 -3
  440. package/dist/shared/cache-control.js.map +1 -1
  441. package/dist/templates/default/.agents/skills/security/SKILL.md +10 -0
  442. package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +15 -6
  443. package/dist/templates/workspace-core/.agents/skills/external-agents/SKILL.md +16 -10
  444. package/dist/templates/workspace-core/.agents/skills/performance/SKILL.md +20 -1
  445. package/dist/templates/workspace-core/.agents/skills/security/SKILL.md +10 -0
  446. package/docs/content/actions.mdx +1 -1
  447. package/docs/content/authentication.mdx +1 -1
  448. package/docs/content/dispatch.mdx +3 -3
  449. package/docs/content/external-agents.mdx +30 -19
  450. package/docs/content/locales/ar-SA/actions.mdx +1 -1
  451. package/docs/content/locales/ar-SA/authentication.mdx +1 -1
  452. package/docs/content/locales/ar-SA/dispatch.mdx +3 -3
  453. package/docs/content/locales/ar-SA/external-agents.mdx +23 -19
  454. package/docs/content/locales/ar-SA/mcp-clients.mdx +31 -3
  455. package/docs/content/locales/ar-SA/mcp-protocol.mdx +29 -15
  456. package/docs/content/locales/ar-SA/plan-plugin.mdx +3 -3
  457. package/docs/content/locales/ar-SA/server.mdx +2 -2
  458. package/docs/content/locales/ar-SA/skills-guide.mdx +1 -1
  459. package/docs/content/locales/ar-SA/template-assets.mdx +1 -1
  460. package/docs/content/locales/ar-SA/template-dispatch.mdx +2 -2
  461. package/docs/content/locales/ar-SA/template-plan.mdx +3 -3
  462. package/docs/content/locales/de-DE/actions.mdx +1 -1
  463. package/docs/content/locales/de-DE/authentication.mdx +1 -1
  464. package/docs/content/locales/de-DE/dispatch.mdx +3 -3
  465. package/docs/content/locales/de-DE/external-agents.mdx +23 -19
  466. package/docs/content/locales/de-DE/mcp-clients.mdx +37 -3
  467. package/docs/content/locales/de-DE/mcp-protocol.mdx +29 -15
  468. package/docs/content/locales/de-DE/plan-plugin.mdx +3 -3
  469. package/docs/content/locales/de-DE/server.mdx +2 -2
  470. package/docs/content/locales/de-DE/skills-guide.mdx +1 -1
  471. package/docs/content/locales/de-DE/template-assets.mdx +1 -1
  472. package/docs/content/locales/de-DE/template-dispatch.mdx +2 -2
  473. package/docs/content/locales/de-DE/template-plan.mdx +3 -3
  474. package/docs/content/locales/es-ES/actions.mdx +1 -1
  475. package/docs/content/locales/es-ES/authentication.mdx +1 -1
  476. package/docs/content/locales/es-ES/dispatch.mdx +3 -3
  477. package/docs/content/locales/es-ES/external-agents.mdx +32 -19
  478. package/docs/content/locales/es-ES/mcp-clients.mdx +17 -3
  479. package/docs/content/locales/es-ES/mcp-protocol.mdx +38 -15
  480. package/docs/content/locales/es-ES/plan-plugin.mdx +3 -3
  481. package/docs/content/locales/es-ES/server.mdx +2 -2
  482. package/docs/content/locales/es-ES/skills-guide.mdx +1 -1
  483. package/docs/content/locales/es-ES/template-assets.mdx +1 -1
  484. package/docs/content/locales/es-ES/template-dispatch.mdx +2 -2
  485. package/docs/content/locales/es-ES/template-plan.mdx +3 -3
  486. package/docs/content/locales/fr-FR/actions.mdx +1 -1
  487. package/docs/content/locales/fr-FR/authentication.mdx +1 -1
  488. package/docs/content/locales/fr-FR/dispatch.mdx +3 -3
  489. package/docs/content/locales/fr-FR/external-agents.mdx +23 -19
  490. package/docs/content/locales/fr-FR/mcp-clients.mdx +17 -3
  491. package/docs/content/locales/fr-FR/mcp-protocol.mdx +29 -15
  492. package/docs/content/locales/fr-FR/plan-plugin.mdx +3 -3
  493. package/docs/content/locales/fr-FR/server.mdx +2 -2
  494. package/docs/content/locales/fr-FR/skills-guide.mdx +1 -1
  495. package/docs/content/locales/fr-FR/template-assets.mdx +1 -1
  496. package/docs/content/locales/fr-FR/template-dispatch.mdx +2 -2
  497. package/docs/content/locales/fr-FR/template-plan.mdx +3 -3
  498. package/docs/content/locales/hi-IN/actions.mdx +1 -1
  499. package/docs/content/locales/hi-IN/authentication.mdx +1 -1
  500. package/docs/content/locales/hi-IN/dispatch.mdx +3 -3
  501. package/docs/content/locales/hi-IN/external-agents.mdx +31 -19
  502. package/docs/content/locales/hi-IN/mcp-clients.mdx +17 -3
  503. package/docs/content/locales/hi-IN/mcp-protocol.mdx +36 -15
  504. package/docs/content/locales/hi-IN/plan-plugin.mdx +3 -3
  505. package/docs/content/locales/hi-IN/server.mdx +2 -2
  506. package/docs/content/locales/hi-IN/skills-guide.mdx +1 -1
  507. package/docs/content/locales/hi-IN/template-assets.mdx +1 -1
  508. package/docs/content/locales/hi-IN/template-dispatch.mdx +2 -2
  509. package/docs/content/locales/hi-IN/template-plan.mdx +3 -3
  510. package/docs/content/locales/ja-JP/actions.mdx +1 -1
  511. package/docs/content/locales/ja-JP/authentication.mdx +1 -1
  512. package/docs/content/locales/ja-JP/dispatch.mdx +3 -3
  513. package/docs/content/locales/ja-JP/external-agents.mdx +23 -19
  514. package/docs/content/locales/ja-JP/mcp-clients.mdx +34 -3
  515. package/docs/content/locales/ja-JP/mcp-protocol.mdx +29 -15
  516. package/docs/content/locales/ja-JP/plan-plugin.mdx +3 -3
  517. package/docs/content/locales/ja-JP/server.mdx +2 -2
  518. package/docs/content/locales/ja-JP/skills-guide.mdx +1 -1
  519. package/docs/content/locales/ja-JP/template-assets.mdx +1 -1
  520. package/docs/content/locales/ja-JP/template-dispatch.mdx +2 -2
  521. package/docs/content/locales/ja-JP/template-plan.mdx +3 -3
  522. package/docs/content/locales/ko-KR/actions.mdx +1 -1
  523. package/docs/content/locales/ko-KR/authentication.mdx +1 -1
  524. package/docs/content/locales/ko-KR/dispatch.mdx +3 -3
  525. package/docs/content/locales/ko-KR/external-agents.mdx +30 -19
  526. package/docs/content/locales/ko-KR/mcp-clients.mdx +33 -3
  527. package/docs/content/locales/ko-KR/mcp-protocol.mdx +36 -15
  528. package/docs/content/locales/ko-KR/plan-plugin.mdx +3 -3
  529. package/docs/content/locales/ko-KR/server.mdx +2 -2
  530. package/docs/content/locales/ko-KR/skills-guide.mdx +1 -1
  531. package/docs/content/locales/ko-KR/template-assets.mdx +1 -1
  532. package/docs/content/locales/ko-KR/template-dispatch.mdx +2 -2
  533. package/docs/content/locales/ko-KR/template-plan.mdx +3 -3
  534. package/docs/content/locales/pt-BR/actions.mdx +1 -1
  535. package/docs/content/locales/pt-BR/authentication.mdx +1 -1
  536. package/docs/content/locales/pt-BR/dispatch.mdx +3 -3
  537. package/docs/content/locales/pt-BR/external-agents.mdx +32 -19
  538. package/docs/content/locales/pt-BR/mcp-clients.mdx +34 -3
  539. package/docs/content/locales/pt-BR/mcp-protocol.mdx +32 -15
  540. package/docs/content/locales/pt-BR/plan-plugin.mdx +3 -3
  541. package/docs/content/locales/pt-BR/server.mdx +2 -2
  542. package/docs/content/locales/pt-BR/skills-guide.mdx +1 -1
  543. package/docs/content/locales/pt-BR/template-assets.mdx +1 -1
  544. package/docs/content/locales/pt-BR/template-dispatch.mdx +2 -2
  545. package/docs/content/locales/pt-BR/template-plan.mdx +3 -3
  546. package/docs/content/locales/zh-CN/actions.mdx +1 -1
  547. package/docs/content/locales/zh-CN/authentication.mdx +1 -1
  548. package/docs/content/locales/zh-CN/dispatch.mdx +3 -3
  549. package/docs/content/locales/zh-CN/external-agents.mdx +23 -19
  550. package/docs/content/locales/zh-CN/mcp-clients.mdx +28 -3
  551. package/docs/content/locales/zh-CN/mcp-protocol.mdx +29 -15
  552. package/docs/content/locales/zh-CN/plan-plugin.mdx +3 -3
  553. package/docs/content/locales/zh-CN/server.mdx +2 -2
  554. package/docs/content/locales/zh-CN/skills-guide.mdx +1 -1
  555. package/docs/content/locales/zh-CN/template-assets.mdx +1 -1
  556. package/docs/content/locales/zh-CN/template-dispatch.mdx +2 -2
  557. package/docs/content/locales/zh-CN/template-plan.mdx +3 -3
  558. package/docs/content/locales/zh-TW/actions.mdx +1 -1
  559. package/docs/content/locales/zh-TW/authentication.mdx +1 -1
  560. package/docs/content/locales/zh-TW/dispatch.mdx +3 -3
  561. package/docs/content/locales/zh-TW/external-agents.mdx +23 -19
  562. package/docs/content/locales/zh-TW/mcp-clients.mdx +28 -3
  563. package/docs/content/locales/zh-TW/mcp-protocol.mdx +30 -15
  564. package/docs/content/locales/zh-TW/plan-plugin.mdx +3 -3
  565. package/docs/content/locales/zh-TW/server.mdx +2 -2
  566. package/docs/content/locales/zh-TW/skills-guide.mdx +1 -1
  567. package/docs/content/locales/zh-TW/template-assets.mdx +1 -1
  568. package/docs/content/locales/zh-TW/template-dispatch.mdx +2 -2
  569. package/docs/content/locales/zh-TW/template-plan.mdx +3 -3
  570. package/docs/content/mcp-clients.mdx +31 -4
  571. package/docs/content/mcp-protocol.mdx +35 -15
  572. package/docs/content/plan-plugin.mdx +3 -3
  573. package/docs/content/server.mdx +2 -2
  574. package/docs/content/skills-guide.mdx +1 -1
  575. package/docs/content/template-assets.mdx +1 -1
  576. package/docs/content/template-dispatch.mdx +2 -2
  577. package/docs/content/template-plan.mdx +3 -3
  578. package/package.json +2 -2
  579. package/src/templates/default/.agents/skills/security/SKILL.md +10 -0
  580. package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +15 -6
  581. package/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +16 -10
  582. package/src/templates/workspace-core/.agents/skills/performance/SKILL.md +20 -1
  583. package/src/templates/workspace-core/.agents/skills/security/SKILL.md +10 -0
@@ -1 +1 @@
1
- {"version":3,"file":"pr-visual-recap-workflow.js","sourceRoot":"","sources":["../../src/cli/pr-visual-recap-workflow.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,MAAM,CAAC,MAAM,4BAA4B,GACvC,gk/CAAgk/C,CAAC","sourcesContent":["/** Canonical PR Visual Recap workflow bundled by the CLI installer. */\nexport const PR_VISUAL_RECAP_WORKFLOW_YML =\n 'name: PR Visual Recap\\n\\n# Visual code review: a coding agent runs the repo\\'s visual-recap skill over the\\n# PR diff, publishes a plan, and upserts one sticky comment with a screenshot.\\n# Plain `pull_request` (NOT `pull_request_target`) so fork code never sees secrets.\\n\\non:\\n pull_request:\\n types: [opened, synchronize, reopened, ready_for_review, closed]\\n\\npermissions:\\n contents: read\\n\\nconcurrency:\\n group: pr-visual-recap-${{ github.event.pull_request.number }}\\n cancel-in-progress: true\\n\\nenv:\\n VISUAL_RECAP_AGENT: ${{ vars.VISUAL_RECAP_AGENT || \\'claude\\' }}\\n VISUAL_RECAP_BASE_URL: ${{ vars.VISUAL_RECAP_BASE_URL || \\'\\' }}\\n VISUAL_RECAP_SKILL_SOURCE: ${{ vars.VISUAL_RECAP_SKILL_SOURCE || \\'auto\\' }}\\n VISUAL_RECAP_SECRET_SCAN: ${{ vars.VISUAL_RECAP_SECRET_SCAN || \\'high-confidence\\' }}\\n\\njobs:\\n gate:\\n name: Gate\\n # A custom plain-label runner is allowed only for trusted same-repo authors.\\n # Fork and untrusted PRs are forced onto GitHub-hosted ubuntu-latest before\\n # any step starts. The only fromJSON input is this static association list.\\n runs-on: ${{ github.event.pull_request.head.repo.full_name == github.repository && contains(fromJSON(\\'[\"OWNER\",\"MEMBER\",\"COLLABORATOR\"]\\'), github.event.pull_request.author_association) && (vars.VISUAL_RECAP_GATE_RUNS_ON || \\'ubuntu-latest\\') || \\'ubuntu-latest\\' }}\\n timeout-minutes: 10\\n permissions:\\n contents: read\\n issues: write\\n pull-requests: write\\n outputs:\\n run: ${{ steps.decide.outputs.run }}\\n agent: ${{ steps.decide.outputs.agent }}\\n runs_on: ${{ steps.decide.outputs.runs_on }}\\n steps:\\n - id: decide\\n uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0\\n env:\\n # Presence-only signals — never expose secret VALUES to the gate.\\n HAS_PLAN: ${{ secrets.PLAN_RECAP_TOKEN != \\'\\' }}\\n HAS_ANTHROPIC: ${{ secrets.ANTHROPIC_API_KEY != \\'\\' }}\\n HAS_OPENAI: ${{ secrets.OPENAI_API_KEY != \\'\\' }}\\n HAS_COMPATIBLE: ${{ secrets.VISUAL_RECAP_API_KEY != \\'\\' }}\\n AGENT: ${{ env.VISUAL_RECAP_AGENT }}\\n VISUAL_RECAP_BASE_URL: ${{ env.VISUAL_RECAP_BASE_URL }}\\n VISUAL_RECAP_MODEL: ${{ vars.VISUAL_RECAP_MODEL }}\\n VISUAL_RECAP_RUNS_ON: ${{ vars.VISUAL_RECAP_RUNS_ON || \\'\"ubuntu-latest\"\\' }}\\n VISUAL_RECAP_SKILL_SOURCE: ${{ env.VISUAL_RECAP_SKILL_SOURCE }}\\n HEAD_SHA: ${{ github.event.pull_request.head.sha }}\\n with:\\n script: |\\n const pr = context.payload.pull_request;\\n const reasons = [];\\n\\n if (!pr) reasons.push(\\'no pull_request payload\\');\\n if (pr && pr.draft) reasons.push(\\'draft PR\\');\\n if (pr && context.payload.action === \\'closed\\' && !pr.merged) {\\n reasons.push(\\'closed without merge\\');\\n }\\n\\n // Fork PRs only receive repo secrets when the org/repo opts into\\n // GitHub\\'s \"Send secrets to workflows from pull requests\" setting\\n // (common in private orgs that use forks heavily). Gate on secret\\n // availability, not fork-ness: run on forks that have the token,\\n // and skip — with an actionable hint — those that don\\'t.\\n const headRepo = pr && pr.head && pr.head.repo && pr.head.repo.full_name;\\n const isFork = !!(pr && headRepo && headRepo !== process.env.GITHUB_REPOSITORY);\\n const isPrivate = !!(context.payload.repository && context.payload.repository.private);\\n const association = (pr && pr.author_association || \\'\\').toUpperCase();\\n const trustedAssociations = [\\'OWNER\\', \\'MEMBER\\', \\'COLLABORATOR\\'];\\n const isTrustedAuthor = trustedAssociations.includes(association);\\n let configuredRunner = \\'ubuntu-latest\\';\\n let usesSelfHostedRunner = false;\\n try {\\n const candidate = JSON.parse(process.env.VISUAL_RECAP_RUNS_ON || \\'\"ubuntu-latest\"\\');\\n const hosted = typeof candidate === \\'string\\' && /^(?:ubuntu|windows|macos)-[A-Za-z0-9.-]+$/.test(candidate);\\n const selfHosted = Array.isArray(candidate) && candidate.length >= 1 && candidate.length <= 20 && candidate.includes(\\'self-hosted\\') && candidate.every((label) => typeof label === \\'string\\' && label.length >= 1 && label.length <= 100 && !/[\\\\u0000-\\\\u001f\\\\u007f]/.test(label)) && new Set(candidate).size === candidate.length;\\n if (!hosted && !selfHosted) throw new Error(\\'unsupported runner value\\');\\n configuredRunner = candidate;\\n usesSelfHostedRunner = selfHosted;\\n } catch {\\n reasons.push(\\'invalid VISUAL_RECAP_RUNS_ON JSON\\');\\n }\\n if (usesSelfHostedRunner && (isFork || !isTrustedAuthor)) {\\n reasons.push(\\'self-hosted runner mode requires a trusted same-repository PR author\\');\\n }\\n if (isFork && process.env.HAS_PLAN !== \\'true\\') {\\n reasons.push(`fork PR (${headRepo}) without secret access — enable \"Send secrets to workflows from pull requests\" (and write tokens) in the repo/org Actions settings to run recaps on forks`);\\n }\\n\\n const login = (pr && pr.user && pr.user.login || \\'\\').toLowerCase();\\n const botAuthors = [\\'dependabot[bot]\\', \\'dependabot\\', \\'renovate[bot]\\', \\'renovate\\'];\\n if (botAuthors.includes(login)) reasons.push(`bot author (${login})`);\\n if (pr && pr.user && pr.user.type === \\'Bot\\') reasons.push(\\'bot author (type=Bot)\\');\\n\\n if (!isFork && process.env.HAS_PLAN !== \\'true\\') reasons.push(\\'PLAN_RECAP_TOKEN not configured\\');\\n\\n // Normalize + validate the agent so a mis-cased value can\\'t pass the\\n // gate and then match neither agent step below.\\n const rawAgent = (process.env.AGENT || \\'claude\\').toLowerCase();\\n const agent = [\\'deepseek\\', \\'kimi\\', \\'moonshot\\', \\'custom\\'].includes(rawAgent) ? \\'openai-compatible\\' : rawAgent;\\n if (![\\'claude\\', \\'codex\\', \\'openai-compatible\\'].includes(agent)) {\\n reasons.push(`unsupported VISUAL_RECAP_AGENT \"${process.env.AGENT}\" (expected \"claude\", \"codex\", or \"openai-compatible\")`);\\n } else if (agent === \\'codex\\') {\\n if (process.env.HAS_OPENAI !== \\'true\\') reasons.push(\\'OPENAI_API_KEY not configured (codex backend)\\');\\n } else if (agent === \\'claude\\') {\\n if (process.env.HAS_ANTHROPIC !== \\'true\\') reasons.push(\\'ANTHROPIC_API_KEY not configured (claude backend)\\');\\n } else {\\n if (process.env.HAS_COMPATIBLE !== \\'true\\') reasons.push(\\'VISUAL_RECAP_API_KEY not configured (openai-compatible backend)\\');\\n if (!(process.env.VISUAL_RECAP_MODEL || \\'\\').trim()) reasons.push(\\'VISUAL_RECAP_MODEL is required (openai-compatible backend)\\');\\n const baseUrl = process.env.VISUAL_RECAP_BASE_URL || \\'\\';\\n try {\\n const parsed = new URL(baseUrl);\\n if (![\\'http:\\', \\'https:\\'].includes(parsed.protocol) || parsed.username || parsed.password) {\\n reasons.push(\\'VISUAL_RECAP_BASE_URL must be an http(s) URL without credentials\\');\\n }\\n } catch {\\n reasons.push(\\'VISUAL_RECAP_BASE_URL must be a valid http(s) URL\\');\\n }\\n }\\n\\n // Validate the model before it reaches the agent CLI.\\n const model = process.env.VISUAL_RECAP_MODEL || \\'\\';\\n if (model && !/^[a-zA-Z0-9._-]{1,80}$/.test(model)) {\\n reasons.push(`invalid VISUAL_RECAP_MODEL value (must match [a-zA-Z0-9._-]{1,80})`);\\n }\\n\\n const skillSource = (process.env.VISUAL_RECAP_SKILL_SOURCE || \\'auto\\').toLowerCase();\\n if (![\\'auto\\', \\'latest\\', \\'repo\\'].includes(skillSource)) {\\n reasons.push(\\'invalid VISUAL_RECAP_SKILL_SOURCE value (expected \"auto\", \"latest\", or \"repo\")\\');\\n }\\n const usesRepoSkill = skillSource === \\'repo\\';\\n\\n // Self-modifying guard, evaluated in the trusted gate (runs NO\\n // PR-checked-out code): skip the ENTIRE job if the PR touches the\\n // repo-pinned skill instructions or any agent config the runner\\n // loads, so a PR can\\'t rewrite what the agent loads and exfiltrate\\n // secrets. With the default bundled skill source, visual skill and\\n // recap workflow files are reviewed content, not instructions loaded\\n // by the runner.\\n // Keep this guard for untrusted forks and untrusted public-repo PRs.\\n // Trusted write actors may edit recap-control files as normal\\n // reviewable content; running the recap is useful signal for those\\n // changes.\\n if (pr && !isTrustedAuthor && (isFork || !isPrivate)) {\\n try {\\n const files = await github.paginate(github.rest.pulls.listFiles, {\\n owner: context.repo.owner,\\n repo: context.repo.repo,\\n pull_number: pr.number,\\n per_page: 100,\\n });\\n const isSensitive = (p) =>\\n (usesRepoSkill && /(^|\\\\/)skills\\\\/visual-(recap|plan|plans)\\\\//.test(p)) ||\\n p.startsWith(\\'.claude/\\') ||\\n p === \\'CLAUDE.md\\' ||\\n p === \\'AGENTS.md\\' ||\\n p === \\'.mcp.json\\';\\n const hits = files.map((f) => f.filename).filter(isSensitive);\\n if (hits.length) {\\n reasons.push(`PR modifies recap-control files (${hits.slice(0, 3).join(\\', \\')}${hits.length > 3 ? \\', …\\' : \\'\\'}) — skipping so untrusted PR code never runs with secrets`);\\n }\\n } catch (e) {\\n // Fail closed: if the file list can\\'t be read, skip.\\n reasons.push(`could not list PR files for the self-modifying guard (${e.message}); skipping to be safe`);\\n }\\n }\\n\\n const run = reasons.length === 0;\\n core.setOutput(\\'run\\', run ? \\'true\\' : \\'false\\');\\n core.setOutput(\\'agent\\', agent);\\n core.setOutput(\\'runs_on\\', JSON.stringify(configuredRunner));\\n if (run) {\\n core.info(`Visual recap will run (${agent}).`);\\n } else {\\n // Surface the skip reason as a run-summary annotation, not just a\\n // buried info log, so it\\'s clear in the Actions UI why we skipped.\\n core.notice(`Visual recap skipped: ${reasons.join(\\'; \\')}`);\\n }\\n\\n // When skipping, upsert a sticky recap comment with a short skip\\n // line so the PR always explains why the recap job did not run.\\n if (!run && pr) {\\n try {\\n const MARKER = \\'<!-- pr-visual-recap -->\\';\\n const { data: comments } = await github.rest.issues.listComments({\\n owner: context.repo.owner,\\n repo: context.repo.repo,\\n issue_number: pr.number,\\n per_page: 100,\\n });\\n const existing = comments.find(\\n (c) => c.user && c.user.type === \\'Bot\\' && c.body && c.body.includes(MARKER)\\n );\\n const headShort = (process.env.HEAD_SHA || \\'\\').slice(0, 7);\\n const shaRef = headShort ? `\\\\`${headShort}\\\\`` : \\'latest push\\';\\n const primaryReason = reasons.filter(\\n (r) => !r.startsWith(\\'could not list PR files for the self-modifying guard\\')\\n )[0] || reasons[0] || \\'skipped\\';\\n const skipLine = `_Recap skipped for ${shaRef}: ${primaryReason}._`;\\n const baseBody = `${MARKER}\\\\n### Visual recap — skipped\\\\n\\\\nThe visual recap job did not run for this pull request. This is informational only and does **not** block the PR.`;\\n const planIdMatch = (existing && existing.body ? existing.body : \\'\\').match(/<!--\\\\s*plan-id:\\\\s*([A-Za-z0-9_-]{1,64})\\\\s*-->/);\\n const planIdMarker = planIdMatch ? `\\\\n\\\\n<!-- plan-id: ${planIdMatch[1]} -->` : \\'\\';\\n const updatedBody = `${baseBody}${planIdMarker}\\\\n\\\\n${skipLine}`;\\n if (existing) {\\n await github.rest.issues.updateComment({\\n owner: context.repo.owner,\\n repo: context.repo.repo,\\n comment_id: existing.id,\\n body: updatedBody,\\n });\\n } else {\\n await github.rest.issues.createComment({\\n owner: context.repo.owner,\\n repo: context.repo.repo,\\n issue_number: pr.number,\\n body: updatedBody,\\n });\\n }\\n } catch (e) {\\n core.warning(`Could not update recap skip comment: ${e.message}`);\\n }\\n }\\n\\n recap:\\n name: Generate visual recap\\n needs: gate\\n if: needs.gate.outputs.run == \\'true\\'\\n runs-on: ${{ fromJSON(needs.gate.outputs.runs_on) }}\\n timeout-minutes: 30\\n permissions:\\n actions: write\\n checks: write\\n contents: read\\n issues: write\\n pull-requests: write\\n env:\\n PLAN_RECAP_APP_URL: ${{ secrets.PLAN_RECAP_APP_URL || \\'https://plan.agent-native.com\\' }}\\n PLAN_RECAP_TOKEN: ${{ secrets.PLAN_RECAP_TOKEN }}\\n GH_TOKEN: ${{ github.token }}\\n PR_NUMBER: ${{ github.event.pull_request.number }}\\n PR_STATE: ${{ github.event.pull_request.state }}\\n PR_MERGED: ${{ github.event.pull_request.merged }}\\n PR_MERGED_AT: ${{ github.event.pull_request.merged_at }}\\n HEAD_SHA: ${{ github.event.pull_request.head.sha }}\\n VISUAL_RECAP_MODEL: ${{ vars.VISUAL_RECAP_MODEL }}\\n VISUAL_RECAP_BASE_URL: ${{ vars.VISUAL_RECAP_BASE_URL || \\'\\' }}\\n VISUAL_RECAP_REASONING: ${{ vars.VISUAL_RECAP_REASONING }}\\n VISUAL_RECAP_SKILL_SOURCE: ${{ vars.VISUAL_RECAP_SKILL_SOURCE || \\'auto\\' }}\\n VISUAL_RECAP_SECRET_SCAN: ${{ vars.VISUAL_RECAP_SECRET_SCAN || \\'high-confidence\\' }}\\n steps:\\n - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3\\n with:\\n fetch-depth: 0\\n # This job runs an agent over untrusted PR diff; don\\'t leave the token\\n # in .git/config (it uses GH_TOKEN for gh API calls, never git push).\\n persist-credentials: false\\n\\n # Dogfood trusted base-branch source inside this monorepo, else install the\\n # published package once. Never execute PR-head recap CLI code.\\n - name: Resolve recap CLI\\n id: cli\\n env:\\n # Optional: pin the consumer CLI version (e.g. \"1.2.3\"). Defaults to\\n # \"latest\" when unset. Set via repository variable RECAP_CLI_VERSION.\\n RECAP_CLI_VERSION: ${{ vars.RECAP_CLI_VERSION || \\'latest\\' }}\\n run: |\\n if [ \"$GITHUB_REPOSITORY\" = \"BuilderIO/agent-native\" ] && [ -f packages/core/src/cli/index.ts ]; then\\n echo \"local=true\" >> \"$GITHUB_OUTPUT\"\\n else\\n echo \"local=false\" >> \"$GITHUB_OUTPUT\"\\n fi\\n\\n - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3\\n if: steps.cli.outputs.local == \\'true\\'\\n with:\\n ref: ${{ github.event.pull_request.base.sha }}\\n path: .recap-cli-source\\n fetch-depth: 1\\n persist-credentials: false\\n\\n - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8\\n if: steps.cli.outputs.local == \\'true\\'\\n\\n - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0\\n with:\\n node-version: \"22\"\\n cache: ${{ steps.cli.outputs.local == \\'true\\' && \\'pnpm\\' || \\'\\' }}\\n\\n - name: Install trusted workspace recap CLI\\n if: steps.cli.outputs.local == \\'true\\'\\n working-directory: .recap-cli-source\\n run: |\\n set -euo pipefail\\n pnpm install --frozen-lockfile --ignore-scripts\\n echo \"RECAP_CLI=$PWD/node_modules/.bin/tsx $PWD/packages/core/src/cli/index.ts\" >> \"$GITHUB_ENV\"\\n echo \"RECAP_PLAYWRIGHT=$PWD/node_modules/.bin/playwright\" >> \"$GITHUB_ENV\"\\n\\n - name: Install published recap CLI\\n if: steps.cli.outputs.local != \\'true\\'\\n env:\\n RECAP_CLI_VERSION: ${{ vars.RECAP_CLI_VERSION || \\'latest\\' }}\\n run: |\\n set -euo pipefail\\n VERSION=\"$RECAP_CLI_VERSION\"\\n if [ \"$VERSION\" = \"latest\" ]; then\\n VERSION=\"$(npm view @agent-native/core@latest version)\"\\n fi\\n for attempt in 1 2 3; do\\n if npm install --prefix \"$RUNNER_TEMP/recap-cli\" --no-audit --no-fund \"@agent-native/core@$VERSION\"; then\\n break\\n fi\\n if [ \"$attempt\" = \"3\" ]; then exit 1; fi\\n sleep $((attempt * 10))\\n done\\n echo \"RECAP_CLI=$RUNNER_TEMP/recap-cli/node_modules/.bin/agent-native\" >> \"$GITHUB_ENV\"\\n echo \"RECAP_PLAYWRIGHT=$RUNNER_TEMP/recap-cli/node_modules/.bin/playwright\" >> \"$GITHUB_ENV\"\\n\\n - name: Install OpenAI-compatible provider runtime\\n if: needs.gate.outputs.agent == \\'openai-compatible\\' && steps.cli.outputs.local != \\'true\\'\\n run: |\\n set -euo pipefail\\n npm install --prefix \"$RUNNER_TEMP/recap-cli\" --no-audit --no-fund ai @ai-sdk/openai\\n\\n - name: Start visual recap check\\n id: recap_check\\n continue-on-error: true\\n run: |\\n set -uo pipefail\\n $RECAP_CLI recap check start --sha \"$HEAD_SHA\" --workflow-url \"$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID\"\\n\\n - name: Fetch pull request head\\n env:\\n PR_NUMBER_ENV: ${{ github.event.pull_request.number }}\\n run: |\\n set -euo pipefail\\n if git cat-file -e \"${HEAD_SHA}^{commit}\" 2>/dev/null; then\\n git update-ref refs/recap/pr-head \"$HEAD_SHA\"\\n else\\n AUTH_B64=\"$(printf \\'x-access-token:%s\\' \"$GH_TOKEN\" | base64 | tr -d \\'\\\\n\\')\"\\n git -c \"http.https://github.com/.extraheader=AUTHORIZATION: basic $AUTH_B64\" fetch origin \"pull/${PR_NUMBER_ENV}/head:refs/recap/pr-head\"\\n fi\\n FETCHED_SHA=\"$(git rev-parse refs/recap/pr-head)\"\\n if [ \"$FETCHED_SHA\" != \"$HEAD_SHA\" ]; then\\n echo \"FATAL: fetched PR head $FETCHED_SHA != event HEAD_SHA $HEAD_SHA — aborting to avoid recapping the wrong commit\"\\n exit 1\\n fi\\n\\n - name: Collect bounded diff\\n id: diff\\n env:\\n BASE_SHA: ${{ github.event.pull_request.base.sha }}\\n run: |\\n set -euo pipefail\\n $RECAP_CLI recap collect-diff --base \"$BASE_SHA\" --head refs/recap/pr-head --out recap.diff --stat recap.stat\\n\\n - name: Probe plan-app auth\\n id: auth_probe\\n if: steps.diff.outputs.tiny != \\'true\\'\\n continue-on-error: true\\n run: |\\n set -uo pipefail\\n # Hit the plan app\\'s action surface with the publish token. A 401 means\\n # the token is expired/revoked; surface it in the sticky comment so the\\n # repo owner knows to re-mint it instead of seeing a generic failure.\\n HTTP_STATUS=$(node -e \\'\\n const https = require(\"https\");\\n const url = new URL(\"/_agent-native/actions/record-recap-usage\", process.env.PLAN_RECAP_APP_URL || \"https://plan.agent-native.com\");\\n const req = https.request(url, { method: \"POST\", headers: { \"authorization\": \"Bearer \" + process.env.PLAN_RECAP_TOKEN, \"content-type\": \"application/json\" }, timeout: 8000 }, (res) => { process.stdout.write(String(res.statusCode)); req.destroy(); });\\n req.on(\"error\", () => process.stdout.write(\"0\"));\\n req.end(JSON.stringify({ planId: \"__probe__\" }));\\n \\' 2>/dev/null || echo \"0\")\\n if [ \"$HTTP_STATUS\" = \"401\" ]; then\\n echo \"auth_failed=true\" >> \"$GITHUB_OUTPUT\"\\n else\\n echo \"auth_failed=false\" >> \"$GITHUB_OUTPUT\"\\n fi\\n\\n - name: Probe plan-app route health\\n id: route_health\\n if: steps.diff.outputs.tiny != \\'true\\'\\n continue-on-error: true\\n run: |\\n set -uo pipefail\\n # Pre-publish health gate: confirm the plan app\\'s recap action routes\\n # are actually deployed BEFORE the agent runs. A 404 from\\n # create-visual-recap (POST) or get-plan-blocks (GET) means the\\n # plan-app deploy has not propagated yet (the client is ahead of the\\n # deployed server). Say that plainly here instead of letting the agent\\n # run and then fail confusingly at publish time. A 401 or 200 is\\n # healthy — the route exists, it just rejected/accepted the probe.\\n probe_status() {\\n ROUTE=\"$1\" METHOD=\"$2\" node -e \\'\\n const https = require(\"https\");\\n const base = process.env.PLAN_RECAP_APP_URL || \"https://plan.agent-native.com\";\\n const url = new URL(process.env.ROUTE, base);\\n if (process.env.METHOD === \"GET\") url.searchParams.set(\"format\", \"reference\");\\n const req = https.request(url, { method: process.env.METHOD, headers: { \"authorization\": \"Bearer \" + (process.env.PLAN_RECAP_TOKEN || \"\"), \"content-type\": \"application/json\" }, timeout: 8000 }, (res) => { process.stdout.write(String(res.statusCode)); req.destroy(); });\\n req.on(\"error\", () => process.stdout.write(\"0\"));\\n req.on(\"timeout\", () => { process.stdout.write(\"0\"); req.destroy(); });\\n if (process.env.METHOD === \"POST\") { req.end(JSON.stringify({ __probe__: true })); } else { req.end(); }\\n \\' 2>/dev/null || echo \"0\"\\n }\\n CREATE_STATUS=\"$(probe_status /_agent-native/actions/create-visual-recap POST)\"\\n BLOCKS_STATUS=\"$(probe_status /_agent-native/actions/get-plan-blocks GET)\"\\n REASON=\"\"\\n if [ \"$CREATE_STATUS\" = \"404\" ] || [ \"$BLOCKS_STATUS\" = \"404\" ]; then\\n REASON=\"Plan app routes return 404 — deploy not yet propagated (create-visual-recap: $CREATE_STATUS, get-plan-blocks: $BLOCKS_STATUS). The plan-app client is ahead of the deployed server; re-run once the deploy finishes propagating.\"\\n echo \"::error::$REASON\"\\n echo \"unhealthy=true\" >> \"$GITHUB_OUTPUT\"\\n else\\n echo \"unhealthy=false\" >> \"$GITHUB_OUTPUT\"\\n fi\\n {\\n echo \\'reason<<__RECAP_ROUTE_HEALTH_EOF__\\'\\n echo \"$REASON\"\\n echo \\'__RECAP_ROUTE_HEALTH_EOF__\\'\\n } >> \"$GITHUB_OUTPUT\"\\n\\n - name: Secret scan\\n id: scan\\n if: steps.diff.outputs.tiny != \\'true\\' && steps.route_health.outputs.unhealthy != \\'true\\'\\n run: |\\n set -uo pipefail\\n # Fail CLOSED: a scanner error or invalid JSON suppresses the diff so a\\n # credential-bearing diff is never handed to the agent / plan service.\\n if ! SCAN_JSON=\"$($RECAP_CLI recap scan --diff recap.diff --mode \"$VISUAL_RECAP_SECRET_SCAN\")\"; then\\n SCAN_JSON=\\'{\"suppressed\":true,\"reason\":\"secret scan failed to run; failing closed\"}\\'\\n fi\\n {\\n echo \\'json<<__RECAP_SCAN_EOF__\\'\\n echo \"$SCAN_JSON\"\\n echo \\'__RECAP_SCAN_EOF__\\'\\n } >> \"$GITHUB_OUTPUT\"\\n SUPPRESSED=$(node -e \\'try{process.stdout.write(JSON.parse(process.argv[1]).suppressed?\"true\":\"false\")}catch{process.stdout.write(\"true\")}\\' \"$SCAN_JSON\")\\n echo \"suppressed=$SUPPRESSED\" >> \"$GITHUB_OUTPUT\"\\n\\n - name: Read previous plan id\\n id: prev\\n if: steps.diff.outputs.tiny != \\'true\\' && steps.route_health.outputs.unhealthy != \\'true\\'\\n continue-on-error: true\\n run: |\\n set -euo pipefail\\n PLAN_ID=\"$($RECAP_CLI recap comment find-plan-id --repo \"$GITHUB_REPOSITORY\" --issue \"$PR_NUMBER\" --token \"$GH_TOKEN\")\"\\n echo \"plan_id=$PLAN_ID\" >> \"$GITHUB_OUTPUT\"\\n\\n - name: Fetch plan block reference\\n id: block_reference\\n if: steps.diff.outputs.tiny != \\'true\\' && steps.route_health.outputs.unhealthy != \\'true\\' && steps.scan.outputs.suppressed != \\'true\\'\\n continue-on-error: true\\n run: |\\n set -uo pipefail\\n if $RECAP_CLI recap block-reference --app-url \"$PLAN_RECAP_APP_URL\" --out recap-blocks.md; then\\n echo \"ok=true\" >> \"$GITHUB_OUTPUT\"\\n else\\n echo \"ok=false\" >> \"$GITHUB_OUTPUT\"\\n {\\n echo \\'summary<<__RECAP_BLOCK_REFERENCE_EOF__\\'\\n echo \"Could not fetch the live plan block reference; the agent will fall back to bundled visual-recap instructions and the publisher will validate the final MDX.\"\\n echo \\'__RECAP_BLOCK_REFERENCE_EOF__\\'\\n } >> \"$GITHUB_OUTPUT\"\\n cat > recap-blocks.md <<\\'EOF\\'\\n Live plan block reference unavailable. Follow the bundled visual-recap skill and author conservative MDX; the deterministic publisher will validate the source before posting.\\n EOF\\n fi\\n\\n - name: Build recap prompt\\n id: prompt\\n if: steps.diff.outputs.tiny != \\'true\\' && steps.route_health.outputs.unhealthy != \\'true\\' && steps.scan.outputs.suppressed != \\'true\\'\\n env:\\n # Pass step outputs via env, NOT ${{ }} interpolation into the run body:\\n # the prev plan id is parsed from a PR comment and could inject shell.\\n PREV_PLAN_ID: ${{ steps.prev.outputs.plan_id }}\\n DIFF_HUGE: ${{ steps.diff.outputs.huge }}\\n IS_FORK: ${{ github.event.pull_request.head.repo.full_name != github.repository }}\\n run: |\\n set -euo pipefail\\n ARGS=(--diff recap.diff --stat recap.stat --block-reference recap-blocks.md --pr \"$PR_NUMBER\" --repo \"$GITHUB_REPOSITORY\" --head \"$HEAD_SHA\" --app-url \"$PLAN_RECAP_APP_URL\" --skill-source \"$VISUAL_RECAP_SKILL_SOURCE\" --out recap-prompt.md)\\n if [ \"${DIFF_HUGE:-}\" = \"true\" ]; then ARGS+=(--huge); fi\\n if [ \"${IS_FORK:-}\" = \"true\" ]; then ARGS+=(--fork-pr true); fi\\n if [ -n \"${PREV_PLAN_ID:-}\" ]; then ARGS+=(--prev-plan-id \"$PREV_PLAN_ID\"); fi\\n $RECAP_CLI recap build-prompt \"${ARGS[@]}\"\\n\\n - name: Run agent (Claude Code)\\n id: claude\\n if: needs.gate.outputs.agent == \\'claude\\' && steps.diff.outputs.tiny != \\'true\\' && steps.route_health.outputs.unhealthy != \\'true\\' && steps.scan.outputs.suppressed != \\'true\\'\\n continue-on-error: true\\n env:\\n ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}\\n run: |\\n set -uo pipefail\\n CLAUDE_ALLOWED_TOOLS=\"Read,Write,Bash(git diff:*)\"\\n CLAUDE_ARGS=(-p \"$(cat recap-prompt.md)\" --allowedTools \"$CLAUDE_ALLOWED_TOOLS\" --permission-mode dontAsk --output-format json)\\n if [ -n \"${VISUAL_RECAP_MODEL:-}\" ]; then CLAUDE_ARGS+=(--model \"$VISUAL_RECAP_MODEL\"); fi\\n rm -f recap-source.json recap-url.txt recap-url-reason.txt claude-result.json claude-stderr.log\\n run_claude() {\\n set +e\\n npx -y @anthropic-ai/claude-code@2 \"${CLAUDE_ARGS[@]}\" > claude-result.json 2> claude-stderr.log\\n CLAUDE_STATUS=\"$?\"\\n set -e\\n echo \"$CLAUDE_STATUS\" > claude-exit-code.txt\\n }\\n run_claude\\n # A clean agent exit WITHOUT recap-source.json is the strongest\\n # \"retry me\" signal — the deterministic publisher needs that file, and\\n # the agent occasionally finishes a turn without writing it. Retry once.\\n if [ ! -s recap-source.json ]; then\\n echo \"::warning::recap-source.json missing after the agent run; retrying the agent once.\"\\n sleep 5\\n run_claude\\n fi\\n\\n - name: Run agent (Codex)\\n id: codex\\n if: needs.gate.outputs.agent == \\'codex\\' && steps.diff.outputs.tiny != \\'true\\' && steps.route_health.outputs.unhealthy != \\'true\\' && steps.scan.outputs.suppressed != \\'true\\'\\n continue-on-error: true\\n env:\\n OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}\\n run: |\\n set -uo pipefail\\n # `codex login` writes ~/.codex/auth.json (the bare env var is dropped on\\n # the gpt-5.5 wss transport); stdin keeps the key out of process args.\\n printenv OPENAI_API_KEY | npx -y @openai/codex@0 login --with-api-key || true\\n # The runner is itself an ephemeral sandbox; bypass Codex\\'s own sandbox\\n # (bubblewrap can\\'t init here) and approval gate (cancels the MCP write).\\n CODEX_ARGS=(exec --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check)\\n if [ -n \"${VISUAL_RECAP_MODEL:-}\" ]; then CODEX_ARGS+=(--model \"$VISUAL_RECAP_MODEL\"); fi\\n # Validate reasoning against the enum before embedding it in the TOML override.\\n case \"${VISUAL_RECAP_REASONING:-}\" in\\n none|minimal|low|medium|high|xhigh)\\n CODEX_ARGS+=(-c \"model_reasoning_effort=\\\\\"$VISUAL_RECAP_REASONING\\\\\"\") ;;\\n \"\") ;;\\n *) echo \"Ignoring invalid VISUAL_RECAP_REASONING: $VISUAL_RECAP_REASONING\" ;;\\n esac\\n rm -f recap-source.json recap-url.txt recap-url-reason.txt codex-events.jsonl codex-stderr.log\\n run_codex() {\\n set +e\\n npx -y @openai/codex@0 \"${CODEX_ARGS[@]}\" --json \"$(cat recap-prompt.md)\" 2> codex-stderr.log | tee codex-events.jsonl\\n CODEX_STATUS=\"${PIPESTATUS[0]}\"\\n set -e\\n echo \"$CODEX_STATUS\" > codex-exit-code.txt\\n }\\n run_codex\\n # Retry once if the agent exited without writing recap-source.json\\n # (see the Claude step) — the publisher needs that file.\\n if [ ! -s recap-source.json ]; then\\n echo \"::warning::recap-source.json missing after the agent run; retrying the agent once.\"\\n sleep 5\\n run_codex\\n fi\\n\\n - name: Run agent (OpenAI-compatible)\\n id: openai_compatible\\n if: needs.gate.outputs.agent == \\'openai-compatible\\' && steps.diff.outputs.tiny != \\'true\\' && steps.route_health.outputs.unhealthy != \\'true\\' && steps.scan.outputs.suppressed != \\'true\\'\\n continue-on-error: true\\n env:\\n OPENAI_API_KEY: ${{ secrets.VISUAL_RECAP_API_KEY }}\\n OPENAI_BASE_URL: ${{ vars.VISUAL_RECAP_BASE_URL }}\\n AGENT_ENGINE: ai-sdk:openai\\n AGENT_MODEL: ${{ vars.VISUAL_RECAP_MODEL }}\\n AGENT_NATIVE_CODE_USAGE_FILE: openai-compatible-usage.json\\n AGENT_NATIVE_CODE_TOOL_PROFILE: recap-source\\n run: |\\n set -uo pipefail\\n rm -f recap-source.json recap-url.txt recap-url-reason.txt openai-compatible-result.txt openai-compatible-usage.json openai-compatible-stderr.log\\n run_openai_compatible() {\\n set +e\\n $RECAP_CLI code exec --permission-mode auto-edit \"$(cat recap-prompt.md)\" > openai-compatible-result.txt 2> openai-compatible-stderr.log\\n OPENAI_COMPATIBLE_STATUS=\"$?\"\\n set -e\\n echo \"$OPENAI_COMPATIBLE_STATUS\" > openai-compatible-exit-code.txt\\n }\\n run_openai_compatible\\n if [ ! -s recap-source.json ]; then\\n echo \"::warning::recap-source.json missing after the agent run; retrying the agent once.\"\\n sleep 5\\n run_openai_compatible\\n fi\\n\\n - name: Publish recap source\\n id: publish\\n if: steps.diff.outputs.tiny != \\'true\\' && steps.route_health.outputs.unhealthy != \\'true\\' && steps.scan.outputs.suppressed != \\'true\\'\\n continue-on-error: true\\n env:\\n PREV_PLAN_ID: ${{ steps.prev.outputs.plan_id }}\\n run: |\\n set -uo pipefail\\n ARGS=(--source recap-source.json --out recap-url.txt --repo \"$GITHUB_REPOSITORY\" --pr \"$PR_NUMBER\" --app-url \"$PLAN_RECAP_APP_URL\" --token \"$PLAN_RECAP_TOKEN\")\\n if [ -n \"${PREV_PLAN_ID:-}\" ]; then ARGS+=(--prev-plan-id \"$PREV_PLAN_ID\"); fi\\n ARGS+=(--source-type pull-request --source-repo \"$GITHUB_REPOSITORY\" --source-pr-number \"$PR_NUMBER\")\\n if [ \"${PR_MERGED:-false}\" = \"true\" ] || [ -n \"${PR_MERGED_AT:-}\" ]; then\\n ARGS+=(--source-pr-state merged)\\n elif [ -n \"${PR_STATE:-}\" ]; then\\n ARGS+=(--source-pr-state \"$PR_STATE\")\\n fi\\n if [ -n \"${PR_MERGED_AT:-}\" ]; then ARGS+=(--source-pr-merged-at \"$PR_MERGED_AT\"); fi\\n $RECAP_CLI recap publish \"${ARGS[@]}\"\\n\\n - name: Read plan URL\\n id: url\\n if: steps.diff.outputs.tiny != \\'true\\' && steps.route_health.outputs.unhealthy != \\'true\\' && steps.scan.outputs.suppressed != \\'true\\'\\n run: |\\n set -uo pipefail\\n PLAN_URL=\"\"\\n URL_REASON=\"\"\\n if [ -f recap-url.txt ]; then\\n PLAN_URL=\"$(tr -d \\'\\\\r\\\\n\\' < recap-url.txt | tr -d \\' \\')\"\\n elif [ -f recap-url-reason.txt ]; then\\n URL_REASON=\"$(cat recap-url-reason.txt)\"\\n else\\n URL_REASON=\"recap-url.txt was not created.\"\\n fi\\n # recap-url.txt is agent-written -> untrusted. Rebuild a canonical\\n # recap URL from the trusted app base and a strictly validated plan id,\\n # preserving path-prefixed self-hosted mounts.\\n if [ -z \"$URL_REASON\" ]; then\\n URL_RESULT=$(PLAN_URL=\"$PLAN_URL\" node <<\\'NODE\\'\\n const emit = (value) => process.stdout.write(JSON.stringify(value));\\n try {\\n const raw = process.env.PLAN_URL || \"\";\\n if (!raw) {\\n emit({ url: \"\", reason: \"recap-url.txt was empty\" });\\n process.exit(0);\\n }\\n const trusted = new URL(process.env.PLAN_RECAP_APP_URL || \"https://plan.agent-native.com\");\\n const parsed = /^https?:\\\\/\\\\//i.test(raw)\\n ? new URL(raw)\\n : new URL(raw, trusted);\\n if (parsed.origin !== trusted.origin) {\\n emit({ url: \"\", reason: `recap-url.txt points at ${parsed.origin}, expected ${trusted.origin}` });\\n process.exit(0);\\n }\\n\\n const base = trusted.pathname.replace(/\\\\/$/, \"\");\\n const paths = [parsed.pathname];\\n if (base && parsed.pathname.startsWith(`${base}/`)) {\\n paths.push(parsed.pathname.slice(base.length) || \"/\");\\n }\\n\\n for (const path of paths) {\\n const match = path.match(/^\\\\/(?:plans|recaps)\\\\/([A-Za-z0-9_-]+)\\\\/?$/);\\n if (match) {\\n emit({ url: `${trusted.origin}${base}/recaps/${match[1]}`, reason: \"\" });\\n process.exit(0);\\n }\\n }\\n emit({ url: \"\", reason: \"recap-url.txt did not contain a valid /plans/<id> or /recaps/<id> URL for the configured plan app\" });\\n } catch {\\n emit({ url: \"\", reason: \"recap-url.txt was not a valid URL or recap path\" });\\n }\\n NODE\\n )\\n CANONICAL_URL=$(node -e \\'try{process.stdout.write(JSON.parse(process.argv[1]).url||\"\")}catch{process.stdout.write(\"\")}\\' \"$URL_RESULT\")\\n URL_REASON=$(node -e \\'try{process.stdout.write(JSON.parse(process.argv[1]).reason||\"\")}catch{process.stdout.write(\"recap-url.txt URL validation failed\")}\\' \"$URL_RESULT\")\\n else\\n CANONICAL_URL=\"\"\\n fi\\n if [ -n \"$CANONICAL_URL\" ]; then\\n echo \"plan_url=$CANONICAL_URL\" >> \"$GITHUB_OUTPUT\"; echo \"ok=true\" >> \"$GITHUB_OUTPUT\"\\n else\\n echo \"plan_url=\" >> \"$GITHUB_OUTPUT\"; echo \"ok=false\" >> \"$GITHUB_OUTPUT\"\\n fi\\n {\\n echo \\'reason<<__RECAP_URL_REASON_EOF__\\'\\n echo \"$URL_REASON\"\\n echo \\'__RECAP_URL_REASON_EOF__\\'\\n } >> \"$GITHUB_OUTPUT\"\\n\\n - name: Summarize agent failure\\n id: agent_summary\\n if: steps.url.outputs.ok != \\'true\\' && steps.diff.outputs.tiny != \\'true\\' && steps.route_health.outputs.unhealthy != \\'true\\' && steps.scan.outputs.suppressed != \\'true\\'\\n continue-on-error: true\\n env:\\n RECAP_AGENT: ${{ needs.gate.outputs.agent }}\\n RECAP_BLOCK_REFERENCE_SUMMARY: ${{ steps.block_reference.outputs.summary }}\\n RECAP_PUBLISH_REASON: ${{ steps.publish.outputs.reason }}\\n run: |\\n set -uo pipefail\\n if [ -n \"${RECAP_BLOCK_REFERENCE_SUMMARY:-}\" ]; then\\n {\\n echo \\'summary<<__RECAP_BLOCK_REFERENCE_SUMMARY_EOF__\\'\\n echo \"$RECAP_BLOCK_REFERENCE_SUMMARY\"\\n echo \\'__RECAP_BLOCK_REFERENCE_SUMMARY_EOF__\\'\\n } >> \"$GITHUB_OUTPUT\"\\n node -e \\'process.stdout.write(JSON.stringify({ ok: true, summary: process.env.RECAP_BLOCK_REFERENCE_SUMMARY || \"\" }) + \"\\\\n\")\\'\\n exit 0\\n fi\\n if [ -n \"${RECAP_PUBLISH_REASON:-}\" ]; then\\n {\\n echo \\'summary<<__RECAP_PUBLISH_SUMMARY_EOF__\\'\\n echo \"$RECAP_PUBLISH_REASON\"\\n echo \\'__RECAP_PUBLISH_SUMMARY_EOF__\\'\\n } >> \"$GITHUB_OUTPUT\"\\n node -e \\'process.stdout.write(JSON.stringify({ ok: true, summary: process.env.RECAP_PUBLISH_REASON || \"\" }) + \"\\\\n\")\\'\\n exit 0\\n fi\\n RESULT=claude-result.json\\n STDERR=claude-stderr.log\\n EXIT_CODE=claude-exit-code.txt\\n if [ \"$RECAP_AGENT\" = \"codex\" ]; then\\n RESULT=codex-events.jsonl\\n STDERR=codex-stderr.log\\n EXIT_CODE=codex-exit-code.txt\\n elif [ \"$RECAP_AGENT\" = \"openai-compatible\" ]; then\\n RESULT=openai-compatible-result.txt\\n STDERR=openai-compatible-stderr.log\\n EXIT_CODE=openai-compatible-exit-code.txt\\n fi\\n $RECAP_CLI recap agent-summary --agent \"$RECAP_AGENT\" --result-file \"$RESULT\" --stderr-file \"$STDERR\" --exit-code-file \"$EXIT_CODE\" || true\\n\\n - name: Attach usage\\n if: steps.url.outputs.ok == \\'true\\'\\n continue-on-error: true\\n env:\\n PLAN_URL: ${{ steps.url.outputs.plan_url }}\\n # Use the gate-normalized agent so \"Codex\" still selects the right file.\\n RECAP_AGENT: ${{ needs.gate.outputs.agent }}\\n run: |\\n set -uo pipefail\\n RESULT=claude-result.json\\n if [ \"$RECAP_AGENT\" = \"codex\" ]; then RESULT=codex-events.jsonl; fi\\n if [ \"$RECAP_AGENT\" = \"openai-compatible\" ]; then RESULT=openai-compatible-usage.json; fi\\n if [ -f \"$RESULT\" ]; then $RECAP_CLI recap usage --plan-url \"$PLAN_URL\" --agent \"$RECAP_AGENT\" --result-file \"$RESULT\" --model \"${VISUAL_RECAP_MODEL:-}\" --app-url \"$PLAN_RECAP_APP_URL\" --token \"$PLAN_RECAP_TOKEN\" || true; fi\\n\\n - name: Cache Playwright browsers\\n if: steps.url.outputs.ok == \\'true\\'\\n uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3\\n with:\\n path: ~/.cache/ms-playwright\\n key: playwright-1-${{ runner.os }}\\n\\n - name: Screenshot + upload\\n id: shot\\n if: steps.url.outputs.ok == \\'true\\'\\n continue-on-error: true\\n env:\\n # recap-url.txt is untrusted agent output; pass via env, never ${{ }}.\\n PLAN_URL: ${{ steps.url.outputs.plan_url }}\\n run: |\\n set -uo pipefail\\n if [ -n \"${RECAP_PLAYWRIGHT:-}\" ] && [ -x \"$RECAP_PLAYWRIGHT\" ]; then\\n \"$RECAP_PLAYWRIGHT\" install --with-deps chromium || true\\n elif command -v pnpm >/dev/null 2>&1; then\\n pnpm exec playwright install --with-deps chromium 2>/dev/null || npx -y playwright@1 install --with-deps chromium || true\\n else\\n npx -y playwright@1 install --with-deps chromium || true\\n fi\\n IMAGE_CACHE_KEY=\"$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT\"\\n LIGHT_SHOT_JSON=\"$($RECAP_CLI recap shot --url \"$PLAN_URL\" --token \"$PLAN_RECAP_TOKEN\" --app-url \"$PLAN_RECAP_APP_URL\" --out recap.png --theme light --image-cache-key \"$IMAGE_CACHE_KEY\" || echo \\'{}\\')\"\\n DARK_SHOT_JSON=\"$($RECAP_CLI recap shot --url \"$PLAN_URL\" --token \"$PLAN_RECAP_TOKEN\" --app-url \"$PLAN_RECAP_APP_URL\" --out recap-dark.png --theme dark --image-cache-key \"$IMAGE_CACHE_KEY\" || echo \\'{}\\')\"\\n for SHOT_LABEL in light dark; do\\n if [ \"$SHOT_LABEL\" = \"light\" ]; then SHOT_JSON=\"$LIGHT_SHOT_JSON\"; else SHOT_JSON=\"$DARK_SHOT_JSON\"; fi\\n SHOT_LABEL=\"$SHOT_LABEL\" SHOT_JSON=\"$SHOT_JSON\" node -e \\'const label = process.env.SHOT_LABEL || \"shot\"; let parsed = {}; try { parsed = JSON.parse(process.env.SHOT_JSON || \"{}\"); } catch { parsed = { ok: false, reason: \"invalid shot JSON\" }; } const summary = { ok: parsed.ok === true, imageUrl: parsed.imageUrl ? \"[present]\" : \"\", out: typeof parsed.out === \"string\" ? parsed.out : \"\", reason: typeof parsed.reason === \"string\" ? parsed.reason.slice(0, 500) : \"\" }; console.log(`[recap shot] ${label}: ${JSON.stringify(summary)}`);\\'\\n done\\n IMAGE_URL=$(node -e \\'try{process.stdout.write(JSON.parse(process.argv[1]).imageUrl||\"\")}catch{process.stdout.write(\"\")}\\' \"$LIGHT_SHOT_JSON\")\\n DARK_IMAGE_URL=$(node -e \\'try{process.stdout.write(JSON.parse(process.argv[1]).imageUrl||\"\")}catch{process.stdout.write(\"\")}\\' \"$DARK_SHOT_JSON\")\\n SHOT_STATUS=$(LIGHT_SHOT_JSON=\"$LIGHT_SHOT_JSON\" DARK_SHOT_JSON=\"$DARK_SHOT_JSON\" node <<\\'NODE\\'\\n const parse = (raw) => { try { return JSON.parse(raw || \"{}\"); } catch { return { ok: false, reason: \"invalid shot JSON\" }; } };\\n const shots = [[\"light\", parse(process.env.LIGHT_SHOT_JSON)], [\"dark\", parse(process.env.DARK_SHOT_JSON)]];\\n const hasImage = shots.some(([, shot]) => typeof shot.imageUrl === \"string\" && shot.imageUrl.trim());\\n const reasons = shots.flatMap(([label, shot]) => {\\n if (typeof shot.reason === \"string\" && shot.reason.trim()) return [`${label}: ${shot.reason.trim()}`];\\n if (!(typeof shot.imageUrl === \"string\" && shot.imageUrl.trim())) return [`${label}: no imageUrl returned`];\\n return [];\\n });\\n process.stdout.write(JSON.stringify({ ok: hasImage, reason: hasImage ? \"\" : reasons.join(\"; \").slice(0, 1000) }));\\n NODE\\n )\\n SHOT_OK=$(node -e \\'try{process.stdout.write(JSON.parse(process.argv[1]).ok===true?\"true\":\"false\")}catch{process.stdout.write(\"false\")}\\' \"$SHOT_STATUS\")\\n SHOT_REASON=$(node -e \\'try{process.stdout.write(JSON.parse(process.argv[1]).reason||\"\")}catch{process.stdout.write(\"invalid shot status JSON\")}\\' \"$SHOT_STATUS\")\\n if [ \"$SHOT_OK\" != \"true\" ]; then\\n echo \"::warning::Visual recap screenshot unavailable; posting screenshot-failed recap comment. $SHOT_REASON\"\\n fi\\n echo \"image_url=$IMAGE_URL\" >> \"$GITHUB_OUTPUT\"\\n echo \"light_image_url=$IMAGE_URL\" >> \"$GITHUB_OUTPUT\"\\n echo \"dark_image_url=$DARK_IMAGE_URL\" >> \"$GITHUB_OUTPUT\"\\n echo \"shot_ok=$SHOT_OK\" >> \"$GITHUB_OUTPUT\"\\n {\\n echo \\'shot_reason<<__RECAP_SHOT_REASON_EOF__\\'\\n echo \"$SHOT_REASON\"\\n echo \\'__RECAP_SHOT_REASON_EOF__\\'\\n } >> \"$GITHUB_OUTPUT\"\\n if [ -f recap.png ] || [ -f recap-dark.png ]; then echo \"captured=true\" >> \"$GITHUB_OUTPUT\"; else echo \"captured=false\" >> \"$GITHUB_OUTPUT\"; fi\\n\\n - name: Upload recap screenshot artifact\\n if: steps.shot.outputs.captured == \\'true\\'\\n uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1\\n with:\\n name: pr-visual-recap-${{ github.event.pull_request.number }}\\n path: |\\n recap.png\\n recap-dark.png\\n if-no-files-found: ignore\\n retention-days: 14\\n\\n - name: Upload recap source artifact\\n if: always() && !cancelled()\\n uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1\\n with:\\n # recap-source.json + the agent transcript (claude-result.json /\\n # codex-events.jsonl + stderr) are the only window into WHAT the agent\\n # did when a publish fails (no plan URL) — INCLUDING the case where it\\n # finished without writing recap-source.json at all. The sticky comment\\n # only shows the screenshot, so without these a failed recap is\\n # undebuggable. Uploaded on success + failure; tolerant when absent.\\n name: pr-visual-recap-source-${{ github.event.pull_request.number }}\\n path: |\\n recap-source.json\\n claude-result.json\\n claude-stderr.log\\n codex-events.jsonl\\n codex-stderr.log\\n openai-compatible-result.txt\\n openai-compatible-usage.json\\n openai-compatible-stderr.log\\n if-no-files-found: ignore\\n retention-days: 14\\n\\n - name: Upsert sticky comment\\n if: always() && !cancelled()\\n continue-on-error: true\\n env:\\n PLAN_URL: ${{ steps.url.outputs.plan_url }}\\n RECAP_IMAGE_URL: ${{ steps.shot.outputs.image_url }}\\n RECAP_LIGHT_IMAGE_URL: ${{ steps.shot.outputs.light_image_url }}\\n RECAP_DARK_IMAGE_URL: ${{ steps.shot.outputs.dark_image_url }}\\n RECAP_SHOT_OK: ${{ steps.shot.outputs.shot_ok }}\\n RECAP_SHOT_REASON: ${{ steps.shot.outputs.shot_reason }}\\n SUPPRESSED: ${{ steps.scan.outputs.suppressed }}\\n SUPPRESSED_JSON: ${{ steps.scan.outputs.json }}\\n DIFF_HUGE: ${{ steps.diff.outputs.huge }}\\n DIFF_TINY: ${{ steps.diff.outputs.tiny }}\\n PREV_PLAN_ID: ${{ steps.prev.outputs.plan_id }}\\n RECAP_AUTH_FAILED: ${{ steps.auth_probe.outputs.auth_failed }}\\n RECAP_AGENT_SUMMARY: ${{ steps.agent_summary.outputs.summary }}\\n # Prefer the route-health diagnostic when the plan app routes are not\\n # yet deployed so the comment explains the 404 instead of a generic\\n # \"recap-url.txt was not created\" message.\\n RECAP_URL_REASON: ${{ steps.route_health.outputs.reason || steps.url.outputs.reason }}\\n run: |\\n set -euo pipefail\\n $RECAP_CLI recap comment upsert --repo \"$GITHUB_REPOSITORY\" --issue \"$PR_NUMBER\" --token \"$GH_TOKEN\" --head-sha \"$HEAD_SHA\"\\n\\n - name: Complete visual recap check\\n if: always() && !cancelled() && steps.recap_check.outputs.check_run_id != \\'\\'\\n continue-on-error: true\\n env:\\n # Untrusted/step values via env (NOT ${{ }}-interpolated into the run\\n # body): the agent-written plan URL and the scan JSON could inject shell.\\n CHECK_RUN_ID: ${{ steps.recap_check.outputs.check_run_id }}\\n PLAN_OK: ${{ steps.url.outputs.ok }}\\n PLAN_URL: ${{ steps.url.outputs.plan_url }}\\n SUPPRESSED: ${{ steps.scan.outputs.suppressed }}\\n SUPPRESSED_JSON: ${{ steps.scan.outputs.json }}\\n DIFF_HUGE: ${{ steps.diff.outputs.huge }}\\n DIFF_TINY: ${{ steps.diff.outputs.tiny }}\\n RECAP_AGENT_SUMMARY: ${{ steps.agent_summary.outputs.summary }}\\n RECAP_URL_REASON: ${{ steps.route_health.outputs.reason || steps.url.outputs.reason }}\\n run: |\\n set -uo pipefail\\n $RECAP_CLI recap check complete \\\\\\n --check-run-id \"$CHECK_RUN_ID\" \\\\\\n --plan-ok \"$PLAN_OK\" \\\\\\n --plan-url \"$PLAN_URL\" \\\\\\n --suppressed \"$SUPPRESSED\" \\\\\\n --suppressed-json \"$SUPPRESSED_JSON\" \\\\\\n --huge \"$DIFF_HUGE\" \\\\\\n --tiny \"$DIFF_TINY\" \\\\\\n --failure-summary \"$RECAP_AGENT_SUMMARY\" \\\\\\n --url-reason \"$RECAP_URL_REASON\" \\\\\\n --workflow-url \"$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID\"\\n';\n"]}
1
+ {"version":3,"file":"pr-visual-recap-workflow.js","sourceRoot":"","sources":["../../src/cli/pr-visual-recap-workflow.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,MAAM,CAAC,MAAM,4BAA4B,GACvC,24hDAA24hD,CAAC","sourcesContent":["/** Canonical PR Visual Recap workflow bundled by the CLI installer. */\nexport const PR_VISUAL_RECAP_WORKFLOW_YML =\n 'name: PR Visual Recap\\n\\n# Visual code review: a coding agent runs the repo\\'s visual-recap skill over the\\n# PR diff, publishes a plan, and upserts one sticky comment with a screenshot.\\n# Plain `pull_request` (NOT `pull_request_target`) so fork code never sees secrets.\\n\\non:\\n pull_request:\\n types: [opened, synchronize, reopened, ready_for_review, closed]\\n\\npermissions:\\n contents: read\\n\\nconcurrency:\\n group: pr-visual-recap-${{ github.event.pull_request.number }}\\n cancel-in-progress: true\\n\\nenv:\\n VISUAL_RECAP_AGENT: ${{ vars.VISUAL_RECAP_AGENT || \\'claude\\' }}\\n VISUAL_RECAP_BASE_URL: ${{ vars.VISUAL_RECAP_BASE_URL || \\'\\' }}\\n VISUAL_RECAP_SKILL_SOURCE: ${{ vars.VISUAL_RECAP_SKILL_SOURCE || \\'auto\\' }}\\n VISUAL_RECAP_SECRET_SCAN: ${{ vars.VISUAL_RECAP_SECRET_SCAN || \\'high-confidence\\' }}\\n\\njobs:\\n gate:\\n name: Gate\\n # A custom plain-label runner is allowed only for trusted same-repo authors.\\n # Fork and untrusted PRs are forced onto GitHub-hosted ubuntu-latest before\\n # any step starts. The only fromJSON input is this static association list.\\n runs-on: ${{ github.event.pull_request.head.repo.full_name == github.repository && contains(fromJSON(\\'[\"OWNER\",\"MEMBER\",\"COLLABORATOR\"]\\'), github.event.pull_request.author_association) && (vars.VISUAL_RECAP_GATE_RUNS_ON || \\'ubuntu-latest\\') || \\'ubuntu-latest\\' }}\\n timeout-minutes: 10\\n permissions:\\n contents: read\\n issues: write\\n pull-requests: write\\n outputs:\\n run: ${{ steps.decide.outputs.run }}\\n agent: ${{ steps.decide.outputs.agent }}\\n runs_on: ${{ steps.decide.outputs.runs_on }}\\n steps:\\n - id: decide\\n uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0\\n env:\\n # Presence-only signals — never expose secret VALUES to the gate.\\n HAS_PLAN: ${{ secrets.PLAN_RECAP_TOKEN != \\'\\' }}\\n HAS_ANTHROPIC: ${{ secrets.ANTHROPIC_API_KEY != \\'\\' }}\\n HAS_OPENAI: ${{ secrets.OPENAI_API_KEY != \\'\\' }}\\n HAS_COMPATIBLE: ${{ secrets.VISUAL_RECAP_API_KEY != \\'\\' }}\\n AGENT: ${{ env.VISUAL_RECAP_AGENT }}\\n VISUAL_RECAP_BASE_URL: ${{ env.VISUAL_RECAP_BASE_URL }}\\n VISUAL_RECAP_MODEL: ${{ vars.VISUAL_RECAP_MODEL }}\\n VISUAL_RECAP_RUNS_ON: ${{ vars.VISUAL_RECAP_RUNS_ON || \\'\"ubuntu-latest\"\\' }}\\n VISUAL_RECAP_SKILL_SOURCE: ${{ env.VISUAL_RECAP_SKILL_SOURCE }}\\n HEAD_SHA: ${{ github.event.pull_request.head.sha }}\\n with:\\n script: |\\n const pr = context.payload.pull_request;\\n const reasons = [];\\n\\n if (!pr) reasons.push(\\'no pull_request payload\\');\\n if (pr && pr.draft) reasons.push(\\'draft PR\\');\\n if (pr && context.payload.action === \\'closed\\' && !pr.merged) {\\n reasons.push(\\'closed without merge\\');\\n }\\n\\n // Fork PRs only receive repo secrets when the org/repo opts into\\n // GitHub\\'s \"Send secrets to workflows from pull requests\" setting\\n // (common in private orgs that use forks heavily). Gate on secret\\n // availability, not fork-ness: run on forks that have the token,\\n // and skip — with an actionable hint — those that don\\'t.\\n const headRepo = pr && pr.head && pr.head.repo && pr.head.repo.full_name;\\n const isFork = !!(pr && headRepo && headRepo !== process.env.GITHUB_REPOSITORY);\\n const isPrivate = !!(context.payload.repository && context.payload.repository.private);\\n const association = (pr && pr.author_association || \\'\\').toUpperCase();\\n const trustedAssociations = [\\'OWNER\\', \\'MEMBER\\', \\'COLLABORATOR\\'];\\n const isTrustedAuthor = trustedAssociations.includes(association);\\n let configuredRunner = \\'ubuntu-latest\\';\\n let usesSelfHostedRunner = false;\\n try {\\n const candidate = JSON.parse(process.env.VISUAL_RECAP_RUNS_ON || \\'\"ubuntu-latest\"\\');\\n const hosted = typeof candidate === \\'string\\' && /^(?:ubuntu|windows|macos)-[A-Za-z0-9.-]+$/.test(candidate);\\n const selfHosted = Array.isArray(candidate) && candidate.length >= 1 && candidate.length <= 20 && candidate.includes(\\'self-hosted\\') && candidate.every((label) => typeof label === \\'string\\' && label.length >= 1 && label.length <= 100 && !/[\\\\u0000-\\\\u001f\\\\u007f]/.test(label)) && new Set(candidate).size === candidate.length;\\n if (!hosted && !selfHosted) throw new Error(\\'unsupported runner value\\');\\n configuredRunner = candidate;\\n usesSelfHostedRunner = selfHosted;\\n } catch {\\n reasons.push(\\'invalid VISUAL_RECAP_RUNS_ON JSON\\');\\n }\\n if (usesSelfHostedRunner && (isFork || !isTrustedAuthor)) {\\n reasons.push(\\'self-hosted runner mode requires a trusted same-repository PR author\\');\\n }\\n if (isFork && process.env.HAS_PLAN !== \\'true\\') {\\n reasons.push(`fork PR (${headRepo}) without secret access — enable \"Send secrets to workflows from pull requests\" (and write tokens) in the repo/org Actions settings to run recaps on forks`);\\n }\\n\\n const login = (pr && pr.user && pr.user.login || \\'\\').toLowerCase();\\n const botAuthors = [\\'dependabot[bot]\\', \\'dependabot\\', \\'renovate[bot]\\', \\'renovate\\'];\\n if (botAuthors.includes(login)) reasons.push(`bot author (${login})`);\\n if (pr && pr.user && pr.user.type === \\'Bot\\') reasons.push(\\'bot author (type=Bot)\\');\\n\\n if (!isFork && process.env.HAS_PLAN !== \\'true\\') reasons.push(\\'PLAN_RECAP_TOKEN not configured\\');\\n\\n // Normalize + validate the agent so a mis-cased value can\\'t pass the\\n // gate and then match neither agent step below.\\n const rawAgent = (process.env.AGENT || \\'claude\\').toLowerCase();\\n const agent = [\\'deepseek\\', \\'kimi\\', \\'moonshot\\', \\'custom\\'].includes(rawAgent) ? \\'openai-compatible\\' : rawAgent;\\n if (![\\'claude\\', \\'codex\\', \\'openai-compatible\\'].includes(agent)) {\\n reasons.push(`unsupported VISUAL_RECAP_AGENT \"${process.env.AGENT}\" (expected \"claude\", \"codex\", or \"openai-compatible\")`);\\n } else if (agent === \\'codex\\') {\\n if (process.env.HAS_OPENAI !== \\'true\\') reasons.push(\\'OPENAI_API_KEY not configured (codex backend)\\');\\n } else if (agent === \\'claude\\') {\\n if (process.env.HAS_ANTHROPIC !== \\'true\\') reasons.push(\\'ANTHROPIC_API_KEY not configured (claude backend)\\');\\n } else {\\n if (process.env.HAS_COMPATIBLE !== \\'true\\') reasons.push(\\'VISUAL_RECAP_API_KEY not configured (openai-compatible backend)\\');\\n if (!(process.env.VISUAL_RECAP_MODEL || \\'\\').trim()) reasons.push(\\'VISUAL_RECAP_MODEL is required (openai-compatible backend)\\');\\n const baseUrl = process.env.VISUAL_RECAP_BASE_URL || \\'\\';\\n try {\\n const parsed = new URL(baseUrl);\\n if (![\\'http:\\', \\'https:\\'].includes(parsed.protocol) || parsed.username || parsed.password) {\\n reasons.push(\\'VISUAL_RECAP_BASE_URL must be an http(s) URL without credentials\\');\\n }\\n } catch {\\n reasons.push(\\'VISUAL_RECAP_BASE_URL must be a valid http(s) URL\\');\\n }\\n }\\n\\n // Validate the model before it reaches the agent CLI.\\n const model = process.env.VISUAL_RECAP_MODEL || \\'\\';\\n if (model && !/^[a-zA-Z0-9._-]{1,80}$/.test(model)) {\\n reasons.push(`invalid VISUAL_RECAP_MODEL value (must match [a-zA-Z0-9._-]{1,80})`);\\n }\\n\\n const skillSource = (process.env.VISUAL_RECAP_SKILL_SOURCE || \\'auto\\').toLowerCase();\\n if (![\\'auto\\', \\'latest\\', \\'repo\\'].includes(skillSource)) {\\n reasons.push(\\'invalid VISUAL_RECAP_SKILL_SOURCE value (expected \"auto\", \"latest\", or \"repo\")\\');\\n }\\n const usesRepoSkill = skillSource === \\'repo\\';\\n\\n // Self-modifying guard, evaluated in the trusted gate (runs NO\\n // PR-checked-out code): skip the ENTIRE job if the PR touches the\\n // repo-pinned skill instructions or any agent config the runner\\n // loads, so a PR can\\'t rewrite what the agent loads and exfiltrate\\n // secrets. With the default bundled skill source, visual skill and\\n // recap workflow files are reviewed content, not instructions loaded\\n // by the runner.\\n // Keep this guard for untrusted forks and untrusted public-repo PRs.\\n // Trusted write actors may edit recap-control files as normal\\n // reviewable content; running the recap is useful signal for those\\n // changes.\\n if (pr && !isTrustedAuthor && (isFork || !isPrivate)) {\\n try {\\n const files = await github.paginate(github.rest.pulls.listFiles, {\\n owner: context.repo.owner,\\n repo: context.repo.repo,\\n pull_number: pr.number,\\n per_page: 100,\\n });\\n const isSensitive = (p) =>\\n (usesRepoSkill && /(^|\\\\/)skills\\\\/visual-(recap|plan|plans)\\\\//.test(p)) ||\\n p.startsWith(\\'.claude/\\') ||\\n p === \\'CLAUDE.md\\' ||\\n p === \\'AGENTS.md\\' ||\\n p === \\'.mcp.json\\';\\n const hits = files.map((f) => f.filename).filter(isSensitive);\\n if (hits.length) {\\n reasons.push(`PR modifies recap-control files (${hits.slice(0, 3).join(\\', \\')}${hits.length > 3 ? \\', …\\' : \\'\\'}) — skipping so untrusted PR code never runs with secrets`);\\n }\\n } catch (e) {\\n // Fail closed: if the file list can\\'t be read, skip.\\n reasons.push(`could not list PR files for the self-modifying guard (${e.message}); skipping to be safe`);\\n }\\n }\\n\\n const run = reasons.length === 0;\\n core.setOutput(\\'run\\', run ? \\'true\\' : \\'false\\');\\n core.setOutput(\\'agent\\', agent);\\n core.setOutput(\\'runs_on\\', JSON.stringify(configuredRunner));\\n if (run) {\\n core.info(`Visual recap will run (${agent}).`);\\n } else {\\n // Surface the skip reason as a run-summary annotation, not just a\\n // buried info log, so it\\'s clear in the Actions UI why we skipped.\\n core.notice(`Visual recap skipped: ${reasons.join(\\'; \\')}`);\\n }\\n\\n // When skipping, upsert a sticky recap comment with a short skip\\n // line so the PR always explains why the recap job did not run.\\n if (!run && pr) {\\n try {\\n const MARKER = \\'<!-- pr-visual-recap -->\\';\\n const { data: comments } = await github.rest.issues.listComments({\\n owner: context.repo.owner,\\n repo: context.repo.repo,\\n issue_number: pr.number,\\n per_page: 100,\\n });\\n const existing = comments.find(\\n (c) => c.user && c.user.type === \\'Bot\\' && c.body && c.body.includes(MARKER)\\n );\\n const headShort = (process.env.HEAD_SHA || \\'\\').slice(0, 7);\\n const shaRef = headShort ? `\\\\`${headShort}\\\\`` : \\'latest push\\';\\n const primaryReason = reasons.filter(\\n (r) => !r.startsWith(\\'could not list PR files for the self-modifying guard\\')\\n )[0] || reasons[0] || \\'skipped\\';\\n const skipLine = `_Recap skipped for ${shaRef}: ${primaryReason}._`;\\n const baseBody = `${MARKER}\\\\n### Visual recap — skipped\\\\n\\\\nThe visual recap job did not run for this pull request. This is informational only and does **not** block the PR.`;\\n const planIdMatch = (existing && existing.body ? existing.body : \\'\\').match(/<!--\\\\s*plan-id:\\\\s*([A-Za-z0-9_-]{1,64})\\\\s*-->/);\\n const planIdMarker = planIdMatch ? `\\\\n\\\\n<!-- plan-id: ${planIdMatch[1]} -->` : \\'\\';\\n const updatedBody = `${baseBody}${planIdMarker}\\\\n\\\\n${skipLine}`;\\n if (existing) {\\n await github.rest.issues.updateComment({\\n owner: context.repo.owner,\\n repo: context.repo.repo,\\n comment_id: existing.id,\\n body: updatedBody,\\n });\\n } else {\\n await github.rest.issues.createComment({\\n owner: context.repo.owner,\\n repo: context.repo.repo,\\n issue_number: pr.number,\\n body: updatedBody,\\n });\\n }\\n } catch (e) {\\n core.warning(`Could not update recap skip comment: ${e.message}`);\\n }\\n }\\n\\n recap:\\n name: Generate visual recap\\n needs: gate\\n if: needs.gate.outputs.run == \\'true\\'\\n runs-on: ${{ fromJSON(needs.gate.outputs.runs_on) }}\\n timeout-minutes: 30\\n permissions:\\n actions: write\\n checks: write\\n contents: read\\n issues: write\\n pull-requests: write\\n env:\\n PLAN_RECAP_APP_URL: ${{ secrets.PLAN_RECAP_APP_URL || \\'https://plan.agent-native.com\\' }}\\n PLAN_RECAP_TOKEN: ${{ secrets.PLAN_RECAP_TOKEN }}\\n GH_TOKEN: ${{ github.token }}\\n PR_NUMBER: ${{ github.event.pull_request.number }}\\n PR_STATE: ${{ github.event.pull_request.state }}\\n PR_MERGED: ${{ github.event.pull_request.merged }}\\n PR_MERGED_AT: ${{ github.event.pull_request.merged_at }}\\n HEAD_SHA: ${{ github.event.pull_request.head.sha }}\\n VISUAL_RECAP_MODEL: ${{ vars.VISUAL_RECAP_MODEL }}\\n VISUAL_RECAP_BASE_URL: ${{ vars.VISUAL_RECAP_BASE_URL || \\'\\' }}\\n VISUAL_RECAP_REASONING: ${{ vars.VISUAL_RECAP_REASONING }}\\n VISUAL_RECAP_SKILL_SOURCE: ${{ vars.VISUAL_RECAP_SKILL_SOURCE || \\'auto\\' }}\\n VISUAL_RECAP_SECRET_SCAN: ${{ vars.VISUAL_RECAP_SECRET_SCAN || \\'high-confidence\\' }}\\n steps:\\n - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3\\n with:\\n fetch-depth: 0\\n # This job runs an agent over untrusted PR diff; don\\'t leave the token\\n # in .git/config (it uses GH_TOKEN for gh API calls, never git push).\\n persist-credentials: false\\n\\n # Dogfood trusted base-branch source inside this monorepo, else install the\\n # published package once. Never execute PR-head recap CLI code.\\n - name: Resolve recap CLI\\n id: cli\\n env:\\n # Optional: pin the consumer CLI version (e.g. \"1.2.3\"). Defaults to\\n # \"latest\" when unset. Set via repository variable RECAP_CLI_VERSION.\\n RECAP_CLI_VERSION: ${{ vars.RECAP_CLI_VERSION || \\'latest\\' }}\\n run: |\\n if [ \"$GITHUB_REPOSITORY\" = \"BuilderIO/agent-native\" ] && [ -f packages/core/src/cli/index.ts ]; then\\n echo \"local=true\" >> \"$GITHUB_OUTPUT\"\\n else\\n echo \"local=false\" >> \"$GITHUB_OUTPUT\"\\n fi\\n\\n - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3\\n if: steps.cli.outputs.local == \\'true\\'\\n with:\\n ref: ${{ github.event.pull_request.base.sha }}\\n path: .recap-cli-source\\n fetch-depth: 1\\n persist-credentials: false\\n\\n - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8\\n if: steps.cli.outputs.local == \\'true\\'\\n\\n - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0\\n with:\\n node-version: \"22\"\\n cache: ${{ steps.cli.outputs.local == \\'true\\' && \\'pnpm\\' || \\'\\' }}\\n\\n - name: Install trusted workspace recap CLI\\n if: steps.cli.outputs.local == \\'true\\'\\n working-directory: .recap-cli-source\\n run: |\\n set -euo pipefail\\n pnpm install --frozen-lockfile --ignore-scripts\\n echo \"RECAP_CLI=$PWD/node_modules/.bin/tsx $PWD/packages/core/src/cli/index.ts\" >> \"$GITHUB_ENV\"\\n echo \"RECAP_PLAYWRIGHT=$PWD/node_modules/.bin/playwright\" >> \"$GITHUB_ENV\"\\n\\n - name: Install published recap CLI\\n if: steps.cli.outputs.local != \\'true\\'\\n env:\\n RECAP_CLI_VERSION: ${{ vars.RECAP_CLI_VERSION || \\'latest\\' }}\\n run: |\\n set -euo pipefail\\n VERSION=\"$RECAP_CLI_VERSION\"\\n if [ \"$VERSION\" = \"latest\" ]; then\\n VERSION=\"$(npm view @agent-native/core@latest version)\"\\n fi\\n for attempt in 1 2 3; do\\n if npm install --prefix \"$RUNNER_TEMP/recap-cli\" --no-audit --no-fund \"@agent-native/core@$VERSION\"; then\\n break\\n fi\\n if [ \"$attempt\" = \"3\" ]; then exit 1; fi\\n sleep $((attempt * 10))\\n done\\n echo \"RECAP_CLI=$RUNNER_TEMP/recap-cli/node_modules/.bin/agent-native\" >> \"$GITHUB_ENV\"\\n echo \"RECAP_PLAYWRIGHT=$RUNNER_TEMP/recap-cli/node_modules/.bin/playwright\" >> \"$GITHUB_ENV\"\\n\\n - name: Install OpenAI-compatible provider runtime\\n if: needs.gate.outputs.agent == \\'openai-compatible\\' && steps.cli.outputs.local != \\'true\\'\\n run: |\\n set -euo pipefail\\n npm install --prefix \"$RUNNER_TEMP/recap-cli\" --no-audit --no-fund ai @ai-sdk/openai\\n\\n - name: Start visual recap check\\n id: recap_check\\n continue-on-error: true\\n run: |\\n set -uo pipefail\\n $RECAP_CLI recap check start --sha \"$HEAD_SHA\" --workflow-url \"$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID\"\\n\\n - name: Fetch pull request head\\n env:\\n PR_NUMBER_ENV: ${{ github.event.pull_request.number }}\\n run: |\\n set -euo pipefail\\n if git cat-file -e \"${HEAD_SHA}^{commit}\" 2>/dev/null; then\\n git update-ref refs/recap/pr-head \"$HEAD_SHA\"\\n else\\n AUTH_B64=\"$(printf \\'x-access-token:%s\\' \"$GH_TOKEN\" | base64 | tr -d \\'\\\\n\\')\"\\n git -c \"http.https://github.com/.extraheader=AUTHORIZATION: basic $AUTH_B64\" fetch origin \"pull/${PR_NUMBER_ENV}/head:refs/recap/pr-head\"\\n fi\\n FETCHED_SHA=\"$(git rev-parse refs/recap/pr-head)\"\\n if [ \"$FETCHED_SHA\" != \"$HEAD_SHA\" ]; then\\n echo \"FATAL: fetched PR head $FETCHED_SHA != event HEAD_SHA $HEAD_SHA — aborting to avoid recapping the wrong commit\"\\n exit 1\\n fi\\n\\n - name: Collect bounded diff\\n id: diff\\n env:\\n BASE_SHA: ${{ github.event.pull_request.base.sha }}\\n run: |\\n set -euo pipefail\\n $RECAP_CLI recap collect-diff --base \"$BASE_SHA\" --head refs/recap/pr-head --out recap.diff --stat recap.stat\\n\\n - name: Probe plan-app auth\\n id: auth_probe\\n if: steps.diff.outputs.tiny != \\'true\\'\\n continue-on-error: true\\n run: |\\n set -uo pipefail\\n # Hit the plan app\\'s action surface with the publish token. A 401 means\\n # the token is expired/revoked; surface it in the sticky comment so the\\n # repo owner knows to re-mint it instead of seeing a generic failure.\\n HTTP_STATUS=$(node -e \\'\\n const https = require(\"https\");\\n const url = new URL(\"/_agent-native/actions/record-recap-usage\", process.env.PLAN_RECAP_APP_URL || \"https://plan.agent-native.com\");\\n const req = https.request(url, { method: \"POST\", headers: { \"authorization\": \"Bearer \" + process.env.PLAN_RECAP_TOKEN, \"content-type\": \"application/json\" }, timeout: 8000 }, (res) => { process.stdout.write(String(res.statusCode)); req.destroy(); });\\n req.on(\"error\", () => process.stdout.write(\"0\"));\\n req.end(JSON.stringify({ planId: \"__probe__\" }));\\n \\' 2>/dev/null || echo \"0\")\\n if [ \"$HTTP_STATUS\" = \"401\" ]; then\\n echo \"auth_failed=true\" >> \"$GITHUB_OUTPUT\"\\n else\\n echo \"auth_failed=false\" >> \"$GITHUB_OUTPUT\"\\n fi\\n\\n - name: Probe plan-app route health\\n id: route_health\\n if: steps.diff.outputs.tiny != \\'true\\'\\n continue-on-error: true\\n run: |\\n set -uo pipefail\\n # Pre-publish health gate: confirm the plan app\\'s recap action routes\\n # are actually deployed BEFORE the agent runs. A 404 from\\n # create-visual-recap (POST) or get-plan-blocks (GET) means the\\n # plan-app deploy has not propagated yet (the client is ahead of the\\n # deployed server). Say that plainly here instead of letting the agent\\n # run and then fail confusingly at publish time. A 401 or 200 is\\n # healthy — the route exists, it just rejected/accepted the probe.\\n probe_status() {\\n ROUTE=\"$1\" METHOD=\"$2\" node -e \\'\\n const https = require(\"https\");\\n const base = process.env.PLAN_RECAP_APP_URL || \"https://plan.agent-native.com\";\\n const url = new URL(process.env.ROUTE, base);\\n if (process.env.METHOD === \"GET\") url.searchParams.set(\"format\", \"reference\");\\n const req = https.request(url, { method: process.env.METHOD, headers: { \"authorization\": \"Bearer \" + (process.env.PLAN_RECAP_TOKEN || \"\"), \"content-type\": \"application/json\" }, timeout: 8000 }, (res) => { process.stdout.write(String(res.statusCode)); req.destroy(); });\\n req.on(\"error\", () => process.stdout.write(\"0\"));\\n req.on(\"timeout\", () => { process.stdout.write(\"0\"); req.destroy(); });\\n if (process.env.METHOD === \"POST\") { req.end(JSON.stringify({ __probe__: true })); } else { req.end(); }\\n \\' 2>/dev/null || echo \"0\"\\n }\\n CREATE_STATUS=\"$(probe_status /_agent-native/actions/create-visual-recap POST)\"\\n BLOCKS_STATUS=\"$(probe_status /_agent-native/actions/get-plan-blocks GET)\"\\n REASON=\"\"\\n if [ \"$CREATE_STATUS\" = \"404\" ] || [ \"$BLOCKS_STATUS\" = \"404\" ]; then\\n REASON=\"Plan app routes return 404 — deploy not yet propagated (create-visual-recap: $CREATE_STATUS, get-plan-blocks: $BLOCKS_STATUS). The plan-app client is ahead of the deployed server; re-run once the deploy finishes propagating.\"\\n echo \"::error::$REASON\"\\n echo \"unhealthy=true\" >> \"$GITHUB_OUTPUT\"\\n else\\n echo \"unhealthy=false\" >> \"$GITHUB_OUTPUT\"\\n fi\\n {\\n echo \\'reason<<__RECAP_ROUTE_HEALTH_EOF__\\'\\n echo \"$REASON\"\\n echo \\'__RECAP_ROUTE_HEALTH_EOF__\\'\\n } >> \"$GITHUB_OUTPUT\"\\n\\n - name: Secret scan\\n id: scan\\n if: steps.diff.outputs.tiny != \\'true\\' && steps.route_health.outputs.unhealthy != \\'true\\'\\n run: |\\n set -uo pipefail\\n # Fail CLOSED: a scanner error or invalid JSON suppresses the diff so a\\n # credential-bearing diff is never handed to the agent / plan service.\\n if ! SCAN_JSON=\"$($RECAP_CLI recap scan --diff recap.diff --mode \"$VISUAL_RECAP_SECRET_SCAN\")\"; then\\n SCAN_JSON=\\'{\"suppressed\":true,\"reason\":\"secret scan failed to run; failing closed\"}\\'\\n fi\\n {\\n echo \\'json<<__RECAP_SCAN_EOF__\\'\\n echo \"$SCAN_JSON\"\\n echo \\'__RECAP_SCAN_EOF__\\'\\n } >> \"$GITHUB_OUTPUT\"\\n SUPPRESSED=$(node -e \\'try{process.stdout.write(JSON.parse(process.argv[1]).suppressed?\"true\":\"false\")}catch{process.stdout.write(\"true\")}\\' \"$SCAN_JSON\")\\n echo \"suppressed=$SUPPRESSED\" >> \"$GITHUB_OUTPUT\"\\n\\n - name: Read previous plan id\\n id: prev\\n if: steps.diff.outputs.tiny != \\'true\\' && steps.route_health.outputs.unhealthy != \\'true\\'\\n continue-on-error: true\\n run: |\\n set -euo pipefail\\n PLAN_ID=\"$($RECAP_CLI recap comment find-plan-id --repo \"$GITHUB_REPOSITORY\" --issue \"$PR_NUMBER\" --token \"$GH_TOKEN\")\"\\n echo \"plan_id=$PLAN_ID\" >> \"$GITHUB_OUTPUT\"\\n\\n - name: Fetch plan block reference\\n id: block_reference\\n if: steps.diff.outputs.tiny != \\'true\\' && steps.route_health.outputs.unhealthy != \\'true\\' && steps.scan.outputs.suppressed != \\'true\\'\\n continue-on-error: true\\n run: |\\n set -uo pipefail\\n if $RECAP_CLI recap block-reference --app-url \"$PLAN_RECAP_APP_URL\" --out recap-blocks.md; then\\n echo \"ok=true\" >> \"$GITHUB_OUTPUT\"\\n else\\n echo \"ok=false\" >> \"$GITHUB_OUTPUT\"\\n {\\n echo \\'summary<<__RECAP_BLOCK_REFERENCE_EOF__\\'\\n echo \"Could not fetch the live plan block reference; the agent will fall back to bundled visual-recap instructions and the publisher will validate the final MDX.\"\\n echo \\'__RECAP_BLOCK_REFERENCE_EOF__\\'\\n } >> \"$GITHUB_OUTPUT\"\\n cat > recap-blocks.md <<\\'EOF\\'\\n Live plan block reference unavailable. Follow the bundled visual-recap skill and author conservative MDX; the deterministic publisher will validate the source before posting.\\n EOF\\n fi\\n\\n - name: Build recap prompt\\n id: prompt\\n if: steps.diff.outputs.tiny != \\'true\\' && steps.route_health.outputs.unhealthy != \\'true\\' && steps.scan.outputs.suppressed != \\'true\\'\\n env:\\n # Pass step outputs via env, NOT ${{ }} interpolation into the run body:\\n # the prev plan id is parsed from a PR comment and could inject shell.\\n PREV_PLAN_ID: ${{ steps.prev.outputs.plan_id }}\\n DIFF_HUGE: ${{ steps.diff.outputs.huge }}\\n IS_FORK: ${{ github.event.pull_request.head.repo.full_name != github.repository }}\\n run: |\\n set -euo pipefail\\n ARGS=(--diff recap.diff --stat recap.stat --block-reference recap-blocks.md --pr \"$PR_NUMBER\" --repo \"$GITHUB_REPOSITORY\" --head \"$HEAD_SHA\" --app-url \"$PLAN_RECAP_APP_URL\" --skill-source \"$VISUAL_RECAP_SKILL_SOURCE\" --out recap-prompt.md)\\n if [ \"${DIFF_HUGE:-}\" = \"true\" ]; then ARGS+=(--huge); fi\\n if [ \"${IS_FORK:-}\" = \"true\" ]; then ARGS+=(--fork-pr true); fi\\n if [ -n \"${PREV_PLAN_ID:-}\" ]; then ARGS+=(--prev-plan-id \"$PREV_PLAN_ID\"); fi\\n $RECAP_CLI recap build-prompt \"${ARGS[@]}\"\\n\\n - name: Run agent (Claude Code)\\n id: claude\\n if: needs.gate.outputs.agent == \\'claude\\' && steps.diff.outputs.tiny != \\'true\\' && steps.route_health.outputs.unhealthy != \\'true\\' && steps.scan.outputs.suppressed != \\'true\\'\\n continue-on-error: true\\n env:\\n ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}\\n run: |\\n set -uo pipefail\\n CLAUDE_ALLOWED_TOOLS=\"Read,Write,Bash(git diff:*)\"\\n CLAUDE_ARGS=(-p \"$(cat recap-prompt.md)\" --allowedTools \"$CLAUDE_ALLOWED_TOOLS\" --permission-mode dontAsk --output-format json)\\n if [ -n \"${VISUAL_RECAP_MODEL:-}\" ]; then CLAUDE_ARGS+=(--model \"$VISUAL_RECAP_MODEL\"); fi\\n rm -f recap-source.json recap-url.txt recap-url-reason.txt claude-result.json claude-stderr.log\\n run_claude() {\\n set +e\\n npx -y @anthropic-ai/claude-code@2 \"${CLAUDE_ARGS[@]}\" > claude-result.json 2> claude-stderr.log\\n CLAUDE_STATUS=\"$?\"\\n set -e\\n echo \"$CLAUDE_STATUS\" > claude-exit-code.txt\\n }\\n run_claude\\n # A clean agent exit WITHOUT recap-source.json is the strongest\\n # \"retry me\" signal — the deterministic publisher needs that file, and\\n # the agent occasionally finishes a turn without writing it. Retry once.\\n if [ ! -s recap-source.json ]; then\\n if grep -Eiq -- \\'quota exceeded|billing details|insufficient (credits|quota)|rate[-_ ]limit|invalid (api )?key|authentication (failed|error)|unauthorized|forbidden\\' claude-result.json claude-stderr.log 2>/dev/null; then\\n echo \"::error::Visual recap agent failed with a non-retryable provider error; skipping the duplicate retry.\"\\n else\\n echo \"::warning::recap-source.json missing after the agent run; retrying the agent once.\"\\n sleep 5\\n run_claude\\n fi\\n fi\\n\\n - name: Run agent (Codex)\\n id: codex\\n if: needs.gate.outputs.agent == \\'codex\\' && steps.diff.outputs.tiny != \\'true\\' && steps.route_health.outputs.unhealthy != \\'true\\' && steps.scan.outputs.suppressed != \\'true\\'\\n continue-on-error: true\\n env:\\n OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}\\n run: |\\n set -uo pipefail\\n # `codex login` writes ~/.codex/auth.json (the bare env var is dropped on\\n # the gpt-5.5 wss transport); stdin keeps the key out of process args.\\n printenv OPENAI_API_KEY | npx -y @openai/codex@0 login --with-api-key || true\\n # The runner is itself an ephemeral sandbox; bypass Codex\\'s own sandbox\\n # (bubblewrap can\\'t init here) and approval gate (cancels the MCP write).\\n CODEX_ARGS=(exec --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check)\\n if [ -n \"${VISUAL_RECAP_MODEL:-}\" ]; then CODEX_ARGS+=(--model \"$VISUAL_RECAP_MODEL\"); fi\\n # Validate reasoning against the enum before embedding it in the TOML override.\\n case \"${VISUAL_RECAP_REASONING:-}\" in\\n none|minimal|low|medium|high|xhigh)\\n CODEX_ARGS+=(-c \"model_reasoning_effort=\\\\\"$VISUAL_RECAP_REASONING\\\\\"\") ;;\\n \"\") ;;\\n *) echo \"Ignoring invalid VISUAL_RECAP_REASONING: $VISUAL_RECAP_REASONING\" ;;\\n esac\\n rm -f recap-source.json recap-url.txt recap-url-reason.txt codex-events.jsonl codex-stderr.log\\n run_codex() {\\n set +e\\n npx -y @openai/codex@0 \"${CODEX_ARGS[@]}\" --json \"$(cat recap-prompt.md)\" 2> codex-stderr.log | tee codex-events.jsonl\\n CODEX_STATUS=\"${PIPESTATUS[0]}\"\\n set -e\\n echo \"$CODEX_STATUS\" > codex-exit-code.txt\\n }\\n run_codex\\n # Retry once if the agent exited without writing recap-source.json\\n # (see the Claude step) — the publisher needs that file.\\n if [ ! -s recap-source.json ]; then\\n if grep -Eiq -- \\'quota exceeded|billing details|insufficient (credits|quota)|rate[-_ ]limit|invalid (api )?key|authentication (failed|error)|unauthorized|forbidden\\' codex-events.jsonl codex-stderr.log 2>/dev/null; then\\n echo \"::error::Visual recap agent failed with a non-retryable provider error; skipping the duplicate retry.\"\\n else\\n echo \"::warning::recap-source.json missing after the agent run; retrying the agent once.\"\\n sleep 5\\n run_codex\\n fi\\n fi\\n\\n - name: Run agent (OpenAI-compatible)\\n id: openai_compatible\\n if: needs.gate.outputs.agent == \\'openai-compatible\\' && steps.diff.outputs.tiny != \\'true\\' && steps.route_health.outputs.unhealthy != \\'true\\' && steps.scan.outputs.suppressed != \\'true\\'\\n continue-on-error: true\\n env:\\n OPENAI_API_KEY: ${{ secrets.VISUAL_RECAP_API_KEY }}\\n OPENAI_BASE_URL: ${{ vars.VISUAL_RECAP_BASE_URL }}\\n AGENT_ENGINE: ai-sdk:openai\\n AGENT_MODEL: ${{ vars.VISUAL_RECAP_MODEL }}\\n AGENT_NATIVE_CODE_USAGE_FILE: openai-compatible-usage.json\\n AGENT_NATIVE_CODE_TOOL_PROFILE: recap-source\\n run: |\\n set -uo pipefail\\n rm -f recap-source.json recap-url.txt recap-url-reason.txt openai-compatible-result.txt openai-compatible-usage.json openai-compatible-stderr.log\\n run_openai_compatible() {\\n set +e\\n $RECAP_CLI code exec --permission-mode auto-edit \"$(cat recap-prompt.md)\" > openai-compatible-result.txt 2> openai-compatible-stderr.log\\n OPENAI_COMPATIBLE_STATUS=\"$?\"\\n set -e\\n echo \"$OPENAI_COMPATIBLE_STATUS\" > openai-compatible-exit-code.txt\\n }\\n run_openai_compatible\\n if [ ! -s recap-source.json ]; then\\n if grep -Eiq -- \\'quota exceeded|billing details|insufficient (credits|quota)|rate[-_ ]limit|invalid (api )?key|authentication (failed|error)|unauthorized|forbidden\\' openai-compatible-result.txt openai-compatible-stderr.log 2>/dev/null; then\\n echo \"::error::Visual recap agent failed with a non-retryable provider error; skipping the duplicate retry.\"\\n else\\n echo \"::warning::recap-source.json missing after the agent run; retrying the agent once.\"\\n sleep 5\\n run_openai_compatible\\n fi\\n fi\\n\\n - name: Publish recap source\\n id: publish\\n if: steps.diff.outputs.tiny != \\'true\\' && steps.route_health.outputs.unhealthy != \\'true\\' && steps.scan.outputs.suppressed != \\'true\\'\\n continue-on-error: true\\n env:\\n PREV_PLAN_ID: ${{ steps.prev.outputs.plan_id }}\\n run: |\\n set -uo pipefail\\n ARGS=(--source recap-source.json --out recap-url.txt --repo \"$GITHUB_REPOSITORY\" --pr \"$PR_NUMBER\" --app-url \"$PLAN_RECAP_APP_URL\" --token \"$PLAN_RECAP_TOKEN\")\\n if [ -n \"${PREV_PLAN_ID:-}\" ]; then ARGS+=(--prev-plan-id \"$PREV_PLAN_ID\"); fi\\n ARGS+=(--source-type pull-request --source-repo \"$GITHUB_REPOSITORY\" --source-pr-number \"$PR_NUMBER\")\\n if [ \"${PR_MERGED:-false}\" = \"true\" ] || [ -n \"${PR_MERGED_AT:-}\" ]; then\\n ARGS+=(--source-pr-state merged)\\n elif [ -n \"${PR_STATE:-}\" ]; then\\n ARGS+=(--source-pr-state \"$PR_STATE\")\\n fi\\n if [ -n \"${PR_MERGED_AT:-}\" ]; then ARGS+=(--source-pr-merged-at \"$PR_MERGED_AT\"); fi\\n $RECAP_CLI recap publish \"${ARGS[@]}\"\\n\\n - name: Read plan URL\\n id: url\\n if: steps.diff.outputs.tiny != \\'true\\' && steps.route_health.outputs.unhealthy != \\'true\\' && steps.scan.outputs.suppressed != \\'true\\'\\n run: |\\n set -uo pipefail\\n PLAN_URL=\"\"\\n URL_REASON=\"\"\\n if [ -f recap-url.txt ]; then\\n PLAN_URL=\"$(tr -d \\'\\\\r\\\\n\\' < recap-url.txt | tr -d \\' \\')\"\\n elif [ -f recap-url-reason.txt ]; then\\n URL_REASON=\"$(cat recap-url-reason.txt)\"\\n else\\n URL_REASON=\"recap-url.txt was not created.\"\\n fi\\n # recap-url.txt is agent-written -> untrusted. Rebuild a canonical\\n # recap URL from the trusted app base and a strictly validated plan id,\\n # preserving path-prefixed self-hosted mounts.\\n if [ -z \"$URL_REASON\" ]; then\\n URL_RESULT=$(PLAN_URL=\"$PLAN_URL\" node <<\\'NODE\\'\\n const emit = (value) => process.stdout.write(JSON.stringify(value));\\n try {\\n const raw = process.env.PLAN_URL || \"\";\\n if (!raw) {\\n emit({ url: \"\", reason: \"recap-url.txt was empty\" });\\n process.exit(0);\\n }\\n const trusted = new URL(process.env.PLAN_RECAP_APP_URL || \"https://plan.agent-native.com\");\\n const parsed = /^https?:\\\\/\\\\//i.test(raw)\\n ? new URL(raw)\\n : new URL(raw, trusted);\\n if (parsed.origin !== trusted.origin) {\\n emit({ url: \"\", reason: `recap-url.txt points at ${parsed.origin}, expected ${trusted.origin}` });\\n process.exit(0);\\n }\\n\\n const base = trusted.pathname.replace(/\\\\/$/, \"\");\\n const paths = [parsed.pathname];\\n if (base && parsed.pathname.startsWith(`${base}/`)) {\\n paths.push(parsed.pathname.slice(base.length) || \"/\");\\n }\\n\\n for (const path of paths) {\\n const match = path.match(/^\\\\/(?:plans|recaps)\\\\/([A-Za-z0-9_-]+)\\\\/?$/);\\n if (match) {\\n emit({ url: `${trusted.origin}${base}/recaps/${match[1]}`, reason: \"\" });\\n process.exit(0);\\n }\\n }\\n emit({ url: \"\", reason: \"recap-url.txt did not contain a valid /plans/<id> or /recaps/<id> URL for the configured plan app\" });\\n } catch {\\n emit({ url: \"\", reason: \"recap-url.txt was not a valid URL or recap path\" });\\n }\\n NODE\\n )\\n CANONICAL_URL=$(node -e \\'try{process.stdout.write(JSON.parse(process.argv[1]).url||\"\")}catch{process.stdout.write(\"\")}\\' \"$URL_RESULT\")\\n URL_REASON=$(node -e \\'try{process.stdout.write(JSON.parse(process.argv[1]).reason||\"\")}catch{process.stdout.write(\"recap-url.txt URL validation failed\")}\\' \"$URL_RESULT\")\\n else\\n CANONICAL_URL=\"\"\\n fi\\n if [ -n \"$CANONICAL_URL\" ]; then\\n echo \"plan_url=$CANONICAL_URL\" >> \"$GITHUB_OUTPUT\"; echo \"ok=true\" >> \"$GITHUB_OUTPUT\"\\n else\\n echo \"plan_url=\" >> \"$GITHUB_OUTPUT\"; echo \"ok=false\" >> \"$GITHUB_OUTPUT\"\\n fi\\n {\\n echo \\'reason<<__RECAP_URL_REASON_EOF__\\'\\n echo \"$URL_REASON\"\\n echo \\'__RECAP_URL_REASON_EOF__\\'\\n } >> \"$GITHUB_OUTPUT\"\\n\\n - name: Summarize agent failure\\n id: agent_summary\\n if: steps.url.outputs.ok != \\'true\\' && steps.diff.outputs.tiny != \\'true\\' && steps.route_health.outputs.unhealthy != \\'true\\' && steps.scan.outputs.suppressed != \\'true\\'\\n continue-on-error: true\\n env:\\n RECAP_AGENT: ${{ needs.gate.outputs.agent }}\\n RECAP_BLOCK_REFERENCE_SUMMARY: ${{ steps.block_reference.outputs.summary }}\\n RECAP_PUBLISH_REASON: ${{ steps.publish.outputs.reason }}\\n run: |\\n set -uo pipefail\\n RESULT=claude-result.json\\n STDERR=claude-stderr.log\\n EXIT_CODE=claude-exit-code.txt\\n if [ \"$RECAP_AGENT\" = \"codex\" ]; then\\n RESULT=codex-events.jsonl\\n STDERR=codex-stderr.log\\n EXIT_CODE=codex-exit-code.txt\\n elif [ \"$RECAP_AGENT\" = \"openai-compatible\" ]; then\\n RESULT=openai-compatible-result.txt\\n STDERR=openai-compatible-stderr.log\\n EXIT_CODE=openai-compatible-exit-code.txt\\n fi\\n SUMMARY_JSON=\"$(GITHUB_OUTPUT=/dev/null $RECAP_CLI recap agent-summary --agent \"$RECAP_AGENT\" --result-file \"$RESULT\" --stderr-file \"$STDERR\" --exit-code-file \"$EXIT_CODE\" || echo \\'{}\\')\"\\n SUMMARY=\"$(node -e \\'try { const value = JSON.parse(process.argv[1]).summary; process.stdout.write(typeof value === \"string\" ? value : \"\"); } catch {}\\' \"$SUMMARY_JSON\")\"\\n if [ -n \"$SUMMARY\" ]; then\\n {\\n echo \\'summary<<__RECAP_AGENT_SUMMARY_EOF__\\'\\n echo \"$SUMMARY\"\\n echo \\'__RECAP_AGENT_SUMMARY_EOF__\\'\\n } >> \"$GITHUB_OUTPUT\"\\n elif [ -n \"${RECAP_BLOCK_REFERENCE_SUMMARY:-}\" ]; then\\n {\\n echo \\'summary<<__RECAP_BLOCK_REFERENCE_SUMMARY_EOF__\\'\\n echo \"$RECAP_BLOCK_REFERENCE_SUMMARY\"\\n echo \\'__RECAP_BLOCK_REFERENCE_SUMMARY_EOF__\\'\\n } >> \"$GITHUB_OUTPUT\"\\n elif [ -n \"${RECAP_PUBLISH_REASON:-}\" ]; then\\n {\\n echo \\'summary<<__RECAP_PUBLISH_SUMMARY_EOF__\\'\\n echo \"$RECAP_PUBLISH_REASON\"\\n echo \\'__RECAP_PUBLISH_SUMMARY_EOF__\\'\\n } >> \"$GITHUB_OUTPUT\"\\n fi\\n\\n - name: Attach usage\\n if: steps.url.outputs.ok == \\'true\\'\\n continue-on-error: true\\n env:\\n PLAN_URL: ${{ steps.url.outputs.plan_url }}\\n # Use the gate-normalized agent so \"Codex\" still selects the right file.\\n RECAP_AGENT: ${{ needs.gate.outputs.agent }}\\n run: |\\n set -uo pipefail\\n RESULT=claude-result.json\\n if [ \"$RECAP_AGENT\" = \"codex\" ]; then RESULT=codex-events.jsonl; fi\\n if [ \"$RECAP_AGENT\" = \"openai-compatible\" ]; then RESULT=openai-compatible-usage.json; fi\\n if [ -f \"$RESULT\" ]; then $RECAP_CLI recap usage --plan-url \"$PLAN_URL\" --agent \"$RECAP_AGENT\" --result-file \"$RESULT\" --model \"${VISUAL_RECAP_MODEL:-}\" --app-url \"$PLAN_RECAP_APP_URL\" --token \"$PLAN_RECAP_TOKEN\" || true; fi\\n\\n - name: Cache Playwright browsers\\n if: steps.url.outputs.ok == \\'true\\'\\n uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3\\n with:\\n path: ~/.cache/ms-playwright\\n key: playwright-1-${{ runner.os }}\\n\\n - name: Screenshot + upload\\n id: shot\\n if: steps.url.outputs.ok == \\'true\\'\\n continue-on-error: true\\n env:\\n # recap-url.txt is untrusted agent output; pass via env, never ${{ }}.\\n PLAN_URL: ${{ steps.url.outputs.plan_url }}\\n run: |\\n set -uo pipefail\\n if [ -n \"${RECAP_PLAYWRIGHT:-}\" ] && [ -x \"$RECAP_PLAYWRIGHT\" ]; then\\n \"$RECAP_PLAYWRIGHT\" install --with-deps chromium || true\\n elif command -v pnpm >/dev/null 2>&1; then\\n pnpm exec playwright install --with-deps chromium 2>/dev/null || npx -y playwright@1 install --with-deps chromium || true\\n else\\n npx -y playwright@1 install --with-deps chromium || true\\n fi\\n IMAGE_CACHE_KEY=\"$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT\"\\n LIGHT_SHOT_JSON=\"$($RECAP_CLI recap shot --url \"$PLAN_URL\" --token \"$PLAN_RECAP_TOKEN\" --app-url \"$PLAN_RECAP_APP_URL\" --out recap.png --theme light --image-cache-key \"$IMAGE_CACHE_KEY\" || echo \\'{}\\')\"\\n DARK_SHOT_JSON=\"$($RECAP_CLI recap shot --url \"$PLAN_URL\" --token \"$PLAN_RECAP_TOKEN\" --app-url \"$PLAN_RECAP_APP_URL\" --out recap-dark.png --theme dark --image-cache-key \"$IMAGE_CACHE_KEY\" || echo \\'{}\\')\"\\n for SHOT_LABEL in light dark; do\\n if [ \"$SHOT_LABEL\" = \"light\" ]; then SHOT_JSON=\"$LIGHT_SHOT_JSON\"; else SHOT_JSON=\"$DARK_SHOT_JSON\"; fi\\n SHOT_LABEL=\"$SHOT_LABEL\" SHOT_JSON=\"$SHOT_JSON\" node -e \\'const label = process.env.SHOT_LABEL || \"shot\"; let parsed = {}; try { parsed = JSON.parse(process.env.SHOT_JSON || \"{}\"); } catch { parsed = { ok: false, reason: \"invalid shot JSON\" }; } const summary = { ok: parsed.ok === true, imageUrl: parsed.imageUrl ? \"[present]\" : \"\", out: typeof parsed.out === \"string\" ? parsed.out : \"\", reason: typeof parsed.reason === \"string\" ? parsed.reason.slice(0, 500) : \"\" }; console.log(`[recap shot] ${label}: ${JSON.stringify(summary)}`);\\'\\n done\\n IMAGE_URL=$(node -e \\'try{process.stdout.write(JSON.parse(process.argv[1]).imageUrl||\"\")}catch{process.stdout.write(\"\")}\\' \"$LIGHT_SHOT_JSON\")\\n DARK_IMAGE_URL=$(node -e \\'try{process.stdout.write(JSON.parse(process.argv[1]).imageUrl||\"\")}catch{process.stdout.write(\"\")}\\' \"$DARK_SHOT_JSON\")\\n SHOT_STATUS=$(LIGHT_SHOT_JSON=\"$LIGHT_SHOT_JSON\" DARK_SHOT_JSON=\"$DARK_SHOT_JSON\" node <<\\'NODE\\'\\n const parse = (raw) => { try { return JSON.parse(raw || \"{}\"); } catch { return { ok: false, reason: \"invalid shot JSON\" }; } };\\n const shots = [[\"light\", parse(process.env.LIGHT_SHOT_JSON)], [\"dark\", parse(process.env.DARK_SHOT_JSON)]];\\n const hasImage = shots.some(([, shot]) => typeof shot.imageUrl === \"string\" && shot.imageUrl.trim());\\n const reasons = shots.flatMap(([label, shot]) => {\\n if (typeof shot.reason === \"string\" && shot.reason.trim()) return [`${label}: ${shot.reason.trim()}`];\\n if (!(typeof shot.imageUrl === \"string\" && shot.imageUrl.trim())) return [`${label}: no imageUrl returned`];\\n return [];\\n });\\n process.stdout.write(JSON.stringify({ ok: hasImage, reason: hasImage ? \"\" : reasons.join(\"; \").slice(0, 1000) }));\\n NODE\\n )\\n SHOT_OK=$(node -e \\'try{process.stdout.write(JSON.parse(process.argv[1]).ok===true?\"true\":\"false\")}catch{process.stdout.write(\"false\")}\\' \"$SHOT_STATUS\")\\n SHOT_REASON=$(node -e \\'try{process.stdout.write(JSON.parse(process.argv[1]).reason||\"\")}catch{process.stdout.write(\"invalid shot status JSON\")}\\' \"$SHOT_STATUS\")\\n if [ \"$SHOT_OK\" != \"true\" ]; then\\n echo \"::warning::Visual recap screenshot unavailable; posting screenshot-failed recap comment. $SHOT_REASON\"\\n fi\\n echo \"image_url=$IMAGE_URL\" >> \"$GITHUB_OUTPUT\"\\n echo \"light_image_url=$IMAGE_URL\" >> \"$GITHUB_OUTPUT\"\\n echo \"dark_image_url=$DARK_IMAGE_URL\" >> \"$GITHUB_OUTPUT\"\\n echo \"shot_ok=$SHOT_OK\" >> \"$GITHUB_OUTPUT\"\\n {\\n echo \\'shot_reason<<__RECAP_SHOT_REASON_EOF__\\'\\n echo \"$SHOT_REASON\"\\n echo \\'__RECAP_SHOT_REASON_EOF__\\'\\n } >> \"$GITHUB_OUTPUT\"\\n if [ -f recap.png ] || [ -f recap-dark.png ]; then echo \"captured=true\" >> \"$GITHUB_OUTPUT\"; else echo \"captured=false\" >> \"$GITHUB_OUTPUT\"; fi\\n\\n - name: Upload recap screenshot artifact\\n if: steps.shot.outputs.captured == \\'true\\'\\n uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1\\n with:\\n name: pr-visual-recap-${{ github.event.pull_request.number }}\\n path: |\\n recap.png\\n recap-dark.png\\n if-no-files-found: ignore\\n retention-days: 14\\n\\n - name: Upload recap source artifact\\n if: always() && !cancelled()\\n uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1\\n with:\\n # recap-source.json + the agent transcript (claude-result.json /\\n # codex-events.jsonl + stderr) are the only window into WHAT the agent\\n # did when a publish fails (no plan URL) — INCLUDING the case where it\\n # finished without writing recap-source.json at all. The sticky comment\\n # only shows the screenshot, so without these a failed recap is\\n # undebuggable. Uploaded on success + failure; tolerant when absent.\\n name: pr-visual-recap-source-${{ github.event.pull_request.number }}\\n path: |\\n recap-source.json\\n claude-result.json\\n claude-stderr.log\\n codex-events.jsonl\\n codex-stderr.log\\n openai-compatible-result.txt\\n openai-compatible-usage.json\\n openai-compatible-stderr.log\\n if-no-files-found: ignore\\n retention-days: 14\\n\\n - name: Upsert sticky comment\\n if: always() && !cancelled()\\n continue-on-error: true\\n env:\\n PLAN_URL: ${{ steps.url.outputs.plan_url }}\\n RECAP_IMAGE_URL: ${{ steps.shot.outputs.image_url }}\\n RECAP_LIGHT_IMAGE_URL: ${{ steps.shot.outputs.light_image_url }}\\n RECAP_DARK_IMAGE_URL: ${{ steps.shot.outputs.dark_image_url }}\\n RECAP_SHOT_OK: ${{ steps.shot.outputs.shot_ok }}\\n RECAP_SHOT_REASON: ${{ steps.shot.outputs.shot_reason }}\\n SUPPRESSED: ${{ steps.scan.outputs.suppressed }}\\n SUPPRESSED_JSON: ${{ steps.scan.outputs.json }}\\n DIFF_HUGE: ${{ steps.diff.outputs.huge }}\\n DIFF_TINY: ${{ steps.diff.outputs.tiny }}\\n PREV_PLAN_ID: ${{ steps.prev.outputs.plan_id }}\\n RECAP_AUTH_FAILED: ${{ steps.auth_probe.outputs.auth_failed }}\\n RECAP_AGENT_SUMMARY: ${{ steps.agent_summary.outputs.summary }}\\n # Prefer the route-health diagnostic when the plan app routes are not\\n # yet deployed so the comment explains the 404 instead of a generic\\n # \"recap-url.txt was not created\" message.\\n RECAP_URL_REASON: ${{ steps.route_health.outputs.reason || steps.url.outputs.reason }}\\n run: |\\n set -euo pipefail\\n $RECAP_CLI recap comment upsert --repo \"$GITHUB_REPOSITORY\" --issue \"$PR_NUMBER\" --token \"$GH_TOKEN\" --head-sha \"$HEAD_SHA\"\\n\\n - name: Complete visual recap check\\n if: always() && !cancelled() && steps.recap_check.outputs.check_run_id != \\'\\'\\n continue-on-error: true\\n env:\\n # Untrusted/step values via env (NOT ${{ }}-interpolated into the run\\n # body): the agent-written plan URL and the scan JSON could inject shell.\\n CHECK_RUN_ID: ${{ steps.recap_check.outputs.check_run_id }}\\n PLAN_OK: ${{ steps.url.outputs.ok }}\\n PLAN_URL: ${{ steps.url.outputs.plan_url }}\\n SUPPRESSED: ${{ steps.scan.outputs.suppressed }}\\n SUPPRESSED_JSON: ${{ steps.scan.outputs.json }}\\n DIFF_HUGE: ${{ steps.diff.outputs.huge }}\\n DIFF_TINY: ${{ steps.diff.outputs.tiny }}\\n RECAP_AGENT_SUMMARY: ${{ steps.agent_summary.outputs.summary }}\\n RECAP_URL_REASON: ${{ steps.route_health.outputs.reason || steps.url.outputs.reason }}\\n run: |\\n set -uo pipefail\\n $RECAP_CLI recap check complete \\\\\\n --check-run-id \"$CHECK_RUN_ID\" \\\\\\n --plan-ok \"$PLAN_OK\" \\\\\\n --plan-url \"$PLAN_URL\" \\\\\\n --suppressed \"$SUPPRESSED\" \\\\\\n --suppressed-json \"$SUPPRESSED_JSON\" \\\\\\n --huge \"$DIFF_HUGE\" \\\\\\n --tiny \"$DIFF_TINY\" \\\\\\n --failure-summary \"$RECAP_AGENT_SUMMARY\" \\\\\\n --url-reason \"$RECAP_URL_REASON\" \\\\\\n --workflow-url \"$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID\"\\n';\n"]}
@@ -1,2 +1,2 @@
1
- export declare const ASSETS_SKILL_MD = "---\nname: assets\ndescription: >-\n Use Assets for image or video generation requests, brand-safe media,\n human picker UI, search/list/export actions, and cross-app asset selection.\n Prefer this over generic image tools when installed.\nmetadata:\n visibility: exported\n---\n\n# Assets\n\nUse the Assets app when a workflow needs reusable brand media, a human picker,\nor generated image/video assets that another app can reference by ID and URL.\nWhen this skill is available, route plain image-generation requests here instead\nof using a generic image generator.\n\n## Choose The Path\n\n- Use `open-asset-picker` when a person should browse, search, generate, and\n select an asset in UI. Pass `mediaType: \"image\"` by default, or\n `mediaType: \"video\"` for video libraries. When the user asks to create a\n specific image and choose the best option, pass `prompt`,\n `autoGenerate: true`, and `count: 3` so the picker opens with candidates\n to preview and select.\n- Use unattended actions when the agent already knows what to do:\n `search-assets`, `list-assets`, `generate-image`,\n `generate-image-batch`, `generate-video`,\n `refresh-generation-run`, and `export-asset`.\n- Use browser/deep-link fallback when the host cannot render MCP Apps inline.\n Surface the returned picker link. If it opens in a normal browser tab, have\n the user select an asset there and paste back the copied handoff summary.\n Treat Codex, Claude Code, and Claude Desktop Code as link-out hosts; do not\n promise inline MCP App rendering there.\n If the skill instructions are available but the MCP tool namespace has not\n appeared yet, use the Assets browser fallback URL shape instead of switching\n to a generic generator:\n `https://assets.agent-native.com/library?mediaType=image&prompt=...&autoGenerate=1&count=3`.\n When reporting the final selected image in Codex or Claude Code, include the\n asset link and, if an inline preview is important, download the selected\n `previewUrl`/`downloadUrl` to a local temp image and embed that absolute\n local path. Remote CDN markdown images can fail to render in code-editor chat\n surfaces.\n\n## Image And Video Workflows\n\n1. Pick or match the library with `list-libraries` or `match-library`.\n2. For images, call `generate-image` or `generate-image-batch`. Image\n actions are synchronous: one batch call should return the finished image\n candidates, so do not poll or regenerate unless a returned slot failed.\n3. For videos, call `generate-video` and poll `refresh-generation-run`\n until the run completes.\n4. Preserve returned `assetId`, `runId`, `previewUrl`, `downloadUrl`,\n media type, and dimensions so the caller can attach or embed the result.\n\n## Cross-App Use\n\n- Hosted default: connect `https://assets.agent-native.com/_agent-native/mcp`.\n Do not put shared secrets in skill files.\n- For CLI/code-editor clients, keep any `npx @agent-native/core@latest connect` command\n running until browser authorization finishes. Stopping it early can leave the\n browser approved but the local MCP config unwritten. Restart or reload the\n agent client after installing or connecting if Assets tools do not appear in\n the live session.\n- Local customization: use `npx @agent-native/core@latest app-skill launch --local` from an\n Assets app-skill manifest, or pass `--into <path>` for editable source.\n- Do not call image/video providers directly from another app. Assets owns\n generation, picker UI, search/list/export, and asset context.\n- If an Assets tool call returns `Session terminated`, `needs auth`, or\n another connector/session error, do not keep retrying the tool. Stop and give\n the user the reconnect step: in Claude Code run `/mcp` and choose\n Authenticate/Reconnect for the Assets connector; from any terminal run\n `npx -y @agent-native/core@latest reconnect https://assets.agent-native.com` \u2014 this\n re-authenticates WITHOUT reinstalling. Never reinstall from scratch just to fix\n auth. Continue once the connector is available.\n- Do not hand-roll MCP HTTP requests with curl from the agent session. Use the\n host-exposed Assets tools after restart/reload, or use the returned\n browser/deep-link fallback.\n- If a batch image generation request times out in browser fallback, retry with\n `count: 1` only after telling the user the multi-candidate request timed out.\n- If you inspect local MCP config, redact `Authorization`, `http_headers`,\n and token values. Never paste bearer tokens into chat or logs.\n";
1
+ export declare const ASSETS_SKILL_MD = "---\nname: assets\ndescription: >-\n Use Assets for image or video generation requests, brand-safe media,\n human picker UI, search/list/export actions, and cross-app asset selection.\n Prefer this over generic image tools when installed.\nmetadata:\n visibility: exported\n---\n\n# Assets\n\nUse the Assets app when a workflow needs reusable brand media, a human picker,\nor generated image/video assets that another app can reference by ID and URL.\nWhen this skill is available, route plain image-generation requests here instead\nof using a generic image generator.\n\n## Choose The Path\n\n- Use `open-asset-picker` when a person should browse, search, generate, and\n select an asset in UI. Pass `mediaType: \"image\"` by default, or\n `mediaType: \"video\"` for video libraries. When the user asks to create a\n specific image and choose the best option, pass `prompt`,\n `autoGenerate: true`, and `count: 3` so the picker opens with candidates\n to preview and select.\n- Use unattended actions when the agent already knows what to do:\n `search-assets`, `list-assets`, `generate-image`,\n `generate-image-batch`, `generate-video`,\n `refresh-generation-run`, and `export-asset`.\n- Use browser/deep-link fallback when the host cannot render MCP Apps inline.\n Surface the returned picker link. If it opens in a normal browser tab, have\n the user select an asset there and paste back the copied handoff summary.\n Treat Codex, Claude Code, and Claude Desktop Code as link-out hosts; do not\n promise inline MCP App rendering there.\n If the skill instructions are available but the MCP tool namespace has not\n appeared yet, use the Assets browser fallback URL shape instead of switching\n to a generic generator:\n `https://assets.agent-native.com/library?mediaType=image&prompt=...&autoGenerate=1&count=3`.\n When reporting the final selected image in Codex or Claude Code, include the\n asset link and, if an inline preview is important, download the selected\n `previewUrl`/`downloadUrl` to a local temp image and embed that absolute\n local path. Remote CDN markdown images can fail to render in code-editor chat\n surfaces.\n\n## Image And Video Workflows\n\n1. Pick or match the library with `list-libraries` or `match-library`.\n2. For images, call `generate-image` or `generate-image-batch`. Image\n actions are synchronous: one batch call should return the finished image\n candidates, so do not poll or regenerate unless a returned slot failed.\n3. For videos, call `generate-video` and poll `refresh-generation-run`\n until the run completes.\n4. Preserve returned `assetId`, `runId`, `previewUrl`, `downloadUrl`,\n media type, and dimensions so the caller can attach or embed the result.\n\n## Cross-App Use\n\n- Hosted default: connect `https://assets.agent-native.com/mcp`.\n Do not put shared secrets in skill files.\n- For CLI/code-editor clients, keep any `npx @agent-native/core@latest connect` command\n running until browser authorization finishes. Stopping it early can leave the\n browser approved but the local MCP config unwritten. Restart or reload the\n agent client after installing or connecting if Assets tools do not appear in\n the live session.\n- Local customization: use `npx @agent-native/core@latest app-skill launch --local` from an\n Assets app-skill manifest, or pass `--into <path>` for editable source.\n- Do not call image/video providers directly from another app. Assets owns\n generation, picker UI, search/list/export, and asset context.\n- If an Assets tool call returns `Session terminated`, `needs auth`, or\n another connector/session error, do not keep retrying the tool. Stop and give\n the user the reconnect step: in Claude Code run `/mcp` and choose\n Authenticate/Reconnect for the Assets connector; from any terminal run\n `npx -y @agent-native/core@latest reconnect https://assets.agent-native.com` \u2014 this\n re-authenticates WITHOUT reinstalling. Never reinstall from scratch just to fix\n auth. Continue once the connector is available.\n- Do not hand-roll MCP HTTP requests with curl from the agent session. Use the\n host-exposed Assets tools after restart/reload, or use the returned\n browser/deep-link fallback.\n- If a batch image generation request times out in browser fallback, retry with\n `count: 1` only after telling the user the multi-candidate request timed out.\n- If you inspect local MCP config, redact `Authorization`, `http_headers`,\n and token values. Never paste bearer tokens into chat or logs.\n";
2
2
  //# sourceMappingURL=assets-skill.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"assets-skill.d.ts","sourceRoot":"","sources":["../../../src/cli/skills-content/assets-skill.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,eAAe,m9IAkF3B,CAAC"}
1
+ {"version":3,"file":"assets-skill.d.ts","sourceRoot":"","sources":["../../../src/cli/skills-content/assets-skill.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,eAAe,q8IAkF3B,CAAC"}
@@ -55,7 +55,7 @@ of using a generic image generator.
55
55
 
56
56
  ## Cross-App Use
57
57
 
58
- - Hosted default: connect \`https://assets.agent-native.com/_agent-native/mcp\`.
58
+ - Hosted default: connect \`https://assets.agent-native.com/mcp\`.
59
59
  Do not put shared secrets in skill files.
60
60
  - For CLI/code-editor clients, keep any \`npx @agent-native/core@latest connect\` command
61
61
  running until browser authorization finishes. Stopping it early can leave the
@@ -1 +1 @@
1
- {"version":3,"file":"assets-skill.js","sourceRoot":"","sources":["../../../src/cli/skills-content/assets-skill.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkF9B,CAAC","sourcesContent":["export const ASSETS_SKILL_MD = `---\nname: assets\ndescription: >-\n Use Assets for image or video generation requests, brand-safe media,\n human picker UI, search/list/export actions, and cross-app asset selection.\n Prefer this over generic image tools when installed.\nmetadata:\n visibility: exported\n---\n\n# Assets\n\nUse the Assets app when a workflow needs reusable brand media, a human picker,\nor generated image/video assets that another app can reference by ID and URL.\nWhen this skill is available, route plain image-generation requests here instead\nof using a generic image generator.\n\n## Choose The Path\n\n- Use \\`open-asset-picker\\` when a person should browse, search, generate, and\n select an asset in UI. Pass \\`mediaType: \"image\"\\` by default, or\n \\`mediaType: \"video\"\\` for video libraries. When the user asks to create a\n specific image and choose the best option, pass \\`prompt\\`,\n \\`autoGenerate: true\\`, and \\`count: 3\\` so the picker opens with candidates\n to preview and select.\n- Use unattended actions when the agent already knows what to do:\n \\`search-assets\\`, \\`list-assets\\`, \\`generate-image\\`,\n \\`generate-image-batch\\`, \\`generate-video\\`,\n \\`refresh-generation-run\\`, and \\`export-asset\\`.\n- Use browser/deep-link fallback when the host cannot render MCP Apps inline.\n Surface the returned picker link. If it opens in a normal browser tab, have\n the user select an asset there and paste back the copied handoff summary.\n Treat Codex, Claude Code, and Claude Desktop Code as link-out hosts; do not\n promise inline MCP App rendering there.\n If the skill instructions are available but the MCP tool namespace has not\n appeared yet, use the Assets browser fallback URL shape instead of switching\n to a generic generator:\n \\`https://assets.agent-native.com/library?mediaType=image&prompt=...&autoGenerate=1&count=3\\`.\n When reporting the final selected image in Codex or Claude Code, include the\n asset link and, if an inline preview is important, download the selected\n \\`previewUrl\\`/\\`downloadUrl\\` to a local temp image and embed that absolute\n local path. Remote CDN markdown images can fail to render in code-editor chat\n surfaces.\n\n## Image And Video Workflows\n\n1. Pick or match the library with \\`list-libraries\\` or \\`match-library\\`.\n2. For images, call \\`generate-image\\` or \\`generate-image-batch\\`. Image\n actions are synchronous: one batch call should return the finished image\n candidates, so do not poll or regenerate unless a returned slot failed.\n3. For videos, call \\`generate-video\\` and poll \\`refresh-generation-run\\`\n until the run completes.\n4. Preserve returned \\`assetId\\`, \\`runId\\`, \\`previewUrl\\`, \\`downloadUrl\\`,\n media type, and dimensions so the caller can attach or embed the result.\n\n## Cross-App Use\n\n- Hosted default: connect \\`https://assets.agent-native.com/_agent-native/mcp\\`.\n Do not put shared secrets in skill files.\n- For CLI/code-editor clients, keep any \\`npx @agent-native/core@latest connect\\` command\n running until browser authorization finishes. Stopping it early can leave the\n browser approved but the local MCP config unwritten. Restart or reload the\n agent client after installing or connecting if Assets tools do not appear in\n the live session.\n- Local customization: use \\`npx @agent-native/core@latest app-skill launch --local\\` from an\n Assets app-skill manifest, or pass \\`--into <path>\\` for editable source.\n- Do not call image/video providers directly from another app. Assets owns\n generation, picker UI, search/list/export, and asset context.\n- If an Assets tool call returns \\`Session terminated\\`, \\`needs auth\\`, or\n another connector/session error, do not keep retrying the tool. Stop and give\n the user the reconnect step: in Claude Code run \\`/mcp\\` and choose\n Authenticate/Reconnect for the Assets connector; from any terminal run\n \\`npx -y @agent-native/core@latest reconnect https://assets.agent-native.com\\` — this\n re-authenticates WITHOUT reinstalling. Never reinstall from scratch just to fix\n auth. Continue once the connector is available.\n- Do not hand-roll MCP HTTP requests with curl from the agent session. Use the\n host-exposed Assets tools after restart/reload, or use the returned\n browser/deep-link fallback.\n- If a batch image generation request times out in browser fallback, retry with\n \\`count: 1\\` only after telling the user the multi-candidate request timed out.\n- If you inspect local MCP config, redact \\`Authorization\\`, \\`http_headers\\`,\n and token values. Never paste bearer tokens into chat or logs.\n`;\n"]}
1
+ {"version":3,"file":"assets-skill.js","sourceRoot":"","sources":["../../../src/cli/skills-content/assets-skill.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkF9B,CAAC","sourcesContent":["export const ASSETS_SKILL_MD = `---\nname: assets\ndescription: >-\n Use Assets for image or video generation requests, brand-safe media,\n human picker UI, search/list/export actions, and cross-app asset selection.\n Prefer this over generic image tools when installed.\nmetadata:\n visibility: exported\n---\n\n# Assets\n\nUse the Assets app when a workflow needs reusable brand media, a human picker,\nor generated image/video assets that another app can reference by ID and URL.\nWhen this skill is available, route plain image-generation requests here instead\nof using a generic image generator.\n\n## Choose The Path\n\n- Use \\`open-asset-picker\\` when a person should browse, search, generate, and\n select an asset in UI. Pass \\`mediaType: \"image\"\\` by default, or\n \\`mediaType: \"video\"\\` for video libraries. When the user asks to create a\n specific image and choose the best option, pass \\`prompt\\`,\n \\`autoGenerate: true\\`, and \\`count: 3\\` so the picker opens with candidates\n to preview and select.\n- Use unattended actions when the agent already knows what to do:\n \\`search-assets\\`, \\`list-assets\\`, \\`generate-image\\`,\n \\`generate-image-batch\\`, \\`generate-video\\`,\n \\`refresh-generation-run\\`, and \\`export-asset\\`.\n- Use browser/deep-link fallback when the host cannot render MCP Apps inline.\n Surface the returned picker link. If it opens in a normal browser tab, have\n the user select an asset there and paste back the copied handoff summary.\n Treat Codex, Claude Code, and Claude Desktop Code as link-out hosts; do not\n promise inline MCP App rendering there.\n If the skill instructions are available but the MCP tool namespace has not\n appeared yet, use the Assets browser fallback URL shape instead of switching\n to a generic generator:\n \\`https://assets.agent-native.com/library?mediaType=image&prompt=...&autoGenerate=1&count=3\\`.\n When reporting the final selected image in Codex or Claude Code, include the\n asset link and, if an inline preview is important, download the selected\n \\`previewUrl\\`/\\`downloadUrl\\` to a local temp image and embed that absolute\n local path. Remote CDN markdown images can fail to render in code-editor chat\n surfaces.\n\n## Image And Video Workflows\n\n1. Pick or match the library with \\`list-libraries\\` or \\`match-library\\`.\n2. For images, call \\`generate-image\\` or \\`generate-image-batch\\`. Image\n actions are synchronous: one batch call should return the finished image\n candidates, so do not poll or regenerate unless a returned slot failed.\n3. For videos, call \\`generate-video\\` and poll \\`refresh-generation-run\\`\n until the run completes.\n4. Preserve returned \\`assetId\\`, \\`runId\\`, \\`previewUrl\\`, \\`downloadUrl\\`,\n media type, and dimensions so the caller can attach or embed the result.\n\n## Cross-App Use\n\n- Hosted default: connect \\`https://assets.agent-native.com/mcp\\`.\n Do not put shared secrets in skill files.\n- For CLI/code-editor clients, keep any \\`npx @agent-native/core@latest connect\\` command\n running until browser authorization finishes. Stopping it early can leave the\n browser approved but the local MCP config unwritten. Restart or reload the\n agent client after installing or connecting if Assets tools do not appear in\n the live session.\n- Local customization: use \\`npx @agent-native/core@latest app-skill launch --local\\` from an\n Assets app-skill manifest, or pass \\`--into <path>\\` for editable source.\n- Do not call image/video providers directly from another app. Assets owns\n generation, picker UI, search/list/export, and asset context.\n- If an Assets tool call returns \\`Session terminated\\`, \\`needs auth\\`, or\n another connector/session error, do not keep retrying the tool. Stop and give\n the user the reconnect step: in Claude Code run \\`/mcp\\` and choose\n Authenticate/Reconnect for the Assets connector; from any terminal run\n \\`npx -y @agent-native/core@latest reconnect https://assets.agent-native.com\\` — this\n re-authenticates WITHOUT reinstalling. Never reinstall from scratch just to fix\n auth. Continue once the connector is available.\n- Do not hand-roll MCP HTTP requests with curl from the agent session. Use the\n host-exposed Assets tools after restart/reload, or use the returned\n browser/deep-link fallback.\n- If a batch image generation request times out in browser fallback, retry with\n \\`count: 1\\` only after telling the user the multi-candidate request timed out.\n- If you inspect local MCP config, redact \\`Authorization\\`, \\`http_headers\\`,\n and token values. Never paste bearer tokens into chat or logs.\n`;\n"]}
@@ -1,2 +1,2 @@
1
- export declare const DESIGN_EXPLORATION_SKILL_MD = "---\nname: design-exploration\ndescription: >-\n Use Design for UI/UX exploration, side-by-side design directions,\n interactive prototype previews, user selection, iteration, and design-to-code\n handoff through the hosted Design MCP app.\nmetadata:\n visibility: exported\n---\n\n# Design Exploration\n\nUse the Design app when a workflow needs visual UI exploration, prototype\niteration, or a human-in-the-loop choice among design directions.\n\n## Choose The Path\n\n- Use `create-design` first to create a project shell. Do not report the\n design as ready until it has renderable HTML.\n- For open-ended UX exploration, generate distinct, compact, complete HTML\n directions (2-5, three by default) and call `present-design-variants`. Each\n direction should be one representative screen or directional snapshot, not a\n full app per variant. Design saves every option as a normal screen on the\n overview board and renders an inline chat choice with one button per screen\n name. After the user picks, delete the unchosen variant screens and continue\n from the kept screen by first calling `get-design-snapshot` with that\n screen's `fileId`, then calling `edit-design` on that same `fileId` in a\n bounded single-file pass. Use `mode: \"replace-file\"` when expanding the\n representative placeholder into the full chosen direction. Do not call\n `generate-design` after a variant pick.\n- If the chat choice buttons are not available in the host, ask the user to\n tell you the screen name they prefer. The variants are already real screens\n on the board, so do not ask them to paste HTML or copy a generated handoff\n summary.\n- For direct refinements to an already chosen direction, call\n `get-design-snapshot`, edit from the current tuned HTML, and use\n `edit-design` for surgical changes or `mode: \"replace-file\"` for a bounded\n selected-file replacement. Use `generate-design` for new files only.\n- Use `export-coding-handoff` when the user wants to implement the chosen\n design in a codebase.\n\n## Exploration Defaults\n\n1. Default to three variants unless the user asks for a different count\n (`present-design-variants` accepts 2-5; three is the sweet spot).\n2. Make variants structurally and stylistically distinct, not just color swaps.\n3. Each variant must be a compact, complete standalone HTML document that\n renders without a build step.\n4. For product UI redesigns, prefer cleaner hierarchy, progressive disclosure,\n and realistic controls over decorative mockups.\n5. After `present-design-variants`, wait for the user's pick before\n generating the next version. Keep the chosen screen, delete the other\n variant screens, call `get-design-snapshot` with `fileId` for the kept\n screen, then call `edit-design` on that same `fileId` in a bounded pass.\n Use `mode: \"replace-file\"` when expanding the representative placeholder\n into the full chosen direction. Do not call `generate-design` after a\n variant pick. Stop after the first successful `edit-design` save.\n\n## Design Quality Bar\n\nGeneric \"AI slop\" comes from letting one prompt set taste, explore, and emit code\nat once \u2014 so the model returns the training-average (Inter, an indigo/violet\ngradient, a centered hero, three rounded cards). The variant flow above exists to\nseparate those jobs; use it, and hold this bar:\n\n- Before generating, name the concrete audience, the screen's primary job, and\n the visual thesis. If the brief is vague, make a reasonable choice and state\n it instead of producing a generic dashboard/landing-page default.\n- Refuse the defaults, and pair every \"don't\" with a \"do\" (banning Inter alone\n just makes you reach for Roboto). Avoid Inter/Roboto/system fonts, the\n indigo/violet slop palette (`#6366F1`/`#8B5CF6`/`#A855F7`) and purple-on-white\n gradients, and centered-hero + three-icon-card layouts; instead pick a\n distinctive font pairing, one non-default palette family with a single decisive\n accent, and an asymmetric layout with a clear focal point.\n- Make each direction distinct in structure and behavior, not just palette.\n Give every variant one memorable signature choice, then keep the surrounding\n chrome disciplined. Even your creative picks converge (Space Grotesk\n everywhere) \u2014 vary deliberately so two directions never share a fingerprint.\n- For existing products, inspect the current screen, design system, tokens, and\n component language before inventing a new direction. Treat any drift back to a\n default as a missing token to pin, and vary layout per screen so on-brand does\n not become same-in-your-colors.\n- Treat copy, data, and imagery as design material. Use realistic domain\n content and first-party/generated assets when images matter; avoid lorem\n ipsum, vague SaaS filler, and decorative placeholder boxes.\n- Build to a quiet quality floor: responsive desktop/mobile layout, visible\n keyboard focus, useful loading/empty/error states for app UI, and reduced\n motion support when custom motion is present.\n- After broad generation or refinement, inspect the rendered Design surface or\n a screenshot-capable host before calling it ready. Fix obvious hierarchy,\n overflow, contrast, broken interaction, and placeholder-content issues first.\n\n## Cross-App Use\n\n- Hosted default: connect `https://design.agent-native.com/_agent-native/mcp`.\n Do not put shared secrets in skill files.\n- For CLI/code-editor clients, keep any `npx @agent-native/core@latest connect` command\n running until browser authorization finishes. Stopping it early can leave the\n browser approved but the local MCP config unwritten. Restart or reload the\n agent client after installing or connecting if Design tools do not appear in\n the live session.\n- Dispatch can expose Design alongside other apps. Use Design for UI/UX design\n tasks, Assets for image/media selection, Slides for decks, and so on.\n- Keep the loop visual: surface the inline MCP App or the returned \"Open\n design\" link instead of pasting large HTML blobs into chat.\n- If a Design tool call returns `Session terminated`, `needs auth`, or\n another connector/session error, do not keep retrying the tool. Stop and give\n the user the reconnect step: in Claude Code run `/mcp` and choose\n Authenticate/Reconnect for the Design connector; from any terminal run\n `npx -y @agent-native/core@latest reconnect https://design.agent-native.com` \u2014 this\n re-authenticates WITHOUT reinstalling. Never reinstall from scratch just to fix\n auth. Continue once the connector is available.\n- Do not hand-roll MCP HTTP requests with curl from the agent session. Use the\n host-exposed Design tools after restart/reload, or use the returned\n browser/deep-link fallback.\n- If you inspect local MCP config, redact `Authorization`, `http_headers`,\n and token values. Never paste bearer tokens into chat or logs.\n";
1
+ export declare const DESIGN_EXPLORATION_SKILL_MD = "---\nname: design-exploration\ndescription: >-\n Use Design for UI/UX exploration, side-by-side design directions,\n interactive prototype previews, user selection, iteration, and design-to-code\n handoff through the hosted Design MCP app.\nmetadata:\n visibility: exported\n---\n\n# Design Exploration\n\nUse the Design app when a workflow needs visual UI exploration, prototype\niteration, or a human-in-the-loop choice among design directions.\n\n## Choose The Path\n\n- Use `create-design` first to create a project shell. Do not report the\n design as ready until it has renderable HTML.\n- For open-ended UX exploration, generate distinct, compact, complete HTML\n directions (2-5, three by default) and call `present-design-variants`. Each\n direction should be one representative screen or directional snapshot, not a\n full app per variant. Design saves every option as a normal screen on the\n overview board and renders an inline chat choice with one button per screen\n name. After the user picks, delete the unchosen variant screens and continue\n from the kept screen by first calling `get-design-snapshot` with that\n screen's `fileId`, then calling `edit-design` on that same `fileId` in a\n bounded single-file pass. Use `mode: \"replace-file\"` when expanding the\n representative placeholder into the full chosen direction. Do not call\n `generate-design` after a variant pick.\n- If the chat choice buttons are not available in the host, ask the user to\n tell you the screen name they prefer. The variants are already real screens\n on the board, so do not ask them to paste HTML or copy a generated handoff\n summary.\n- For direct refinements to an already chosen direction, call\n `get-design-snapshot`, edit from the current tuned HTML, and use\n `edit-design` for surgical changes or `mode: \"replace-file\"` for a bounded\n selected-file replacement. Use `generate-design` for new files only.\n- Use `export-coding-handoff` when the user wants to implement the chosen\n design in a codebase.\n\n## Exploration Defaults\n\n1. Default to three variants unless the user asks for a different count\n (`present-design-variants` accepts 2-5; three is the sweet spot).\n2. Make variants structurally and stylistically distinct, not just color swaps.\n3. Each variant must be a compact, complete standalone HTML document that\n renders without a build step.\n4. For product UI redesigns, prefer cleaner hierarchy, progressive disclosure,\n and realistic controls over decorative mockups.\n5. After `present-design-variants`, wait for the user's pick before\n generating the next version. Keep the chosen screen, delete the other\n variant screens, call `get-design-snapshot` with `fileId` for the kept\n screen, then call `edit-design` on that same `fileId` in a bounded pass.\n Use `mode: \"replace-file\"` when expanding the representative placeholder\n into the full chosen direction. Do not call `generate-design` after a\n variant pick. Stop after the first successful `edit-design` save.\n\n## Design Quality Bar\n\nGeneric \"AI slop\" comes from letting one prompt set taste, explore, and emit code\nat once \u2014 so the model returns the training-average (Inter, an indigo/violet\ngradient, a centered hero, three rounded cards). The variant flow above exists to\nseparate those jobs; use it, and hold this bar:\n\n- Before generating, name the concrete audience, the screen's primary job, and\n the visual thesis. If the brief is vague, make a reasonable choice and state\n it instead of producing a generic dashboard/landing-page default.\n- Refuse the defaults, and pair every \"don't\" with a \"do\" (banning Inter alone\n just makes you reach for Roboto). Avoid Inter/Roboto/system fonts, the\n indigo/violet slop palette (`#6366F1`/`#8B5CF6`/`#A855F7`) and purple-on-white\n gradients, and centered-hero + three-icon-card layouts; instead pick a\n distinctive font pairing, one non-default palette family with a single decisive\n accent, and an asymmetric layout with a clear focal point.\n- Make each direction distinct in structure and behavior, not just palette.\n Give every variant one memorable signature choice, then keep the surrounding\n chrome disciplined. Even your creative picks converge (Space Grotesk\n everywhere) \u2014 vary deliberately so two directions never share a fingerprint.\n- For existing products, inspect the current screen, design system, tokens, and\n component language before inventing a new direction. Treat any drift back to a\n default as a missing token to pin, and vary layout per screen so on-brand does\n not become same-in-your-colors.\n- Treat copy, data, and imagery as design material. Use realistic domain\n content and first-party/generated assets when images matter; avoid lorem\n ipsum, vague SaaS filler, and decorative placeholder boxes.\n- Build to a quiet quality floor: responsive desktop/mobile layout, visible\n keyboard focus, useful loading/empty/error states for app UI, and reduced\n motion support when custom motion is present.\n- After broad generation or refinement, inspect the rendered Design surface or\n a screenshot-capable host before calling it ready. Fix obvious hierarchy,\n overflow, contrast, broken interaction, and placeholder-content issues first.\n\n## Cross-App Use\n\n- Hosted default: connect `https://design.agent-native.com/mcp`.\n Do not put shared secrets in skill files.\n- For CLI/code-editor clients, keep any `npx @agent-native/core@latest connect` command\n running until browser authorization finishes. Stopping it early can leave the\n browser approved but the local MCP config unwritten. Restart or reload the\n agent client after installing or connecting if Design tools do not appear in\n the live session.\n- Dispatch can expose Design alongside other apps. Use Design for UI/UX design\n tasks, Assets for image/media selection, Slides for decks, and so on.\n- Keep the loop visual: surface the inline MCP App or the returned \"Open\n design\" link instead of pasting large HTML blobs into chat.\n- If a Design tool call returns `Session terminated`, `needs auth`, or\n another connector/session error, do not keep retrying the tool. Stop and give\n the user the reconnect step: in Claude Code run `/mcp` and choose\n Authenticate/Reconnect for the Design connector; from any terminal run\n `npx -y @agent-native/core@latest reconnect https://design.agent-native.com` \u2014 this\n re-authenticates WITHOUT reinstalling. Never reinstall from scratch just to fix\n auth. Continue once the connector is available.\n- Do not hand-roll MCP HTTP requests with curl from the agent session. Use the\n host-exposed Design tools after restart/reload, or use the returned\n browser/deep-link fallback.\n- If you inspect local MCP config, redact `Authorization`, `http_headers`,\n and token values. Never paste bearer tokens into chat or logs.\n";
2
2
  //# sourceMappingURL=design-exploration-skill.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"design-exploration-skill.d.ts","sourceRoot":"","sources":["../../../src/cli/skills-content/design-exploration-skill.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,2BAA2B,8yNAqHvC,CAAC"}
1
+ {"version":3,"file":"design-exploration-skill.d.ts","sourceRoot":"","sources":["../../../src/cli/skills-content/design-exploration-skill.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,2BAA2B,gyNAqHvC,CAAC"}
@@ -92,7 +92,7 @@ separate those jobs; use it, and hold this bar:
92
92
 
93
93
  ## Cross-App Use
94
94
 
95
- - Hosted default: connect \`https://design.agent-native.com/_agent-native/mcp\`.
95
+ - Hosted default: connect \`https://design.agent-native.com/mcp\`.
96
96
  Do not put shared secrets in skill files.
97
97
  - For CLI/code-editor clients, keep any \`npx @agent-native/core@latest connect\` command
98
98
  running until browser authorization finishes. Stopping it early can leave the
@@ -1 +1 @@
1
- {"version":3,"file":"design-exploration-skill.js","sourceRoot":"","sources":["../../../src/cli/skills-content/design-exploration-skill.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,2BAA2B,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqH1C,CAAC","sourcesContent":["export const DESIGN_EXPLORATION_SKILL_MD = `---\nname: design-exploration\ndescription: >-\n Use Design for UI/UX exploration, side-by-side design directions,\n interactive prototype previews, user selection, iteration, and design-to-code\n handoff through the hosted Design MCP app.\nmetadata:\n visibility: exported\n---\n\n# Design Exploration\n\nUse the Design app when a workflow needs visual UI exploration, prototype\niteration, or a human-in-the-loop choice among design directions.\n\n## Choose The Path\n\n- Use \\`create-design\\` first to create a project shell. Do not report the\n design as ready until it has renderable HTML.\n- For open-ended UX exploration, generate distinct, compact, complete HTML\n directions (2-5, three by default) and call \\`present-design-variants\\`. Each\n direction should be one representative screen or directional snapshot, not a\n full app per variant. Design saves every option as a normal screen on the\n overview board and renders an inline chat choice with one button per screen\n name. After the user picks, delete the unchosen variant screens and continue\n from the kept screen by first calling \\`get-design-snapshot\\` with that\n screen's \\`fileId\\`, then calling \\`edit-design\\` on that same \\`fileId\\` in a\n bounded single-file pass. Use \\`mode: \"replace-file\"\\` when expanding the\n representative placeholder into the full chosen direction. Do not call\n \\`generate-design\\` after a variant pick.\n- If the chat choice buttons are not available in the host, ask the user to\n tell you the screen name they prefer. The variants are already real screens\n on the board, so do not ask them to paste HTML or copy a generated handoff\n summary.\n- For direct refinements to an already chosen direction, call\n \\`get-design-snapshot\\`, edit from the current tuned HTML, and use\n \\`edit-design\\` for surgical changes or \\`mode: \"replace-file\"\\` for a bounded\n selected-file replacement. Use \\`generate-design\\` for new files only.\n- Use \\`export-coding-handoff\\` when the user wants to implement the chosen\n design in a codebase.\n\n## Exploration Defaults\n\n1. Default to three variants unless the user asks for a different count\n (\\`present-design-variants\\` accepts 2-5; three is the sweet spot).\n2. Make variants structurally and stylistically distinct, not just color swaps.\n3. Each variant must be a compact, complete standalone HTML document that\n renders without a build step.\n4. For product UI redesigns, prefer cleaner hierarchy, progressive disclosure,\n and realistic controls over decorative mockups.\n5. After \\`present-design-variants\\`, wait for the user's pick before\n generating the next version. Keep the chosen screen, delete the other\n variant screens, call \\`get-design-snapshot\\` with \\`fileId\\` for the kept\n screen, then call \\`edit-design\\` on that same \\`fileId\\` in a bounded pass.\n Use \\`mode: \"replace-file\"\\` when expanding the representative placeholder\n into the full chosen direction. Do not call \\`generate-design\\` after a\n variant pick. Stop after the first successful \\`edit-design\\` save.\n\n## Design Quality Bar\n\nGeneric \"AI slop\" comes from letting one prompt set taste, explore, and emit code\nat once — so the model returns the training-average (Inter, an indigo/violet\ngradient, a centered hero, three rounded cards). The variant flow above exists to\nseparate those jobs; use it, and hold this bar:\n\n- Before generating, name the concrete audience, the screen's primary job, and\n the visual thesis. If the brief is vague, make a reasonable choice and state\n it instead of producing a generic dashboard/landing-page default.\n- Refuse the defaults, and pair every \"don't\" with a \"do\" (banning Inter alone\n just makes you reach for Roboto). Avoid Inter/Roboto/system fonts, the\n indigo/violet slop palette (\\`#6366F1\\`/\\`#8B5CF6\\`/\\`#A855F7\\`) and purple-on-white\n gradients, and centered-hero + three-icon-card layouts; instead pick a\n distinctive font pairing, one non-default palette family with a single decisive\n accent, and an asymmetric layout with a clear focal point.\n- Make each direction distinct in structure and behavior, not just palette.\n Give every variant one memorable signature choice, then keep the surrounding\n chrome disciplined. Even your creative picks converge (Space Grotesk\n everywhere) — vary deliberately so two directions never share a fingerprint.\n- For existing products, inspect the current screen, design system, tokens, and\n component language before inventing a new direction. Treat any drift back to a\n default as a missing token to pin, and vary layout per screen so on-brand does\n not become same-in-your-colors.\n- Treat copy, data, and imagery as design material. Use realistic domain\n content and first-party/generated assets when images matter; avoid lorem\n ipsum, vague SaaS filler, and decorative placeholder boxes.\n- Build to a quiet quality floor: responsive desktop/mobile layout, visible\n keyboard focus, useful loading/empty/error states for app UI, and reduced\n motion support when custom motion is present.\n- After broad generation or refinement, inspect the rendered Design surface or\n a screenshot-capable host before calling it ready. Fix obvious hierarchy,\n overflow, contrast, broken interaction, and placeholder-content issues first.\n\n## Cross-App Use\n\n- Hosted default: connect \\`https://design.agent-native.com/_agent-native/mcp\\`.\n Do not put shared secrets in skill files.\n- For CLI/code-editor clients, keep any \\`npx @agent-native/core@latest connect\\` command\n running until browser authorization finishes. Stopping it early can leave the\n browser approved but the local MCP config unwritten. Restart or reload the\n agent client after installing or connecting if Design tools do not appear in\n the live session.\n- Dispatch can expose Design alongside other apps. Use Design for UI/UX design\n tasks, Assets for image/media selection, Slides for decks, and so on.\n- Keep the loop visual: surface the inline MCP App or the returned \"Open\n design\" link instead of pasting large HTML blobs into chat.\n- If a Design tool call returns \\`Session terminated\\`, \\`needs auth\\`, or\n another connector/session error, do not keep retrying the tool. Stop and give\n the user the reconnect step: in Claude Code run \\`/mcp\\` and choose\n Authenticate/Reconnect for the Design connector; from any terminal run\n \\`npx -y @agent-native/core@latest reconnect https://design.agent-native.com\\` — this\n re-authenticates WITHOUT reinstalling. Never reinstall from scratch just to fix\n auth. Continue once the connector is available.\n- Do not hand-roll MCP HTTP requests with curl from the agent session. Use the\n host-exposed Design tools after restart/reload, or use the returned\n browser/deep-link fallback.\n- If you inspect local MCP config, redact \\`Authorization\\`, \\`http_headers\\`,\n and token values. Never paste bearer tokens into chat or logs.\n`;\n"]}
1
+ {"version":3,"file":"design-exploration-skill.js","sourceRoot":"","sources":["../../../src/cli/skills-content/design-exploration-skill.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,2BAA2B,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqH1C,CAAC","sourcesContent":["export const DESIGN_EXPLORATION_SKILL_MD = `---\nname: design-exploration\ndescription: >-\n Use Design for UI/UX exploration, side-by-side design directions,\n interactive prototype previews, user selection, iteration, and design-to-code\n handoff through the hosted Design MCP app.\nmetadata:\n visibility: exported\n---\n\n# Design Exploration\n\nUse the Design app when a workflow needs visual UI exploration, prototype\niteration, or a human-in-the-loop choice among design directions.\n\n## Choose The Path\n\n- Use \\`create-design\\` first to create a project shell. Do not report the\n design as ready until it has renderable HTML.\n- For open-ended UX exploration, generate distinct, compact, complete HTML\n directions (2-5, three by default) and call \\`present-design-variants\\`. Each\n direction should be one representative screen or directional snapshot, not a\n full app per variant. Design saves every option as a normal screen on the\n overview board and renders an inline chat choice with one button per screen\n name. After the user picks, delete the unchosen variant screens and continue\n from the kept screen by first calling \\`get-design-snapshot\\` with that\n screen's \\`fileId\\`, then calling \\`edit-design\\` on that same \\`fileId\\` in a\n bounded single-file pass. Use \\`mode: \"replace-file\"\\` when expanding the\n representative placeholder into the full chosen direction. Do not call\n \\`generate-design\\` after a variant pick.\n- If the chat choice buttons are not available in the host, ask the user to\n tell you the screen name they prefer. The variants are already real screens\n on the board, so do not ask them to paste HTML or copy a generated handoff\n summary.\n- For direct refinements to an already chosen direction, call\n \\`get-design-snapshot\\`, edit from the current tuned HTML, and use\n \\`edit-design\\` for surgical changes or \\`mode: \"replace-file\"\\` for a bounded\n selected-file replacement. Use \\`generate-design\\` for new files only.\n- Use \\`export-coding-handoff\\` when the user wants to implement the chosen\n design in a codebase.\n\n## Exploration Defaults\n\n1. Default to three variants unless the user asks for a different count\n (\\`present-design-variants\\` accepts 2-5; three is the sweet spot).\n2. Make variants structurally and stylistically distinct, not just color swaps.\n3. Each variant must be a compact, complete standalone HTML document that\n renders without a build step.\n4. For product UI redesigns, prefer cleaner hierarchy, progressive disclosure,\n and realistic controls over decorative mockups.\n5. After \\`present-design-variants\\`, wait for the user's pick before\n generating the next version. Keep the chosen screen, delete the other\n variant screens, call \\`get-design-snapshot\\` with \\`fileId\\` for the kept\n screen, then call \\`edit-design\\` on that same \\`fileId\\` in a bounded pass.\n Use \\`mode: \"replace-file\"\\` when expanding the representative placeholder\n into the full chosen direction. Do not call \\`generate-design\\` after a\n variant pick. Stop after the first successful \\`edit-design\\` save.\n\n## Design Quality Bar\n\nGeneric \"AI slop\" comes from letting one prompt set taste, explore, and emit code\nat once — so the model returns the training-average (Inter, an indigo/violet\ngradient, a centered hero, three rounded cards). The variant flow above exists to\nseparate those jobs; use it, and hold this bar:\n\n- Before generating, name the concrete audience, the screen's primary job, and\n the visual thesis. If the brief is vague, make a reasonable choice and state\n it instead of producing a generic dashboard/landing-page default.\n- Refuse the defaults, and pair every \"don't\" with a \"do\" (banning Inter alone\n just makes you reach for Roboto). Avoid Inter/Roboto/system fonts, the\n indigo/violet slop palette (\\`#6366F1\\`/\\`#8B5CF6\\`/\\`#A855F7\\`) and purple-on-white\n gradients, and centered-hero + three-icon-card layouts; instead pick a\n distinctive font pairing, one non-default palette family with a single decisive\n accent, and an asymmetric layout with a clear focal point.\n- Make each direction distinct in structure and behavior, not just palette.\n Give every variant one memorable signature choice, then keep the surrounding\n chrome disciplined. Even your creative picks converge (Space Grotesk\n everywhere) — vary deliberately so two directions never share a fingerprint.\n- For existing products, inspect the current screen, design system, tokens, and\n component language before inventing a new direction. Treat any drift back to a\n default as a missing token to pin, and vary layout per screen so on-brand does\n not become same-in-your-colors.\n- Treat copy, data, and imagery as design material. Use realistic domain\n content and first-party/generated assets when images matter; avoid lorem\n ipsum, vague SaaS filler, and decorative placeholder boxes.\n- Build to a quiet quality floor: responsive desktop/mobile layout, visible\n keyboard focus, useful loading/empty/error states for app UI, and reduced\n motion support when custom motion is present.\n- After broad generation or refinement, inspect the rendered Design surface or\n a screenshot-capable host before calling it ready. Fix obvious hierarchy,\n overflow, contrast, broken interaction, and placeholder-content issues first.\n\n## Cross-App Use\n\n- Hosted default: connect \\`https://design.agent-native.com/mcp\\`.\n Do not put shared secrets in skill files.\n- For CLI/code-editor clients, keep any \\`npx @agent-native/core@latest connect\\` command\n running until browser authorization finishes. Stopping it early can leave the\n browser approved but the local MCP config unwritten. Restart or reload the\n agent client after installing or connecting if Design tools do not appear in\n the live session.\n- Dispatch can expose Design alongside other apps. Use Design for UI/UX design\n tasks, Assets for image/media selection, Slides for decks, and so on.\n- Keep the loop visual: surface the inline MCP App or the returned \"Open\n design\" link instead of pasting large HTML blobs into chat.\n- If a Design tool call returns \\`Session terminated\\`, \\`needs auth\\`, or\n another connector/session error, do not keep retrying the tool. Stop and give\n the user the reconnect step: in Claude Code run \\`/mcp\\` and choose\n Authenticate/Reconnect for the Design connector; from any terminal run\n \\`npx -y @agent-native/core@latest reconnect https://design.agent-native.com\\` — this\n re-authenticates WITHOUT reinstalling. Never reinstall from scratch just to fix\n auth. Continue once the connector is available.\n- Do not hand-roll MCP HTTP requests with curl from the agent session. Use the\n host-exposed Design tools after restart/reload, or use the returned\n browser/deep-link fallback.\n- If you inspect local MCP config, redact \\`Authorization\\`, \\`http_headers\\`,\n and token values. Never paste bearer tokens into chat or logs.\n`;\n"]}
@@ -1,2 +1,2 @@
1
- export declare const HELP = "npx @agent-native/core@latest skills\n\nUsage:\n npx @agent-native/core@latest skills list\n npx @agent-native/core@latest skills status [assets|content|design-exploration|visual-edit|visual-plan|visual-recap|visualize-repo|context-xray|scaffold] [--client codex|claude-code|pi|all] [--scope user|project] [--json]\n npx @agent-native/core@latest skills update [assets|content|design-exploration|visual-edit|visual-plan|visual-recap|visualize-repo|context-xray|scaffold] [--client codex|claude-code|pi|all] [--scope user|project] [--dry-run] [--json]\n npx @agent-native/core@latest skills add assets|content|design-exploration|visual-edit|visual-plan|visual-recap|visualize-repo|context-xray [--client codex|claude-code|cowork|cursor|opencode|github-copilot|all] [--scope user|project] [--mode hosted|local-files|self-hosted] [--mcp-url <url>] [--no-connect] [--with-github-action] [--yes] [--dry-run] [--json]\n npx @agent-native/core@latest skills add <manifest-or-app-dir|skill-repo> [--skill <name>] [--client ...] [--yes]\n\nExamples:\n npx @agent-native/core@latest skills add assets\n npx @agent-native/core@latest skills add content --mode local-files\n npx @agent-native/core@latest skills add design-exploration\n npx @agent-native/core@latest skills add visual-edit\n npx @agent-native/core@latest skills add visual-plan\n npx @agent-native/core@latest skills add visual-recap\n npx @agent-native/core@latest skills add visualize-repo\n npx @agent-native/core@latest skills add visual-recap --with-github-action\n npx @agent-native/core@latest skills add visual-plan --mode local-files\n npx @agent-native/core@latest skills add visual-plan --mode self-hosted --mcp-url https://my-plan-app.example.com\n npx @agent-native/core@latest skills status visual-plan\n npx @agent-native/core@latest skills update visual-plan\n npx @agent-native/core@latest skills update scaffold --project\n npx @agent-native/core@latest skills add visual-plan --no-connect\n npx @agent-native/core@latest skills add context-xray --client all\n npx @agent-native/core@latest skills add assets --client claude-code\n npx @agent-native/core@latest skills add assets --mcp-url https://my-app.ngrok-free.dev\n npx @agent-native/core@latest skills add ./dist/assets-skill --client codex\n npx @agent-native/core@latest skills add BuilderIO/skills --client codex --scope project\n npx @agent-native/core@latest skills add BuilderIO/skills --with-github-action\n\nThe add command installs the SKILL.md instructions, registers the app-backed\nMCP connector, and then authenticates it in one step so you do not hit an OAuth\nwall on the first tool call. Hosted installs can configure Claude Code, Codex,\nClaude Cowork, Cursor, OpenCode, and GitHub Copilot / VS Code; local-files\ninstruction installs target the shared .agents skill path used by Codex, Pi,\nCursor, OpenCode, Copilot, and similar agents, plus Claude Code's native skill\npath when selected. Pass --client to narrow it. Authentication reuses\n\"npx @agent-native/core@latest connect\": OAuth-capable clients (Claude Code,\nCursor, OpenCode, GitHub Copilot / VS Code) get URL-only entries and authenticate\ninside that host, while Codex / Cowork run the browser device-code flow. In a\nnon-interactive shell or CI the auth step is skipped and the exact\n\"npx @agent-native/core@latest connect <url> --client all\" command is printed instead.\n\nRunning \"npx @agent-native/skills@latest add ...\" uses this same shared install\nflow with the broader BuilderIO skills catalog enabled. Pass --no-connect to\nregister MCP where possible without authenticating (leave auth to the host or run\n\"npx @agent-native/core@latest connect\" later). Pass --mcp-url to register that connector against\na custom origin (an ngrok tunnel, a local dev server, or a self-hosted\ndeployment) instead of the built-in hosted default \u2014 a bare origin gets the\nstandard /_agent-native/mcp path appended. Use app-skill pack for marketplace\nbundles and custom adapter output.\n\nWhen installing visual-plan, visual-recap, or visualize-repo interactively, the\nCLI asks where Plans artifacts should live: hosted Plans for shareable\nlinks/comments, local files for \"No sharing, all local.\", or a\nself-hosted/custom Plan app URL.\nPass --mode to choose directly. Local-files mode skips MCP registration and\nauth and installs instructions that default to a no-auth block catalog fetch,\nMDX folders, and the localhost bridge viewer.\n\nWhen installing content with --mode local-files, the CLI installs Content\ninstructions and writes or updates agent-native.json with repo-backed Markdown /\nMDX roots for docs, blog, content, and resources. Use a local Content app, Agent\nNative Desktop, or another trusted local bridge for Content actions to read and\nwrite those files.\n\nWhen installing visual-recap interactively, the CLI offers to add the optional PR\nVisual Recap GitHub Action. Pass --with-github-action to write it directly, then\nrun \"npx @agent-native/core@latest recap setup\" / \"npx @agent-native/core@latest recap doctor\" to configure and\nverify GitHub Actions. Docs: https://www.agent-native.com/docs/pr-visual-recap.\n\nThe status/update commands inspect copied Agent Native skill folders and refresh\ntheir instruction files from the current @agent-native/core package. In generated\napps/workspaces, \"skills update scaffold --project\" refreshes the framework\nskills copied into the scaffold and repairs AGENTS.md / CLAUDE.md and\n.agents/skills / .claude/skills compatibility links.";
1
+ export declare const HELP = "npx @agent-native/core@latest skills\n\nUsage:\n npx @agent-native/core@latest skills list\n npx @agent-native/core@latest skills status [assets|content|design-exploration|visual-edit|visual-plan|visual-recap|visualize-repo|context-xray|scaffold] [--client codex|claude-code|pi|all] [--scope user|project] [--json]\n npx @agent-native/core@latest skills update [assets|content|design-exploration|visual-edit|visual-plan|visual-recap|visualize-repo|context-xray|scaffold] [--client codex|claude-code|pi|all] [--scope user|project] [--dry-run] [--json]\n npx @agent-native/core@latest skills add assets|content|design-exploration|visual-edit|visual-plan|visual-recap|visualize-repo|context-xray [--client codex|claude-code|cowork|cursor|opencode|github-copilot|all] [--scope user|project] [--mode hosted|local-files|self-hosted] [--mcp-url <url>] [--no-connect] [--with-github-action] [--yes] [--dry-run] [--json]\n npx @agent-native/core@latest skills add <manifest-or-app-dir|skill-repo> [--skill <name>] [--client ...] [--yes]\n\nExamples:\n npx @agent-native/core@latest skills add assets\n npx @agent-native/core@latest skills add content --mode local-files\n npx @agent-native/core@latest skills add design-exploration\n npx @agent-native/core@latest skills add visual-edit\n npx @agent-native/core@latest skills add visual-plan\n npx @agent-native/core@latest skills add visual-recap\n npx @agent-native/core@latest skills add visualize-repo\n npx @agent-native/core@latest skills add visual-recap --with-github-action\n npx @agent-native/core@latest skills add visual-plan --mode local-files\n npx @agent-native/core@latest skills add visual-plan --mode self-hosted --mcp-url https://my-plan-app.example.com\n npx @agent-native/core@latest skills status visual-plan\n npx @agent-native/core@latest skills update visual-plan\n npx @agent-native/core@latest skills update scaffold --project\n npx @agent-native/core@latest skills add visual-plan --no-connect\n npx @agent-native/core@latest skills add context-xray --client all\n npx @agent-native/core@latest skills add assets --client claude-code\n npx @agent-native/core@latest skills add assets --mcp-url https://my-app.ngrok-free.dev\n npx @agent-native/core@latest skills add ./dist/assets-skill --client codex\n npx @agent-native/core@latest skills add BuilderIO/skills --client codex --scope project\n npx @agent-native/core@latest skills add BuilderIO/skills --with-github-action\n\nThe add command installs the SKILL.md instructions, registers the app-backed\nMCP connector, and then authenticates it in one step so you do not hit an OAuth\nwall on the first tool call. Hosted installs can configure Claude Code, Codex,\nClaude Cowork, Cursor, OpenCode, and GitHub Copilot / VS Code; local-files\ninstruction installs target the shared .agents skill path used by Codex, Pi,\nCursor, OpenCode, Copilot, and similar agents, plus Claude Code's native skill\npath when selected. Pass --client to narrow it. Authentication reuses\n\"npx @agent-native/core@latest connect\": OAuth-capable clients (Claude Code,\nCursor, OpenCode, GitHub Copilot / VS Code) get URL-only entries and authenticate\ninside that host, while Codex / Cowork run the browser device-code flow. In a\nnon-interactive shell or CI the auth step is skipped and the exact\n\"npx @agent-native/core@latest connect <url> --client all\" command is printed instead.\n\nRunning \"npx @agent-native/skills@latest add ...\" uses this same shared install\nflow with the broader BuilderIO skills catalog enabled. Pass --no-connect to\nregister MCP where possible without authenticating (leave auth to the host or run\n\"npx @agent-native/core@latest connect\" later). Pass --mcp-url to register that connector against\na custom origin (an ngrok tunnel, a local dev server, or a self-hosted\ndeployment) instead of the built-in hosted default \u2014 a bare origin gets the\nstandard /mcp path appended. Use app-skill pack for marketplace\nbundles and custom adapter output.\n\nWhen installing visual-plan, visual-recap, or visualize-repo interactively, the\nCLI asks where Plans artifacts should live: hosted Plans for shareable\nlinks/comments, local files for \"No sharing, all local.\", or a\nself-hosted/custom Plan app URL.\nPass --mode to choose directly. Local-files mode skips MCP registration and\nauth and installs instructions that default to a no-auth block catalog fetch,\nMDX folders, and the localhost bridge viewer.\n\nWhen installing content with --mode local-files, the CLI installs Content\ninstructions and writes or updates agent-native.json with repo-backed Markdown /\nMDX roots for docs, blog, content, and resources. Use a local Content app, Agent\nNative Desktop, or another trusted local bridge for Content actions to read and\nwrite those files.\n\nWhen installing visual-recap interactively, the CLI offers to add the optional PR\nVisual Recap GitHub Action. Pass --with-github-action to write it directly, then\nrun \"npx @agent-native/core@latest recap setup\" / \"npx @agent-native/core@latest recap doctor\" to configure and\nverify GitHub Actions. Docs: https://www.agent-native.com/docs/pr-visual-recap.\n\nThe status/update commands inspect copied Agent Native skill folders and refresh\ntheir instruction files from the current @agent-native/core package. In generated\napps/workspaces, \"skills update scaffold --project\" refreshes the framework\nskills copied into the scaffold and repairs AGENTS.md / CLAUDE.md and\n.agents/skills / .claude/skills compatibility links.";
2
2
  //# sourceMappingURL=help.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../../src/cli/skills-content/help.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,IAAI,k8KA4EoC,CAAC"}
1
+ {"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../../src/cli/skills-content/help.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,IAAI,o7KA4EoC,CAAC"}
@@ -48,7 +48,7 @@ register MCP where possible without authenticating (leave auth to the host or ru
48
48
  "npx @agent-native/core@latest connect" later). Pass --mcp-url to register that connector against
49
49
  a custom origin (an ngrok tunnel, a local dev server, or a self-hosted
50
50
  deployment) instead of the built-in hosted default — a bare origin gets the
51
- standard /_agent-native/mcp path appended. Use app-skill pack for marketplace
51
+ standard /mcp path appended. Use app-skill pack for marketplace
52
52
  bundles and custom adapter output.
53
53
 
54
54
  When installing visual-plan, visual-recap, or visualize-repo interactively, the
@@ -1 +1 @@
1
- {"version":3,"file":"help.js","sourceRoot":"","sources":["../../../src/cli/skills-content/help.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qDA4EiC,CAAC","sourcesContent":["export const HELP = `npx @agent-native/core@latest skills\n\nUsage:\n npx @agent-native/core@latest skills list\n npx @agent-native/core@latest skills status [assets|content|design-exploration|visual-edit|visual-plan|visual-recap|visualize-repo|context-xray|scaffold] [--client codex|claude-code|pi|all] [--scope user|project] [--json]\n npx @agent-native/core@latest skills update [assets|content|design-exploration|visual-edit|visual-plan|visual-recap|visualize-repo|context-xray|scaffold] [--client codex|claude-code|pi|all] [--scope user|project] [--dry-run] [--json]\n npx @agent-native/core@latest skills add assets|content|design-exploration|visual-edit|visual-plan|visual-recap|visualize-repo|context-xray [--client codex|claude-code|cowork|cursor|opencode|github-copilot|all] [--scope user|project] [--mode hosted|local-files|self-hosted] [--mcp-url <url>] [--no-connect] [--with-github-action] [--yes] [--dry-run] [--json]\n npx @agent-native/core@latest skills add <manifest-or-app-dir|skill-repo> [--skill <name>] [--client ...] [--yes]\n\nExamples:\n npx @agent-native/core@latest skills add assets\n npx @agent-native/core@latest skills add content --mode local-files\n npx @agent-native/core@latest skills add design-exploration\n npx @agent-native/core@latest skills add visual-edit\n npx @agent-native/core@latest skills add visual-plan\n npx @agent-native/core@latest skills add visual-recap\n npx @agent-native/core@latest skills add visualize-repo\n npx @agent-native/core@latest skills add visual-recap --with-github-action\n npx @agent-native/core@latest skills add visual-plan --mode local-files\n npx @agent-native/core@latest skills add visual-plan --mode self-hosted --mcp-url https://my-plan-app.example.com\n npx @agent-native/core@latest skills status visual-plan\n npx @agent-native/core@latest skills update visual-plan\n npx @agent-native/core@latest skills update scaffold --project\n npx @agent-native/core@latest skills add visual-plan --no-connect\n npx @agent-native/core@latest skills add context-xray --client all\n npx @agent-native/core@latest skills add assets --client claude-code\n npx @agent-native/core@latest skills add assets --mcp-url https://my-app.ngrok-free.dev\n npx @agent-native/core@latest skills add ./dist/assets-skill --client codex\n npx @agent-native/core@latest skills add BuilderIO/skills --client codex --scope project\n npx @agent-native/core@latest skills add BuilderIO/skills --with-github-action\n\nThe add command installs the SKILL.md instructions, registers the app-backed\nMCP connector, and then authenticates it in one step so you do not hit an OAuth\nwall on the first tool call. Hosted installs can configure Claude Code, Codex,\nClaude Cowork, Cursor, OpenCode, and GitHub Copilot / VS Code; local-files\ninstruction installs target the shared .agents skill path used by Codex, Pi,\nCursor, OpenCode, Copilot, and similar agents, plus Claude Code's native skill\npath when selected. Pass --client to narrow it. Authentication reuses\n\"npx @agent-native/core@latest connect\": OAuth-capable clients (Claude Code,\nCursor, OpenCode, GitHub Copilot / VS Code) get URL-only entries and authenticate\ninside that host, while Codex / Cowork run the browser device-code flow. In a\nnon-interactive shell or CI the auth step is skipped and the exact\n\"npx @agent-native/core@latest connect <url> --client all\" command is printed instead.\n\nRunning \"npx @agent-native/skills@latest add ...\" uses this same shared install\nflow with the broader BuilderIO skills catalog enabled. Pass --no-connect to\nregister MCP where possible without authenticating (leave auth to the host or run\n\"npx @agent-native/core@latest connect\" later). Pass --mcp-url to register that connector against\na custom origin (an ngrok tunnel, a local dev server, or a self-hosted\ndeployment) instead of the built-in hosted default — a bare origin gets the\nstandard /_agent-native/mcp path appended. Use app-skill pack for marketplace\nbundles and custom adapter output.\n\nWhen installing visual-plan, visual-recap, or visualize-repo interactively, the\nCLI asks where Plans artifacts should live: hosted Plans for shareable\nlinks/comments, local files for \"No sharing, all local.\", or a\nself-hosted/custom Plan app URL.\nPass --mode to choose directly. Local-files mode skips MCP registration and\nauth and installs instructions that default to a no-auth block catalog fetch,\nMDX folders, and the localhost bridge viewer.\n\nWhen installing content with --mode local-files, the CLI installs Content\ninstructions and writes or updates agent-native.json with repo-backed Markdown /\nMDX roots for docs, blog, content, and resources. Use a local Content app, Agent\nNative Desktop, or another trusted local bridge for Content actions to read and\nwrite those files.\n\nWhen installing visual-recap interactively, the CLI offers to add the optional PR\nVisual Recap GitHub Action. Pass --with-github-action to write it directly, then\nrun \"npx @agent-native/core@latest recap setup\" / \"npx @agent-native/core@latest recap doctor\" to configure and\nverify GitHub Actions. Docs: https://www.agent-native.com/docs/pr-visual-recap.\n\nThe status/update commands inspect copied Agent Native skill folders and refresh\ntheir instruction files from the current @agent-native/core package. In generated\napps/workspaces, \"skills update scaffold --project\" refreshes the framework\nskills copied into the scaffold and repairs AGENTS.md / CLAUDE.md and\n.agents/skills / .claude/skills compatibility links.`;\n"]}
1
+ {"version":3,"file":"help.js","sourceRoot":"","sources":["../../../src/cli/skills-content/help.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qDA4EiC,CAAC","sourcesContent":["export const HELP = `npx @agent-native/core@latest skills\n\nUsage:\n npx @agent-native/core@latest skills list\n npx @agent-native/core@latest skills status [assets|content|design-exploration|visual-edit|visual-plan|visual-recap|visualize-repo|context-xray|scaffold] [--client codex|claude-code|pi|all] [--scope user|project] [--json]\n npx @agent-native/core@latest skills update [assets|content|design-exploration|visual-edit|visual-plan|visual-recap|visualize-repo|context-xray|scaffold] [--client codex|claude-code|pi|all] [--scope user|project] [--dry-run] [--json]\n npx @agent-native/core@latest skills add assets|content|design-exploration|visual-edit|visual-plan|visual-recap|visualize-repo|context-xray [--client codex|claude-code|cowork|cursor|opencode|github-copilot|all] [--scope user|project] [--mode hosted|local-files|self-hosted] [--mcp-url <url>] [--no-connect] [--with-github-action] [--yes] [--dry-run] [--json]\n npx @agent-native/core@latest skills add <manifest-or-app-dir|skill-repo> [--skill <name>] [--client ...] [--yes]\n\nExamples:\n npx @agent-native/core@latest skills add assets\n npx @agent-native/core@latest skills add content --mode local-files\n npx @agent-native/core@latest skills add design-exploration\n npx @agent-native/core@latest skills add visual-edit\n npx @agent-native/core@latest skills add visual-plan\n npx @agent-native/core@latest skills add visual-recap\n npx @agent-native/core@latest skills add visualize-repo\n npx @agent-native/core@latest skills add visual-recap --with-github-action\n npx @agent-native/core@latest skills add visual-plan --mode local-files\n npx @agent-native/core@latest skills add visual-plan --mode self-hosted --mcp-url https://my-plan-app.example.com\n npx @agent-native/core@latest skills status visual-plan\n npx @agent-native/core@latest skills update visual-plan\n npx @agent-native/core@latest skills update scaffold --project\n npx @agent-native/core@latest skills add visual-plan --no-connect\n npx @agent-native/core@latest skills add context-xray --client all\n npx @agent-native/core@latest skills add assets --client claude-code\n npx @agent-native/core@latest skills add assets --mcp-url https://my-app.ngrok-free.dev\n npx @agent-native/core@latest skills add ./dist/assets-skill --client codex\n npx @agent-native/core@latest skills add BuilderIO/skills --client codex --scope project\n npx @agent-native/core@latest skills add BuilderIO/skills --with-github-action\n\nThe add command installs the SKILL.md instructions, registers the app-backed\nMCP connector, and then authenticates it in one step so you do not hit an OAuth\nwall on the first tool call. Hosted installs can configure Claude Code, Codex,\nClaude Cowork, Cursor, OpenCode, and GitHub Copilot / VS Code; local-files\ninstruction installs target the shared .agents skill path used by Codex, Pi,\nCursor, OpenCode, Copilot, and similar agents, plus Claude Code's native skill\npath when selected. Pass --client to narrow it. Authentication reuses\n\"npx @agent-native/core@latest connect\": OAuth-capable clients (Claude Code,\nCursor, OpenCode, GitHub Copilot / VS Code) get URL-only entries and authenticate\ninside that host, while Codex / Cowork run the browser device-code flow. In a\nnon-interactive shell or CI the auth step is skipped and the exact\n\"npx @agent-native/core@latest connect <url> --client all\" command is printed instead.\n\nRunning \"npx @agent-native/skills@latest add ...\" uses this same shared install\nflow with the broader BuilderIO skills catalog enabled. Pass --no-connect to\nregister MCP where possible without authenticating (leave auth to the host or run\n\"npx @agent-native/core@latest connect\" later). Pass --mcp-url to register that connector against\na custom origin (an ngrok tunnel, a local dev server, or a self-hosted\ndeployment) instead of the built-in hosted default — a bare origin gets the\nstandard /mcp path appended. Use app-skill pack for marketplace\nbundles and custom adapter output.\n\nWhen installing visual-plan, visual-recap, or visualize-repo interactively, the\nCLI asks where Plans artifacts should live: hosted Plans for shareable\nlinks/comments, local files for \"No sharing, all local.\", or a\nself-hosted/custom Plan app URL.\nPass --mode to choose directly. Local-files mode skips MCP registration and\nauth and installs instructions that default to a no-auth block catalog fetch,\nMDX folders, and the localhost bridge viewer.\n\nWhen installing content with --mode local-files, the CLI installs Content\ninstructions and writes or updates agent-native.json with repo-backed Markdown /\nMDX roots for docs, blog, content, and resources. Use a local Content app, Agent\nNative Desktop, or another trusted local bridge for Content actions to read and\nwrite those files.\n\nWhen installing visual-recap interactively, the CLI offers to add the optional PR\nVisual Recap GitHub Action. Pass --with-github-action to write it directly, then\nrun \"npx @agent-native/core@latest recap setup\" / \"npx @agent-native/core@latest recap doctor\" to configure and\nverify GitHub Actions. Docs: https://www.agent-native.com/docs/pr-visual-recap.\n\nThe status/update commands inspect copied Agent Native skill folders and refresh\ntheir instruction files from the current @agent-native/core package. In generated\napps/workspaces, \"skills update scaffold --project\" refreshes the framework\nskills copied into the scaffold and repairs AGENTS.md / CLAUDE.md and\n.agents/skills / .claude/skills compatibility links.`;\n"]}
@@ -5,5 +5,5 @@
5
5
  * `templates/plan/.agents/skills/*`, top-level `skills/*`, and
6
6
  * `.agents/skills/*` are guarded byte-identical by `skills.sync.spec.ts`.
7
7
  */
8
- export declare const PLAN_SETUP_AUTH_MD = "## Setup & Authentication\n\nThere are two ways into Plans.\n\n**Coding agent (CLI).** Install once with the Agent-Native CLI. The command\ninstalls the Plans skills, registers the hosted Plans MCP connector, and runs\nauth/setup for the selected local client(s) in the same step (a one-time browser\nsign-in at setup \u2014 this is intended), so the first tool call in that client does\nnot hit an OAuth wall:\n\n```bash\nnpx @agent-native/core@latest skills add visual-plans\n```\n\nAfter that, `/visual-plan`, `/visual-recap`, and `/visualize-repo` are the\ninstalled slash commands. If you only need one command, use\n`skills add visual-plan`, `skills add visual-recap`, or\n`skills add visualize-repo` instead. The other planning modes\n(`create-ui-plan`, `create-prototype-plan`, `create-plan-design`,\n`create-visual-questions`) are MCP tools reachable from `/visual-plan`, not\nseparate slash commands. Pass `--no-connect` to register the connector without\nauthenticating, then run\n`npx @agent-native/core@latest connect https://plan.agent-native.com --client all`\nwhenever you are ready, or choose a narrower `--client`. Auth and MCP tool\nloading are per client config/session.\n\n**Local-only / text installs.** If the user wants no sharing and all local files,\ninstall with `--mode local-files`:\n\n```bash\nnpx @agent-native/core@latest skills add visual-plans --mode local-files\n```\n\nThis mode does not register the Plan MCP connector. Before authoring structured\nMDX, fetch the no-auth, schema-only block catalog with\n`npx @agent-native/core@latest plan blocks --out plan-blocks.md`, read that file,\nwrite the MDX folder locally, run `plan local check`, then run `plan local serve`.\nFor repo-wide visual docs, run\n`npx @agent-native/core@latest visualize-repo --open` to create/update\n`agent-native.json`, seed `.agent-native/visual-docs/repo-overview`, and open\nthe local bridge.\nPlain text skill\ninstalls (Vercel Skills CLI, copied GitHub files, etc.) can follow that same\nlocal flow if `@agent-native/core` is available. Text alone cannot register\nMCP tools; hosted/shareable Plans still need the Agent-Native CLI\ninstall/reconnect step above.\n\n**Browser (people you share with).** Open the Plans editor and create & edit\nwith no sign-up \u2014 you work as a guest. Sign in only when you want to save or\nshare; signing in claims the plans you made as a guest into your account.\n\nSharing and commenting require an account: public/shared plans are viewable by\nanyone with the link, but commenting on them needs an agent-native account.\n\nFor no-account, no-DB plan storage, use local-files mode and the local bridge\ncommand. The optional `plan blocks` lookup reads only public schema metadata.\nIf network access is unavailable, use the bundled references and a local Plan\napp/runtime for validation.\n\nIf a Plans tool returns `needs auth`, `Unauthorized`, or `Session terminated`,\ndo not keep retrying the tool. Stop and give the user the reconnect step for the\nclient they are using: Codex/Codex Desktop should run\n`npx -y @agent-native/core@latest reconnect https://plan.agent-native.com --client codex`\nand start a new Codex session; Claude Code should run `/mcp` and choose\nAuthenticate/Reconnect for the plan connector, or run the reconnect command with\n`--client claude-code` and restart Claude. To refresh every local client config\nthat already has the Plan entry, use `--client all`, then restart/reload each\nclient. Reconnect re-authenticates WITHOUT reinstalling and finds the entry by\nURL regardless of connector name. Never reinstall from scratch just to fix auth.\nContinue once the connector is available.\n\nHosted default: connect `https://plan.agent-native.com/_agent-native/mcp`. Do\nnot put shared secrets in skill files.";
8
+ export declare const PLAN_SETUP_AUTH_MD = "## Setup & Authentication\n\nThere are two ways into Plans.\n\n**Coding agent (CLI).** Install once with the Agent-Native CLI. The command\ninstalls the Plans skills, registers the hosted Plans MCP connector, and runs\nauth/setup for the selected local client(s) in the same step (a one-time browser\nsign-in at setup \u2014 this is intended), so the first tool call in that client does\nnot hit an OAuth wall:\n\n```bash\nnpx @agent-native/core@latest skills add visual-plans\n```\n\nAfter that, `/visual-plan`, `/visual-recap`, and `/visualize-repo` are the\ninstalled slash commands. If you only need one command, use\n`skills add visual-plan`, `skills add visual-recap`, or\n`skills add visualize-repo` instead. The other planning modes\n(`create-ui-plan`, `create-prototype-plan`, `create-plan-design`,\n`create-visual-questions`) are MCP tools reachable from `/visual-plan`, not\nseparate slash commands. Pass `--no-connect` to register the connector without\nauthenticating, then run\n`npx @agent-native/core@latest connect https://plan.agent-native.com --client all`\nwhenever you are ready, or choose a narrower `--client`. Auth and MCP tool\nloading are per client config/session.\n\n**Local-only / text installs.** If the user wants no sharing and all local files,\ninstall with `--mode local-files`:\n\n```bash\nnpx @agent-native/core@latest skills add visual-plans --mode local-files\n```\n\nThis mode does not register the Plan MCP connector. Before authoring structured\nMDX, fetch the no-auth, schema-only block catalog with\n`npx @agent-native/core@latest plan blocks --out plan-blocks.md`, read that file,\nwrite the MDX folder locally, run `plan local check`, then run `plan local serve`.\nFor repo-wide visual docs, run\n`npx @agent-native/core@latest visualize-repo --open` to create/update\n`agent-native.json`, seed `.agent-native/visual-docs/repo-overview`, and open\nthe local bridge.\nPlain text skill\ninstalls (Vercel Skills CLI, copied GitHub files, etc.) can follow that same\nlocal flow if `@agent-native/core` is available. Text alone cannot register\nMCP tools; hosted/shareable Plans still need the Agent-Native CLI\ninstall/reconnect step above.\n\n**Browser (people you share with).** Open the Plans editor and create & edit\nwith no sign-up \u2014 you work as a guest. Sign in only when you want to save or\nshare; signing in claims the plans you made as a guest into your account.\n\nSharing and commenting require an account: public/shared plans are viewable by\nanyone with the link, but commenting on them needs an agent-native account.\n\nFor no-account, no-DB plan storage, use local-files mode and the local bridge\ncommand. The optional `plan blocks` lookup reads only public schema metadata.\nIf network access is unavailable, use the bundled references and a local Plan\napp/runtime for validation.\n\nIf a Plans tool returns `needs auth`, `Unauthorized`, or `Session terminated`,\ndo not keep retrying the tool. Stop and give the user the reconnect step for the\nclient they are using: Codex/Codex Desktop should run\n`npx -y @agent-native/core@latest reconnect https://plan.agent-native.com --client codex`\nand start a new Codex session; Claude Code should run `/mcp` and choose\nAuthenticate/Reconnect for the plan connector, or run the reconnect command with\n`--client claude-code` and restart Claude. To refresh every local client config\nthat already has the Plan entry, use `--client all`, then restart/reload each\nclient. Reconnect re-authenticates WITHOUT reinstalling and finds the entry by\nURL regardless of connector name. Never reinstall from scratch just to fix auth.\nContinue once the connector is available.\n\nHosted default: connect `https://plan.agent-native.com/mcp`. Do\nnot put shared secrets in skill files.";
9
9
  //# sourceMappingURL=plan-setup-auth.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"plan-setup-auth.d.ts","sourceRoot":"","sources":["../../../src/cli/skills-content/plan-setup-auth.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,ytHAwEQ,CAAC"}
1
+ {"version":3,"file":"plan-setup-auth.d.ts","sourceRoot":"","sources":["../../../src/cli/skills-content/plan-setup-auth.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,2sHAwEQ,CAAC"}
@@ -76,6 +76,6 @@ client. Reconnect re-authenticates WITHOUT reinstalling and finds the entry by
76
76
  URL regardless of connector name. Never reinstall from scratch just to fix auth.
77
77
  Continue once the connector is available.
78
78
 
79
- Hosted default: connect \`https://plan.agent-native.com/_agent-native/mcp\`. Do
79
+ Hosted default: connect \`https://plan.agent-native.com/mcp\`. Do
80
80
  not put shared secrets in skill files.`;
81
81
  //# sourceMappingURL=plan-setup-auth.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"plan-setup-auth.js","sourceRoot":"","sources":["../../../src/cli/skills-content/plan-setup-auth.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uCAwEK,CAAC","sourcesContent":["/**\n * Setup/auth block for the `/visual-plan` skill. Interpolated into\n * `VISUAL_PLANS_SKILL_MD` below so the install + one-step authenticate\n * instructions are single-sourced. The materialized SKILL.md copies under\n * `templates/plan/.agents/skills/*`, top-level `skills/*`, and\n * `.agents/skills/*` are guarded byte-identical by `skills.sync.spec.ts`.\n */\nexport const PLAN_SETUP_AUTH_MD = `## Setup & Authentication\n\nThere are two ways into Plans.\n\n**Coding agent (CLI).** Install once with the Agent-Native CLI. The command\ninstalls the Plans skills, registers the hosted Plans MCP connector, and runs\nauth/setup for the selected local client(s) in the same step (a one-time browser\nsign-in at setup — this is intended), so the first tool call in that client does\nnot hit an OAuth wall:\n\n\\`\\`\\`bash\nnpx @agent-native/core@latest skills add visual-plans\n\\`\\`\\`\n\nAfter that, \\`/visual-plan\\`, \\`/visual-recap\\`, and \\`/visualize-repo\\` are the\ninstalled slash commands. If you only need one command, use\n\\`skills add visual-plan\\`, \\`skills add visual-recap\\`, or\n\\`skills add visualize-repo\\` instead. The other planning modes\n(\\`create-ui-plan\\`, \\`create-prototype-plan\\`, \\`create-plan-design\\`,\n\\`create-visual-questions\\`) are MCP tools reachable from \\`/visual-plan\\`, not\nseparate slash commands. Pass \\`--no-connect\\` to register the connector without\nauthenticating, then run\n\\`npx @agent-native/core@latest connect https://plan.agent-native.com --client all\\`\nwhenever you are ready, or choose a narrower \\`--client\\`. Auth and MCP tool\nloading are per client config/session.\n\n**Local-only / text installs.** If the user wants no sharing and all local files,\ninstall with \\`--mode local-files\\`:\n\n\\`\\`\\`bash\nnpx @agent-native/core@latest skills add visual-plans --mode local-files\n\\`\\`\\`\n\nThis mode does not register the Plan MCP connector. Before authoring structured\nMDX, fetch the no-auth, schema-only block catalog with\n\\`npx @agent-native/core@latest plan blocks --out plan-blocks.md\\`, read that file,\nwrite the MDX folder locally, run \\`plan local check\\`, then run \\`plan local serve\\`.\nFor repo-wide visual docs, run\n\\`npx @agent-native/core@latest visualize-repo --open\\` to create/update\n\\`agent-native.json\\`, seed \\`.agent-native/visual-docs/repo-overview\\`, and open\nthe local bridge.\nPlain text skill\ninstalls (Vercel Skills CLI, copied GitHub files, etc.) can follow that same\nlocal flow if \\`@agent-native/core\\` is available. Text alone cannot register\nMCP tools; hosted/shareable Plans still need the Agent-Native CLI\ninstall/reconnect step above.\n\n**Browser (people you share with).** Open the Plans editor and create & edit\nwith no sign-up — you work as a guest. Sign in only when you want to save or\nshare; signing in claims the plans you made as a guest into your account.\n\nSharing and commenting require an account: public/shared plans are viewable by\nanyone with the link, but commenting on them needs an agent-native account.\n\nFor no-account, no-DB plan storage, use local-files mode and the local bridge\ncommand. The optional \\`plan blocks\\` lookup reads only public schema metadata.\nIf network access is unavailable, use the bundled references and a local Plan\napp/runtime for validation.\n\nIf a Plans tool returns \\`needs auth\\`, \\`Unauthorized\\`, or \\`Session terminated\\`,\ndo not keep retrying the tool. Stop and give the user the reconnect step for the\nclient they are using: Codex/Codex Desktop should run\n\\`npx -y @agent-native/core@latest reconnect https://plan.agent-native.com --client codex\\`\nand start a new Codex session; Claude Code should run \\`/mcp\\` and choose\nAuthenticate/Reconnect for the plan connector, or run the reconnect command with\n\\`--client claude-code\\` and restart Claude. To refresh every local client config\nthat already has the Plan entry, use \\`--client all\\`, then restart/reload each\nclient. Reconnect re-authenticates WITHOUT reinstalling and finds the entry by\nURL regardless of connector name. Never reinstall from scratch just to fix auth.\nContinue once the connector is available.\n\nHosted default: connect \\`https://plan.agent-native.com/_agent-native/mcp\\`. Do\nnot put shared secrets in skill files.`;\n"]}
1
+ {"version":3,"file":"plan-setup-auth.js","sourceRoot":"","sources":["../../../src/cli/skills-content/plan-setup-auth.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uCAwEK,CAAC","sourcesContent":["/**\n * Setup/auth block for the `/visual-plan` skill. Interpolated into\n * `VISUAL_PLANS_SKILL_MD` below so the install + one-step authenticate\n * instructions are single-sourced. The materialized SKILL.md copies under\n * `templates/plan/.agents/skills/*`, top-level `skills/*`, and\n * `.agents/skills/*` are guarded byte-identical by `skills.sync.spec.ts`.\n */\nexport const PLAN_SETUP_AUTH_MD = `## Setup & Authentication\n\nThere are two ways into Plans.\n\n**Coding agent (CLI).** Install once with the Agent-Native CLI. The command\ninstalls the Plans skills, registers the hosted Plans MCP connector, and runs\nauth/setup for the selected local client(s) in the same step (a one-time browser\nsign-in at setup — this is intended), so the first tool call in that client does\nnot hit an OAuth wall:\n\n\\`\\`\\`bash\nnpx @agent-native/core@latest skills add visual-plans\n\\`\\`\\`\n\nAfter that, \\`/visual-plan\\`, \\`/visual-recap\\`, and \\`/visualize-repo\\` are the\ninstalled slash commands. If you only need one command, use\n\\`skills add visual-plan\\`, \\`skills add visual-recap\\`, or\n\\`skills add visualize-repo\\` instead. The other planning modes\n(\\`create-ui-plan\\`, \\`create-prototype-plan\\`, \\`create-plan-design\\`,\n\\`create-visual-questions\\`) are MCP tools reachable from \\`/visual-plan\\`, not\nseparate slash commands. Pass \\`--no-connect\\` to register the connector without\nauthenticating, then run\n\\`npx @agent-native/core@latest connect https://plan.agent-native.com --client all\\`\nwhenever you are ready, or choose a narrower \\`--client\\`. Auth and MCP tool\nloading are per client config/session.\n\n**Local-only / text installs.** If the user wants no sharing and all local files,\ninstall with \\`--mode local-files\\`:\n\n\\`\\`\\`bash\nnpx @agent-native/core@latest skills add visual-plans --mode local-files\n\\`\\`\\`\n\nThis mode does not register the Plan MCP connector. Before authoring structured\nMDX, fetch the no-auth, schema-only block catalog with\n\\`npx @agent-native/core@latest plan blocks --out plan-blocks.md\\`, read that file,\nwrite the MDX folder locally, run \\`plan local check\\`, then run \\`plan local serve\\`.\nFor repo-wide visual docs, run\n\\`npx @agent-native/core@latest visualize-repo --open\\` to create/update\n\\`agent-native.json\\`, seed \\`.agent-native/visual-docs/repo-overview\\`, and open\nthe local bridge.\nPlain text skill\ninstalls (Vercel Skills CLI, copied GitHub files, etc.) can follow that same\nlocal flow if \\`@agent-native/core\\` is available. Text alone cannot register\nMCP tools; hosted/shareable Plans still need the Agent-Native CLI\ninstall/reconnect step above.\n\n**Browser (people you share with).** Open the Plans editor and create & edit\nwith no sign-up — you work as a guest. Sign in only when you want to save or\nshare; signing in claims the plans you made as a guest into your account.\n\nSharing and commenting require an account: public/shared plans are viewable by\nanyone with the link, but commenting on them needs an agent-native account.\n\nFor no-account, no-DB plan storage, use local-files mode and the local bridge\ncommand. The optional \\`plan blocks\\` lookup reads only public schema metadata.\nIf network access is unavailable, use the bundled references and a local Plan\napp/runtime for validation.\n\nIf a Plans tool returns \\`needs auth\\`, \\`Unauthorized\\`, or \\`Session terminated\\`,\ndo not keep retrying the tool. Stop and give the user the reconnect step for the\nclient they are using: Codex/Codex Desktop should run\n\\`npx -y @agent-native/core@latest reconnect https://plan.agent-native.com --client codex\\`\nand start a new Codex session; Claude Code should run \\`/mcp\\` and choose\nAuthenticate/Reconnect for the plan connector, or run the reconnect command with\n\\`--client claude-code\\` and restart Claude. To refresh every local client config\nthat already has the Plan entry, use \\`--client all\\`, then restart/reload each\nclient. Reconnect re-authenticates WITHOUT reinstalling and finds the entry by\nURL regardless of connector name. Never reinstall from scratch just to fix auth.\nContinue once the connector is available.\n\nHosted default: connect \\`https://plan.agent-native.com/mcp\\`. Do\nnot put shared secrets in skill files.`;\n"]}