konpeki 0.3.1 → 0.4.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 (167) hide show
  1. package/AGENTS.md +21 -28
  2. package/AUTHORING.md +68 -229
  3. package/CONTRIBUTING.md +10 -23
  4. package/README.md +98 -106
  5. package/SETUP.md +49 -129
  6. package/docs/development.md +43 -256
  7. package/docs/workflow.md +6 -108
  8. package/html/README.md +140 -0
  9. package/html/browser.ts +103 -0
  10. package/html/document.ts +38 -0
  11. package/html/floor.ts +34 -0
  12. package/html/index.html +5 -0
  13. package/html/inspect.ts +313 -0
  14. package/html/preview.css +62 -0
  15. package/html/preview.tsx +463 -0
  16. package/html/review-hints.ts +63 -0
  17. package/html/server.ts +99 -0
  18. package/html/source.ts +104 -0
  19. package/html/starter.ts +6 -0
  20. package/html/theme-authoring.md +176 -0
  21. package/html/theme.md +61 -0
  22. package/index.html +9 -9
  23. package/package.json +21 -37
  24. package/plugin.json +1 -1
  25. package/public/og.png +0 -0
  26. package/runtime/browser-B-29TH1a.mjs +595 -0
  27. package/runtime/floor-Cmk7G3pU.mjs +41 -0
  28. package/runtime/konpeki.mjs +90 -1410
  29. package/runtime/server-BAqC_5WD.mjs +2 -0
  30. package/runtime/server-DfRpfcY9.mjs +205 -0
  31. package/runtime/source-B_Ui9tMp.mjs +141 -0
  32. package/runtime/source-CZQq9GUO.mjs +2 -0
  33. package/skills/konpeki/SKILL.md +88 -172
  34. package/skills/konpeki/assets/blank.html +17 -0
  35. package/skills/konpeki/floor.md +76 -0
  36. package/skills/konpeki/references/cover.md +27 -0
  37. package/skills/konpeki/references/long-document.md +40 -0
  38. package/skills/konpeki/references/one-pager.md +27 -0
  39. package/skills/konpeki/references/patterns.md +118 -0
  40. package/skills/konpeki/references/resume.md +28 -0
  41. package/skills/konpeki/references/slides.md +28 -0
  42. package/skills/konpeki/scripts/ensure-runtime.mjs +10 -31
  43. package/skills/konpeki/scripts/prepare-document.mjs +25 -14
  44. package/src/components/PageBoard.tsx +156 -0
  45. package/src/lib/alignment.ts +21 -0
  46. package/src/lib/page-board.ts +25 -0
  47. package/src/lib/review-position.ts +19 -0
  48. package/src/styles/base.css +1 -10
  49. package/src/styles/feedback.css +2 -1
  50. package/src/styles/shell.css +94 -354
  51. package/theme-base.css +90 -0
  52. package/theme.css +56 -0
  53. package/vite.config.ts +2 -5
  54. package/composition/README.md +0 -156
  55. package/composition/compile.ts +0 -227
  56. package/composition/document.ts +0 -600
  57. package/composition/schema.json +0 -3001
  58. package/composition/schema.ts +0 -437
  59. package/composition/theme-tokens.ts +0 -16
  60. package/composition/types.ts +0 -269
  61. package/composition/validate.ts +0 -226
  62. package/composition/vector.ts +0 -143
  63. package/composition/visualizations.ts +0 -319
  64. package/design/README.md +0 -17
  65. package/design/palettes/README.md +0 -14
  66. package/design/palettes/base.ts +0 -14
  67. package/design/palettes/candidates.ts +0 -19
  68. package/design/palettes/index.ts +0 -78
  69. package/design/review/color-theme.md +0 -44
  70. package/design/review/layout.md +0 -16
  71. package/design/review/text.md +0 -18
  72. package/design/review/typography.md +0 -15
  73. package/design/review/visuals.md +0 -31
  74. package/design/semantic-patterns.md +0 -43
  75. package/design/themes/README.md +0 -40
  76. package/design/themes/index.ts +0 -24
  77. package/design/visual-languages/technical-product.md +0 -17
  78. package/design/visual-review.md +0 -88
  79. package/lib/assets.d.ts +0 -8
  80. package/lib/charts.ts +0 -18
  81. package/lib/contrast.ts +0 -16
  82. package/lib/layouts.ts +0 -50
  83. package/lib/slide.tsx +0 -42
  84. package/lib/taste.ts +0 -17
  85. package/lib/text.tsx +0 -89
  86. package/lib/typeface.ts +0 -44
  87. package/scripts/migrate-react-page.ts +0 -120
  88. package/skills/konpeki/assets/blank.json +0 -23
  89. package/slides/README.md +0 -56
  90. package/slides/architecture/PROMPT.md +0 -31
  91. package/slides/architecture/index.tsx +0 -102
  92. package/slides/article-brief/PROMPT.md +0 -35
  93. package/slides/article-brief/index.tsx +0 -71
  94. package/slides/bar-chart/PROMPT.md +0 -39
  95. package/slides/bar-chart/index.tsx +0 -97
  96. package/slides/comparison/PROMPT.md +0 -29
  97. package/slides/comparison/index.tsx +0 -95
  98. package/slides/decision-memo/PROMPT.md +0 -34
  99. package/slides/decision-memo/index.tsx +0 -85
  100. package/slides/delivery-plan/PROMPT.md +0 -45
  101. package/slides/delivery-plan/index.tsx +0 -105
  102. package/slides/drawing-references.md +0 -32
  103. package/slides/experiment/PROMPT.md +0 -44
  104. package/slides/experiment/index.tsx +0 -127
  105. package/slides/github-cover/PROMPT.md +0 -21
  106. package/slides/github-cover/README.md +0 -21
  107. package/slides/github-cover/author.ts +0 -67
  108. package/slides/github-cover/composition.json +0 -595
  109. package/slides/incident-workflow/PROMPT.md +0 -57
  110. package/slides/incident-workflow/index.tsx +0 -78
  111. package/slides/introducing-konpeki/PROMPT.md +0 -30
  112. package/slides/introducing-konpeki/README.md +0 -44
  113. package/slides/introducing-konpeki/SOURCE.md +0 -19
  114. package/slides/introducing-konpeki/author.ts +0 -165
  115. package/slides/introducing-konpeki/composition.json +0 -3270
  116. package/slides/line-chart/PROMPT.md +0 -40
  117. package/slides/line-chart/index.tsx +0 -72
  118. package/slides/migration/PROMPT.md +0 -38
  119. package/slides/migration/index.tsx +0 -89
  120. package/slides/og-images/PROMPT.md +0 -21
  121. package/slides/og-images/index.tsx +0 -76
  122. package/slides/product-introduction/PROMPT.md +0 -24
  123. package/slides/product-introduction/index.tsx +0 -105
  124. package/slides/research-brief/PROMPT.md +0 -40
  125. package/slides/research-brief/index.tsx +0 -104
  126. package/slides/results-explanation/PROMPT.md +0 -32
  127. package/slides/results-explanation/index.tsx +0 -96
  128. package/slides/retrospective/PROMPT.md +0 -43
  129. package/slides/retrospective/index.tsx +0 -105
  130. package/slides/sankey/PROMPT.md +0 -11
  131. package/slides/sankey/index.tsx +0 -93
  132. package/slides/teaching/PROMPT.md +0 -45
  133. package/slides/teaching/index.tsx +0 -124
  134. package/slides/vertical-bar-charts/PROMPT.md +0 -13
  135. package/slides/vertical-bar-charts/index.tsx +0 -97
  136. package/src/app/App.tsx +0 -845
  137. package/src/components/BuildOrb.tsx +0 -40
  138. package/src/components/Canvas.tsx +0 -1191
  139. package/src/components/DiagramTypeIcon.tsx +0 -78
  140. package/src/components/InspectorPanel.tsx +0 -757
  141. package/src/components/LeftPanel.tsx +0 -120
  142. package/src/components/PageSizePicker.tsx +0 -30
  143. package/src/components/Presentation.tsx +0 -105
  144. package/src/components/RevisionNotes.tsx +0 -55
  145. package/src/components/RightPanel.tsx +0 -233
  146. package/src/components/VectorOverflowWarning.tsx +0 -73
  147. package/src/components/WorkspaceChrome.tsx +0 -316
  148. package/src/components/ui.tsx +0 -147
  149. package/src/lib/examples/react-page-migration.json +0 -1295
  150. package/src/lib/examples.ts +0 -42
  151. package/src/lib/export-png.ts +0 -104
  152. package/src/lib/file-session.ts +0 -87
  153. package/src/lib/history.ts +0 -53
  154. package/src/lib/model.ts +0 -188
  155. package/src/lib/page-size.ts +0 -24
  156. package/src/lib/presentation.ts +0 -17
  157. package/src/lib/review.ts +0 -26
  158. package/src/lib/storage.ts +0 -71
  159. package/src/lib/theme.ts +0 -25
  160. package/src/lib/use-file-session.ts +0 -249
  161. package/src/main.tsx +0 -29
  162. package/src/styles/canvas.css +0 -299
  163. package/src/styles/chrome.css +0 -475
  164. package/src/styles/component-previews.css +0 -386
  165. package/src/styles/left-panel.css +0 -187
  166. package/src/styles/presentation.css +0 -72
  167. package/src/styles/right-panel.css +0 -1298
