@agent-native/core 0.69.0 → 0.70.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +48 -0
  3. package/corpus/core/package.json +1 -1
  4. package/corpus/core/src/changelog/parse.ts +245 -0
  5. package/corpus/core/src/cli/changelog.ts +199 -0
  6. package/corpus/core/src/cli/index.ts +19 -0
  7. package/corpus/core/src/cli/recap.ts +24 -1
  8. package/corpus/core/src/cli/skills.ts +72 -45
  9. package/corpus/core/src/client/CommandMenu.tsx +183 -75
  10. package/corpus/core/src/client/agent-chat-adapter.ts +44 -7
  11. package/corpus/core/src/client/analytics.ts +181 -0
  12. package/corpus/core/src/client/changelog/Changelog.tsx +321 -0
  13. package/corpus/core/src/client/index.ts +11 -0
  14. package/corpus/core/src/client/mcp-apps/McpAppRenderer.tsx +54 -0
  15. package/corpus/core/src/client/settings/useBuilderStatus.ts +82 -20
  16. package/corpus/core/src/mcp/build-server.ts +1 -1
  17. package/corpus/core/src/mcp/embed-app.ts +112 -6
  18. package/corpus/core/src/server/attribution.ts +211 -0
  19. package/corpus/core/src/server/auth.ts +6 -0
  20. package/corpus/core/src/server/better-auth-instance.ts +49 -5
  21. package/corpus/core/src/server/builder-browser.ts +27 -1
  22. package/corpus/core/src/server/core-routes-plugin.ts +58 -0
  23. package/corpus/core/src/server/google-oauth.ts +19 -6
  24. package/corpus/core/src/shared/mcp-embed-headers.ts +1 -1
  25. package/corpus/core/src/styles/agent-conversation.css +21 -0
  26. package/corpus/core/src/templates/workspace-core/.agents/skills/changelog/SKILL.md +111 -0
  27. package/corpus/core/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +46 -14
  28. package/corpus/templates/analytics/CHANGELOG.md +10 -0
  29. package/corpus/templates/analytics/actions/install-dashboard-template.ts +2 -2
  30. package/corpus/templates/analytics/actions/open-traffic-dashboard.ts +1 -1
  31. package/corpus/templates/analytics/actions/update-dashboard.ts +5 -3
  32. package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +180 -144
  33. package/corpus/templates/analytics/app/components/layout/Header.tsx +2 -2
  34. package/corpus/templates/analytics/app/components/layout/Layout.tsx +7 -5
  35. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +221 -213
  36. package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +6 -3
  37. package/corpus/templates/analytics/app/lib/demo-dashboard-path.ts +1 -1
  38. package/corpus/templates/analytics/app/lib/last-opened.ts +2 -1
  39. package/corpus/templates/analytics/app/pages/Settings.tsx +4 -0
  40. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +3 -3
  41. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/DashboardFilterBar.tsx +2 -2
  42. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +101 -99
  43. package/corpus/templates/analytics/app/pages/overview/OverviewPage.tsx +1 -1
  44. package/corpus/templates/analytics/app/routes/adhoc.$id.tsx +18 -5
  45. package/corpus/templates/analytics/app/routes/catalog.tsx +1 -1
  46. package/corpus/templates/analytics/app/routes/dashboards.$id.tsx +9 -0
  47. package/corpus/templates/analytics/app/routes/traffic.tsx +1 -1
  48. package/corpus/templates/analytics/changelog/2026-06-23-the-dashboards-and-analyses-sidebar-settings-buttons-now-sta.md +6 -0
  49. package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +145 -0
  50. package/corpus/templates/analytics/server/db/index.ts +1 -1
  51. package/corpus/templates/analytics/server/lib/dashboard-catalog.ts +9 -2
  52. package/corpus/templates/analytics/server/lib/demo-dashboards.ts +1 -1
  53. package/corpus/templates/analytics/server/plugins/agent-chat.ts +2 -2
  54. package/corpus/templates/analytics/server/plugins/core-routes.ts +6 -6
  55. package/corpus/templates/assets/CHANGELOG.md +10 -0
  56. package/corpus/templates/assets/app/root.tsx +7 -1
  57. package/corpus/templates/assets/app/routes/settings.tsx +6 -0
  58. package/corpus/templates/brain/CHANGELOG.md +10 -0
  59. package/corpus/templates/brain/app/root.tsx +7 -1
  60. package/corpus/templates/brain/app/routes/settings.tsx +8 -1
  61. package/corpus/templates/calendar/CHANGELOG.md +10 -0
  62. package/corpus/templates/calendar/app/pages/Settings.tsx +4 -0
  63. package/corpus/templates/calendar/app/root.tsx +7 -1
  64. package/corpus/templates/chat/CHANGELOG.md +10 -0
  65. package/corpus/templates/chat/app/root.tsx +7 -1
  66. package/corpus/templates/clips/CHANGELOG.md +10 -0
  67. package/corpus/templates/clips/app/components/player/share-dialog.tsx +33 -7
  68. package/corpus/templates/clips/app/components/player/sign-in-prompt-dialog.tsx +8 -0
  69. package/corpus/templates/clips/app/components/player/video-player.tsx +150 -20
  70. package/corpus/templates/clips/app/components/recorder/pre-record-panel.tsx +7 -11
  71. package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +31 -0
  72. package/corpus/templates/clips/app/components/sharing/slack-share-hint.tsx +71 -0
  73. package/corpus/templates/clips/app/root.tsx +7 -1
  74. package/corpus/templates/clips/app/routes/_app.settings._index.tsx +15 -1
  75. package/corpus/templates/clips/app/routes/record.tsx +78 -5
  76. package/corpus/templates/clips/app/routes/share.$shareId.tsx +86 -5
  77. package/corpus/templates/clips/changelog/2026-06-23-clips-shared-in-slack-no-longer-show-a-could-not-start-playb.md +6 -0
  78. package/corpus/templates/clips/changelog/2026-06-23-made-the-play-button-on-shared-and-embedded-clips-scale-with.md +6 -0
  79. package/corpus/templates/clips/changelog/2026-06-23-public-clip-share-links-now-show-whether-they-ll-play-inline.md +6 -0
  80. package/corpus/templates/clips/changelog/2026-06-23-screen-camera-recordings-now-keep-the-presenter-s-face-in-th.md +6 -0
  81. package/corpus/templates/clips/desktop/src/lib/recorder.ts +20 -0
  82. package/corpus/templates/clips/desktop/src/main.tsx +3 -0
  83. package/corpus/templates/clips/desktop/src/overlays/region-record-border.tsx +76 -0
  84. package/corpus/templates/clips/desktop/src/styles.css +49 -0
  85. package/corpus/templates/clips/desktop/src-tauri/capabilities/default.json +2 -1
  86. package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +67 -1
  87. package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +2 -0
  88. package/corpus/templates/clips/desktop/src-tauri/src/util.rs +4 -1
  89. package/corpus/templates/clips/server/routes/api/video/[recordingId].get.ts +51 -1
  90. package/corpus/templates/clips/shared/share-attribution.ts +79 -0
  91. package/corpus/templates/content/CHANGELOG.md +10 -0
  92. package/corpus/templates/content/app/root.tsx +7 -1
  93. package/corpus/templates/design/CHANGELOG.md +10 -0
  94. package/corpus/templates/design/actions/generate-design.ts +4 -0
  95. package/corpus/templates/design/app/root.tsx +7 -1
  96. package/corpus/templates/design/app/routes/settings.tsx +10 -2
  97. package/corpus/templates/dispatch/CHANGELOG.md +10 -0
  98. package/corpus/templates/dispatch/app/root.tsx +7 -1
  99. package/corpus/templates/forms/CHANGELOG.md +10 -0
  100. package/corpus/templates/forms/app/root.tsx +7 -1
  101. package/corpus/templates/macros/CHANGELOG.md +10 -0
  102. package/corpus/templates/macros/app/root.tsx +7 -1
  103. package/corpus/templates/mail/CHANGELOG.md +10 -0
  104. package/corpus/templates/mail/app/components/layout/CommandPalette.tsx +3 -0
  105. package/corpus/templates/mail/app/pages/SettingsPage.tsx +27 -0
  106. package/corpus/templates/plan/.agents/skills/visual-plan/SKILL.md +31 -17
  107. package/corpus/templates/plan/.agents/skills/visual-plan/references/wireframe.md +7 -4
  108. package/corpus/templates/plan/.agents/skills/visual-recap/SKILL.md +34 -24
  109. package/corpus/templates/plan/.agents/skills/visual-recap/references/wireframe.md +7 -4
  110. package/corpus/templates/plan/AGENTS.md +4 -0
  111. package/corpus/templates/plan/CHANGELOG.md +10 -0
  112. package/corpus/templates/plan/actions/view-screen.ts +5 -0
  113. package/corpus/templates/plan/app/components/layout/Sidebar.tsx +98 -1
  114. package/corpus/templates/plan/app/pages/PlansPage.tsx +107 -7
  115. package/corpus/templates/plan/app/root.tsx +7 -1
  116. package/corpus/templates/plan/shared/share-attribution.ts +72 -0
  117. package/corpus/templates/slides/CHANGELOG.md +10 -0
  118. package/corpus/templates/slides/app/root.tsx +7 -1
  119. package/corpus/templates/videos/CHANGELOG.md +4 -151
  120. package/corpus/templates/videos/app/root.tsx +7 -1
  121. package/dist/changelog/parse.d.ts +70 -0
  122. package/dist/changelog/parse.d.ts.map +1 -0
  123. package/dist/changelog/parse.js +200 -0
  124. package/dist/changelog/parse.js.map +1 -0
  125. package/dist/cli/changelog.d.ts +4 -0
  126. package/dist/cli/changelog.d.ts.map +1 -0
  127. package/dist/cli/changelog.js +166 -0
  128. package/dist/cli/changelog.js.map +1 -0
  129. package/dist/cli/index.js +18 -0
  130. package/dist/cli/index.js.map +1 -1
  131. package/dist/cli/recap.d.ts.map +1 -1
  132. package/dist/cli/recap.js +22 -1
  133. package/dist/cli/recap.js.map +1 -1
  134. package/dist/cli/skills.d.ts +3 -3
  135. package/dist/cli/skills.d.ts.map +1 -1
  136. package/dist/cli/skills.js +72 -45
  137. package/dist/cli/skills.js.map +1 -1
  138. package/dist/client/CommandMenu.d.ts +17 -1
  139. package/dist/client/CommandMenu.d.ts.map +1 -1
  140. package/dist/client/CommandMenu.js +49 -13
  141. package/dist/client/CommandMenu.js.map +1 -1
  142. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  143. package/dist/client/agent-chat-adapter.js +43 -6
  144. package/dist/client/agent-chat-adapter.js.map +1 -1
  145. package/dist/client/analytics.d.ts +18 -0
  146. package/dist/client/analytics.d.ts.map +1 -1
  147. package/dist/client/analytics.js +177 -0
  148. package/dist/client/analytics.js.map +1 -1
  149. package/dist/client/changelog/Changelog.d.ts +47 -0
  150. package/dist/client/changelog/Changelog.d.ts.map +1 -0
  151. package/dist/client/changelog/Changelog.js +138 -0
  152. package/dist/client/changelog/Changelog.js.map +1 -0
  153. package/dist/client/index.d.ts +2 -1
  154. package/dist/client/index.d.ts.map +1 -1
  155. package/dist/client/index.js +2 -1
  156. package/dist/client/index.js.map +1 -1
  157. package/dist/client/mcp-apps/McpAppRenderer.d.ts +1 -0
  158. package/dist/client/mcp-apps/McpAppRenderer.d.ts.map +1 -1
  159. package/dist/client/mcp-apps/McpAppRenderer.js +42 -1
  160. package/dist/client/mcp-apps/McpAppRenderer.js.map +1 -1
  161. package/dist/client/settings/useBuilderStatus.d.ts +2 -0
  162. package/dist/client/settings/useBuilderStatus.d.ts.map +1 -1
  163. package/dist/client/settings/useBuilderStatus.js +58 -10
  164. package/dist/client/settings/useBuilderStatus.js.map +1 -1
  165. package/dist/mcp/build-server.js +1 -1
  166. package/dist/mcp/build-server.js.map +1 -1
  167. package/dist/mcp/embed-app.d.ts.map +1 -1
  168. package/dist/mcp/embed-app.js +112 -6
  169. package/dist/mcp/embed-app.js.map +1 -1
  170. package/dist/server/attribution.d.ts +83 -0
  171. package/dist/server/attribution.d.ts.map +1 -0
  172. package/dist/server/attribution.js +178 -0
  173. package/dist/server/attribution.js.map +1 -0
  174. package/dist/server/auth.d.ts.map +1 -1
  175. package/dist/server/auth.js +7 -0
  176. package/dist/server/auth.js.map +1 -1
  177. package/dist/server/better-auth-instance.d.ts +9 -1
  178. package/dist/server/better-auth-instance.d.ts.map +1 -1
  179. package/dist/server/better-auth-instance.js +32 -2
  180. package/dist/server/better-auth-instance.js.map +1 -1
  181. package/dist/server/builder-browser.d.ts +4 -0
  182. package/dist/server/builder-browser.d.ts.map +1 -1
  183. package/dist/server/builder-browser.js +20 -1
  184. package/dist/server/builder-browser.js.map +1 -1
  185. package/dist/server/core-routes-plugin.d.ts +25 -0
  186. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  187. package/dist/server/core-routes-plugin.js +38 -0
  188. package/dist/server/core-routes-plugin.js.map +1 -1
  189. package/dist/server/google-oauth.d.ts.map +1 -1
  190. package/dist/server/google-oauth.js +16 -2
  191. package/dist/server/google-oauth.js.map +1 -1
  192. package/dist/shared/mcp-embed-headers.js +1 -1
  193. package/dist/shared/mcp-embed-headers.js.map +1 -1
  194. package/dist/styles/agent-conversation.css +21 -0
  195. package/dist/templates/workspace-core/.agents/skills/changelog/SKILL.md +111 -0
  196. package/dist/templates/workspace-core/.agents/skills/tracking/SKILL.md +46 -14
  197. package/package.json +1 -1
  198. package/src/templates/workspace-core/.agents/skills/changelog/SKILL.md +111 -0
  199. package/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +46 -14
  200. /package/corpus/templates/analytics/app/routes/{dashboards.tsx → dashboards._index.tsx} +0 -0
