@agent-native/recap-cli 0.1.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 (49) hide show
  1. package/dist/cli.d.ts +3 -0
  2. package/dist/cli.d.ts.map +1 -0
  3. package/dist/cli.js +10 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/index.d.ts +3 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +3 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/openai-compatible-endpoint.d.ts +3 -0
  10. package/dist/openai-compatible-endpoint.d.ts.map +1 -0
  11. package/dist/openai-compatible-endpoint.js +23 -0
  12. package/dist/openai-compatible-endpoint.js.map +1 -0
  13. package/dist/plan-blocks.d.ts +19 -0
  14. package/dist/plan-blocks.d.ts.map +1 -0
  15. package/dist/plan-blocks.js +96 -0
  16. package/dist/plan-blocks.js.map +1 -0
  17. package/dist/plan-publish-store.d.ts +62 -0
  18. package/dist/plan-publish-store.d.ts.map +1 -0
  19. package/dist/plan-publish-store.js +128 -0
  20. package/dist/plan-publish-store.js.map +1 -0
  21. package/dist/pr-visual-recap-workflow.d.ts +3 -0
  22. package/dist/pr-visual-recap-workflow.d.ts.map +1 -0
  23. package/dist/pr-visual-recap-workflow.js +3 -0
  24. package/dist/pr-visual-recap-workflow.js.map +1 -0
  25. package/dist/recap.d.ts +565 -0
  26. package/dist/recap.d.ts.map +1 -0
  27. package/dist/recap.js +3877 -0
  28. package/dist/recap.js.map +1 -0
  29. package/dist/skill-content/connection.d.ts +2 -0
  30. package/dist/skill-content/connection.d.ts.map +1 -0
  31. package/dist/skill-content/connection.js +53 -0
  32. package/dist/skill-content/connection.js.map +1 -0
  33. package/dist/skill-content/local-files.d.ts +2 -0
  34. package/dist/skill-content/local-files.d.ts.map +1 -0
  35. package/dist/skill-content/local-files.js +101 -0
  36. package/dist/skill-content/local-files.js.map +1 -0
  37. package/dist/skill-content/visual-recap-skill.d.ts +2 -0
  38. package/dist/skill-content/visual-recap-skill.d.ts.map +1 -0
  39. package/dist/skill-content/visual-recap-skill.js +548 -0
  40. package/dist/skill-content/visual-recap-skill.js.map +1 -0
  41. package/dist/skill-content/wireframe.d.ts +4 -0
  42. package/dist/skill-content/wireframe.d.ts.map +1 -0
  43. package/dist/skill-content/wireframe.js +347 -0
  44. package/dist/skill-content/wireframe.js.map +1 -0
  45. package/dist/skill-content.d.ts +8 -0
  46. package/dist/skill-content.d.ts.map +1 -0
  47. package/dist/skill-content.js +11 -0
  48. package/dist/skill-content.js.map +1 -0
  49. package/package.json +50 -0
