konpeki 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/AGENTS.md +1 -1
  2. package/CONTRIBUTING.md +36 -0
  3. package/README.md +81 -28
  4. package/SECURITY.md +22 -0
  5. package/SETUP.md +128 -51
  6. package/composition/README.md +16 -3
  7. package/composition/compile.ts +1 -1
  8. package/composition/schema.json +9 -0
  9. package/composition/schema.ts +3 -1
  10. package/composition/types.ts +3 -1
  11. package/design/themes/README.md +25 -7
  12. package/design/themes/index.ts +15 -4
  13. package/docs/development.md +79 -11
  14. package/docs/workflow.md +11 -4
  15. package/index.html +17 -1
  16. package/package.json +10 -2
  17. package/plugin.json +22 -0
  18. package/public/og.png +0 -0
  19. package/runtime/konpeki.mjs +41 -13
  20. package/skills/konpeki/SKILL.md +186 -0
  21. package/skills/konpeki/assets/blank.json +23 -0
  22. package/skills/konpeki/scripts/ensure-runtime.mjs +69 -0
  23. package/skills/konpeki/scripts/prepare-document.mjs +40 -0
  24. package/slides/README.md +35 -132
  25. package/slides/drawing-references.md +32 -0
  26. package/slides/github-cover/PROMPT.md +21 -0
  27. package/slides/github-cover/README.md +21 -0
  28. package/slides/github-cover/author.ts +67 -0
  29. package/slides/github-cover/composition.json +595 -0
  30. package/slides/introducing-konpeki/PROMPT.md +25 -14
  31. package/slides/introducing-konpeki/README.md +32 -42
  32. package/slides/introducing-konpeki/SOURCE.md +13 -14
  33. package/slides/introducing-konpeki/author.ts +44 -42
  34. package/slides/introducing-konpeki/composition.json +135 -135
  35. package/src/app/App.tsx +149 -56
  36. package/src/components/Canvas.tsx +9 -3
  37. package/src/components/InspectorPanel.tsx +104 -67
  38. package/src/components/RevisionNotes.tsx +6 -7
  39. package/src/components/RightPanel.tsx +42 -10
  40. package/src/components/VectorOverflowWarning.tsx +35 -8
  41. package/src/components/WorkspaceChrome.tsx +125 -10
  42. package/src/components/ui.tsx +95 -1
  43. package/src/lib/storage.ts +38 -10
  44. package/src/lib/use-file-session.ts +60 -38
  45. package/src/main.tsx +3 -0
  46. package/src/styles/base.css +7 -0
  47. package/src/styles/chrome.css +188 -25
  48. package/src/styles/feedback.css +101 -49
  49. package/src/styles/left-panel.css +27 -6
  50. package/src/styles/right-panel.css +114 -30
  51. package/src/styles/shell.css +96 -33
  52. package/.agents/skills/authoring-visuals/SKILL.md +0 -93
@@ -1,54 +1,44 @@
1
1
  # Introducing Konpeki
2
2
 
3
- A six-slide English introduction for first-time users. Defaults to Plex on paper
4
- with theme-linked colors and fonts; deck appearance can switch palettes and
5
- Paper/Night without repainting vector elements. Uses the default authoring mode.
6
-
7
- 1. **Meet Konpeki** — one shared canvas for people and coding agents.
8
- 2. **A round-trip workflow** — draft, download, agent revision, open and present.
9
- 3. **Five semantic components** — Text block, Diagram, Chart, Image and Table.
10
- 4. **Keep the detail editable** — stable vector elements inside their owners.
11
- 5. **What works today** — capabilities alongside practical boundaries.
12
- 6. **Try a real brief** — setup and an example request.
3
+ A six-page introduction covering creation, shared editing, components, revision
4
+ notes, browser/file sessions and a first brief. Uses default authoring mode and
5
+ Precision Paper with theme-linked colors and fonts.
13
6
 
14
7
  ## Open and revise
15
8
 