@@ -36,8 +36,9 @@ In local-files mode:
36
36
  `npx @agent-native/core@latest plan blocks --out plan-blocks.md` when the Plan
37
37
  MCP connector is not registered; it calls the public no-auth
38
38
  `get-plan-blocks` route and sends no recap content. If network access is
39
- unavailable, use the bundled references and validate with
40
- `plan local check` / `plan local serve`. For `checklist` and `question-form`,
39
+ unavailable, use the bundled references and validate the MDX with
40
+ `plan local check`; do not run `plan local serve` unless the hosted Plan UI is
41
+ reachable or a local Plan app is already running. For `checklist` and `question-form`,
41
42
  copy the catalog examples verbatim: checklist items need `id` and `label`;
42
43
  question-form questions need `id`, `title`, and `mode`; and each option needs
43
44
  `id` and `label`. `plan local check` validates these required fields against
@@ -47,21 +48,24 @@ In local-files mode:
47
48
  folder such as `.agent-native/plans/<slug>/` or `/tmp/agent-native-plans/<slug>/`
48
49
  when it should not be checked in. The folder contains `plan.mdx`, optional
49
50
  `canvas.mdx`, optional `prototype.mdx`, and optional `.plan-state.json`. Set
50
- `kind: "recap"` and `localOnly: true` in frontmatter/state when authoring
51
- the source.
52
- - Run `npx @agent-native/core@latest plan local check --dir plans/<slug>`
53
- before serving, then run
54
- `npx @agent-native/core@latest plan local serve --dir plans/<slug> --kind recap --open`.
55
- Report the returned local bridge URL from stdout or `plans/<slug>/.plan-url`.
51
+ `kind: "recap"` and `localOnly: true` in frontmatter/state when authoring the
52
+ source. Use that exact chosen folder as `<plan-dir>` in every local CLI command
53
+ below.
54
+ - Run `npx @agent-native/core@latest plan local check --dir <plan-dir>` before
55
+ any preview. When the hosted Plan UI is reachable, run
56
+ `npx @agent-native/core@latest plan local serve --dir <plan-dir> --kind recap --open`.
57
+ Report the returned local bridge URL from stdout or `<plan-dir>/.plan-url`.
56
58
  Treat `.plan-url` as a local token file and do not commit it. The URL opens