@@ -0,0 +1,548 @@
1
+ export const VISUAL_RECAP_SKILL_MD = `---
2
+ name: visual-recap
3
+ description: >-
4
+ Turn a PR, branch, commit, or git diff into an interactive visual recap with
5
+ diagrams, file maps, API/schema summaries, annotated diffs, and focused review
6
+ notes.
7
+ metadata:
8
+ visibility: exported
9
+ ---
10
+
11
+ # Visual Recap
12
+
13
+ \`/visual-recap\` creates a visual plan built **from** a diff, not toward one. It
14
+ is the reverse of forward planning: instead of describing the change you are
15
+ about to make, you describe the change that was just made, at a higher altitude
16
+ than line-by-line review. The same plan data model serves both directions —
17
+ schema, API, file, and architecture changes become the same \`data-model\`,
18
+ \`api-endpoint\`, \`file-tree\`, and \`diagram\` blocks a forward plan would use, only
19
+ now they summarize work that exists. A reviewer scans the shape of the change
20
+ before spending attention on the literal lines.
21
+
22
+ ## Publish As An Agent-Native Plan — Never Inline
23
+
24
+ The deliverable is ALWAYS a published Agent-Native Plan, created with
25
+ \`create-visual-recap\` on the Plan MCP connector — NEVER inline chat content (not
26
+ Markdown prose, an ASCII sketch, a table, a fenced "wireframe", or a "here's the
27
+ recap" summary). A recap's entire value is the hosted, interactive, annotatable
28
+ plan; an inline summary is not a degraded recap, it is the thing a recap
29
+ replaces. If the \`plan\` (or legacy \`agent-native-plans\`) tools are not visible,
30
+ discover them through the host's \`tool_search\` first; if they are still missing,
31
+ STOP and give the user the client-specific reconnect step rather than improvising
32
+ an inline recap. Before publishing, or whenever a connector or auth error
33
+ appears, READ \`references/connection.md\` in this skill directory — it is the
34
+ single source of truth for the never-inline rule, connector discovery, and the
35
+ per-client reconnect steps. Local-files privacy mode (below) is the one
36
+ exception.
37
+
38
+ ## Local-Files Privacy Mode — read \`references/local-files.md\`
39
+
40
+ When the user wants no hosted Plan database writes — no DB writes, no Plan MCP
41
+ publish, fully local/offline/private recaps, or \`AGENT_NATIVE_PLANS_MODE=local-files\`
42
+ — do not call any hosted Plan tool except the schema-only \`get-plan-blocks\`
43
+ catalog lookup. Read the diff with the local \`recap collect-diff\` / \`scan\` /
44
+ \`build-prompt --local-files\` helpers, author a local MDX folder (set
45
+ \`kind: "recap"\` and \`localOnly: true\`), and preview it with \`plan local check\`,
46
+ \`plan local serve --kind recap\`, and \`plan local verify --kind recap\`. Before
47
+ using local-files mode, READ \`references/local-files.md\` in this skill directory
48
+ — it is the single source of truth for the full contract.
49
+
50
+ ## When To Use
51
+
52
+ Build a recap when a PR or commit is large, multi-file, or touches schema, API
53
+ contracts, or architecture, and a reviewer would benefit from seeing the change
54
+ mapped to structured blocks before reading the raw diff. A GitHub Action can
55
+ generate one automatically from a PR diff; an agent can generate one on request
56
+ ("recap this PR", "show me what this branch changed"). Skip it for small,
57
+ single-file, or obvious diffs — a recap is review overhead, and a tiny change
58
+ reviews faster as plain diff.
59
+
60
+ ## Recap The Whole Work Unit
61
+
62
+ When \`/visual-recap\` is invoked in a chat thread after work has already happened,
63
+ the default scope is the whole current work unit/thread, not only the most recent
64
+ user message, tool action, or follow-up fix. Gather the thread-owned changes
65
+ across the conversation: original implementation work, later bug fixes, UI
66
+ follow-ups, tests, changesets, skill/instruction updates, generated plan/source
67
+ artifacts, and any local import/linking fixes needed to make the recap open.
68
+
69
+ Use the current diff plus conversation context to separate thread-owned changes
70
+ from unrelated dirty work that existed before the thread. Exclude unrelated
71
+ pre-existing edits. If the scope is genuinely ambiguous and cannot be inferred,
72
+ state the assumption or ask a concise question before publishing.
73
+
74
+ When updating an existing recap after feedback, revise the recap so it still
75
+ covers the whole thread/work unit plus the new correction. Do not replace a broad
76
+ recap with a narrow recap of only the latest feedback unless the user explicitly
77
+ asks for that narrower scope.
78
+
79
+ ## Keep The Recap Body Lean
80
+
81
+ Do not add boilerplate intro, disclaimer, provenance, or summary prose blocks to
82
+ the generated plan body. In particular, do not create a \`rich-text\` block just to
83
+ say the recap is an aid, that the reviewer should still review the diff, how many
84
+ files changed, or which ref/working tree generated the recap. The plan title,
85
+ brief, and \`file-tree\` (which carries the per-file change stats) already carry
86
+ that context.
87
+
88
+ Only add prose blocks when they tell the reviewer something specific about the
89
+ change that the structured blocks do not: the objective, a real compatibility
90
+ risk, an important decision visible in the diff, or a grounded review note.
91
+
92
+ ## Recaps Must Be Substantial
93
+
94
+ Lean is not the same as thin. A recap is not a single wireframe plus one
95
+ sentence — that under-serves the reviewer as much as boilerplate prose over-serves
96
+ them. Alongside the visual/structural headline (wireframes, \`data-model\`,
97
+ \`api-endpoint\`, \`diagram\`), a substantial recap also carries the implementation
98
+ evidence:
99
+
100
+ - A short surface/state inventory before authoring: list the changed routes,
101
+ components, popovers/dialogs, role/access states, empty/error states, and
102
+ shared abstractions visible in the diff. The final recap must either represent
103
+ each meaningful item with a block or intentionally omit it because it is tiny,
104
+ redundant, or not user-visible.
105
+ - A \`file-tree\` of the changed files with each entry's \`change\` flag, so the
106
+ reviewer sees the footprint of the work at a glance.
107
+ - The split \`diff\` of the KEY changed files, grouped under a \`## Key changes\`
108
+ \`rich-text\` heading in a single horizontal \`tabs\` block (the default
109
+ orientation, one file per tab), with a one-line \`summary\` and a few
110
+ \`annotations\` on each — so the reviewer can drop from the high-altitude shape
111
+ straight into the load-bearing code. Use horizontal file tabs, not a vertical
112
+ side rail, so the selected file has enough width for the side-by-side diff.
113
+
114
+ Skip the diff appendix only for a genuinely tiny change that reviews faster as
115
+ plain diff (see "When To Use"); for any change worth recapping, the file-tree and
116
+ key-change diffs belong in the plan.
117
+
118
+ ## Canonical Shape And Budgets
119
+
120
+ A strong recap follows one skeleton, top to bottom:
121
+
122
+ 1. UI-impact headline — wireframes first, when the diff changed rendered UI.
123
+ 2. Short outcome narrative (\`rich-text\`): what changed and why, 1-3 paragraphs.
124
+ 3. \`data-model\` / \`api-endpoint\` blocks for schema and contract changes.
125
+ 4. \`file-tree\` of the changed files with \`change\` flags.
126
+ 5. \`## Key changes\` — one horizontal \`tabs\` block of \`diff\` / \`annotated-code\`.
127
+
128
+ Budgets that keep the recap reviewable:
129
+
130
+ - 3-8 key-change tabs. Fewer than 3 on a large change under-serves the
131
+ reviewer; more than 8 stops being a summary.
132
+ - Keep each diff/annotated-code excerpt focused — prefer under ~150 lines per
133
+ tab; summarize or link the rest of a long file instead of dumping it.
134
+ - Title at most ~70 characters; brief 1-3 sentences.
135
+
136
+ **GOOD.** A 25-file auth change: Before/After wireframes of the login surface,
137
+ a two-paragraph narrative, a diff-aware \`data-model\` of the sessions table, an
138
+ \`api-endpoint\` for the new refresh route, a \`file-tree\` with change flags, and
139
+ \`## Key changes\` with five focused tabs, each with a one-line \`summary\` and a
140
+ few annotations on the load-bearing hunks.
141
+
142
+ **BAD.** One giant unsegmented diff dump with no summaries or annotations; or a
143
+ sparse three-block recap of a 40-file change (one wireframe, one sentence, one
144
+ file list) that forces the reviewer back into the raw diff anyway.
145
+
146
+ ## UI Impact Needs Wireframes
147
+
148
+ When the diff changes rendered UI, layout, density, visual state, interaction
149
+ affordances, navigation, controls, menus, dialogs, or design tokens, the recap
150
+ MUST include one or more wireframes. Prose and file diffs are not a substitute
151
+ for showing what changed visually.
152
+
153
+ Before choosing wireframes, make a UI coverage pass from the diff:
154
+
155
+ - Identify the entry surface where the change appears, such as a page header,
156
+ list row, toolbar, route shell, or menu trigger.
157
+ - Identify the interaction surface that opens or changes, such as a popover,
158
+ dialog, tab, sheet, dropdown, inline editor, or toast.
159
+ - Identify the resulting destination or persistent state, such as a public page,
160
+ read-only view, empty state, error state, loading state, permission-denied
161
+ state, or saved/shared state.
162
+ - Identify access or role variants when permissions change. Owner/admin/editor
163
+ versus viewer/non-manager differences are visual behavior and need a compact
164
+ matrix, paired wireframes, or clearly labeled state sequence.
165
+
166
+ For UI-heavy PRs, a single before/after of the entry surface is not enough.
167
+ Show the changed entry point, the main changed interaction surface, and the
168
+ resulting/destination state. Add more states when the diff adds tabs, role-based
169
+ controls, public/private visibility, invite/manage flows, destructive controls,
170
+ or empty/error branches.
171
+
172
+ Choose the smallest visual surface that makes the review clear:
173
+
174
+ - Use a \`Before\` / \`After\` wireframe pair when the reviewer benefits from direct
175
+ comparison, such as a removed or added control, a changed state, layout
176
+ density, ordering, navigation, or a visible component replacement.
177
+ \`references/wireframe.md\` owns how to lay that pair out (columns vs.
178
+ vertical stack by geometry).
179
+ - Use an after-only wireframe when the change is purely additive or the "before"
180
+ state would only show absence without adding review value.
181
+ - Use more than two wireframes when the UI change is flow-dependent, responsive,
182
+ or stateful; show the meaningful states in order instead of forcing a single
183
+ before/after pair.
184
+ - For tiny surfaces like menus, popovers, dialogs, toasts, or panels, use the
185
+ matching \`surface\` (\`popover\`, \`panel\`, etc.) and show the focused sub-surface.
186
+ Do not redraw a full page unless placement in the page is itself part of the
187
+ change.
188
+
189
+ Ground each wireframe in the changed UI behavior, component names, file paths,
190
+ and diff-visible labels/states. If exact pixels are inferred rather than
191
+ captured, say so in the wireframe caption or a concise annotation. For
192
+ local/manual recaps, import or update the plan source that holds the wireframes
193
+ so the rendered recap opens with the UI visual available.
194
+
195
+ ## Wireframe Quality — read \`references/wireframe.md\`
196
+
197
+ UI recap/plan wireframes must meet a strict quality bar — full-width chrome,
198
+ pinned bottom bars, real product content, before/after comparability, the right
199
+ \`surface\` preset, \`--wf-*\` tokens instead of hex, and no \`<html>\`/\`<style>\`/font
200
+ tags. Before authoring ANY wireframe / \`<Screen>\` / \`WireframeBlock\`, READ
201
+ \`references/wireframe.md\` in this skill directory — it is the single source of
202
+ truth for HTML wireframe quality, shared word for word with \`/visual-plan\`
203
+ and \`/visual-recap\`. Do not author wireframes from memory.
204
+
205
+ Use the standard \`WireframeBlock\` / \`<Screen>\` format so the Plan viewer owns the
206
+ surface frame, theme, and sketchy/clean toggle. HTML wireframes are appropriate
207
+ when placement precision matters, especially popovers, menus, dialogs, and dense
208
+ forms. For HTML
209
+ wireframes, keep \`renderMode\` unset or \`wireframe\` unless a design-only editable
210
+ mockup is explicitly required, because \`renderMode="design"\` disables the
211
+ sketchy rough overlay.
212
+
213
+ When a browser tool is available, render a UI-impact recap in the Plan viewer
214
+ and visually inspect it at the current theme before sharing. If any label,
215
+ annotation, toolbar, or wireframe content overlaps another element, fix the MDX
216
+ and re-import before reporting the link. A text-match screenshot is not enough;
217
+ visually inspect the captured image. When no browser is available (for example
218
+ a headless CI agent), state that in the recap handoff instead.
219
+
220
+ ## Top Canvas Recaps — read \`../visual-plan/references/canvas.md\`
221
+
222
+ When a recap includes a top canvas, storyboard, or flow view, READ
223
+ \`../visual-plan/references/canvas.md\` before authoring \`canvas.mdx\`. Recap
224
+ canvas artboards must use the same HTML wireframe path as good document-body
225
+ wireframes: \`<Screen surface="..." html={...} />\` with a semantic HTML fragment.
226
+ Do not author fresh kit-tree children such as \`<FrameScreen>\`, \`<Card>\`,
227
+ \`<Row>\`, \`<Title>\`, or \`<Btn>\` inside canvas \`<Screen>\` tags. Those components
228
+ are legacy compatibility markup for old plans; in new canvas storyboards they
229
+ can produce cramped or overlapping layouts even when the inline body wireframe
230
+ looks good. If a canvas mockup looks worse than the same screen below the fold,
231
+ assume it used the legacy kit path and replace it with an HTML screen.
232
+
233
+ ## Open And Report The Recap
234
+
235
+ In local-files privacy mode, run \`plan local check\` first, then report the local
236
+ bridge URL from
237
+ \`npx @agent-native/core@latest plan local serve --dir <plan-dir> --kind recap --open\`
238
+ or from \`<plan-dir>/.plan-url\`. It opens the hosted Plan UI but reads from the
239
+ localhost bridge on this machine, so it is not shareable across machines. If the
240
+ Plan app itself is running locally with the same \`PLAN_LOCAL_DIR\`, the
241
+ \`/local-plans/<slug>\` route is also valid. Do not invent a hosted database URL
242
+ and do not publish just to get an absolute Plan link.
243
+
244
+ After creating the recap, link the reviewer to the rendered plan with an
245
+ **absolute URL on the origin whose database actually holds the plan**. That
246
+ origin is the Plan MCP server you just created the recap through — NOT whatever
247
+ dev server you happen to know is running. The create tool returns the correct
248
+ link; report THAT. Never make the primary link a local \`plan.mdx\` file, a local
249
+ mirror folder, or a relative path such as \`/plans/<id>\`.
250
+
251
+ When the recap is posted to a PR for a private repo, the plan link is not a
252
+ public URL. Make the PR comment/handoff copy explicit: reviewers may need to
253
+ sign in to Agent-Native Plans with an account that has access to the owning
254
+ organization before the link loads. Use wording like: "Private repo recap:
255
+ sign in with access to this org if the plan does not open." Do not imply the
256
+ link is broken or public when access is gated by repo/org visibility.
257
+
258
+ A recap lives only in the database of the MCP that created it. A separately
259
+ running local dev server (e.g. \`http://localhost:8081\`) has its OWN database and
260
+ will NOT contain a recap created through the hosted MCP, so a hand-built
261
+ \`localhost\` link returns "Plan not found". This is the most common recap
262
+ mistake — do not guess an origin you have not confirmed shares the MCP's data.
263
+
264
+ Resolve the URL in this order:
265
+
266
+ 1. Use the absolute URL the create tool RETURNS — \`openLink.webUrl\`, else the
267
+ \`visualUrl\` in the returned \`plan.mdx\` frontmatter, else \`url\`/\`path\`
268
+ resolved against the MCP server's own origin (for the hosted MCP that is
269
+ \`https://plan.agent-native.com\`). This always points at the database that has
270
+ the plan.
271
+ 2. Use a \`localhost\`/dev origin ONLY when the recap was created through a Plan
272
+ MCP bound to that same origin — i.e. that MCP's url is
273
+ \`http://localhost:<port>/mcp\`. Creating through the hosted MCP
274
+ and linking to localhost is the exact mismatch that 404s.
275
+ 3. If only a plan id is available, build the MCP origin's absolute URL
276
+ (hosted: \`https://plan.agent-native.com/plans/<id>\`) and say it was inferred.
277
+
278
+ If the user wants to review on localhost but the recap was created through the
279
+ hosted MCP, say so plainly: the local dev server cannot see it. To view a recap
280
+ on localhost (e.g. to exercise un-deployed local renderer changes), they must
281
+ connect a LOCAL Plan MCP (\`http://localhost:<port>/mcp\`) and
282
+ re-create the recap through it so it lands in the local database; offer to do
283
+ that rather than handing over a localhost URL that will not resolve.
284
+
285
+ When running in Codex and the Browser/in-app side browser tools are available,
286
+ open the returned absolute recap URL there automatically after creation. Still
287
+ include the same absolute URL in the final response. Local mirror files like
288
+ \`plans/<slug>/plan.mdx\` may be mentioned only as secondary source-control
289
+ artifacts, not as the main way to open the recap.
290
+
291
+ ## Diff → Block Mapping
292
+
293
+ Map each kind of change to the block that carries it, derived mechanically from
294
+ the actual diff. The names below are the CONCEPTUAL block types, not the JSX
295
+ tags — resolve every conceptual name to its exact tag + prop schema with the
296
+ \`get-plan-blocks\` tool (see "Block reference" below) before authoring.
297
+
298
+ - **Schema / migration change** → \`data-model\` for the resulting entities,
299
+ fields, and relations. Flag what moved per field/entity with
300
+ \`change: "added" | "modified" | "removed" | "renamed"\`, and for a changed type
301
+ set \`was\` to the prior value (e.g. the old column type) — grounded in the real
302
+ migration diff. That diff-aware \`data-model\` is the headline; reach for a split
303
+ \`diff\` of the literal SQL only when the exact statement still matters, not by
304
+ default.
305
+ - **API / action / route change** → \`api-endpoint\` with the method, path,
306
+ params, request, and responses as they are after the change. Flag each changed
307
+ param/response with \`change\` (and \`was\` on a param whose type/shape changed),
308
+ and set \`change\` on the endpoint root for a wholly added or removed route. Mark
309
+ removed endpoints with \`deprecated: true\` and explain in prose.
310
+ Keep multiple API endpoints in the normal single-column document flow unless
311
+ they are an explicit before/after contract comparison.
312
+ Author each request/response example as a SINGLE valid JSON value — one
313
+ top-level object or array, parseable on its own — so it renders in the
314
+ collapsible JSON explorer. Do not put \`//\` or \`/* */\` comments, prose,
315
+ trailing commas, or two or more concatenated top-level objects inside one
316
+ example; a non-parseable body falls back to flat text and loses the explorer.
317
+ When an endpoint has several distinct message shapes (for example separate
318
+ websocket frame types, or a success body versus an error body), give each its
319
+ OWN example with its own label rather than cramming them into one body.
320
+ - **Compatibility-sensitive change** → short \`rich-text\` notes beside the
321
+ relevant \`data-model\` / \`api-endpoint\` block. Name the changed field,
322
+ endpoint, or behavior and mark whether it is breaking, risky, or non-breaking;
323
+ pair that note with a split \`diff\` for the literal lines.
324
+ - **Any meaningful code hunk** → \`diff\` with \`mode: "split"\`, carrying the real
325
+ \`before\` / \`after\` text and the \`filename\` / \`language\`. Split mode is the
326
+ default for recap code review because before/after legibility is the point;
327
+ use \`mode: "unified"\` only for a genuinely narrow standalone hunk where
328
+ side-by-side would hide the code. Give every \`diff\` a one-line \`summary\`
329
+ saying what the hunk changes and why; it renders as a description above the
330
+ code so the reviewer reads intent first. Never leave a diff unlabeled.
331
+ For the KEY changed files, attach \`annotations\` to the \`diff\` so the recap
332
+ calls out what each important hunk does — this is the headline affordance for
333
+ annotating the key files updated. Each annotation anchors to the AFTER-side
334
+ line numbers by default (set \`side: "before"\` to point at removed lines). Keep
335
+ it to a few high-signal notes per file, not one per line.
336
+ When several key files each need a substantial diff, introduce the group with a
337
+ \`rich-text\` heading block whose markdown is \`## Key changes\`, then place the
338
+ \`diff\` blocks under it in a reusable \`tabs\` block with horizontal orientation
339
+ (the default — omit \`orientation\`) so the selected file's split diff gets the
340
+ full document width. Let that heading label the section — do NOT also set a
341
+ \`title\` on the \`tabs\` block. Keep each tab label to the file path or a short
342
+ basename plus directory hint.
343
+ The renderer's wide document layout is intentionally allowlisted: \`diff\`,
344
+ \`annotated-code\`, vertical \`tabs\`, and \`tabs\` containing diff-like children
345
+ break out wider than prose. Do not put API endpoints, OpenAPI specs, data
346
+ models, JSON explorers, wireframes, question forms, or custom HTML into tabs
347
+ merely to make them wide.
348
+ If the recap ends with more than one supporting diff, that trailing diff
349
+ appendix should be one horizontal \`tabs\` block under its own \`## Key changes\`
350
+ heading, not a stack of separate \`diff\` blocks.
351
+ - **Brand-new file or a substantial added block with no meaningful "before"** →
352
+ \`annotated-code\` rather than a one-sided split \`diff\`. Carry the real new code
353
+ with its \`filename\` / \`language\` and anchor a few high-signal notes to the lines
354
+ that matter so the reviewer reads what the new code does, not code for code's
355
+ sake. Keep split \`diff\` for true before/after hunks where the removed lines
356
+ still carry meaning, and group several annotated walkthroughs in a horizontal
357
+ \`tabs\` block the same way diffs are grouped.
358
+ - **Files added / removed / renamed** → \`file-tree\` with each entry's \`change\`
359
+ flag (\`added\`, \`removed\`, \`modified\`, \`renamed\`) and a short \`note\`; attach a
360
+ \`snippet\` only when one tells the reviewer something the path does not.
361
+ - **Rendered UI / interaction change** → one or more wireframes showing the
362
+ visible UI delta before the reviewer reads code. Use \`Before\` / \`After\`
363
+ wireframes when the comparison clarifies the change; otherwise use after-only
364
+ or a short state/flow sequence. Use realistic UI surfaces: for a popover
365
+ change, show a popover with its title row, top-right actions, options/fields,
366
+ tabs, selected/disabled states, people/lists/rows, and any opened prompt/menu
367
+ anchored to the correct trigger. If a route was added, show the route body and
368
+ the unavailable/empty state when the diff implements one. If permissions
369
+ changed, show what managers can do and what viewers/non-managers see instead.
370
+ Keep the body lean: the wireframe carries the UI story, while the file tree
371
+ and \`diff\` blocks carry implementation evidence.
372
+ - **Architecture or data-flow shift** → \`diagram\` with \`data.html\` / \`data.css\`
373
+ as a two-panel before/after, layered, or swimlane layout, or \`mermaid\` for a
374
+ quick graph. Use two-dimensional layouts; do not reduce a structural change to
375
+ a left-to-right chain. Do not use \`diagram\` as a stand-in for rendered UI
376
+ controls; UI changes need \`wireframe\` blocks.
377
+ Author diagram HTML/CSS with the renderer-owned \`.diagram-*\` primitives
378
+ (\`.diagram-panel\`, \`.diagram-node\`, \`.diagram-pill\`, \`[data-rough]\`, …) and
379
+ the same \`--wf-*\` theme tokens \`references/wireframe.md\` defines — never
380
+ \`font-family\`, hex, rgb/hsl literals, or one-off dark/light palettes. Choose
381
+ the outer \`frame\` intentionally: recap diagrams usually benefit from
382
+ \`frame: "show"\` when they stand alone, but use \`frame: "hide"\` when columns,
383
+ tabs, a card, or the diagram's own panels already provide the boundary.
384
+ - **Outcome-first narrative** → \`rich-text\` for the "what changed and why" prose:
385
+ the objective the diff served, the key decisions visible in it, and the risks a
386
+ reviewer should weigh. This is the only place the model writes freely.
387
+
388
+ ## Block reference — call \`get-plan-blocks\`, do not memorize tags
389
+
390
+ The conceptual block names above (\`api-endpoint\`, \`data-model\`, \`json-explorer\`,
391
+ \`tabs\`, …) are NOT the JSX tags you author with, and the exact tags, required
392
+ fields, and prop shapes change as the block library evolves. Do not author from
393
+ memorized tags — they drift and silently produce a wrong tag (\`ApiEndpoint\`
394
+ instead of \`Endpoint\`, \`JsonExplorer\` instead of \`Json\`, \`Tabs\` instead of
395
+ \`TabsBlock\`) that errors on import.
396
+
397
+ **Before writing any structured plan content, fetch/read the block catalog.** In
398
+ hosted or self-hosted mode, call \`get-plan-blocks\` on the Plan MCP connector
399
+ (\`plan\` or legacy \`agent-native-plans\`). If no Plan tools are visible yet in a
400
+ lazy-loading client, search/load them through the host's tool discovery surface
401
+ first (\`tool_search\` when available). In local-files mode, or when the skill was
402
+ installed as plain text and no MCP tools are registered after discovery, run
403
+ \`npx @agent-native/core@latest plan blocks --out plan-blocks.md\` and read that
404
+ file first. The CLI command calls the public no-auth \`get-plan-blocks\` route and
405
+ sends no plan/recap content. If network access is unavailable, use the bundled
406
+ references and validate with \`plan local check\`; run \`plan local serve\` only
407
+ when the hosted Plan UI is reachable or a local Plan app is already running.
408
+
409
+ The catalog returns the authoritative, always-current block vocabulary generated
410
+ live from the app's own block registry — the same config the renderer and MDX
411
+ round-trip use — so it can never be stale even if this SKILL.md is an old
412
+ installed copy:
413
+
414
+ - \`get-plan-blocks\` (default \`format: "reference"\`) → a compact table of every
415
+ block's runtime \`type\`, exact MDX \`<Tag>\`, placement, and key data fields.
416
+ This is your map from each conceptual name above to its real tag and props.
417
+ - \`get-plan-blocks\` with \`format: "schema"\` → the full per-block JSON Schema
418
+ plus a worked example for each block, when you need exact field types,
419
+ enums, or nesting (e.g. \`Diff.annotations\`, \`Endpoint.params[].in\`,
420
+ \`DataModel.entities[].fields[]\`).
421
+
422
+ Author the recap source against the tags and schemas that call returns. The
423
+ complete set of valid block-level tags is whatever \`get-plan-blocks\` lists;
424
+ any other capitalized tag at the block level is rejected on import with an
425
+ "Unknown plan block" / "did you mean" error. Lowercase HTML tags inside
426
+ \`rich-text\`/markdown prose (\`<div>\`, \`<span>\`, \`<code>\`, \`<br>\`, …) are always
427
+ fine — only capitalized component-style block tags are validated.
428
+
429
+ A few recap-specific authoring rules the registry table cannot encode:
430
+
431
+ - Every structured block takes a REQUIRED \`id\` (unique across the whole plan)
432
+ plus the shared optional \`summary\` / \`editable\` envelope. Ordinary top-level
433
+ Markdown prose imports as rich-text automatically; use \`<RichText id="...">\`
434
+ only when prose needs explicit metadata or a preserved referenced block id.
435
+ - Every capitalized block component must be self-closing (\`<Diagram ... />\`) or
436
+ explicitly closed around children (\`<RichText ...>...</RichText>\`). Never
437
+ leave a bare opening tag like \`<RichText ...>\` in a paragraph; MDX treats it
438
+ as unclosed JSX and import fails before the recap can render.
439
+ - Code-bearing blocks (\`Code\`, \`AnnotatedCode\`, and \`Diff\`) are
440
+ whitespace-sensitive. Prefer the exact MDX form from the \`get-plan-blocks\`
441
+ examples / source exporter, where multiline code is encoded as JSON string
442
+ attributes such as \`code={"const x =\\n y"}\`. Static template literals are
443
+ accepted only when they are static strings with no \`\${...}\` interpolation.
444
+ - \`Endpoint\`: prose \`description\` is the MDX **children** (body between the
445
+ tags), not an attribute; for a WebSocket upgrade use \`method="GET"\`. Each
446
+ request/response \`example\` is a JSON **string** (the renderer parses it into
447
+ the JSON explorer), so keep it a single parseable JSON value.
448
+ - \`TabsBlock\`: the whole \`tabs\` array (including nested child blocks) is ONE
449
+ JSON \`tabs={[…]}\` prop — there is NO nested \`<Tab>\` element.
450
+ - \`WireframeBlock\`: its body is a single \`<Screen surface ... html=… />\` subtree
451
+ (nested MDX, not a flat prop); \`html\` must be a single-quoted string or static
452
+ template literal, never a dynamic \`html={someVar}\` expression. See
453
+ \`references/wireframe.md\` for the HTML rules.
454
+ - \`Diagram\`: the whole payload is one \`data={{ html?, css?, nodes?, edges?, … }}\`
455
+ attribute and requires either \`html\` or at least one node; \`Mermaid\` is its
456
+ own separate block (\`source\` text), not a \`Diagram\` prop.
457
+
458
+ ## Before / After Is The Headline
459
+
460
+ The recap's center of gravity is the before/after comparison. For document-body
461
+ comparisons there are two primitives, and they cover the whole need together:
462
+
463
+ - **\`columns\`** — the side-by-side container, for **structured** comparisons.
464
+ Use two columns labeled \`Before\` and \`After\`, each holding a block (commonly a
465
+ \`data-model\`, \`api-endpoint\`, or \`rich-text\`), so the reviewer reads the old
466
+ shape against the new shape in one glance. This is the right primitive for
467
+ "the schema went from X to Y" or "the endpoint contract changed like this."
468
+ Do not use \`columns\` simply to compact or group a list of API endpoints.
469
+ - **\`diff\`** — for **code**. It renders the literal removed and added lines. Use
470
+ it for the actual hunks. Use split mode by default for recap code review;
471
+ reserve \`mode: "unified"\` for genuinely narrow standalone hunks where
472
+ side-by-side would hide the code. Key-file diff groups should use horizontal
473
+ tabs so split diffs get the full document width.
474
+
475
+ For UI diffs, wireframes are the visual comparison primitive. Use before/after
476
+ wireframes when the comparison clarifies the change; use after-only or a state
477
+ sequence when that better matches the change. The visual headline must show
478
+ exact placement, realistic chrome, and adequate padding before any abstract
479
+ explanation. Do not stop at the first visible affordance when the diff adds a
480
+ flow; show the entry point, the opened surface, and the resulting state or page
481
+ so the reviewer can trace the actual user path. \`references/wireframe.md\` owns
482
+ the before/after layout choice —
483
+ the \`columns\` renderer keeps narrow surfaces side by side and auto-stacks wide
484
+ \`desktop\`/\`browser\` frames vertically; never hand-build a side-by-side
485
+ wireframe layout in \`custom-html\`. For document-body
486
+ comparisons, there is no other multi-column primitive — \`columns\` plus the
487
+ \`diff\` block are the whole comparison vocabulary. Do not hand-build side-by-side
488
+ layouts in \`custom-html\`, and do not stack two \`data-model\` blocks vertically
489
+ and call it a comparison when \`columns\` exists to put them side by side.
490
+
491
+ ## Grounding Rule
492
+
493
+ Structured blocks are **true by construction** only if they are derived from the
494
+ actual changed lines. The \`diff\`, \`data-model\`, \`api-endpoint\`, and \`file-tree\`
495
+ blocks MUST be built mechanically from the real diff — real paths, real fields,
496
+ real method/path, real before/after text — never inferred, rounded, or invented.
497
+ The model writes only the prose: the "why", the narrative, the risk read. A
498
+ confidently wrong recap is dangerous in a review context, because a reviewer who
499
+ trusts the summary may skip the very line the summary got wrong. When the diff
500
+ does not contain a fact, leave it out rather than guess; mark anything the model
501
+ inferred (not extracted) as inferred in prose.
502
+
503
+ ## Security
504
+
505
+ - **Gate visibility.** Recaps of a private repo are org/login-gated — set the
506
+ plan's visibility to the owning org or login, never auto-public. A recap can
507
+ expose unreleased schema, internal endpoints, and architecture; treat it like
508
+ the source it summarizes. Any PR comment or handoff that links to the recap
509
+ must say that private-repo recaps require signing in with access to the owning
510
+ org if the link does not load.
511
+ - **Never transcribe secrets.** A diff can contain API keys, tokens, webhook
512
+ URLs, signing secrets, \`.env\` values, or credential-looking literals. Do not
513
+ copy any of these into a \`diff\`, \`file-tree\` snippet, \`api-endpoint\`, or prose
514
+ block — redact them (\`sk-•••\`, \`<redacted>\`). This mirrors the repo's
515
+ hardcoded-secret rule: obviously fake placeholders only, never the real value,
516
+ in any block, caption, or note.
517
+
518
+ ## Bidirectional Loop
519
+
520
+ In hosted mode, because a recap is a real, editable plan, the same review loop
521
+ as forward plans applies: a reviewer can annotate any block, and the coding
522
+ agent reads \`get-plan-feedback\` to drive fixes back into the code — annotation →
523
+ agent → diff, the same close-the-loop flow forward plans use. After a reviewer
524
+ annotates a block, call \`get-plan-feedback\` to read the structured feedback,
525
+ then either update the recap with \`create-visual-recap\` (passing the existing
526
+ \`planId\` to replace it in place) or apply targeted changes with
527
+ \`update-visual-plan\`. The loop is live and wired. In local-files privacy mode,
528
+ do not call those hosted tools; read review notes from chat or local files, edit
529
+ \`<plan-dir>/*.mdx\` directly, and rerun \`plan local check\`, \`serve\`, or \`verify\`
530
+ for \`<plan-dir>\`. The one thing not yet automatic is PR-comment-triggered
531
+ re-runs: the GitHub Action creates an initial recap per PR, but it does not yet
532
+ re-run automatically when new review feedback is posted in GitHub — that
533
+ auto-re-run is the remaining fast-follow.
534
+
535
+ ## Related Skills
536
+
537
+ - **visual-plan** — the canonical command and the source of the shared Wireframe
538
+ & Canvas and Document Quality cores; a recap follows the same block discipline
539
+ in reverse.
540
+ - **comment anchors** — recap comments use the same anchor rules as forward
541
+ plans; see "Interpreting comment anchors" in the visual-plan skill for
542
+ coordinate frames, wireframe node ids, text-quote resolution, detached
543
+ threads, routing via \`resolutionTarget\`, and two-axis consumed/resolved state.
544
+ - **security** — data scoping, secret handling, and the hardcoded-secret rule the
545
+ recap's redaction and visibility gating mirror.
546
+ - **sharing** — org/login-gated visibility for the plan that holds the recap.
547
+ `;
548
+ //# sourceMappingURL=visual-recap-skill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visual-recap-skill.js","sourceRoot":"","sources":["../../src/skill-content/visual-recap-skill.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,qBAAqB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkiBpC,CAAC","sourcesContent":["export const VISUAL_RECAP_SKILL_MD = `---\nname: visual-recap\ndescription: >-\n Turn a PR, branch, commit, or git diff into an interactive visual recap with\n diagrams, file maps, API/schema summaries, annotated diffs, and focused review\n notes.\nmetadata:\n visibility: exported\n---\n\n# Visual Recap\n\n\\`/visual-recap\\` creates a visual plan built **from** a diff, not toward one. It\nis the reverse of forward planning: instead of describing the change you are\nabout to make, you describe the change that was just made, at a higher altitude\nthan line-by-line review. The same plan data model serves both directions —\nschema, API, file, and architecture changes become the same \\`data-model\\`,\n\\`api-endpoint\\`, \\`file-tree\\`, and \\`diagram\\` blocks a forward plan would use, only\nnow they summarize work that exists. A reviewer scans the shape of the change\nbefore spending attention on the literal lines.\n\n## Publish As An Agent-Native Plan — Never Inline\n\nThe deliverable is ALWAYS a published Agent-Native Plan, created with\n\\`create-visual-recap\\` on the Plan MCP connector — NEVER inline chat content (not\nMarkdown prose, an ASCII sketch, a table, a fenced \"wireframe\", or a \"here's the\nrecap\" summary). A recap's entire value is the hosted, interactive, annotatable\nplan; an inline summary is not a degraded recap, it is the thing a recap\nreplaces. If the \\`plan\\` (or legacy \\`agent-native-plans\\`) tools are not visible,\ndiscover them through the host's \\`tool_search\\` first; if they are still missing,\nSTOP and give the user the client-specific reconnect step rather than improvising\nan inline recap. Before publishing, or whenever a connector or auth error\nappears, READ \\`references/connection.md\\` in this skill directory — it is the\nsingle source of truth for the never-inline rule, connector discovery, and the\nper-client reconnect steps. Local-files privacy mode (below) is the one\nexception.\n\n## Local-Files Privacy Mode — read \\`references/local-files.md\\`\n\nWhen the user wants no hosted Plan database writes — no DB writes, no Plan MCP\npublish, fully local/offline/private recaps, or \\`AGENT_NATIVE_PLANS_MODE=local-files\\`\n— do not call any hosted Plan tool except the schema-only \\`get-plan-blocks\\`\ncatalog lookup. Read the diff with the local \\`recap collect-diff\\` / \\`scan\\` /\n\\`build-prompt --local-files\\` helpers, author a local MDX folder (set\n\\`kind: \"recap\"\\` and \\`localOnly: true\\`), and preview it with \\`plan local check\\`,\n\\`plan local serve --kind recap\\`, and \\`plan local verify --kind recap\\`. Before\nusing local-files mode, READ \\`references/local-files.md\\` in this skill directory\n— it is the single source of truth for the full contract.\n\n## When To Use\n\nBuild a recap when a PR or commit is large, multi-file, or touches schema, API\ncontracts, or architecture, and a reviewer would benefit from seeing the change\nmapped to structured blocks before reading the raw diff. A GitHub Action can\ngenerate one automatically from a PR diff; an agent can generate one on request\n(\"recap this PR\", \"show me what this branch changed\"). Skip it for small,\nsingle-file, or obvious diffs — a recap is review overhead, and a tiny change\nreviews faster as plain diff.\n\n## Recap The Whole Work Unit\n\nWhen \\`/visual-recap\\` is invoked in a chat thread after work has already happened,\nthe default scope is the whole current work unit/thread, not only the most recent\nuser message, tool action, or follow-up fix. Gather the thread-owned changes\nacross the conversation: original implementation work, later bug fixes, UI\nfollow-ups, tests, changesets, skill/instruction updates, generated plan/source\nartifacts, and any local import/linking fixes needed to make the recap open.\n\nUse the current diff plus conversation context to separate thread-owned changes\nfrom unrelated dirty work that existed before the thread. Exclude unrelated\npre-existing edits. If the scope is genuinely ambiguous and cannot be inferred,\nstate the assumption or ask a concise question before publishing.\n\nWhen updating an existing recap after feedback, revise the recap so it still\ncovers the whole thread/work unit plus the new correction. Do not replace a broad\nrecap with a narrow recap of only the latest feedback unless the user explicitly\nasks for that narrower scope.\n\n## Keep The Recap Body Lean\n\nDo not add boilerplate intro, disclaimer, provenance, or summary prose blocks to\nthe generated plan body. In particular, do not create a \\`rich-text\\` block just to\nsay the recap is an aid, that the reviewer should still review the diff, how many\nfiles changed, or which ref/working tree generated the recap. The plan title,\nbrief, and \\`file-tree\\` (which carries the per-file change stats) already carry\nthat context.\n\nOnly add prose blocks when they tell the reviewer something specific about the\nchange that the structured blocks do not: the objective, a real compatibility\nrisk, an important decision visible in the diff, or a grounded review note.\n\n## Recaps Must Be Substantial\n\nLean is not the same as thin. A recap is not a single wireframe plus one\nsentence — that under-serves the reviewer as much as boilerplate prose over-serves\nthem. Alongside the visual/structural headline (wireframes, \\`data-model\\`,\n\\`api-endpoint\\`, \\`diagram\\`), a substantial recap also carries the implementation\nevidence:\n\n- A short surface/state inventory before authoring: list the changed routes,\n components, popovers/dialogs, role/access states, empty/error states, and\n shared abstractions visible in the diff. The final recap must either represent\n each meaningful item with a block or intentionally omit it because it is tiny,\n redundant, or not user-visible.\n- A \\`file-tree\\` of the changed files with each entry's \\`change\\` flag, so the\n reviewer sees the footprint of the work at a glance.\n- The split \\`diff\\` of the KEY changed files, grouped under a \\`## Key changes\\`\n \\`rich-text\\` heading in a single horizontal \\`tabs\\` block (the default\n orientation, one file per tab), with a one-line \\`summary\\` and a few\n \\`annotations\\` on each — so the reviewer can drop from the high-altitude shape\n straight into the load-bearing code. Use horizontal file tabs, not a vertical\n side rail, so the selected file has enough width for the side-by-side diff.\n\nSkip the diff appendix only for a genuinely tiny change that reviews faster as\nplain diff (see \"When To Use\"); for any change worth recapping, the file-tree and\nkey-change diffs belong in the plan.\n\n## Canonical Shape And Budgets\n\nA strong recap follows one skeleton, top to bottom:\n\n1. UI-impact headline — wireframes first, when the diff changed rendered UI.\n2. Short outcome narrative (\\`rich-text\\`): what changed and why, 1-3 paragraphs.\n3. \\`data-model\\` / \\`api-endpoint\\` blocks for schema and contract changes.\n4. \\`file-tree\\` of the changed files with \\`change\\` flags.\n5. \\`## Key changes\\` — one horizontal \\`tabs\\` block of \\`diff\\` / \\`annotated-code\\`.\n\nBudgets that keep the recap reviewable:\n\n- 3-8 key-change tabs. Fewer than 3 on a large change under-serves the\n reviewer; more than 8 stops being a summary.\n- Keep each diff/annotated-code excerpt focused — prefer under ~150 lines per\n tab; summarize or link the rest of a long file instead of dumping it.\n- Title at most ~70 characters; brief 1-3 sentences.\n\n**GOOD.** A 25-file auth change: Before/After wireframes of the login surface,\na two-paragraph narrative, a diff-aware \\`data-model\\` of the sessions table, an\n\\`api-endpoint\\` for the new refresh route, a \\`file-tree\\` with change flags, and\n\\`## Key changes\\` with five focused tabs, each with a one-line \\`summary\\` and a\nfew annotations on the load-bearing hunks.\n\n**BAD.** One giant unsegmented diff dump with no summaries or annotations; or a\nsparse three-block recap of a 40-file change (one wireframe, one sentence, one\nfile list) that forces the reviewer back into the raw diff anyway.\n\n## UI Impact Needs Wireframes\n\nWhen the diff changes rendered UI, layout, density, visual state, interaction\naffordances, navigation, controls, menus, dialogs, or design tokens, the recap\nMUST include one or more wireframes. Prose and file diffs are not a substitute\nfor showing what changed visually.\n\nBefore choosing wireframes, make a UI coverage pass from the diff:\n\n- Identify the entry surface where the change appears, such as a page header,\n list row, toolbar, route shell, or menu trigger.\n- Identify the interaction surface that opens or changes, such as a popover,\n dialog, tab, sheet, dropdown, inline editor, or toast.\n- Identify the resulting destination or persistent state, such as a public page,\n read-only view, empty state, error state, loading state, permission-denied\n state, or saved/shared state.\n- Identify access or role variants when permissions change. Owner/admin/editor\n versus viewer/non-manager differences are visual behavior and need a compact\n matrix, paired wireframes, or clearly labeled state sequence.\n\nFor UI-heavy PRs, a single before/after of the entry surface is not enough.\nShow the changed entry point, the main changed interaction surface, and the\nresulting/destination state. Add more states when the diff adds tabs, role-based\ncontrols, public/private visibility, invite/manage flows, destructive controls,\nor empty/error branches.\n\nChoose the smallest visual surface that makes the review clear:\n\n- Use a \\`Before\\` / \\`After\\` wireframe pair when the reviewer benefits from direct\n comparison, such as a removed or added control, a changed state, layout\n density, ordering, navigation, or a visible component replacement.\n \\`references/wireframe.md\\` owns how to lay that pair out (columns vs.\n vertical stack by geometry).\n- Use an after-only wireframe when the change is purely additive or the \"before\"\n state would only show absence without adding review value.\n- Use more than two wireframes when the UI change is flow-dependent, responsive,\n or stateful; show the meaningful states in order instead of forcing a single\n before/after pair.\n- For tiny surfaces like menus, popovers, dialogs, toasts, or panels, use the\n matching \\`surface\\` (\\`popover\\`, \\`panel\\`, etc.) and show the focused sub-surface.\n Do not redraw a full page unless placement in the page is itself part of the\n change.\n\nGround each wireframe in the changed UI behavior, component names, file paths,\nand diff-visible labels/states. If exact pixels are inferred rather than\ncaptured, say so in the wireframe caption or a concise annotation. For\nlocal/manual recaps, import or update the plan source that holds the wireframes\nso the rendered recap opens with the UI visual available.\n\n## Wireframe Quality — read \\`references/wireframe.md\\`\n\nUI recap/plan wireframes must meet a strict quality bar — full-width chrome,\npinned bottom bars, real product content, before/after comparability, the right\n\\`surface\\` preset, \\`--wf-*\\` tokens instead of hex, and no \\`<html>\\`/\\`<style>\\`/font\ntags. Before authoring ANY wireframe / \\`<Screen>\\` / \\`WireframeBlock\\`, READ\n\\`references/wireframe.md\\` in this skill directory — it is the single source of\ntruth for HTML wireframe quality, shared word for word with \\`/visual-plan\\`\nand \\`/visual-recap\\`. Do not author wireframes from memory.\n\nUse the standard \\`WireframeBlock\\` / \\`<Screen>\\` format so the Plan viewer owns the\nsurface frame, theme, and sketchy/clean toggle. HTML wireframes are appropriate\nwhen placement precision matters, especially popovers, menus, dialogs, and dense\nforms. For HTML\nwireframes, keep \\`renderMode\\` unset or \\`wireframe\\` unless a design-only editable\nmockup is explicitly required, because \\`renderMode=\"design\"\\` disables the\nsketchy rough overlay.\n\nWhen a browser tool is available, render a UI-impact recap in the Plan viewer\nand visually inspect it at the current theme before sharing. If any label,\nannotation, toolbar, or wireframe content overlaps another element, fix the MDX\nand re-import before reporting the link. A text-match screenshot is not enough;\nvisually inspect the captured image. When no browser is available (for example\na headless CI agent), state that in the recap handoff instead.\n\n## Top Canvas Recaps — read \\`../visual-plan/references/canvas.md\\`\n\nWhen a recap includes a top canvas, storyboard, or flow view, READ\n\\`../visual-plan/references/canvas.md\\` before authoring \\`canvas.mdx\\`. Recap\ncanvas artboards must use the same HTML wireframe path as good document-body\nwireframes: \\`<Screen surface=\"...\" html={...} />\\` with a semantic HTML fragment.\nDo not author fresh kit-tree children such as \\`<FrameScreen>\\`, \\`<Card>\\`,\n\\`<Row>\\`, \\`<Title>\\`, or \\`<Btn>\\` inside canvas \\`<Screen>\\` tags. Those components\nare legacy compatibility markup for old plans; in new canvas storyboards they\ncan produce cramped or overlapping layouts even when the inline body wireframe\nlooks good. If a canvas mockup looks worse than the same screen below the fold,\nassume it used the legacy kit path and replace it with an HTML screen.\n\n## Open And Report The Recap\n\nIn local-files privacy mode, run \\`plan local check\\` first, then report the local\nbridge URL from\n\\`npx @agent-native/core@latest plan local serve --dir <plan-dir> --kind recap --open\\`\nor from \\`<plan-dir>/.plan-url\\`. It opens the hosted Plan UI but reads from the\nlocalhost bridge on this machine, so it is not shareable across machines. If the\nPlan app itself is running locally with the same \\`PLAN_LOCAL_DIR\\`, the\n\\`/local-plans/<slug>\\` route is also valid. Do not invent a hosted database URL\nand do not publish just to get an absolute Plan link.\n\nAfter creating the recap, link the reviewer to the rendered plan with an\n**absolute URL on the origin whose database actually holds the plan**. That\norigin is the Plan MCP server you just created the recap through — NOT whatever\ndev server you happen to know is running. The create tool returns the correct\nlink; report THAT. Never make the primary link a local \\`plan.mdx\\` file, a local\nmirror folder, or a relative path such as \\`/plans/<id>\\`.\n\nWhen the recap is posted to a PR for a private repo, the plan link is not a\npublic URL. Make the PR comment/handoff copy explicit: reviewers may need to\nsign in to Agent-Native Plans with an account that has access to the owning\norganization before the link loads. Use wording like: \"Private repo recap:\nsign in with access to this org if the plan does not open.\" Do not imply the\nlink is broken or public when access is gated by repo/org visibility.\n\nA recap lives only in the database of the MCP that created it. A separately\nrunning local dev server (e.g. \\`http://localhost:8081\\`) has its OWN database and\nwill NOT contain a recap created through the hosted MCP, so a hand-built\n\\`localhost\\` link returns \"Plan not found\". This is the most common recap\nmistake — do not guess an origin you have not confirmed shares the MCP's data.\n\nResolve the URL in this order:\n\n1. Use the absolute URL the create tool RETURNS — \\`openLink.webUrl\\`, else the\n \\`visualUrl\\` in the returned \\`plan.mdx\\` frontmatter, else \\`url\\`/\\`path\\`\n resolved against the MCP server's own origin (for the hosted MCP that is\n \\`https://plan.agent-native.com\\`). This always points at the database that has\n the plan.\n2. Use a \\`localhost\\`/dev origin ONLY when the recap was created through a Plan\n MCP bound to that same origin — i.e. that MCP's url is\n \\`http://localhost:<port>/mcp\\`. Creating through the hosted MCP\n and linking to localhost is the exact mismatch that 404s.\n3. If only a plan id is available, build the MCP origin's absolute URL\n (hosted: \\`https://plan.agent-native.com/plans/<id>\\`) and say it was inferred.\n\nIf the user wants to review on localhost but the recap was created through the\nhosted MCP, say so plainly: the local dev server cannot see it. To view a recap\non localhost (e.g. to exercise un-deployed local renderer changes), they must\nconnect a LOCAL Plan MCP (\\`http://localhost:<port>/mcp\\`) and\nre-create the recap through it so it lands in the local database; offer to do\nthat rather than handing over a localhost URL that will not resolve.\n\nWhen running in Codex and the Browser/in-app side browser tools are available,\nopen the returned absolute recap URL there automatically after creation. Still\ninclude the same absolute URL in the final response. Local mirror files like\n\\`plans/<slug>/plan.mdx\\` may be mentioned only as secondary source-control\nartifacts, not as the main way to open the recap.\n\n## Diff → Block Mapping\n\nMap each kind of change to the block that carries it, derived mechanically from\nthe actual diff. The names below are the CONCEPTUAL block types, not the JSX\ntags — resolve every conceptual name to its exact tag + prop schema with the\n\\`get-plan-blocks\\` tool (see \"Block reference\" below) before authoring.\n\n- **Schema / migration change** → \\`data-model\\` for the resulting entities,\n fields, and relations. Flag what moved per field/entity with\n \\`change: \"added\" | \"modified\" | \"removed\" | \"renamed\"\\`, and for a changed type\n set \\`was\\` to the prior value (e.g. the old column type) — grounded in the real\n migration diff. That diff-aware \\`data-model\\` is the headline; reach for a split\n \\`diff\\` of the literal SQL only when the exact statement still matters, not by\n default.\n- **API / action / route change** → \\`api-endpoint\\` with the method, path,\n params, request, and responses as they are after the change. Flag each changed\n param/response with \\`change\\` (and \\`was\\` on a param whose type/shape changed),\n and set \\`change\\` on the endpoint root for a wholly added or removed route. Mark\n removed endpoints with \\`deprecated: true\\` and explain in prose.\n Keep multiple API endpoints in the normal single-column document flow unless\n they are an explicit before/after contract comparison.\n Author each request/response example as a SINGLE valid JSON value — one\n top-level object or array, parseable on its own — so it renders in the\n collapsible JSON explorer. Do not put \\`//\\` or \\`/* */\\` comments, prose,\n trailing commas, or two or more concatenated top-level objects inside one\n example; a non-parseable body falls back to flat text and loses the explorer.\n When an endpoint has several distinct message shapes (for example separate\n websocket frame types, or a success body versus an error body), give each its\n OWN example with its own label rather than cramming them into one body.\n- **Compatibility-sensitive change** → short \\`rich-text\\` notes beside the\n relevant \\`data-model\\` / \\`api-endpoint\\` block. Name the changed field,\n endpoint, or behavior and mark whether it is breaking, risky, or non-breaking;\n pair that note with a split \\`diff\\` for the literal lines.\n- **Any meaningful code hunk** → \\`diff\\` with \\`mode: \"split\"\\`, carrying the real\n \\`before\\` / \\`after\\` text and the \\`filename\\` / \\`language\\`. Split mode is the\n default for recap code review because before/after legibility is the point;\n use \\`mode: \"unified\"\\` only for a genuinely narrow standalone hunk where\n side-by-side would hide the code. Give every \\`diff\\` a one-line \\`summary\\`\n saying what the hunk changes and why; it renders as a description above the\n code so the reviewer reads intent first. Never leave a diff unlabeled.\n For the KEY changed files, attach \\`annotations\\` to the \\`diff\\` so the recap\n calls out what each important hunk does — this is the headline affordance for\n annotating the key files updated. Each annotation anchors to the AFTER-side\n line numbers by default (set \\`side: \"before\"\\` to point at removed lines). Keep\n it to a few high-signal notes per file, not one per line.\n When several key files each need a substantial diff, introduce the group with a\n \\`rich-text\\` heading block whose markdown is \\`## Key changes\\`, then place the\n \\`diff\\` blocks under it in a reusable \\`tabs\\` block with horizontal orientation\n (the default — omit \\`orientation\\`) so the selected file's split diff gets the\n full document width. Let that heading label the section — do NOT also set a\n \\`title\\` on the \\`tabs\\` block. Keep each tab label to the file path or a short\n basename plus directory hint.\n The renderer's wide document layout is intentionally allowlisted: \\`diff\\`,\n \\`annotated-code\\`, vertical \\`tabs\\`, and \\`tabs\\` containing diff-like children\n break out wider than prose. Do not put API endpoints, OpenAPI specs, data\n models, JSON explorers, wireframes, question forms, or custom HTML into tabs\n merely to make them wide.\n If the recap ends with more than one supporting diff, that trailing diff\n appendix should be one horizontal \\`tabs\\` block under its own \\`## Key changes\\`\n heading, not a stack of separate \\`diff\\` blocks.\n- **Brand-new file or a substantial added block with no meaningful \"before\"** →\n \\`annotated-code\\` rather than a one-sided split \\`diff\\`. Carry the real new code\n with its \\`filename\\` / \\`language\\` and anchor a few high-signal notes to the lines\n that matter so the reviewer reads what the new code does, not code for code's\n sake. Keep split \\`diff\\` for true before/after hunks where the removed lines\n still carry meaning, and group several annotated walkthroughs in a horizontal\n \\`tabs\\` block the same way diffs are grouped.\n- **Files added / removed / renamed** → \\`file-tree\\` with each entry's \\`change\\`\n flag (\\`added\\`, \\`removed\\`, \\`modified\\`, \\`renamed\\`) and a short \\`note\\`; attach a\n \\`snippet\\` only when one tells the reviewer something the path does not.\n- **Rendered UI / interaction change** → one or more wireframes showing the\n visible UI delta before the reviewer reads code. Use \\`Before\\` / \\`After\\`\n wireframes when the comparison clarifies the change; otherwise use after-only\n or a short state/flow sequence. Use realistic UI surfaces: for a popover\n change, show a popover with its title row, top-right actions, options/fields,\n tabs, selected/disabled states, people/lists/rows, and any opened prompt/menu\n anchored to the correct trigger. If a route was added, show the route body and\n the unavailable/empty state when the diff implements one. If permissions\n changed, show what managers can do and what viewers/non-managers see instead.\n Keep the body lean: the wireframe carries the UI story, while the file tree\n and \\`diff\\` blocks carry implementation evidence.\n- **Architecture or data-flow shift** → \\`diagram\\` with \\`data.html\\` / \\`data.css\\`\n as a two-panel before/after, layered, or swimlane layout, or \\`mermaid\\` for a\n quick graph. Use two-dimensional layouts; do not reduce a structural change to\n a left-to-right chain. Do not use \\`diagram\\` as a stand-in for rendered UI\n controls; UI changes need \\`wireframe\\` blocks.\n Author diagram HTML/CSS with the renderer-owned \\`.diagram-*\\` primitives\n (\\`.diagram-panel\\`, \\`.diagram-node\\`, \\`.diagram-pill\\`, \\`[data-rough]\\`, …) and\n the same \\`--wf-*\\` theme tokens \\`references/wireframe.md\\` defines — never\n \\`font-family\\`, hex, rgb/hsl literals, or one-off dark/light palettes. Choose\n the outer \\`frame\\` intentionally: recap diagrams usually benefit from\n \\`frame: \"show\"\\` when they stand alone, but use \\`frame: \"hide\"\\` when columns,\n tabs, a card, or the diagram's own panels already provide the boundary.\n- **Outcome-first narrative** → \\`rich-text\\` for the \"what changed and why\" prose:\n the objective the diff served, the key decisions visible in it, and the risks a\n reviewer should weigh. This is the only place the model writes freely.\n\n## Block reference — call \\`get-plan-blocks\\`, do not memorize tags\n\nThe conceptual block names above (\\`api-endpoint\\`, \\`data-model\\`, \\`json-explorer\\`,\n\\`tabs\\`, …) are NOT the JSX tags you author with, and the exact tags, required\nfields, and prop shapes change as the block library evolves. Do not author from\nmemorized tags — they drift and silently produce a wrong tag (\\`ApiEndpoint\\`\ninstead of \\`Endpoint\\`, \\`JsonExplorer\\` instead of \\`Json\\`, \\`Tabs\\` instead of\n\\`TabsBlock\\`) that errors on import.\n\n**Before writing any structured plan content, fetch/read the block catalog.** In\nhosted or self-hosted mode, call \\`get-plan-blocks\\` on the Plan MCP connector\n(\\`plan\\` or legacy \\`agent-native-plans\\`). If no Plan tools are visible yet in a\nlazy-loading client, search/load them through the host's tool discovery surface\nfirst (\\`tool_search\\` when available). In local-files mode, or when the skill was\ninstalled as plain text and no MCP tools are registered after discovery, run\n\\`npx @agent-native/core@latest plan blocks --out plan-blocks.md\\` and read that\nfile first. The CLI command calls the public no-auth \\`get-plan-blocks\\` route and\nsends no plan/recap content. If network access is unavailable, use the bundled\nreferences and validate with \\`plan local check\\`; run \\`plan local serve\\` only\nwhen the hosted Plan UI is reachable or a local Plan app is already running.\n\nThe catalog returns the authoritative, always-current block vocabulary generated\nlive from the app's own block registry — the same config the renderer and MDX\nround-trip use — so it can never be stale even if this SKILL.md is an old\ninstalled copy:\n\n- \\`get-plan-blocks\\` (default \\`format: \"reference\"\\`) → a compact table of every\n block's runtime \\`type\\`, exact MDX \\`<Tag>\\`, placement, and key data fields.\n This is your map from each conceptual name above to its real tag and props.\n- \\`get-plan-blocks\\` with \\`format: \"schema\"\\` → the full per-block JSON Schema\n plus a worked example for each block, when you need exact field types,\n enums, or nesting (e.g. \\`Diff.annotations\\`, \\`Endpoint.params[].in\\`,\n \\`DataModel.entities[].fields[]\\`).\n\nAuthor the recap source against the tags and schemas that call returns. The\ncomplete set of valid block-level tags is whatever \\`get-plan-blocks\\` lists;\nany other capitalized tag at the block level is rejected on import with an\n\"Unknown plan block\" / \"did you mean\" error. Lowercase HTML tags inside\n\\`rich-text\\`/markdown prose (\\`<div>\\`, \\`<span>\\`, \\`<code>\\`, \\`<br>\\`, …) are always\nfine — only capitalized component-style block tags are validated.\n\nA few recap-specific authoring rules the registry table cannot encode:\n\n- Every structured block takes a REQUIRED \\`id\\` (unique across the whole plan)\n plus the shared optional \\`summary\\` / \\`editable\\` envelope. Ordinary top-level\n Markdown prose imports as rich-text automatically; use \\`<RichText id=\"...\">\\`\n only when prose needs explicit metadata or a preserved referenced block id.\n- Every capitalized block component must be self-closing (\\`<Diagram ... />\\`) or\n explicitly closed around children (\\`<RichText ...>...</RichText>\\`). Never\n leave a bare opening tag like \\`<RichText ...>\\` in a paragraph; MDX treats it\n as unclosed JSX and import fails before the recap can render.\n- Code-bearing blocks (\\`Code\\`, \\`AnnotatedCode\\`, and \\`Diff\\`) are\n whitespace-sensitive. Prefer the exact MDX form from the \\`get-plan-blocks\\`\n examples / source exporter, where multiline code is encoded as JSON string\n attributes such as \\`code={\"const x =\\\\n y\"}\\`. Static template literals are\n accepted only when they are static strings with no \\`\\${...}\\` interpolation.\n- \\`Endpoint\\`: prose \\`description\\` is the MDX **children** (body between the\n tags), not an attribute; for a WebSocket upgrade use \\`method=\"GET\"\\`. Each\n request/response \\`example\\` is a JSON **string** (the renderer parses it into\n the JSON explorer), so keep it a single parseable JSON value.\n- \\`TabsBlock\\`: the whole \\`tabs\\` array (including nested child blocks) is ONE\n JSON \\`tabs={[…]}\\` prop — there is NO nested \\`<Tab>\\` element.\n- \\`WireframeBlock\\`: its body is a single \\`<Screen surface ... html=… />\\` subtree\n (nested MDX, not a flat prop); \\`html\\` must be a single-quoted string or static\n template literal, never a dynamic \\`html={someVar}\\` expression. See\n \\`references/wireframe.md\\` for the HTML rules.\n- \\`Diagram\\`: the whole payload is one \\`data={{ html?, css?, nodes?, edges?, … }}\\`\n attribute and requires either \\`html\\` or at least one node; \\`Mermaid\\` is its\n own separate block (\\`source\\` text), not a \\`Diagram\\` prop.\n\n## Before / After Is The Headline\n\nThe recap's center of gravity is the before/after comparison. For document-body\ncomparisons there are two primitives, and they cover the whole need together:\n\n- **\\`columns\\`** — the side-by-side container, for **structured** comparisons.\n Use two columns labeled \\`Before\\` and \\`After\\`, each holding a block (commonly a\n \\`data-model\\`, \\`api-endpoint\\`, or \\`rich-text\\`), so the reviewer reads the old\n shape against the new shape in one glance. This is the right primitive for\n \"the schema went from X to Y\" or \"the endpoint contract changed like this.\"\n Do not use \\`columns\\` simply to compact or group a list of API endpoints.\n- **\\`diff\\`** — for **code**. It renders the literal removed and added lines. Use\n it for the actual hunks. Use split mode by default for recap code review;\n reserve \\`mode: \"unified\"\\` for genuinely narrow standalone hunks where\n side-by-side would hide the code. Key-file diff groups should use horizontal\n tabs so split diffs get the full document width.\n\nFor UI diffs, wireframes are the visual comparison primitive. Use before/after\nwireframes when the comparison clarifies the change; use after-only or a state\nsequence when that better matches the change. The visual headline must show\nexact placement, realistic chrome, and adequate padding before any abstract\nexplanation. Do not stop at the first visible affordance when the diff adds a\nflow; show the entry point, the opened surface, and the resulting state or page\nso the reviewer can trace the actual user path. \\`references/wireframe.md\\` owns\nthe before/after layout choice —\nthe \\`columns\\` renderer keeps narrow surfaces side by side and auto-stacks wide\n\\`desktop\\`/\\`browser\\` frames vertically; never hand-build a side-by-side\nwireframe layout in \\`custom-html\\`. For document-body\ncomparisons, there is no other multi-column primitive — \\`columns\\` plus the\n\\`diff\\` block are the whole comparison vocabulary. Do not hand-build side-by-side\nlayouts in \\`custom-html\\`, and do not stack two \\`data-model\\` blocks vertically\nand call it a comparison when \\`columns\\` exists to put them side by side.\n\n## Grounding Rule\n\nStructured blocks are **true by construction** only if they are derived from the\nactual changed lines. The \\`diff\\`, \\`data-model\\`, \\`api-endpoint\\`, and \\`file-tree\\`\nblocks MUST be built mechanically from the real diff — real paths, real fields,\nreal method/path, real before/after text — never inferred, rounded, or invented.\nThe model writes only the prose: the \"why\", the narrative, the risk read. A\nconfidently wrong recap is dangerous in a review context, because a reviewer who\ntrusts the summary may skip the very line the summary got wrong. When the diff\ndoes not contain a fact, leave it out rather than guess; mark anything the model\ninferred (not extracted) as inferred in prose.\n\n## Security\n\n- **Gate visibility.** Recaps of a private repo are org/login-gated — set the\n plan's visibility to the owning org or login, never auto-public. A recap can\n expose unreleased schema, internal endpoints, and architecture; treat it like\n the source it summarizes. Any PR comment or handoff that links to the recap\n must say that private-repo recaps require signing in with access to the owning\n org if the link does not load.\n- **Never transcribe secrets.** A diff can contain API keys, tokens, webhook\n URLs, signing secrets, \\`.env\\` values, or credential-looking literals. Do not\n copy any of these into a \\`diff\\`, \\`file-tree\\` snippet, \\`api-endpoint\\`, or prose\n block — redact them (\\`sk-•••\\`, \\`<redacted>\\`). This mirrors the repo's\n hardcoded-secret rule: obviously fake placeholders only, never the real value,\n in any block, caption, or note.\n\n## Bidirectional Loop\n\nIn hosted mode, because a recap is a real, editable plan, the same review loop\nas forward plans applies: a reviewer can annotate any block, and the coding\nagent reads \\`get-plan-feedback\\` to drive fixes back into the code — annotation →\nagent → diff, the same close-the-loop flow forward plans use. After a reviewer\nannotates a block, call \\`get-plan-feedback\\` to read the structured feedback,\nthen either update the recap with \\`create-visual-recap\\` (passing the existing\n\\`planId\\` to replace it in place) or apply targeted changes with\n\\`update-visual-plan\\`. The loop is live and wired. In local-files privacy mode,\ndo not call those hosted tools; read review notes from chat or local files, edit\n\\`<plan-dir>/*.mdx\\` directly, and rerun \\`plan local check\\`, \\`serve\\`, or \\`verify\\`\nfor \\`<plan-dir>\\`. The one thing not yet automatic is PR-comment-triggered\nre-runs: the GitHub Action creates an initial recap per PR, but it does not yet\nre-run automatically when new review feedback is posted in GitHub — that\nauto-re-run is the remaining fast-follow.\n\n## Related Skills\n\n- **visual-plan** — the canonical command and the source of the shared Wireframe\n & Canvas and Document Quality cores; a recap follows the same block discipline\n in reverse.\n- **comment anchors** — recap comments use the same anchor rules as forward\n plans; see \"Interpreting comment anchors\" in the visual-plan skill for\n coordinate frames, wireframe node ids, text-quote resolution, detached\n threads, routing via \\`resolutionTarget\\`, and two-axis consumed/resolved state.\n- **security** — data scoping, secret handling, and the hardcoded-secret rule the\n recap's redaction and visibility gating mirror.\n- **sharing** — org/login-gated visibility for the plan that holds the recap.\n`;\n"]}