16
- Run `pnpm dev` from the repository root and open
17
- `?example=introducing-konpeki` in the application. Select **Present** for viewing.
18
- The example preview does not autosave: use **Download** to keep changes, then
19
- **Open** the saved JSON from the ordinary canvas for browser-local autosave.
9
+ Open the [playground example](https://vcfgdev.github.io/konpeki/?example=introducing-konpeki)
10
+ and select **Present**. Edits save to a separate browser-local copy; use
11
+ **Browser → Download JSON** to keep them. **Reset example** restores the bundled
12
+ version, so download your work first. Browser storage is not a backup or agent sync.
13
+
14
+ For agent revisions, follow [setup](../../SETUP.md) and open a copy of
15
+ [composition.json](composition.json) in a file-backed preview. Notes, **Build it**
16
+ and **Copy prompt** work there, not in the standalone playground. See the
17
+ [canvas workflow](../../docs/workflow.md) for handoff details.
18
+
19
+ The JSON is the editable source: double-click text to edit it; diagrams contain
20
+ editable vector elements. [author.ts](author.ts) reconstructs the original deck:
20
21
 
21
- [composition.json](composition.json) is the authoritative editable deck. Each
22
- slide contains semantic components. Ordinary text uses native content and typography
23
- fields; diagrams and custom specimens keep editable vector elements. Double-click
24
- ordinary text to edit it directly; Content intent remains separate agent guidance.
25
- This is not a second React deck runtime or a collection of page images.
22
+ ```sh
23
+ mise exec -- node slides/introducing-konpeki/author.ts
24
+ ```
26
25
 
27
- [author.ts](author.ts) records the initial drawing instructions. Running
28
- `node slides/introducing-konpeki/author.ts` validates and regenerates the JSON;
29
- it **replaces manual canvas revisions**, so do not rerun it over revised work.
30
- See [the public brief excerpt](PROMPT.md) and [source facts / provenance](SOURCE.md).
26
+ Run from the repository root. **This overwrites canvas edits.**
27
+ [Brief](PROMPT.md) · [Sources](SOURCE.md) · [Reviewed screenshots](screenshots/)
31
28
 
32
29
  ## Review
33
30
 
34
- - `pnpm check`, `pnpm test` (91 tests), `pnpm build`, `git diff --check`: passed.
35
- - Inspected all six actual canvas renders at 1920×1080 and 1024×768, DPR2.
36
- - Browser text bounds checked after font loading: no text outside its component
37
- viewport at either size. Visible navigation exercised across all six pages.
38
- - Enlarged essential notes and clarified placeholder wording after first review.
39
- - Follow-up alignment review: removed renderer insets that displaced vector
40
- titles and body text. Added `review.mjs` to verify each authored viewport maps
41
- to its component rectangle within 0.5 screen pixels at both review sizes.
42
- Run `node slides/introducing-konpeki/review.mjs` with the dev server running
43
- and `agent-browser` installed; inspect its captures after the assertions pass.
44
- - Native-text verification: all six slides passed text/viewport checks in Plex
45
- Paper, Precision Night and Editorial Paper, at both sizes (36 states).
46
- Pass output directory, theme label and mode after the base URL to `review.mjs`.
47
- `node scripts/check-themes.mjs` exercises all eight palettes in both modes,
48
- fixed overrides, overflow warnings, linking, undo/redo, Prompt guidance and
49
- autosave/reload/presentation. Literal imported artwork is intentionally fixed.
50
- - Final reviewed presentation captures: [screenshots](screenshots/).
51
- - Chart values are illustrative; diagrams are explanatory artwork, not screenshots.
52
- - No PDF/PPTX export, native mobile or cross-application fidelity was tested.
31
+ With a dev/preview server and `agent-browser`, run from the repository root:
32
+
33
+ ```sh
34
+ mise exec -- node slides/introducing-konpeki/review.mjs <preview-url> /tmp/konpeki-intro Precision paper
35
+ ```
36
+
37
+ The script checks text bounds and vector alignment at 1920×1080 and 1024×768,
38
+ DPR2. Repeat with `Precision night` and `Editorial paper`, then inspect captures.
39
+ An optional final font ID overrides the palette's default, e.g. `Green paper plex-serif`.
40
+ These 36 states passed the original visual review, alongside validation, typecheck,
41
+ tests and build. Browser review does not verify agent-client installation,
42
+ PDF/PPTX, mobile, reduced motion, focus styling or cross-application fidelity.
53
43
 
54
44
  ![Title slide](screenshots/page-1.png)
@@ -1,20 +1,19 @@
1
1
  # Source facts and provenance
2
2
 
3
- This is a factual introduction to Konpeki, not a fictional customer case study.
3
+ Product claims come from repository documentation, not a customer case study.
4
4
 
5
5
  | Claim | Repository evidence |
6
6
  | --- | --- |
7
- | One canvas for human drafts, agent output, revision and presentation | ../../README.md; ../../AGENTS.md |
8
- | Composition JSON is authoritative; imported JSX never executes | ../../composition/README.md; ../../AUTHORING.md |
9
- | Five top-level kinds: Text block, Diagram, Chart, Image, Table | ../../composition/types.ts |
10
- | Open / Download / Present workflow; browser-local storage | ../../README.md; ../../src/lib/storage.ts |
11
- | Stable vector IDs, text/attribute edits, ordering, deletion and undo/redo | ../../README.md; ../../composition/vector.ts |
12
- | Standard component illustrations are drafts, not data or image uploads | ../../README.md |
13
- | Node 24+, pnpm; repository distribution, no Konpeki account/backend required | ../../README.md; ../../package.json |
7
+ | Covers, social graphics, charts, diagrams and presentations share one canvas | [Product](../../README.md); [authoring](../../AUTHORING.md) |
8
+ | Skill-led creation; init optional; Node.js 24+, npm, file/command access and a browser required | [User setup](../../SETUP.md) |
9
+ | Browser and agent edit the same JSON; file sessions support notes, Build it and Copy prompt | [File-backed workflow](../../docs/workflow.md#file-backed-editing-with-an-agent) |
10
+ | Text block, Diagram, Chart, Image and Table; editable vectors with stable IDs | [Contract](../../composition/README.md); [types](../../composition/types.ts) |
11
+ | Direct text, shape and layout editing with undo/redo | [Operations](../../composition/document.ts) |
12
+ | Diagram, Chart and Table defaults are structural drafts; finished artwork needs source data | [Exports](../../docs/workflow.md#documents-and-exports); [fidelity rules](../../AUTHORING.md#requirements) |
13
+ | Playground: independent local copies, JSON import/download, blank/reset, PNG and Present; no agent sync, connected AI or cloud storage | [Hosting](../../docs/development.md#development-server-and-demo-hosting); [storage](../../src/lib/storage.ts); [controls](../../src/components/WorkspaceChrome.tsx) |
14
14
 
15
- The architecture drawings, vector selection example and component specimens are
16
- original explanatory artwork for this deck, not product screenshots. The tiny
17
- chart uses explicitly labeled illustrative values, not measured product data.
18
- No third-party image assets or customer claims are used. IBM Plex Sans comes from
19
- the repository's Fontsource dependency. No PDF/PPTX or cross-application fidelity
20
- is claimed.
15
+ Drawings are original explanatory artwork, not screenshots. Chart values and
16
+ the announcement brief are illustrative, not product measurements or customer
17
+ results. No third-party images are used. Precision defaults to bundled Noto Sans;
18
+ text follows the selected font roles. See the [review scope](README.md#review)
19
+ for verification limits.
@@ -1,6 +1,7 @@
1
- // Initial authoring source. composition.json is the editable deck of record.
1
+ // Authoring source. composition.json is the editable deck of record.
2
2
  // Re-running this script replaces it; preserve canvas revisions before rebuilding.
3
3
  import { writeFile } from "node:fs/promises";
4
+ import { canonicalJSON } from "../../composition/compile.ts";
4
5
  import { createComponent } from "../../composition/document.ts";
5
6
  import { validateComposition } from "../../composition/validate.ts";
6
7
  import {
@@ -24,6 +25,7 @@ function arrow(id: string, x: number, y: number, end: number) {
24
25
  }
25
26
  function component(id: string, kind: CompositionComponent["kind"], x: number, y: number, width: number, height: number, description: string, elements: VectorElement[]): CompositionComponent {
26
27
  const base = createComponent(kind, 1);
28
+ if (base.kind === "diagram" || base.kind === "chart") base.appearance.selection = "explicit";
27
29
  return { ...base, id, slotIds: [`${id}-content`], preferredRect: { x, y, width, height }, intent: description,
28
30
  customVisual: { format: "vector", viewBox: { x: 0, y: 0, width, height }, fit: "contain", description, elements } };
29
31
  }
@@ -52,40 +54,40 @@ function heading(id: string, title: string, subtitle: string) {
52
54
  const slides: CompositionSlide[] = [];
53
55
  slides.push(slide("introduction", "Meet Konpeki", "What is Konpeki?", [
54
56
  copy("brand", 112, 140, 820, ["Konpeki"], 112, blue, 600),
55
- copy("promise", 112, 328, 960, ["A shared slide canvas", "for people and coding agents."], 56, ink, 500),
56
- copy("summary", 112, 548, 870, ["Sketch the idea. Generate the detail.", "Keep revising the same document."], 36, muted),
57
+ copy("promise", 112, 328, 960, ["Create clear visuals", "with your coding agent."], 56, ink, 500),
58
+ copy("summary", 112, 548, 870, ["Bring a brief. Get an editable result.", "Keep revising the same document."], 36, muted),
57
59
  component("shared-canvas", "diagram", 1090, 185, 700, 590, "A single editable composition contains a headline, diagram and supporting text; people and agents revise it.", [
58
60
  rect("canvas-frame", 8, 25, 670, 395),
59
- text("canvas-title", "An idea, made clear", 45, 93, 36, ink, 500),
61
+ text("canvas-title", "From brief to visual", 45, 93, 36, ink, 500),
60
62
  path("headline-rule", "M45 120H640", line, 2),
61
63
  rect("source-node", 50, 183, 160, 90, blue), rect("result-node", 310, 183, 320, 90, blue),
62
- text("source-label", "Idea", 98, 239, 28), text("result-label", "Explanation", 382, 239, 28),
64
+ text("source-label", "Brief", 98, 239, 28), text("result-label", "Editable visual", 374, 239, 28),
63
65
  arrow("connection", 228, 228, 292),
64
66
  path("body-lines", "M50 323H395M50 351H525", line, 8),
65
67
  text("document-label", "composition.json", 178, 484, 32, blue, 500),
66
68
  text("participants", "Human edits + agent revisions", 116, 548, 28, muted),
67
69
  ]),
68
- copy("intro-note", 112, 870, 1696, ["For technical explanations, product stories and decision decks."], 34),
70
+ copy("intro-note", 112, 870, 1696, ["Covers, social graphics, charts, diagrams and presentations."], 34),
69
71
  ]));
70
72
 
71
- slides.push(slide("workflow", "A round-trip workflow", "How do a person and an agent work together?", [
72
- ...heading("workflow", "A handoff that comes back to the canvas", "The agent works on the document you can keep editing."),
73
- component("roundtrip", "diagram", 112, 342, 1696, 470, "Draft on the canvas, download composition JSON, ask a coding agent to revise it, then open the returned JSON and present. Further edits repeat this loop.", [
73
+ slides.push(slide("workflow", "Create and revise together", "How do a person and an agent work together?", [
74
+ ...heading("workflow", "Start with a brief. Keep editing the result.", "In the agent-opened editor, you and your agent edit the same file."),
75
+ component("roundtrip", "diagram", 112, 342, 1696, 470, "Share a brief and materials. The agent creates a visual and opens its file-backed preview. Edit that canvas, then ask for revisions in the same conversation. The agent updates the same file; the loop returns to editing, not a new brief.", [
74
76
  ...[0, 1, 2, 3].flatMap((index) => {
75
77
  const x = index * 438;
76
78
  return [text(`number-${index}`, `0${index + 1}`, x, 48, 26, blue, 500),
77
- text(`step-${index}`, ["Draft", "Download", "Agent revises", "Open + present"][index], x, 122, 42, ink, 500),
78
- text(`detail-a-${index}`, ["Place components.", "Save the editable", "Return a completed", "Review the result."][index], x, 190, 29, muted),
79
- text(`detail-b-${index}`, ["Describe the intent.", "composition JSON.", "composition JSON.", "Make the next edit."][index], x, 234, 29, muted),
79
+ text(`step-${index}`, ["Brief", "Generate", "Edit", "Revise"][index], x, 122, 42, ink, 500),
80
+ text(`detail-a-${index}`, ["Share your materials.", "Agent creates a visual.", "Edit the open canvas.", "Ask in the same chat."][index], x, 190, 29, muted),
81
+ text(`detail-b-${index}`, ["Describe the result.", "Opens its file preview.", "Review the details.", "Agent updates that file."][index], x, 234, 29, muted),
80
82
  ...(index < 3 ? [arrow(`handoff-${index}`, x + 338, 109, x + 398)] : [])];
81
83
  }),
82
- path("revision-loop", "M1510 285V365H115V285M103 299L115 285L127 299", blue),
83
- text("loop-label", "Revisions stay in the same editable format", 490, 431, 32, blue),
84
+ path("revision-loop", "M1510 285V365H991V285M979 299L991 285L1003 299", blue),
85
+ text("loop-label", "Both edit the same composition.json", 490, 431, 32, blue),
84
86
  ]),
85
- copy("workflow-note", 112, 870, 1696, ["Use your coding agent alongside Konpeki; bring its returned JSON back to the canvas."], 34, ink),
87
+ copy("workflow-note", 112, 870, 1696, ["Prefer to sketch first? Add a component, describe its intent, then choose Build it."], 34, ink),
86
88
  ]));
87
89
 
88
- slides.push(slide("components", "Five semantic components", "What can a slide contain?", [
90
+ slides.push(slide("components", "Five semantic components", "What can a page contain?", [
89
91
  ...heading("components", "Five components. One composition.", "Each component keeps its meaning, outer geometry and editable interior."),
90
92
  component("text-specimen", "text-block", 112, 360, 296, 360, "Text block: headlines, body text, captions and footnotes.", [
91
93
  text("label", "Text block", 0, 40, 38, ink, 500), text("sample", "Aa", 0, 166, 96, blue),
@@ -111,14 +113,14 @@ slides.push(slide("components", "Five semantic components", "What can a slide co
111
113
  text("label", "Table", 0, 40, 38, ink, 500),
112
114
  text("col-a", "Stage", 0, 120, 26, ink, 500), text("col-b", "Owner", 157, 120, 26, ink, 500),
113
115
  path("rules", "M0 136H285M0 190H285M0 244H285", line, 2),
114
- text("row-a", "Draft", 0, 174, 25), text("row-a-owner", "Human", 157, 174, 25), text("row-b", "Revise", 0, 228, 25), text("row-b-owner", "Agent", 157, 228, 25),
116
+ text("row-a", "Create", 0, 174, 25), text("row-a-owner", "Agent", 157, 174, 25), text("row-b", "Review", 0, 228, 25), text("row-b-owner", "You", 157, 228, 25),
115
117
  text("detail", "Structured detail", 0, 317, 28, muted),
116
118
  ]),
117
- copy("component-note", 112, 876, 1696, ["Draft previews express intent. Agents return completed artwork as editable vectors."], 34, ink),
119
+ copy("component-note", 112, 848, 1696, ["Diagram, Chart and Table previews are structural drafts.", "Give the agent real data and sources for finished artwork."], 32, ink),
118
120
  ]));
119
121
 
120
122
  slides.push(slide("editing", "Keep the detail editable", "What remains editable after an agent finishes?", [
121
- ...heading("editing", "The detail stays editable", "Revise a label, a path or a group without replacing the whole slide."),
123
+ ...heading("editing", "Keep editing—or ask your agent", "Change text, shapes and layout directly. Undo and redo stay available."),
122
124
  component("editable-diagram", "diagram", 112, 340, 980, 475, "Explanatory illustration: a selected Review node inside its owning Diagram component. The shape keeps stable ID review-node.", [
123
125
  rect("owner", 5, 5, 965, 390), text("owner-label", "Diagram · review-flow", 35, 53, 27, muted),
124
126
  rect("draft", 55, 158, 220, 120), rect("review-node", 385, 158, 220, 120, blue), rect("present", 715, 158, 220, 120),
@@ -127,37 +129,37 @@ slides.push(slide("editing", "Keep the detail editable", "What remains editable
127
129
  ...[[380,153],[600,153],[380,273],[600,273]].map(([x,y], i) => rect(`handle-${i}`,x,y,10,10,blue)),
128
130
  text("stable-id", "Selected element: review-node", 36, 450, 32, blue),
129
131
  ]),
130
- copy("editing-actions-title", 1210, 343, 580, ["Change the part that matters"], 35, ink, 500),
131
- copy("editing-actions", 1210, 440, 580, ["Edit text and attributes.", "Reorder sibling elements.", "Delete a shape or a group.", "Undo and redo your changes."], 31, muted),
132
- copy("editing-note", 112, 885, 1696, ["Composition JSON owns the structure. Imported JSX never executes in the canvas."], 34, ink),
132
+ copy("editing-actions-title", 1210, 343, 580, ["Ask for a targeted revision"], 35, ink, 500),
133
+ copy("editing-actions", 1210, 440, 580, ["Select a component or element.", "Add a Revision note in Notes.", "Choose Build it to submit.", "Agent revises the same file."], 31, muted),
134
+ copy("editing-note", 112, 852, 1696, ["Notes and Build it are available in the agent-opened editor, not the browser playground.", "Build it cannot wake an idle agent. Use Copy prompt to resume it."], 32, ink),
133
135
  ]));
134
136
 
135
- slides.push(slide("today", "What works today", "What should a first-time user expect?", [
136
- ...heading("today", "An editable workflow, with clear boundaries", "Use the canvas for drafting, revision and presentation today."),
137
- copy("available-heading", 112, 350, 790, ["Available now"], 42, blue, 500),
138
- copy("available-1", 112, 451, 790, ["Arrange slides and semantic components.", "Open and download composition JSON."], 33),
139
- copy("available-2", 112, 605, 790, ["Revise vector text, shapes and paths.", "Present with the same canvas renderer."], 33),
140
- copy("available-3", 112, 790, 790, ["Browser-local drafts.", "No Konpeki account or backend required."], 32, ink),
141
- copy("limits-heading", 1020, 350, 788, ["Know the boundaries"], 42, ink, 500),
142
- copy("limits-1", 1020, 451, 788, ["Standard previews are placeholders.", "They do not load data or image files."], 33),
143
- copy("limits-2", 1020, 605, 788, ["Your coding agent supplies the output.", "Review its facts, layout and caveats."], 33),
144
- copy("limits-3", 1020, 790, 788, ["Desktop-first editing; storage is local.", "No PDF/PPTX fidelity claim."], 32, ink),
137
+ slides.push(slide("today", "Browser or agent editor", "What can I do here, and what needs a coding agent?", [
138
+ ...heading("today", "Try the browser. Continue with your agent.", "The same editable format, with different saving and generation paths."),
139
+ copy("available-heading", 112, 350, 790, ["Browser playground"], 42, blue, 500),
140
+ copy("available-1", 112, 451, 790, ["Edit an example or start blank.", "Import editable composition JSON."], 33),
141
+ copy("available-2", 112, 605, 790, ["Saved only in this browser.", "No connected agent or cloud sync."], 33),
142
+ copy("available-3", 112, 790, 790, ["Download JSON to keep your work.", "Export PNG or use Present."], 32, ink),
143
+ copy("limits-heading", 1020, 350, 788, ["With your coding agent"], 42, ink, 500),
144
+ copy("limits-1", 1020, 451, 788, ["The agent creates and revises visuals.", "Its preview saves to a local JSON file."], 33),
145
+ copy("limits-2", 1020, 605, 788, ["Bring downloaded JSON to your agent.", "Continue in its file-backed editor."], 33),
146
+ copy("limits-3", 1020, 790, 788, ["Playground and file copies do not sync.", "Review generated facts and visuals."], 32, ink),
145
147
  ]));
146
148
 
147
149
  slides.push(slide("start", "Try a real brief", "How do I start?", [
148
- ...heading("start", "Bring a brief. Build an editable deck.", "Start with one real explanation you need to give."),
149
- copy("setup-heading", 112, 350, 710, ["Open the project"], 40, ink, 500),
150
+ ...heading("start", "Install the skill. Bring a real brief.", "Ask for a cover, social graphic, chart, diagram or presentation."),
151
+ copy("setup-heading", 112, 350, 710, ["Install the Konpeki skill"], 40, ink, 500),
150
152
  copy("repository", 112, 435, 850, ["github.com/vcfgdev/konpeki"], 38, blue, 500),
151
- copy("commands", 112, 543, 840, ["pnpm install --frozen-lockfile", "pnpm dev"], 34),
152
- copy("requirements", 112, 696, 780, ["Node.js 24+ · pnpm", "A coding agent · a browser"], 34, ink),
153
- copy("brief-heading", 1020, 350, 788, ["Give your agent a concrete brief"], 40, ink, 500),
154
- copy("brief", 1020, 450, 788, ["“Explain this system to a new engineer.", "Show the request flow and failure path.", "Preserve the source facts and caveats.", "Return an editable composition JSON.”"], 31),
155
- copy("next-step", 1020, 708, 788, ["Open the result. Make one revision.", "Then present it."], 34, blue, 500),
156
- copy("closing", 112, 906, 1696, ["This presentation is itself an editable Konpeki composition."], 30, muted),
153
+ copy("commands", 112, 543, 840, ["Use your agent’s skill installer.", "Choose skills/konpeki in the repo."], 34),
154
+ copy("requirements", 112, 696, 780, ["Node.js 24+ · npm", "An agent with file + command access", "A browser for the editable preview"], 32, ink),
155
+ copy("brief-heading", 1020, 350, 788, ["Then give it one sentence"], 40, ink, 500),
156
+ copy("brief", 1020, 450, 788, ["“Use Konpeki to turn these launch", "notes into a product announcement.”"], 35),
157
+ copy("next-step", 1020, 696, 788, ["Need an empty canvas? Ask for init.", "A creation brief selects generate."], 32, blue, 500),
158
+ copy("closing", 112, 906, 1696, ["Attach your materials; the agent opens and checks the editable result. No separate init needed."], 30, muted),
157
159
  ]));
158
160
 
159
- const document: CompositionDocument = { schema: compositionSchema, title: "Introducing Konpeki", authoringMode: "default", theme: { id: "plex", mode: "paper" }, slides };
161
+ const document: CompositionDocument = { schema: compositionSchema, title: "Introducing Konpeki", authoringMode: "default", theme: { id: "precision", mode: "paper" }, slides };
160
162
  const result = validateComposition(document);
161
163
  if (!result.ok) throw new Error(JSON.stringify(result.issues, null, 2));
162
- await writeFile(new URL("./composition.json", import.meta.url), JSON.stringify(result.document, null, 2) + "\n");
164
+ await writeFile(new URL("./composition.json", import.meta.url), canonicalJSON(result.document) + "\n");
163
165
  console.log(`Authored ${slides.length} editable slides.`);