57
59
  the hosted Plan UI but reads from the localhost bridge on this machine, so it
58
60
  is not shareable across machines. On macOS, `--open` prefers Chromium browsers;
59
61
  if Safari opens, switch to Chrome/Chromium because Safari can block the hosted
60
62
  HTTPS page from fetching the HTTP localhost bridge. If the Plan app itself is
61
63
  running locally with the same `PLAN_LOCAL_DIR`, the `/local-plans/<slug>` route
62
- is also valid.
64
+ is also valid. In a truly offline environment, hand off the local `<plan-dir>`
65
+ path after `plan local check` and note that interactive preview requires either
66
+ network access to the hosted Plan UI or a running local Plan app.
63
67
  - For headless verification, run
64
- `npx @agent-native/core@latest plan local verify --dir plans/<slug> --kind recap`.
68
+ `npx @agent-native/core@latest plan local verify --dir <plan-dir> --kind recap`.
65
69
  It starts the bridge, checks the private-network preflight and JSON payload,
66
70
  prints diagnostics, and exits. If the browser hangs on "Loading plan", fetch
67
71
  the `bridgeUrl` from the verify/serve JSON to read the concrete validation
@@ -72,7 +76,9 @@ In local-files mode:
72
76
  `set-resource-visibility`, or any hosted Plan tool for that recap except the