@@ -1,78 +0,0 @@
1
- import type { ReactNode } from 'react';
2
- import '@fontsource/ibm-plex-sans/latin-400.css';
3
- import '@fontsource/ibm-plex-sans/latin-600.css';
4
-
5
- const ink = '#152B39', muted = '#465D6B', accent = '#006B75';
6
- function Copy({ x = 112, y, lines, size = 34, color = ink, weight = 400 }: {
7
- x?: number; y: number; lines: string[]; size?: number; color?: string; weight?: number;
8
- }) {
9
- return <text x={x} y={y} fill={color} fontSize={size} fontWeight={weight}>
10
- {lines.map((s, i) => <tspan key={i} x={x} dy={i ? size * 1.32 : 0}>{s}</tspan>)}
11
- </text>;
12
- }
13
- function Frame({ title, description, page, children }: { title: string; description: string; page: number; children: ReactNode }) {
14
- return <svg xmlns="http://www.w3.org/2000/svg" width="1920" height="1080" viewBox="0 0 1920 1080" fontFamily="IBM Plex Sans" role="img" aria-labelledby={`title-${page} desc-${page}`}>
15
- <title id={`title-${page}`}>{title}</title><desc id={`desc-${page}`}>{description}</desc>
16
- <rect width="1920" height="1080" fill="#FFFFFF" />
17
- <Copy y={135} lines={[title]} size={64} weight={600} />
18
- {children}
19
- <Copy x={1760} y={1025} lines={[`${page} / 3`]} size={26} color={muted} />
20
- </svg>;
21
- }
22
-
23
- const Diagnosis = () => <Frame page={1} title="The release outpaced the connection pool" description="Fictional Lantern incident, 18 August 2026, UTC. API accepts events into a durable queue; workers deliver to customer webhook endpoints. Concurrency rose from 20 to 80 per worker at 09:00 while the pool stayed at 20. At 09:05 oldest pending age was six minutes and queue depth 18,000. At 09:08 API acceptance was healthy, CPU below 50%, outbound timeouts increased. At 09:12 steady traffic, widespread endpoint timeouts and traces waiting for connections support a worker-side bottleneck rather than traffic surge or independent customer failures. Not yet reproduced under controlled load.">
24
- <Copy y={202} lines={['Lantern · fictional incident · 18 August 2026 · all times UTC']} size={28} color={muted} />
25
- <Copy y={290} lines={['API accepts events']} weight={600} />
26
- <Copy x={630} y={290} lines={['Durable queue']} weight={600} />
27
- <Copy x={1150} y={290} lines={['Workers deliver to webhooks']} weight={600} />
28
- <path d="M435 278 H578 M564 266 L578 278 L564 290 M910 278 H1098 M1084 266 L1098 278 L1084 290" stroke={accent} strokeWidth="3" fill="none" />
29
- <Copy y={350} lines={['Objective: 99% of accepted events get a successful endpoint response within five minutes.']} size={31} color={muted} />
30
- <Copy y={447} lines={['09:00 Release']} size={36} weight={600} color={accent} />
31
- <Copy y={502} lines={['Concurrency per worker: 20 → 80', 'Worker count and incoming volume unchanged.']} size={32} />
32
- <Copy y={630} lines={['09:05–09:08 Symptoms']} size={36} weight={600} color={accent} />
33
- <Copy y={685} lines={['18,000 queued events; oldest waiting 6 min.', 'API acceptance healthy; worker CPU <50%.', 'Outbound requests timed out more often.']} size={32} />
34
- <Copy x={970} y={447} lines={['09:12 Test the three explanations']} size={36} weight={600} color={accent} />
35
- <Copy x={970} y={510} lines={['Traffic surge? Volume matched pre-release.', 'Endpoint failures? Many unrelated endpoints.', 'Worker bottleneck? Traces waited for a', 'connection; each pool still had only 20.']} size={32} />
36
- <Copy x={970} y={737} lines={['Supported diagnosis: concurrency / pool mismatch.', 'The evidence points to shared worker capacity.']} size={31} weight={600} />
37
- <Copy x={970} y={853} lines={['The failure has not yet been reproduced', 'in a controlled test.']} size={29} color={muted} />
38
- <Copy y={925} lines={['Queue age = time the oldest', 'pending event has waited.']} size={29} color={muted} />
39
- </Frame>;
40
-
41
- const Mitigation = () => <Frame page={2} title="Rollback relieved waits before the backlog cleared" description="At 09:15 the team rolled concurrency back to 20, without purging the queue or replaying completed jobs. At 09:20 connection waits and timeout rates were back to pre-release levels, but 24,000 events remained queued, down from a peak of 30,000, and oldest pending age was 14 minutes. At 09:40 queue depth was in its usual 0–500 range and oldest age 40 seconds. Recovery after rollback strengthens the diagnosis but does not replace controlled reproduction.">
42
- <Copy y={208} lines={['Operational sequence · all times UTC · fictional incident']} size={28} color={muted} />
43
- <Copy y={340} lines={['09:15']} size={72} color={accent} weight={600} />
44
- <Copy y={410} lines={['Mitigate the mismatch']} size={37} weight={600} />
45
- <Copy y={478} lines={['Roll concurrency back to 20.', 'Keep the durable queue intact.', 'Do not replay completed jobs.']} size={33} />
46
- <Copy y={685} lines={['Why this intervention?']} size={32} weight={600} />
47
- <Copy y={738} lines={['Match concurrent deliveries', 'to the existing 20-connection', 'pool rather than add pressure.']} size={32} />
48
- <Copy x={760} y={340} lines={['09:20']} size={72} color={accent} weight={600} />
49
- <Copy x={760} y={410} lines={['Transport stabilizes']} size={37} weight={600} />
50
- <Copy x={760} y={478} lines={['Connection waits and timeout', 'rates return to pre-release levels.']} size={33} />
51
- <Copy x={760} y={635} lines={['24,000 events remain']} size={40} weight={600} />
52
- <Copy x={760} y={695} lines={['Down from a peak of 30,000.', 'Oldest pending age: 14 min.', 'The backlog is still draining.']} size={32} />
53
- <Copy x={1340} y={340} lines={['09:40']} size={72} color={accent} weight={600} />
54
- <Copy x={1340} y={410} lines={['Queue normalizes']} size={37} weight={600} />
55
- <Copy x={1340} y={478} lines={['Depth returns to its usual', 'range of 0–500 events.']} size={33} />
56
- <Copy x={1340} y={635} lines={['40 seconds']} size={40} weight={600} />
57
- <Copy x={1340} y={695} lines={['Oldest pending event age.', 'Confirm backlog recovery', 'separately from timeouts.']} size={32} />
58
- <Copy y={935} lines={['Recovery after rollback strengthens the diagnosis; controlled reproduction is still needed.']} size={31} color={muted} />
59
- </Frame>;
60
-
61
- const Recovery = () => <Frame page={3} title="Recovery is a measured window, not a clean slate" description="At 10:10 UTC, 99.3% of newly accepted events over the preceding 30 minutes received a successful endpoint response within five minutes, exceeding the 99% objective for that cohort. It does not erase the incident delivery-objective breach. No data loss observed, but event-by-event audit incomplete. Next: reproduce mismatch under load, validate concurrency and pool settings together before release, and add connection-wait time to the rollout dashboard.">
62
- <Copy y={208} lines={['10:10 UTC check · fictional incident']} size={28} color={muted} />
63
- <Copy y={385} lines={['99.3%']} size={132} color={accent} weight={600} />
64
- <Copy y={466} lines={['of newly accepted events']} size={42} weight={600} />
65
- <Copy y={533} lines={['received a successful endpoint response', 'within five minutes in the preceding', '30 minutes (09:40–10:10 UTC).']} size={34} />
66
- <Copy y={730} lines={['Objective: 99% within five minutes.']} size={33} weight={600} />
67
- <Copy y={794} lines={['This cohort met the objective. The incident’s', 'delivery-objective breach still happened.']} size={33} />
68
- <Copy x={1050} y={330} lines={['Close the evidence gaps']} size={43} weight={600} />
69
- <Copy x={1050} y={420} lines={['Reproduce the mismatch under load.']} size={34} weight={600} />
70
- <Copy x={1050} y={473} lines={['Test the supported cause in a controlled run.']} size={31} color={muted} />
71
- <Copy x={1050} y={575} lines={['Validate both settings before release.']} size={34} weight={600} />
72
- <Copy x={1050} y={628} lines={['Check concurrency and pool capacity together.']} size={31} color={muted} />
73
- <Copy x={1050} y={730} lines={['Expose connection-wait time.']} size={34} weight={600} />
74
- <Copy x={1050} y={783} lines={['Add the signal to the rollout dashboard.']} size={31} color={muted} />
75
- <Copy y={957} lines={['No data loss was observed; an event-by-event delivery audit is not yet complete.']} size={31} color={muted} />
76
- </Frame>;
77
-
78
- export default [Diagnosis, Mitigation, Recovery];
@@ -1,30 +0,0 @@
1
- # Public brief excerpt
2
-
3
- Public requests and authoring decisions; debugging and product-development
4
- follow-ups are omitted. This is not the complete conversation.
5
-
6
- > build a pre to introduce konpeki
7
-
8
- ## Creation
9
-
10
- - Interpreted “pre” as a six-page English introduction for first-time users.
11
- - No mode or visual preferences supplied; chose default mode, white, IBM Plex
12
- Sans, dark ink and Konpeki blue, with restrained diagrams and clear hierarchy.
13
- - Use documented capabilities, not invented metrics or export claims.
14
- Deliver editable JSON, browser presentation and reviewed captures.
15
-
16
- ## Revision
17
-
18
- > review the example composition and revise if needed
19
-
20
- - Show creation from a brief, with init optional. Canvas-first intent / Build it
21
- remains an alternative; Konpeki is not primarily a slide explainer.
22
- - Separate browser-local storage from agent-opened files. Notes and Build it
23
- require a file session; Copy prompt resumes an idle agent.
24
- - Use skill installation and user prerequisites, not contributor setup or
25
- assumptions that every agent supports the same slash command.
26
- - Retain default mode, six pages, stable IDs, unrelated geometry and the existing
27
- Precision Paper appearance. Its Noto Sans differs from the original font choice.
28
- - Refresh JSON, authoring source, source notes and captures.
29
-
30
- See [SOURCE.md](SOURCE.md) for capability evidence and artwork provenance.
@@ -1,44 +0,0 @@
1
- # Introducing Konpeki
2
-
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.
6
-
7
- ## Open and revise
8
-
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:
21
-
22
- ```sh
23
- mise exec -- node slides/introducing-konpeki/author.ts
24
- ```
25
-
26
- Run from the repository root. **This overwrites canvas edits.**
27
- [Brief](PROMPT.md) · [Sources](SOURCE.md) · [Reviewed screenshots](screenshots/)
28
-
29
- ## Review
30
-
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.
43
-
44
- ![Title slide](screenshots/page-1.png)
@@ -1,19 +0,0 @@
1
- # Source facts and provenance
2
-
3
- Product claims come from repository documentation, not a customer case study.
4
-
5
- | Claim | Repository evidence |
6
- | --- | --- |
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
-
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,165 +0,0 @@
1
- // Authoring source. composition.json is the editable deck of record.
2
- // Re-running this script replaces it; preserve canvas revisions before rebuilding.
3
- import { writeFile } from "node:fs/promises";
4
- import { canonicalJSON } from "../../composition/compile.ts";
5
- import { createComponent } from "../../composition/document.ts";
6
- import { validateComposition } from "../../composition/validate.ts";
7
- import {
8
- compositionSchema, canvasSize, canvasPadding,
9
- type CompositionComponent, type CompositionDocument, type CompositionSlide,
10
- type VectorElement,
11
- } from "../../composition/types.ts";
12
-
13
- const ink = "theme:ink", blue = "theme:accent", muted = "theme:muted", line = "theme:divider";
14
- function text(id: string, value: string, x: number, y: number, size = 34, fill = ink, weight = 400): VectorElement {
15
- return { id, kind: "text", text: value, attributes: { x, y, "font-family": size >= 56 ? "theme:heading-font" : "theme:body-font", "font-size": size, "font-weight": weight, fill } };
16
- }
17
- function rect(id: string, x: number, y: number, width: number, height: number, stroke = line, fill = "theme:background"): VectorElement {
18
- return { id, kind: "rect", attributes: { x, y, width, height, rx: 4, fill, stroke, "stroke-width": 2 } };
19
- }
20
- function path(id: string, d: string, stroke = blue, width = 3): VectorElement {
21
- return { id, kind: "path", attributes: { d, fill: "none", stroke, "stroke-width": width, "stroke-linecap": "round", "stroke-linejoin": "round" } };
22
- }
23
- function arrow(id: string, x: number, y: number, end: number) {
24
- return path(id, `M${x} ${y}H${end}M${end - 14} ${y - 12}L${end} ${y}L${end - 14} ${y + 12}`);
25
- }
26
- function component(id: string, kind: CompositionComponent["kind"], x: number, y: number, width: number, height: number, description: string, elements: VectorElement[]): CompositionComponent {
27
- const base = createComponent(kind, 1);
28
- if (base.kind === "diagram" || base.kind === "chart") base.appearance.selection = "explicit";
29
- return { ...base, id, slotIds: [`${id}-content`], preferredRect: { x, y, width, height }, intent: description,
30
- customVisual: { format: "vector", viewBox: { x: 0, y: 0, width, height }, fit: "contain", description, elements } };
31
- }
32
- function copy(id: string, x: number, y: number, width: number, lines: string[], size = 36, color = ink, weight = 400) {
33
- const result = component(id, "text-block", x, y, width, Math.ceil(lines.length * size * 1.4 + 20), lines.join(" "),
34
- lines.map((value, index) => text(`${id}-line-${index + 1}`, value, 0, size + 8 + index * size * 1.4, size, color, weight)));
35
- if (result.kind === "text-block" && (id.endsWith("-title") || id === "brand")) result.appearance.role = "title";
36
- if (result.kind === "text-block") {
37
- delete result.customVisual;
38
- result.content = lines.join("\n");
39
- result.textStyle = { size, weight: weight as 400 | 500 | 600, lineHeight: 1.4,
40
- color: color === blue ? "accent" : color === muted ? "muted" : "ink", font: size >= 56 ? "heading" : "body" };
41
- }
42
- return result;
43
- }
44
- function slide(id: string, name: string, question: string, components: CompositionComponent[]): CompositionSlide {
45
- return { id, name, canvas: canvasSize, innerPadding: canvasPadding, pageNumber: { style: "01/02", color: "muted" },
46
- audience: "People and coding-agent users discovering Konpeki", question, intendedViewingSize: "presentation",
47
- components, contentSlots: components.map((c) => ({ id: c.slotIds[0], label: c.id, role: "body", required: true, instruction: c.intent! })),
48
- groups: [], readingOrder: components.map((c) => ({ kind: "component", id: c.id })), paintOrder: components.map((c) => c.id), relationships: [] };
49
- }
50
- function heading(id: string, title: string, subtitle: string) {
51
- return [copy(`${id}-title`, 112, 88, 1696, [title], 62, ink, 600), copy(`${id}-subtitle`, 112, 184, 1696, [subtitle], 32, muted)];
52
- }
53
-
54
- const slides: CompositionSlide[] = [];
55
- slides.push(slide("introduction", "Meet Konpeki", "What is Konpeki?", [
56
- copy("brand", 112, 140, 820, ["Konpeki"], 112, blue, 600),
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),
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.", [
60
- rect("canvas-frame", 8, 25, 670, 395),
61
- text("canvas-title", "From brief to visual", 45, 93, 36, ink, 500),
62
- path("headline-rule", "M45 120H640", line, 2),
63
- rect("source-node", 50, 183, 160, 90, blue), rect("result-node", 310, 183, 320, 90, blue),
64
- text("source-label", "Brief", 98, 239, 28), text("result-label", "Editable visual", 374, 239, 28),
65
- arrow("connection", 228, 228, 292),
66
- path("body-lines", "M50 323H395M50 351H525", line, 8),
67
- text("document-label", "composition.json", 178, 484, 32, blue, 500),
68
- text("participants", "Human edits + agent revisions", 116, 548, 28, muted),
69
- ]),
70
- copy("intro-note", 112, 870, 1696, ["Covers, social graphics, charts, diagrams and presentations."], 34),
71
- ]));
72
-
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.", [
76
- ...[0, 1, 2, 3].flatMap((index) => {
77
- const x = index * 438;
78
- return [text(`number-${index}`, `0${index + 1}`, x, 48, 26, blue, 500),
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),
82
- ...(index < 3 ? [arrow(`handoff-${index}`, x + 338, 109, x + 398)] : [])];
83
- }),
84
- path("revision-loop", "M1510 285V365H991V285M979 299L991 285L1003 299", blue),
85
- text("loop-label", "Both edit the same composition.json", 490, 431, 32, blue),
86
- ]),
87
- copy("workflow-note", 112, 870, 1696, ["Prefer to sketch first? Add a component, describe its intent, then choose Build it."], 34, ink),
88
- ]));
89
-
90
- slides.push(slide("components", "Five semantic components", "What can a page contain?", [
91
- ...heading("components", "Five components. One composition.", "Each component keeps its meaning, outer geometry and editable interior."),
92
- component("text-specimen", "text-block", 112, 360, 296, 360, "Text block: headlines, body text, captions and footnotes.", [
93
- text("label", "Text block", 0, 40, 38, ink, 500), text("sample", "Aa", 0, 166, 96, blue),
94
- text("detail-1", "Headlines, body", 0, 277, 28, muted), text("detail-2", "and captions", 0, 317, 28, muted),
95
- ]),
96
- component("diagram-specimen", "diagram", 462, 360, 296, 360, "Diagram: entities and their relationships.", [
97
- text("label", "Diagram", 0, 40, 38, ink, 500), rect("node-1", 4, 112, 94, 78, blue), rect("node-2", 195, 112, 94, 78, blue), arrow("edge", 112, 151, 181),
98
- text("detail-1", "Entities and", 0, 277, 28, muted), text("detail-2", "relationships", 0, 317, 28, muted),
99
- ]),
100
- component("chart-specimen", "chart", 812, 360, 296, 400, "Chart specimen with illustrative values A 2 and B 3; not product measurements.", [
101
- text("label", "Chart", 0, 40, 38, ink, 500), path("axis", "M5 84V209H285", line, 2),
102
- rect("bar-a", 54, 129, 66, 80, blue, blue), rect("bar-b", 188, 89, 66, 120, blue, blue),
103
- text("value-a", "2", 77, 117, 24), text("value-b", "3", 209, 77, 24), text("axis-a", "A", 77, 240, 22, muted), text("axis-b", "B", 209, 240, 22, muted),
104
- text("detail-1", "Quantitative", 0, 297, 28, muted), text("detail-2", "comparisons", 0, 337, 28, muted), text("caveat", "Illustrative values", 0, 388, 26, ink),
105
- ]),
106
- component("image-specimen", "image", 1162, 360, 296, 360, "Image: a visual asset or illustration, represented here by original vector artwork.", [
107
- text("label", "Image", 0, 40, 38, ink, 500), rect("frame", 4, 91, 278, 135),
108
- { id: "sun", kind: "circle", attributes: { cx: 227, cy: 126, r: 17, fill: blue } },
109
- path("landscape", "M24 205L88 135L151 194L193 159L264 205", blue, 4),
110
- text("detail-1", "Visual assets", 0, 277, 28, muted), text("detail-2", "and illustrations", 0, 317, 28, muted),
111
- ]),
112
- component("table-specimen", "table", 1512, 360, 296, 360, "Table: structured comparisons with clear row and column associations.", [
113
- text("label", "Table", 0, 40, 38, ink, 500),
114
- text("col-a", "Stage", 0, 120, 26, ink, 500), text("col-b", "Owner", 157, 120, 26, ink, 500),
115
- path("rules", "M0 136H285M0 190H285M0 244H285", line, 2),
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),
117
- text("detail", "Structured detail", 0, 317, 28, muted),
118
- ]),
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),
120
- ]));
121
-
122
- slides.push(slide("editing", "Keep the detail editable", "What remains editable after an agent finishes?", [
123
- ...heading("editing", "Keep editing—or ask your agent", "Change text, shapes and layout directly. Undo and redo stay available."),
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.", [
125
- rect("owner", 5, 5, 965, 390), text("owner-label", "Diagram · review-flow", 35, 53, 27, muted),
126
- rect("draft", 55, 158, 220, 120), rect("review-node", 385, 158, 220, 120, blue), rect("present", 715, 158, 220, 120),
127
- text("draft-label", "Draft", 113, 232, 38), text("review-label", "Review", 433, 232, 38, blue, 500), text("present-label", "Present", 753, 232, 38),
128
- arrow("draft-review", 293, 218, 367), arrow("review-present", 623, 218, 697),
129
- ...[[380,153],[600,153],[380,273],[600,273]].map(([x,y], i) => rect(`handle-${i}`,x,y,10,10,blue)),
130
- text("stable-id", "Selected element: review-node", 36, 450, 32, blue),
131
- ]),
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),
135
- ]));
136
-
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),
147
- ]));
148
-
149
- slides.push(slide("start", "Try a real brief", "How do I start?", [
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),
152
- copy("repository", 112, 435, 850, ["github.com/vcfgdev/konpeki"], 38, blue, 500),
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),
159
- ]));
160
-
161
- const document: CompositionDocument = { schema: compositionSchema, title: "Introducing Konpeki", authoringMode: "default", theme: { id: "precision", mode: "paper" }, slides };
162
- const result = validateComposition(document);
163
- if (!result.ok) throw new Error(JSON.stringify(result.issues, null, 2));
164
- await writeFile(new URL("./composition.json", import.meta.url), canonicalJSON(result.document) + "\n");
165
- console.log(`Authored ${slides.length} editable slides.`);