73
77
  schema-only block catalog lookup above.
74
78
  - Treat review feedback as file or chat feedback: update the MDX files directly,
75
- rerun the local bridge command, and summarize the new local bridge URL.
79
+ rerun `plan local check`, and rerun `serve` or `verify` only when that preview
80
+ path is available. Summarize the new local URL when one exists; otherwise
81
+ summarize the checked local folder path.
76
82
  Hosted comments, sharing, screenshots, usage attachment, and PR sticky comment
77
83
  publishing are unavailable until the user explicitly opts into publishing.
78
84
 
@@ -288,10 +294,10 @@ and re-import before reporting the link. A text-match screenshot is not enough;
288
294
  visually inspect the captured image. When no browser is available (for example
289
295
  a headless CI agent), state that in the recap handoff instead.
290
296
 
291
- ## Top Canvas Recaps — read `../visual-plans/references/canvas.md`
297
+ ## Top Canvas Recaps — read `../visual-plan/references/canvas.md`
292
298
 
293
299
  When a recap includes a top canvas, storyboard, or flow view, READ
294
- `../visual-plans/references/canvas.md` before authoring `canvas.mdx`. Recap
300
+ `../visual-plan/references/canvas.md` before authoring `canvas.mdx`. Recap
295
301
  canvas artboards must use the same HTML wireframe path as good document-body
296
302
  wireframes: `<Screen surface="..." html={...} />` with a semantic HTML fragment.
297
303
  Do not author fresh kit-tree children such as `<FrameScreen>`, `<Card>`,
@@ -305,8 +311,8 @@ assume it used the legacy kit path and replace it with an HTML screen.
305
311
 
306
312
  In local-files privacy mode, run `plan local check` first, then report the local
307
313
  bridge URL from
308
- `npx @agent-native/core@latest plan local serve --dir plans/<slug> --kind recap --open`
309
- or from `plans/<slug>/.plan-url`. It opens the hosted Plan UI but reads from the
314
+ `npx @agent-native/core@latest plan local serve --dir <plan-dir> --kind recap --open`
315
+ or from `<plan-dir>/.plan-url`. It opens the hosted Plan UI but reads from the
310
316
  localhost bridge on this machine, so it is not shareable across machines. If the
311
317
  Plan app itself is running locally with the same `PLAN_LOCAL_DIR`, the
312
318
  `/local-plans/<slug>` route is also valid. Do not invent a hosted database URL
@@ -471,7 +477,8 @@ installed as plain text and no MCP tools are registered after discovery, run
471
477
  `npx @agent-native/core@latest plan blocks --out plan-blocks.md` and read that
472
478
  file first. The CLI command calls the public no-auth `get-plan-blocks` route and
473
479
  sends no plan/recap content. If network access is unavailable, use the bundled
474
- references and validate with `plan local check` / `plan local serve`.
480
+ references and validate with `plan local check`; run `plan local serve` only
481
+ when the hosted Plan UI is reachable or a local Plan app is already running.
475
482
 
476
483
  The catalog returns the authoritative, always-current block vocabulary generated
477
484
  live from the app's own block registry — the same config the renderer and MDX
@@ -579,14 +586,17 @@ inferred (not extracted) as inferred in prose.
579
586
 
580
587
  ## Bidirectional Loop
581
588
 
582
- Because a recap is a real, editable plan, the same review loop as forward plans
583
- applies: a reviewer can annotate any block, and the coding agent reads
584
- `get-plan-feedback` to drive fixes back into the code — annotation → agent →
585
- diff, the same close-the-loop flow forward plans use. After a reviewer annotates
586
- a block, call `get-plan-feedback` to read the structured feedback, then either
587
- update the recap with `create-visual-recap` (passing the existing `planId` to
588
- replace it in place) or apply targeted changes with `update-visual-plan`. The
589
- loop is live and wired. The one thing not yet automatic is PR-comment-triggered
589
+ In hosted mode, because a recap is a real, editable plan, the same review loop
590
+ as forward plans applies: a reviewer can annotate any block, and the coding
591
+ agent reads `get-plan-feedback` to drive fixes back into the code — annotation →
592
+ agent → diff, the same close-the-loop flow forward plans use. After a reviewer
593
+ annotates a block, call `get-plan-feedback` to read the structured feedback,
594
+ then either update the recap with `create-visual-recap` (passing the existing
595
+ `planId` to replace it in place) or apply targeted changes with
596
+ `update-visual-plan`. The loop is live and wired. In local-files privacy mode,
597
+ do not call those hosted tools; read review notes from chat or local files, edit
598
+ `<plan-dir>/*.mdx` directly, and rerun `plan local check`, `serve`, or `verify`
599
+ for `<plan-dir>`. The one thing not yet automatic is PR-comment-triggered
590
600
  re-runs: the GitHub Action creates an initial recap per PR, but it does not yet
591
601
  re-run automatically when new review feedback is posted in GitHub — that
592
602
  auto-re-run is the remaining fast-follow.
@@ -135,12 +135,15 @@ no labels or copy. The renderer drops borders, sketch, and color into the
135
135
  skeleton register automatically. Never escape to a `custom-html` document block
136
136
  to fake a loader.
137
137
 
138
- **Editing an existing mockup.** To change one element, text, or color in an
139
- existing html mockup, call `update-visual-plan`
140
- with `contentPatches: [{ op: "patch-wireframe-html", blockId, edits: [{ find,
138
+ **Editing an existing mockup.** In hosted mode, to change one element, text, or
139
+ color in an existing html mockup, do not regenerate the frame — call
140
+ `update-visual-plan` with
141
+ `contentPatches: [{ op: "patch-wireframe-html", blockId, edits: [{ find,
141
142
  replace }] }]`. Each `find` is a unique snippet of the current html (read it
142
143
  first with `get-visual-plan`); set `all: true` on an edit to replace every
143
- occurrence. The result is re-sanitized.
144
+ occurrence. The result is re-sanitized. In local-files privacy mode, do not call
145
+ hosted Plan tools; edit the local MDX source directly and rerun the local
146
+ check/serve or verify command for `<plan-dir>`.
144
147
 
145
148
  **Treat the wireframe border as part of the visible design.** Always wrap HTML
146
149
  wireframe content in a root container with real inner padding before drawing
@@ -46,6 +46,10 @@ review before code changes happen.
46
46
  resource paths for the latest code index, file tree, and captured source
47
47
  snapshots.
48
48
  - `navigate` moves the UI to the plan list or a specific visual plan.
49
+ - The sidebar brand header has a `Customize branding` popover. Treat it as a
50
+ source-code request, not plan data: local Code mode edits `templates/plan`
51
+ source directly, while hosted/live surfaces route people to Desktop or
52
+ Builder for code customization.
49
53
 
50
54
  ## Normal Planning Flow
51
55
 
@@ -0,0 +1,10 @@
1
+ # Changelog
2
+
3
+ All notable user-facing changes to Agent-Native Plan are documented here. Open it any
4
+ time from the command menu (Cmd+K → "What's new").
5
+
6
+ ## 2026-06-23
7
+
8
+ ### Added
9
+
10
+ - See what's new right inside Agent-Native Plan — a changelog now lives in the command menu (Cmd+K).
@@ -34,6 +34,11 @@ export default defineAction({
34
34
  const screen: Record<string, unknown> = {};
35
35
  if (navigation) screen.navigation = navigation;
36
36
  if (localCodebase) screen.localCodebase = localCodebase;
37
+ screen.brandingCustomization = {
38
+ surface: "sidebar brand header",
39
+ workflow:
40
+ "The Customize branding popover sends a source-code request. In local Code mode it routes to the local code agent; on hosted/live surfaces it should guide the user to Desktop or Builder for source edits.",
41
+ };
37
42
  const nav = navigation as {
38
43
  planId?: string;
39
44
  localPlanSlug?: string;
@@ -28,7 +28,11 @@ import {
28
28
  appPath,
29
29
  markAgentChatHomeHandoff,
30
30
  navigateWithAgentChatViewTransition,
31
+ PromptComposer,
32
+ sendToAgentChat,
33
+ useCodeMode,
31
34
  useChatThreads,
35
+ useSendToAgentChat,
32
36
  useSession,
33
37
  type ChatThreadSummary,
34
38
  } from "@agent-native/core/client";
@@ -44,6 +48,11 @@ import {
44
48
  DropdownMenuTrigger,
45
49
  } from "@/components/ui/dropdown-menu";
46
50
  import { Input } from "@/components/ui/input";
51
+ import {
52
+ Popover,
53
+ PopoverContent,
54
+ PopoverTrigger,
55
+ } from "@/components/ui/popover";
47
56
  import { Skeleton } from "@/components/ui/skeleton";
48
57
  import {
49
58
  Tooltip,
@@ -53,6 +62,23 @@ import {
53
62
 
54
63
  const PLAN_CHAT_STORAGE_KEY = "plans";
55
64
 
65
+ const PLAN_BRANDING_CODE_CONTEXT = [
66
+ "The user is using the Plan app branding customization popover.",
67
+ "Make source-code changes for Agent-Native Plan branding in templates/plan.",
68
+ "Inspect the current brand surfaces first: app/lib/app-config.ts, app/components/layout/Sidebar.tsx, app/root.tsx metadata/icons, public brand assets, and app/global.css theme tokens.",
69
+ "Keep runtime plan data, stored plans, recaps, comments, and generated plan content unchanged unless the user explicitly asks for those data changes.",
70
+ "Use existing Plan styling, shadcn primitives, Tabler icons, and repo patterns. Keep changes tightly scoped.",
71
+ ].join("\n");
72
+
73
+ function buildBrandingCustomizationMessage(request: string) {
74
+ return [
75
+ "Customize the Agent-Native Plan app branding.",
76
+ "",
77
+ "Request:",
78
+ request,
79
+ ].join("\n");
80
+ }
81
+
56
82
  const navItems = [
57
83
  { icon: IconMessageCircle, label: "Ask", href: "/" },
58
84
  { icon: IconClipboardCheck, label: "Plan", href: "/plans" },
@@ -521,6 +547,76 @@ function PlansSidebarSection({ collapsed }: { collapsed: boolean }) {
521
547
  );
522
548
  }
523
549
 
550
+ function BrandingCustomizePopover() {
551
+ const [open, setOpen] = useState(false);
552
+ const { isCodeMode } = useCodeMode();
553
+ const { send, isGenerating, codeRequiredDialog } = useSendToAgentChat();
554
+
555
+ function handleSubmit(text: string) {
556
+ const trimmed = text.trim();
557
+ if (!trimmed || isGenerating) return;
558
+ const message = buildBrandingCustomizationMessage(trimmed);
559
+ const payload = {
560
+ message,
561
+ context: PLAN_BRANDING_CODE_CONTEXT,
562
+ submit: true,
563
+ type: "code" as const,
564
+ newTab: true,
565
+ };
566
+ const tabId = isCodeMode ? sendToAgentChat(payload) : send(payload);
567
+ setOpen(false);
568
+ if (tabId) {
569
+ toast.success(
570
+ isCodeMode
571
+ ? "Sent branding request to the local code agent"
572
+ : "Sent branding request to the code agent",
573
+ );
574
+ }
575
+ }
576
+
577
+ return (
578
+ <>
579
+ {codeRequiredDialog}
580
+ <Popover open={open} onOpenChange={setOpen}>
581
+ <PopoverTrigger asChild>
582
+ <button
583
+ type="button"
584
+ aria-label="Customize Plan branding"
585
+ title="Customize branding"
586
+ className="flex size-7 shrink-0 items-center justify-center rounded-md text-sidebar-foreground/55 opacity-0 transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring group-hover/brand:opacity-100 group-focus-within/brand:opacity-100 data-[state=open]:opacity-100"
587
+ >
588
+ <IconEdit className="size-3.5" />
589
+ </button>
590
+ </PopoverTrigger>
591
+ <PopoverContent
592
+ side="right"
593
+ align="start"
594
+ sideOffset={8}
595
+ className="w-[calc(100vw-2rem)] max-w-[420px] rounded-xl border-border bg-card p-3 shadow-xl sm:w-[420px]"
596
+ >
597
+ <div className="mb-2 px-1">
598
+ <h3 className="text-sm font-semibold text-foreground">
599
+ Customize branding
600
+ </h3>
601
+ <p className="mt-1 text-xs text-muted-foreground">
602
+ Describe the brand changes to make across Plan.
603
+ </p>
604
+ </div>
605
+ <PromptComposer
606
+ autoFocus
607
+ disabled={isGenerating}
608
+ attachmentsEnabled={false}
609
+ showModelSelector={false}
610
+ placeholder="Use our logo, change the app name, update colors..."
611
+ draftScope="plans:customize-branding"
612
+ onSubmit={handleSubmit}
613
+ />
614
+ </PopoverContent>
615
+ </Popover>
616
+ </>
617
+ );
618
+ }
619
+
524
620
  export function Sidebar({
525
621
  collapsed = false,
526
622
  collapsible = true,
@@ -562,7 +658,7 @@ export function Sidebar({
562
658
  >
563
659
  <div
564
660
  className={cn(
565
- "flex h-12 shrink-0 items-center border-b border-border",
661
+ "group/brand flex h-12 shrink-0 items-center border-b border-border",
566
662
  collapsed ? "justify-center px-0" : "gap-2 px-3",
567
663
  )}
568
664
  >
@@ -590,6 +686,7 @@ export function Sidebar({
590
686
  </span>
591
687
  )}
592
688
  </div>
689
+ {!collapsed && <BrandingCustomizePopover />}
593
690
  </div>
594
691
 
595
692
  <nav className="flex-1 space-y-1 overflow-y-auto px-2 py-2">
@@ -68,6 +68,7 @@ import {
68
68
  useAgentEngineConfigured,
69
69
  useActionQuery,
70
70
  useSession,
71
+ track,
71
72
  emailToColor,
72
73
  emailToName,
73
74
  type AgentSidebarStateChangeDetail,
@@ -219,6 +220,11 @@ import {
219
220
  type PlanVersionDetail,
220
221
  type PlanVersionSummary,
221
222
  } from "@shared/types";
223
+ import {
224
+ PLAN_SHARE_SURFACE,
225
+ readPlanShareAttribution,
226
+ withPlanShareAttribution,
227
+ } from "@shared/share-attribution";
222
228
  import {
223
229
  diffPlanVersions,
224
230
  formatVersionDiffSummary,
@@ -3783,13 +3789,92 @@ export function PlansPage({ localPlanSlug }: { localPlanSlug?: string } = {}) {
3783
3789
  }
3784
3790
  if (!selectedId) return undefined;
3785
3791
  const base = bundle?.plan.kind === "recap" ? "recaps" : "plans";
3786
- return `${window.location.origin}${appPath(`/${base}/${selectedId}`)}`;
3792
+ const url = `${window.location.origin}${appPath(`/${base}/${selectedId}`)}`;
3793
+ // Viral attribution: tag the shared/public plan link so signups arriving
3794
+ // from it can be attributed even when `document.referrer` is empty. `via`
3795
+ // is a non-PII owner id and is only set when the current viewer is the
3796
+ // owner (the only person whose session userId is the plan owner's id).
3797
+ const ownerViaId =
3798
+ effectivePlanAccessRole === "owner" ? (session?.userId ?? null) : null;
3799
+ return withPlanShareAttribution(url, ownerViaId);
3787
3800
  }, [
3788
3801
  bundle?.plan.kind,
3802
+ effectivePlanAccessRole,
3789
3803
  localPlanMode,
3790
3804
  localPlanRepoPath,
3791
3805
  localPlanSlug,
3792
3806
  selectedId,
3807
+ session?.userId,
3808
+ ]);
3809
+
3810
+ // Viral attribution: read the `ref`/`via` the visitor arrived on (from a
3811
+ // tagged share link) so funnel events carry the same attribution the
3812
+ // framework first-touch cookie captured. Read once from the URL on mount.
3813
+ const shareAttribution = useMemo(
3814
+ () =>
3815
+ readPlanShareAttribution(
3816
+ typeof window === "undefined" ? "" : window.location.search,
3817
+ ),
3818
+ [],
3819
+ );
3820
+
3821
+ // A logged-out visitor looking at a public plan/recap is the share funnel
3822
+ // audience. Their CTAs (comment, sign in) route through `openSignIn`.
3823
+ const isLoggedOutPublicPlanView =
3824
+ !sessionLoading &&
3825
+ !session &&
3826
+ !localPlanMode &&
3827
+ Boolean(selectedId) &&
3828
+ effectivePlanVisibility === "public";
3829
+
3830
+ // share_cta_click — fire alongside (never instead of) the real navigation.
3831
+ // `track` is non-throwing, but guard anyway so analytics can never break a
3832
+ // CTA. Only fires for the logged-out public-plan funnel audience.
3833
+ const fireShareCtaClick = useCallback(
3834
+ (cta: string) => {
3835
+ if (!isLoggedOutPublicPlanView) return;
3836
+ try {
3837
+ void track("share_cta_click", {
3838
+ surface: PLAN_SHARE_SURFACE,
3839
+ plan_id: selectedId ?? "",
3840
+ cta,
3841
+ ref: shareAttribution.ref,
3842
+ via: shareAttribution.via,
3843
+ });
3844
+ } catch {
3845
+ // Never let analytics break a CTA.
3846
+ }
3847
+ },
3848
+ [
3849
+ isLoggedOutPublicPlanView,
3850
+ selectedId,
3851
+ shareAttribution.ref,
3852
+ shareAttribution.via,
3853
+ ],
3854
+ );
3855
+
3856
+ // share_view — fire once when a logged-out visitor views a public plan. The
3857
+ // ref guard prevents double-fire across re-renders / StrictMode double-invoke.
3858
+ const shareViewFiredRef = useRef(false);
3859
+ useEffect(() => {
3860
+ if (!isLoggedOutPublicPlanView) return;
3861
+ if (shareViewFiredRef.current) return;
3862
+ shareViewFiredRef.current = true;
3863
+ try {
3864
+ void track("share_view", {
3865
+ surface: PLAN_SHARE_SURFACE,
3866
+ plan_id: selectedId ?? "",
3867
+ ref: shareAttribution.ref,
3868
+ via: shareAttribution.via,
3869
+ });
3870
+ } catch {
3871
+ // Never let analytics break the page render.
3872
+ }
3873
+ }, [
3874
+ isLoggedOutPublicPlanView,
3875
+ selectedId,
3876
+ shareAttribution.ref,
3877
+ shareAttribution.via,
3793
3878
  ]);
3794
3879
 
3795
3880
  useEffect(() => {
@@ -6227,11 +6312,14 @@ export function PlansPage({ localPlanSlug }: { localPlanSlug?: string } = {}) {
6227
6312
  {!session ? (
6228
6313
  <GuestCommentCta
6229
6314
  position={inlineCommentPosition}
6230
- onSignIn={() =>
6315
+ onSignIn={() => {
6316
+ // share funnel: logged-out viewer of a public plan
6317
+ // clicking the "create account to comment" CTA.
6318
+ fireShareCtaClick("comment_signin");
6231
6319
  openSignIn(
6232
6320
  window.location.pathname + window.location.search,
6233
- )
6234
- }
6321
+ );
6322
+ }}
6235
6323
  onCancel={closeInlineComment}
6236
6324
  />
6237
6325
  ) : (
@@ -6669,9 +6757,12 @@ function PlanShareControl({
6669
6757
  effectivePublishedUrl && hostedPlanOnCurrentOrigin && effectiveHostedPlanId
6670
6758
  ? effectiveHostedPlanId
6671
6759
  : planId;
6760
+ // Viral attribution: the owner is the one publishing/managing the share here,
6761
+ // so `via` is their non-PII session userId. `localShareUrl` is already tagged
6762
+ // upstream; tag the hosted/public URL too so both paths self-attribute.
6672
6763
  const managedShareUrl =
6673
6764
  effectivePublishedUrl && hostedPlanOnCurrentOrigin
6674
- ? effectivePublishedUrl
6765
+ ? withPlanShareAttribution(effectivePublishedUrl, session?.userId ?? null)
6675
6766
  : localShareUrl;
6676
6767
 
6677
6768
  useEffect(() => {
@@ -6713,11 +6804,20 @@ function PlanShareControl({
6713
6804
  hostedPlanId: result.hostedPlanId,
6714
6805
  });
6715
6806
  setAuthPrompt(null);
6716
- copyPublishedUrl(result.hostedPlanUrl ?? result.url);
6807
+ // Tag the freshly-minted public link so signups from it are
6808
+ // attributed. The publisher is the owner, so `via` is their userId.
6809
+ copyPublishedUrl(
6810
+ withPlanShareAttribution(
6811
+ result.hostedPlanUrl ?? result.url,
6812
+ session?.userId ?? null,
6813
+ ) ??
6814
+ result.hostedPlanUrl ??
6815
+ result.url,
6816
+ );
6717
6817
  },
6718
6818
  },
6719
6819
  );
6720
- }, [copyPublishedUrl, planId, publishPlan]);
6820
+ }, [copyPublishedUrl, planId, publishPlan, session?.userId]);
6721
6821
 
6722
6822
  // Logged-in / local-dev: manage shares for the plan in this app instance.
6723
6823
  if (canManageLocalShares) {
@@ -22,6 +22,7 @@ import {
22
22
  } from "@agent-native/core/client";
23
23
  import { IconSun, IconMoon } from "@tabler/icons-react";
24
24
  import { useTheme } from "next-themes";
25
+ import changelog from "../CHANGELOG.md?raw";
25
26
  import { Toaster } from "@/components/ui/sonner";
26
27
  import { Layout as AppLayout } from "@/components/layout/Layout";
27
28
  import { TAB_ID } from "@/lib/tab-id";
@@ -106,7 +107,12 @@ function AppContent() {
106
107
  );
107
108
  return (
108
109
  <>
109
- <CommandMenu open={cmdkOpen} onOpenChange={setCmdkOpen}>
110
+ <CommandMenu
111
+ open={cmdkOpen}
112
+ onOpenChange={setCmdkOpen}
113
+ changelog={changelog}
114
+ changelogKey="plan"
115
+ >
110
116
  <CommandMenu.Group heading="Actions">
111
117
  <CommandMenu.Item onSelect={() => go("/")}>Ask Plan</CommandMenu.Item>
112
118
  <CommandMenu.Item onSelect={() => go("/plans")}>
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Viral attribution contract for shared/public Plan links.
3
+ *
4
+ * Public plan/recap URLs self-attribute so the signup funnel can be measured
5
+ * even when `document.referrer` is empty (desktop app, Slack, native clients,
6
+ * etc.). The framework captures first-touch from these params into a cookie and
7
+ * enriches the `signup` event; Plan's job is to (a) tag the share/public URLs it
8
+ * mints and (b) emit funnel events when a logged-out visitor views a public plan
9
+ * and clicks a sign-up CTA.
10
+ *
11
+ * Contract strings are centralized here so the minting side (share popover /
12
+ * copy-link) and the measuring side (public plan view) cannot drift apart. The
13
+ * framework also derives `plan_share` from public plan paths (`/p/`, `/plan/`,
14
+ * `/plans/`, `/recaps/`, `/share-plan/`) as a fallback when the param is lost.
15
+ *
16
+ * Privacy: `via` must be a non-PII stable id (the owner's user id), never an
17
+ * email. Omit `via` rather than leak PII into a public URL or event.
18
+ */
19
+
20
+ /** Fixed referral source for plan shares. */
21
+ export const PLAN_SHARE_REF = "plan_share";
22
+
23
+ /** Surface tag included on plan share funnel events. */
24
+ export const PLAN_SHARE_SURFACE = "plan";
25
+
26
+ /** Query param names that carry attribution. */
27
+ export const REF_PARAM = "ref";
28
+ export const VIA_PARAM = "via";
29
+
30
+ /**
31
+ * Append `ref=plan_share` (and `via=<ownerId>` when a non-PII owner id is known)
32
+ * to an absolute share/public plan URL, preserving any existing query params.
33
+ * Returns the input unchanged when it isn't a parseable absolute URL.
34
+ */
35
+ export function withPlanShareAttribution(
36
+ url: string | undefined,
37
+ ownerId?: string | null,
38
+ ): string | undefined {
39
+ if (!url) return url;
40
+ try {
41
+ const parsed = new URL(url);
42
+ parsed.searchParams.set(REF_PARAM, PLAN_SHARE_REF);
43
+ const owner = (ownerId ?? "").trim();
44
+ if (owner) parsed.searchParams.set(VIA_PARAM, owner);
45
+ return parsed.toString();
46
+ } catch {
47
+ return url;
48
+ }
49
+ }
50
+
51
+ export type ShareAttribution = {
52
+ ref: string | undefined;
53
+ via: string | undefined;
54
+ };
55
+
56
+ /**
57
+ * Read `ref`/`via` from a query string (e.g. `window.location.search`). Falls
58
+ * back to `ref=plan_share` so downstream attribution stays meaningful even when
59
+ * the visitor arrived via a link that lost the param. Never throws.
60
+ */
61
+ export function readPlanShareAttribution(search: string): ShareAttribution {
62
+ let ref: string | undefined;
63
+ let via: string | undefined;
64
+ try {
65
+ const params = new URLSearchParams(search ?? "");
66
+ ref = params.get(REF_PARAM) ?? undefined;
67
+ via = params.get(VIA_PARAM) ?? undefined;
68
+ } catch {
69
+ // Ignore malformed query strings — fall through to the default below.
70
+ }
71
+ return { ref: ref || PLAN_SHARE_REF, via: via || undefined };
72
+ }
@@ -0,0 +1,10 @@
1
+ # Changelog
2
+
3
+ All notable user-facing changes to Agent-Native Slides are documented here. Open it any
4
+ time from the command menu (Cmd+K → "What's new").
5
+
6
+ ## 2026-06-23
7
+
8
+ ### Added
9
+
10
+ - See what's new right inside Agent-Native Slides — a changelog now lives in the command menu (Cmd+K).
@@ -28,6 +28,7 @@ import { useQueryClient } from "@tanstack/react-query";
28
28
  import type { LinksFunction } from "react-router";
29
29
  import stylesheet from "./global.css?url";
30
30
  import { configureTracking } from "@agent-native/core/client";
31
+ import changelog from "../CHANGELOG.md?raw";
31
32
  import { getThemeInitScript } from "@agent-native/core/client";
32
33
  import { TAB_ID } from "@/lib/tab-id";
33
34
  configureTracking({
@@ -162,7 +163,12 @@ function AppContent() {
162
163
 
163
164
  return (
164
165
  <>
165
- <CommandMenu open={cmdkOpen} onOpenChange={setCmdkOpen}>
166
+ <CommandMenu
167
+ open={cmdkOpen}
168
+ onOpenChange={setCmdkOpen}
169
+ changelog={changelog}
170
+ changelogKey="slides"
171
+ >
166
172
  <CommandMenu.Group heading="Presentations">
167
173
  <CommandMenu.Item onSelect={() => {}}>Search decks</CommandMenu.Item>
168
174
  </CommandMenu.Group>