pmx-canvas 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 (226) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/LICENSE +21 -0
  3. package/Readme.md +865 -0
  4. package/dist/canvas/global.css +3173 -0
  5. package/dist/canvas/index.js +183 -0
  6. package/dist/json-render/index.css +2 -0
  7. package/dist/json-render/index.js +389 -0
  8. package/dist/types/cli/agent.d.ts +13 -0
  9. package/dist/types/cli/index.d.ts +2 -0
  10. package/dist/types/cli/watch.d.ts +5 -0
  11. package/dist/types/client/App.d.ts +1 -0
  12. package/dist/types/client/canvas/AttentionHistory.d.ts +1 -0
  13. package/dist/types/client/canvas/AttentionToast.d.ts +1 -0
  14. package/dist/types/client/canvas/CanvasNode.d.ts +8 -0
  15. package/dist/types/client/canvas/CanvasViewport.d.ts +8 -0
  16. package/dist/types/client/canvas/CommandPalette.d.ts +4 -0
  17. package/dist/types/client/canvas/ContextMenu.d.ts +24 -0
  18. package/dist/types/client/canvas/ContextPinBar.d.ts +1 -0
  19. package/dist/types/client/canvas/ContextPinHud.d.ts +1 -0
  20. package/dist/types/client/canvas/DockedNode.d.ts +4 -0
  21. package/dist/types/client/canvas/EdgeLayer.d.ts +8 -0
  22. package/dist/types/client/canvas/ExpandedNodeOverlay.d.ts +1 -0
  23. package/dist/types/client/canvas/FocusFieldLayer.d.ts +1 -0
  24. package/dist/types/client/canvas/Minimap.d.ts +23 -0
  25. package/dist/types/client/canvas/SelectionBar.d.ts +1 -0
  26. package/dist/types/client/canvas/ShortcutOverlay.d.ts +3 -0
  27. package/dist/types/client/canvas/SnapshotPanel.d.ts +7 -0
  28. package/dist/types/client/canvas/snap-guides.d.ts +23 -0
  29. package/dist/types/client/canvas/use-node-drag.d.ts +15 -0
  30. package/dist/types/client/canvas/use-node-resize.d.ts +15 -0
  31. package/dist/types/client/canvas/use-pan-zoom.d.ts +16 -0
  32. package/dist/types/client/ext-app/bridge.d.ts +161 -0
  33. package/dist/types/client/icons.d.ts +70 -0
  34. package/dist/types/client/index.d.ts +1 -0
  35. package/dist/types/client/nodes/ContextNode.d.ts +34 -0
  36. package/dist/types/client/nodes/ExtAppFrame.d.ts +18 -0
  37. package/dist/types/client/nodes/FileNode.d.ts +5 -0
  38. package/dist/types/client/nodes/GroupNode.d.ts +6 -0
  39. package/dist/types/client/nodes/ImageNode.d.ts +10 -0
  40. package/dist/types/client/nodes/InlineFormatBar.d.ts +7 -0
  41. package/dist/types/client/nodes/InlineMarkdownEditor.d.ts +14 -0
  42. package/dist/types/client/nodes/LedgerNode.d.ts +4 -0
  43. package/dist/types/client/nodes/MarkdownNode.d.ts +6 -0
  44. package/dist/types/client/nodes/McpAppNode.d.ts +4 -0
  45. package/dist/types/client/nodes/MdFormatBar.d.ts +8 -0
  46. package/dist/types/client/nodes/PromptNode.d.ts +5 -0
  47. package/dist/types/client/nodes/ResponseNode.d.ts +5 -0
  48. package/dist/types/client/nodes/StatusNode.d.ts +4 -0
  49. package/dist/types/client/nodes/StatusSummary.d.ts +4 -0
  50. package/dist/types/client/nodes/TraceNode.d.ts +4 -0
  51. package/dist/types/client/nodes/WebpageNode.d.ts +5 -0
  52. package/dist/types/client/nodes/image-warnings.d.ts +6 -0
  53. package/dist/types/client/nodes/inline-editor-commands.d.ts +11 -0
  54. package/dist/types/client/nodes/md-format.d.ts +25 -0
  55. package/dist/types/client/state/attention-bridge.d.ts +3 -0
  56. package/dist/types/client/state/attention-store.d.ts +25 -0
  57. package/dist/types/client/state/canvas-store.d.ts +74 -0
  58. package/dist/types/client/state/intent-bridge.d.ts +158 -0
  59. package/dist/types/client/state/sse-bridge.d.ts +5 -0
  60. package/dist/types/client/theme/tokens.d.ts +27 -0
  61. package/dist/types/client/types.d.ts +40 -0
  62. package/dist/types/client/utils/ext-app-tool-result.d.ts +1 -0
  63. package/dist/types/client/utils/placement.d.ts +1 -0
  64. package/dist/types/client/utils/platform.d.ts +2 -0
  65. package/dist/types/json-render/catalog.d.ts +815 -0
  66. package/dist/types/json-render/charts/components.d.ts +54 -0
  67. package/dist/types/json-render/charts/definitions.d.ts +103 -0
  68. package/dist/types/json-render/charts/extra-components.d.ts +58 -0
  69. package/dist/types/json-render/charts/extra-definitions.d.ts +181 -0
  70. package/dist/types/json-render/renderer/index.d.ts +16 -0
  71. package/dist/types/json-render/schema.d.ts +46 -0
  72. package/dist/types/json-render/server.d.ts +55 -0
  73. package/dist/types/mcp/server.d.ts +22 -0
  74. package/dist/types/server/agent-context.d.ts +21 -0
  75. package/dist/types/server/artifact-paths.d.ts +3 -0
  76. package/dist/types/server/canvas-operations.d.ts +154 -0
  77. package/dist/types/server/canvas-provenance.d.ts +13 -0
  78. package/dist/types/server/canvas-schema.d.ts +49 -0
  79. package/dist/types/server/canvas-serialization.d.ts +25 -0
  80. package/dist/types/server/canvas-state.d.ts +174 -0
  81. package/dist/types/server/canvas-validation.d.ts +33 -0
  82. package/dist/types/server/chart-template.d.ts +29 -0
  83. package/dist/types/server/code-graph.d.ts +67 -0
  84. package/dist/types/server/context-cards.d.ts +24 -0
  85. package/dist/types/server/diagram-presets.d.ts +28 -0
  86. package/dist/types/server/ext-app-call-registry.d.ts +16 -0
  87. package/dist/types/server/ext-app-tool-result.d.ts +1 -0
  88. package/dist/types/server/file-watcher.d.ts +16 -0
  89. package/dist/types/server/index.d.ts +243 -0
  90. package/dist/types/server/mcp-app-candidate.d.ts +25 -0
  91. package/dist/types/server/mcp-app-host.d.ts +65 -0
  92. package/dist/types/server/mcp-app-runtime.d.ts +47 -0
  93. package/dist/types/server/mutation-history.d.ts +105 -0
  94. package/dist/types/server/placement.d.ts +37 -0
  95. package/dist/types/server/server.d.ts +103 -0
  96. package/dist/types/server/spatial-analysis.d.ts +87 -0
  97. package/dist/types/server/trace-manager.d.ts +48 -0
  98. package/dist/types/server/web-artifacts.d.ts +50 -0
  99. package/dist/types/server/webpage-node.d.ts +25 -0
  100. package/dist/types/shared/auto-arrange.d.ts +29 -0
  101. package/dist/types/shared/ext-app-tool-result.d.ts +9 -0
  102. package/dist/types/shared/placement.d.ts +26 -0
  103. package/dist/types/shared/semantic-attention.d.ts +97 -0
  104. package/package.json +109 -0
  105. package/skills/data-analysis/SKILL.md +324 -0
  106. package/skills/doc-coauthoring/SKILL.md +375 -0
  107. package/skills/frontend-design/SKILL.md +45 -0
  108. package/skills/json-render-codegen/SKILL.md +112 -0
  109. package/skills/json-render-core/SKILL.md +265 -0
  110. package/skills/json-render-ink/SKILL.md +273 -0
  111. package/skills/json-render-mcp/SKILL.md +132 -0
  112. package/skills/json-render-react/SKILL.md +264 -0
  113. package/skills/json-render-shadcn/SKILL.md +159 -0
  114. package/skills/playwright-cli/SKILL.md +67 -0
  115. package/skills/pmx-canvas/SKILL.md +668 -0
  116. package/skills/pmx-canvas/evals/evals.json +186 -0
  117. package/skills/pmx-canvas-testing/SKILL.md +78 -0
  118. package/skills/published-consumer-e2e/SKILL.md +43 -0
  119. package/skills/published-consumer-e2e/scripts/run-published-consumer-e2e.sh +241 -0
  120. package/skills/web-artifacts-builder/SKILL.md +80 -0
  121. package/skills/web-artifacts-builder/scripts/bundle-artifact.sh +167 -0
  122. package/skills/web-artifacts-builder/scripts/init-artifact.sh +425 -0
  123. package/skills/web-artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
  124. package/skills/web-design-guidelines/SKILL.md +39 -0
  125. package/src/cli/agent.ts +2144 -0
  126. package/src/cli/index.ts +622 -0
  127. package/src/cli/watch.ts +88 -0
  128. package/src/client/App.tsx +507 -0
  129. package/src/client/canvas/AttentionHistory.tsx +81 -0
  130. package/src/client/canvas/AttentionToast.tsx +19 -0
  131. package/src/client/canvas/CanvasNode.tsx +363 -0
  132. package/src/client/canvas/CanvasViewport.tsx +590 -0
  133. package/src/client/canvas/CommandPalette.tsx +302 -0
  134. package/src/client/canvas/ContextMenu.tsx +601 -0
  135. package/src/client/canvas/ContextPinBar.tsx +25 -0
  136. package/src/client/canvas/ContextPinHud.tsx +22 -0
  137. package/src/client/canvas/DockedNode.tsx +66 -0
  138. package/src/client/canvas/EdgeLayer.tsx +280 -0
  139. package/src/client/canvas/ExpandedNodeOverlay.tsx +260 -0
  140. package/src/client/canvas/FocusFieldLayer.tsx +107 -0
  141. package/src/client/canvas/Minimap.tsx +301 -0
  142. package/src/client/canvas/SelectionBar.tsx +69 -0
  143. package/src/client/canvas/ShortcutOverlay.tsx +69 -0
  144. package/src/client/canvas/SnapshotPanel.tsx +236 -0
  145. package/src/client/canvas/snap-guides.ts +170 -0
  146. package/src/client/canvas/use-node-drag.ts +51 -0
  147. package/src/client/canvas/use-node-resize.ts +59 -0
  148. package/src/client/canvas/use-pan-zoom.ts +191 -0
  149. package/src/client/ext-app/bridge.ts +542 -0
  150. package/src/client/icons.tsx +424 -0
  151. package/src/client/index.tsx +7 -0
  152. package/src/client/nodes/ContextNode.tsx +412 -0
  153. package/src/client/nodes/ExtAppFrame.tsx +509 -0
  154. package/src/client/nodes/FileNode.tsx +256 -0
  155. package/src/client/nodes/GroupNode.tsx +39 -0
  156. package/src/client/nodes/ImageNode.tsx +160 -0
  157. package/src/client/nodes/InlineFormatBar.tsx +169 -0
  158. package/src/client/nodes/InlineMarkdownEditor.tsx +123 -0
  159. package/src/client/nodes/LedgerNode.tsx +37 -0
  160. package/src/client/nodes/MarkdownNode.tsx +359 -0
  161. package/src/client/nodes/McpAppNode.tsx +85 -0
  162. package/src/client/nodes/MdFormatBar.tsx +109 -0
  163. package/src/client/nodes/PromptNode.tsx +597 -0
  164. package/src/client/nodes/ResponseNode.tsx +153 -0
  165. package/src/client/nodes/StatusNode.tsx +84 -0
  166. package/src/client/nodes/StatusSummary.tsx +38 -0
  167. package/src/client/nodes/TraceNode.tsx +120 -0
  168. package/src/client/nodes/WebpageNode.tsx +288 -0
  169. package/src/client/nodes/image-warnings.ts +95 -0
  170. package/src/client/nodes/inline-editor-commands.ts +37 -0
  171. package/src/client/nodes/md-format.ts +206 -0
  172. package/src/client/state/attention-bridge.ts +328 -0
  173. package/src/client/state/attention-store.ts +73 -0
  174. package/src/client/state/canvas-store.ts +631 -0
  175. package/src/client/state/intent-bridge.ts +315 -0
  176. package/src/client/state/sse-bridge.ts +965 -0
  177. package/src/client/theme/global.css +3173 -0
  178. package/src/client/theme/tokens.ts +72 -0
  179. package/src/client/types-shims.d.ts +5 -0
  180. package/src/client/types.ts +81 -0
  181. package/src/client/utils/ext-app-tool-result.ts +4 -0
  182. package/src/client/utils/placement.ts +4 -0
  183. package/src/client/utils/platform.ts +2 -0
  184. package/src/json-render/catalog.ts +256 -0
  185. package/src/json-render/charts/components.tsx +198 -0
  186. package/src/json-render/charts/definitions.ts +81 -0
  187. package/src/json-render/charts/extra-components.tsx +267 -0
  188. package/src/json-render/charts/extra-definitions.ts +145 -0
  189. package/src/json-render/renderer/index.css +174 -0
  190. package/src/json-render/renderer/index.tsx +86 -0
  191. package/src/json-render/schema.ts +62 -0
  192. package/src/json-render/server.ts +597 -0
  193. package/src/mcp/server.ts +1377 -0
  194. package/src/server/agent-context.ts +242 -0
  195. package/src/server/artifact-paths.ts +17 -0
  196. package/src/server/canvas-operations.ts +1279 -0
  197. package/src/server/canvas-provenance.ts +243 -0
  198. package/src/server/canvas-schema.ts +432 -0
  199. package/src/server/canvas-serialization.ts +95 -0
  200. package/src/server/canvas-state.ts +1134 -0
  201. package/src/server/canvas-validation.ts +114 -0
  202. package/src/server/chart-template.ts +449 -0
  203. package/src/server/code-graph.ts +370 -0
  204. package/src/server/context-cards.ts +31 -0
  205. package/src/server/diagram-presets.ts +71 -0
  206. package/src/server/ext-app-call-registry.ts +77 -0
  207. package/src/server/ext-app-tool-result.ts +4 -0
  208. package/src/server/file-watcher.ts +121 -0
  209. package/src/server/index.ts +647 -0
  210. package/src/server/mcp-app-candidate.ts +174 -0
  211. package/src/server/mcp-app-host.ts +814 -0
  212. package/src/server/mcp-app-runtime.ts +459 -0
  213. package/src/server/mutation-history.ts +350 -0
  214. package/src/server/placement.ts +125 -0
  215. package/src/server/server.ts +3846 -0
  216. package/src/server/spatial-analysis.ts +356 -0
  217. package/src/server/trace-manager.ts +333 -0
  218. package/src/server/web-artifacts/scripts/bundle-artifact.sh +167 -0
  219. package/src/server/web-artifacts/scripts/init-artifact.sh +426 -0
  220. package/src/server/web-artifacts/scripts/shadcn-components.tar.gz +0 -0
  221. package/src/server/web-artifacts.ts +442 -0
  222. package/src/server/webpage-node.ts +328 -0
  223. package/src/shared/auto-arrange.ts +439 -0
  224. package/src/shared/ext-app-tool-result.ts +76 -0
  225. package/src/shared/placement.ts +81 -0
  226. package/src/shared/semantic-attention.ts +598 -0
@@ -0,0 +1,186 @@
1
+ {
2
+ "skill_name": "pmx-canvas",
3
+ "evals": [
4
+ {
5
+ "id": 1,
6
+ "name": "investigation-board",
7
+ "prompt": "I'm debugging a memory leak in our Node.js API. The /api/users endpoint is leaking memory on every request. I found a suspicious closure in src/handlers/users.ts that captures the entire request object, and the heap snapshot shows growing EventEmitter listeners. Can you set up an investigation board on the canvas so I can see the full picture?",
8
+ "expected_output": "Creates multiple nodes (bug description, code file, heap findings, hypothesis) connected with edges, arranged in a tree layout. Uses appropriate node types (markdown for findings, file for source, status for investigation progress).",
9
+ "assertions": [
10
+ {
11
+ "name": "creates-multiple-nodes",
12
+ "description": "Creates at least 3 nodes representing different aspects of the investigation",
13
+ "type": "output_check"
14
+ },
15
+ {
16
+ "name": "uses-edges",
17
+ "description": "Connects nodes with labeled edges showing relationships between evidence",
18
+ "type": "output_check"
19
+ },
20
+ {
21
+ "name": "uses-tree-or-arrange",
22
+ "description": "Arranges the nodes using tree layout or explicit positioning for readability",
23
+ "type": "output_check"
24
+ },
25
+ {
26
+ "name": "uses-appropriate-types",
27
+ "description": "Uses file nodes for source code and markdown/status for findings rather than all markdown",
28
+ "type": "output_check"
29
+ }
30
+ ]
31
+ },
32
+ {
33
+ "id": 2,
34
+ "name": "architecture-diagram",
35
+ "prompt": "We're building a microservices backend with these services: API Gateway (Express, port 3000), Auth Service (JWT + OAuth2, port 3001), User Service (CRUD, port 3002), PostgreSQL (port 5432), and Redis (caching, port 6379). The API Gateway routes to Auth and User services, both Auth and User read/write to PostgreSQL, and User Service uses Redis for caching. Can you visualize this architecture on the canvas?",
36
+ "expected_output": "Creates nodes for each service with relevant details, connects them with flow/depends-on edges with descriptive labels, groups related services, and arranges in a readable layout.",
37
+ "assertions": [
38
+ {
39
+ "name": "all-services-present",
40
+ "description": "Creates nodes for all 5 services/datastores mentioned",
41
+ "type": "output_check"
42
+ },
43
+ {
44
+ "name": "correct-connections",
45
+ "description": "Creates edges matching the described relationships (Gateway->Auth, Gateway->User, Auth->PG, User->PG, User->Redis)",
46
+ "type": "output_check"
47
+ },
48
+ {
49
+ "name": "edge-labels",
50
+ "description": "Uses descriptive edge labels (not bare unlabeled edges)",
51
+ "type": "output_check"
52
+ },
53
+ {
54
+ "name": "layout-applied",
55
+ "description": "Applies auto-arrange or uses explicit positioning for readable layout",
56
+ "type": "output_check"
57
+ }
58
+ ]
59
+ },
60
+ {
61
+ "id": 3,
62
+ "name": "task-plan-tracking",
63
+ "prompt": "I need to implement a new payment feature. Here's the plan: 1) Define payment schema (done), 2) Build Stripe integration (in progress), 3) Create payment API routes (blocked by #2), 4) Add webhook handlers (blocked by #3), 5) Write integration tests (blocked by #4), 6) Update API docs (can start anytime). Show this on the canvas as a task board with dependencies.",
64
+ "expected_output": "Creates status nodes for each task with appropriate colors (green=done, yellow=in-progress, red=blocked, blue=ready), connects with depends-on edges, and arranges to show dependency flow.",
65
+ "assertions": [
66
+ {
67
+ "name": "six-task-nodes",
68
+ "description": "Creates exactly 6 task nodes, one for each task",
69
+ "type": "output_check"
70
+ },
71
+ {
72
+ "name": "semantic-colors",
73
+ "description": "Uses green for done, yellow for in-progress, red for blocked tasks",
74
+ "type": "output_check"
75
+ },
76
+ {
77
+ "name": "dependency-edges",
78
+ "description": "Creates depends-on edges matching the described blocking relationships",
79
+ "type": "output_check"
80
+ },
81
+ {
82
+ "name": "status-node-type",
83
+ "description": "Uses status node type (not markdown) for task items",
84
+ "type": "output_check"
85
+ }
86
+ ]
87
+ },
88
+ {
89
+ "id": 4,
90
+ "name": "read-pinned-context",
91
+ "prompt": "I've pinned some nodes on the canvas that I want you to look at. Can you read what I've pinned and summarize what you think I'm focusing on?",
92
+ "expected_output": "Reads canvas://pinned-context resource, summarizes the pinned nodes' content, identifies spatial neighborhoods, and explains what the human appears to be focusing on based on the pinned context and nearby nodes.",
93
+ "assertions": [
94
+ {
95
+ "name": "reads-pinned-context",
96
+ "description": "Reads the canvas://pinned-context MCP resource (not just canvas_get_layout)",
97
+ "type": "output_check"
98
+ },
99
+ {
100
+ "name": "summarizes-content",
101
+ "description": "Provides a meaningful summary of what the pinned nodes contain",
102
+ "type": "output_check"
103
+ },
104
+ {
105
+ "name": "interprets-intent",
106
+ "description": "Makes an interpretation of what the human is focusing on based on pinned context",
107
+ "type": "output_check"
108
+ }
109
+ ]
110
+ },
111
+ {
112
+ "id": 5,
113
+ "name": "code-exploration-files",
114
+ "prompt": "I'm trying to understand how the authentication flow works in this project. Can you put the relevant auth files on the canvas so I can see how they connect? The main files are src/auth/login.ts, src/auth/middleware.ts, src/auth/jwt.ts, and src/routes/auth.ts.",
115
+ "expected_output": "Creates file nodes for each mentioned file (content auto-loads), relies on code graph to auto-detect import dependencies, groups auth files together, and reads canvas://code-graph for dependency analysis.",
116
+ "assertions": [
117
+ {
118
+ "name": "uses-file-nodes",
119
+ "description": "Creates file type nodes (not markdown with pasted code) for source files",
120
+ "type": "output_check"
121
+ },
122
+ {
123
+ "name": "all-files-added",
124
+ "description": "Adds all 4 mentioned files to the canvas",
125
+ "type": "output_check"
126
+ },
127
+ {
128
+ "name": "groups-files",
129
+ "description": "Groups the auth files together in a canvas group",
130
+ "type": "output_check"
131
+ }
132
+ ]
133
+ },
134
+ {
135
+ "id": 6,
136
+ "name": "status-dashboard-updates",
137
+ "prompt": "I'm running a deployment pipeline. Create a dashboard on the canvas showing: Build (passing), Unit Tests (running), Integration Tests (queued), Deploy to Staging (queued). Then update it - unit tests just passed and integration tests are now running.",
138
+ "expected_output": "Creates status nodes with semantic colors, arranges as grid dashboard, then updates nodes in place using canvas_update_node (not delete+recreate) to reflect new state.",
139
+ "assertions": [
140
+ {
141
+ "name": "initial-dashboard",
142
+ "description": "Creates 4 status nodes with appropriate initial colors",
143
+ "type": "output_check"
144
+ },
145
+ {
146
+ "name": "updates-in-place",
147
+ "description": "Uses canvas_update_node to change status (not remove+add)",
148
+ "type": "output_check"
149
+ },
150
+ {
151
+ "name": "grid-layout",
152
+ "description": "Arranges nodes in grid layout for dashboard view",
153
+ "type": "output_check"
154
+ },
155
+ {
156
+ "name": "color-transitions",
157
+ "description": "Updates colors to reflect new state (unit tests -> green, integration -> yellow)",
158
+ "type": "output_check"
159
+ }
160
+ ]
161
+ },
162
+ {
163
+ "id": 7,
164
+ "name": "snapshot-before-changes",
165
+ "prompt": "I want to reorganize the canvas to explore a different approach, but I don't want to lose what's there now. Can you save the current state, clear it, and set up a fresh workspace for the new approach? If it doesn't work out I want to go back.",
166
+ "expected_output": "Takes a named snapshot of current state, then clears the canvas. Mentions that canvas_restore can bring back the old state. Does NOT just clear without snapshotting.",
167
+ "assertions": [
168
+ {
169
+ "name": "takes-snapshot",
170
+ "description": "Saves a snapshot with canvas_snapshot before clearing",
171
+ "type": "output_check"
172
+ },
173
+ {
174
+ "name": "clears-after-snapshot",
175
+ "description": "Clears the canvas after (not before) saving the snapshot",
176
+ "type": "output_check"
177
+ },
178
+ {
179
+ "name": "mentions-restore",
180
+ "description": "Tells the user how to restore (canvas_restore) if they want to go back",
181
+ "type": "output_check"
182
+ }
183
+ ]
184
+ }
185
+ ]
186
+ }
@@ -0,0 +1,78 @@
1
+ ---
2
+ name: pmx-canvas-testing
3
+ description: >
4
+ Repo-standard test and verification workflow for PMX Canvas. Use when you change code, add
5
+ tests, debug regressions, prepare handoff, or need to decide which local verification commands
6
+ to run. This skill defines the default test ladder, when to run Bun tests vs. browser tests,
7
+ how to handle pre-existing failures, and what evidence to report back.
8
+ ---
9
+
10
+ # PMX Canvas Testing
11
+
12
+ Use this skill whenever you touch code in this repo and need a consistent verification path.
13
+
14
+ ## When To Use
15
+
16
+ - Any code change that should be validated before handoff
17
+ - Adding or updating tests
18
+ - Debugging a regression or flaky behavior
19
+ - Updating CI or coverage commands
20
+ - Deciding the minimum acceptable verification for a task
21
+
22
+ ## Default Verification Ladder
23
+
24
+ Pick the narrowest command that proves the change, then escalate if the change crosses layers.
25
+
26
+ ```bash
27
+ bun run test # Fast Bun suite for server/state/API coverage
28
+ bun run test:coverage # Same Bun suite with coverage output
29
+ bun run test:web-canvas # Browser smoke against a real running app
30
+ bun run test:all # Bun suite + browser smoke
31
+ ```
32
+
33
+ ## Which Command To Run
34
+
35
+ - Server/state/API-only changes: run `bun run test`
36
+ - Test-only changes: run `bun run test` and `bun run test:coverage` if coverage matters
37
+ - Client/UI/browser interaction changes: run `bun run test:web-canvas`
38
+ - Cross-stack or non-trivial changes: run `bun run test:all`
39
+ - Before changing browser-visible behavior under `src/client/`: rebuild with `bun run build`
40
+ Manual browser validation also requires a fresh client bundle. `bun run test:web-canvas`
41
+ already does this for you.
42
+
43
+ ## Current Project Test Surface
44
+
45
+ - Bun tests live under `tests/unit/`
46
+ - Playwright browser smoke lives under `tests/e2e/`
47
+ - CI runs coverage plus the browser smoke flow
48
+
49
+ Prefer extending the existing suites before inventing a one-off script.
50
+
51
+ ## Test Authoring Rules
52
+
53
+ - Keep unit tests isolated. Reset singleton server state between tests.
54
+ - Test public behavior first: HTTP endpoints, persisted state, visible UI outcomes
55
+ - Use browser tests for interactions the user actually performs: node creation, pins, snapshots,
56
+ loading the workbench, and other sync-sensitive flows
57
+ - Avoid brittle selectors. Prefer stable text, roles, titles, or deliberate component hooks
58
+ - If a change spans server and client, add at least one server-side assertion and one browser or
59
+ API-level proof
60
+
61
+ ## Failure Handling
62
+
63
+ - Never wave away a failure without checking whether your change caused it
64
+ - If the failure is truly pre-existing, say that explicitly and include the failing command
65
+ - If a command cannot run in the environment, say what blocked it
66
+ - If browser tests fail after a client change, confirm the bundle was rebuilt and the server
67
+ started from the updated code
68
+
69
+ ## Handoff Standard
70
+
71
+ Before marking work done, report:
72
+
73
+ - Which verification command(s) you ran
74
+ - Whether they passed
75
+ - Any meaningful gaps, skipped checks, or known pre-existing failures
76
+
77
+ For non-trivial changes, the default expectation is `bun run test:all` unless there is a clear
78
+ reason to scope verification more narrowly.
@@ -0,0 +1,43 @@
1
+ ---
2
+ name: published-consumer-e2e
3
+ description: Re-run PMX Canvas like an external user by packing the repo, installing the tarball into a clean temp workspace, seeding the SDLC demo, and validating it in a browser. Use when asked to verify the published-package workflow, artifact/json-render coverage, or the full outside-in demo.
4
+ ---
5
+
6
+ # Published Consumer E2E
7
+
8
+ Use this skill when the goal is to test PMX Canvas from the outside instead of the repo dev path.
9
+
10
+ ## Default Path
11
+
12
+ Run:
13
+
14
+ ```bash
15
+ bash skills/published-consumer-e2e/scripts/run-published-consumer-e2e.sh
16
+ ```
17
+
18
+ That script will:
19
+
20
+ 1. pack the current repo as a tarball,
21
+ 2. create a clean temp consumer workspace,
22
+ 3. install the tarball with Bun,
23
+ 4. copy `examples/published-consumer-sdlc/` into that workspace,
24
+ 5. start the seeded demo through the package's public SDK,
25
+ 6. run a headed `playwright-cli` browser pass that snapshots the live workbench and asserts the article, artifact, json-render, graph, trace, and context surfaces are present.
26
+
27
+ ## Flags
28
+
29
+ - `--port=4600` to change the server port
30
+ - `--skip-playwright` to stop after pack/install + HTTP smoke
31
+ - `--headless` if a visible browser is impossible
32
+ - `--keep-running` to leave the temp consumer server alive after the script exits
33
+ - `--workdir=/tmp/custom-dir` to reuse a known temp location
34
+
35
+ ## Notes
36
+
37
+ - Install the browser tool once with `bun add -g @playwright/cli@latest`.
38
+ - Default to headed browser validation so the human can watch the run.
39
+ - Prefer the script over manually rebuilding the temp consumer.
40
+ - If you change the example assets or this browser test, rerun the full script instead of repo-only tests.
41
+ - The script assembles the tarball manually instead of relying on `npm pack` or `bun pm pack`, because pack/build commands can hang in this workspace.
42
+ - The skill uses `playwright-cli` instead of the repo-local `playwright test` path because the local Playwright CLI is currently incompatible with the Bun/Node mix in this environment.
43
+ - On failure, inspect the temp workspace log path printed by the script before changing code.
@@ -0,0 +1,241 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
+ SKILL_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
6
+ REPO_ROOT="$(cd "${SKILL_DIR}/../.." && pwd)"
7
+
8
+ BUN_BIN="${BUN_BIN:-$HOME/.bun/bin/bun}"
9
+ PORT="4513"
10
+ WORKDIR=""
11
+ KEEP_RUNNING=0
12
+ SKIP_PLAYWRIGHT=0
13
+ HEADED=1
14
+
15
+ for arg in "$@"; do
16
+ case "$arg" in
17
+ --port=*)
18
+ PORT="${arg#*=}"
19
+ ;;
20
+ --workdir=*)
21
+ WORKDIR="${arg#*=}"
22
+ ;;
23
+ --keep-running)
24
+ KEEP_RUNNING=1
25
+ ;;
26
+ --skip-playwright)
27
+ SKIP_PLAYWRIGHT=1
28
+ ;;
29
+ --headless)
30
+ HEADED=0
31
+ ;;
32
+ --headed)
33
+ HEADED=1
34
+ ;;
35
+ *)
36
+ echo "Unknown argument: $arg" >&2
37
+ exit 1
38
+ ;;
39
+ esac
40
+ done
41
+
42
+ if [[ ! -x "${BUN_BIN}" ]]; then
43
+ echo "Bun binary not found at ${BUN_BIN}. Set BUN_BIN or install Bun." >&2
44
+ exit 1
45
+ fi
46
+
47
+ export PATH="/opt/homebrew/bin:/usr/local/bin:$(dirname "${BUN_BIN}"):${PATH}"
48
+
49
+ if [[ -z "${WORKDIR}" ]]; then
50
+ WORKDIR="$(mktemp -d "${TMPDIR:-/tmp}/pmx-canvas-published-consumer.XXXXXX")"
51
+ else
52
+ mkdir -p "${WORKDIR}"
53
+ fi
54
+
55
+ PACK_DIR="${WORKDIR}/pack"
56
+ PACKAGE_STAGING="${WORKDIR}/package"
57
+ CONSUMER_DIR="${WORKDIR}/consumer"
58
+ LOG_FILE="${WORKDIR}/server.log"
59
+ rm -rf "${PACK_DIR}" "${PACKAGE_STAGING}"
60
+ mkdir -p "${PACK_DIR}" "${PACKAGE_STAGING}/package" "${CONSUMER_DIR}/demo"
61
+
62
+ cleanup() {
63
+ if [[ -n "${SERVER_PID:-}" ]] && kill -0 "${SERVER_PID}" 2>/dev/null; then
64
+ kill "${SERVER_PID}" 2>/dev/null || true
65
+ wait "${SERVER_PID}" 2>/dev/null || true
66
+ fi
67
+ }
68
+
69
+ trap cleanup EXIT
70
+
71
+ echo "[published-consumer] assembling install tarball from ${REPO_ROOT}"
72
+ cp "${REPO_ROOT}/package.json" "${PACKAGE_STAGING}/package/package.json"
73
+ cp "${REPO_ROOT}/Readme.md" "${PACKAGE_STAGING}/package/Readme.md"
74
+ if [[ -f "${REPO_ROOT}/LICENSE" ]]; then
75
+ cp "${REPO_ROOT}/LICENSE" "${PACKAGE_STAGING}/package/LICENSE"
76
+ fi
77
+ cp -R "${REPO_ROOT}/src" "${PACKAGE_STAGING}/package/src"
78
+ mkdir -p "${PACKAGE_STAGING}/package/dist/canvas" "${PACKAGE_STAGING}/package/dist/json-render"
79
+ cp "${REPO_ROOT}/dist/canvas/index.js" "${PACKAGE_STAGING}/package/dist/canvas/index.js"
80
+ cp "${REPO_ROOT}/dist/canvas/global.css" "${PACKAGE_STAGING}/package/dist/canvas/global.css"
81
+ cp "${REPO_ROOT}/dist/json-render/index.js" "${PACKAGE_STAGING}/package/dist/json-render/index.js"
82
+ cp "${REPO_ROOT}/dist/json-render/index.css" "${PACKAGE_STAGING}/package/dist/json-render/index.css"
83
+ TARBALL="pmx-canvas-published-consumer.tgz"
84
+ tar -czf "${PACK_DIR}/${TARBALL}" -C "${PACKAGE_STAGING}" package
85
+
86
+ echo "[published-consumer] staging temp consumer at ${CONSUMER_DIR}"
87
+ rm -rf "${CONSUMER_DIR}"
88
+ mkdir -p "${CONSUMER_DIR}/demo"
89
+ cp -R "${REPO_ROOT}/examples/published-consumer-sdlc/." "${CONSUMER_DIR}/demo/"
90
+ cat > "${CONSUMER_DIR}/package.json" <<'JSON'
91
+ {
92
+ "name": "pmx-canvas-published-consumer",
93
+ "private": true,
94
+ "type": "module"
95
+ }
96
+ JSON
97
+
98
+ (cd "${CONSUMER_DIR}" && "${BUN_BIN}" add "${PACK_DIR}/${TARBALL}")
99
+
100
+ echo "[published-consumer] starting seeded demo on port ${PORT}"
101
+ SERVER_PID="$(
102
+ python3 - "${CONSUMER_DIR}" "${BUN_BIN}" "${PORT}" "${LOG_FILE}" <<'PY'
103
+ import subprocess
104
+ import sys
105
+
106
+ consumer_dir, bun_bin, port, log_file = sys.argv[1:5]
107
+
108
+ with open(log_file, "ab", buffering=0) as log:
109
+ proc = subprocess.Popen(
110
+ [bun_bin, "run", "demo/seed-demo.ts", f"--port={port}", "--hold"],
111
+ cwd=consumer_dir,
112
+ stdin=subprocess.DEVNULL,
113
+ stdout=log,
114
+ stderr=subprocess.STDOUT,
115
+ start_new_session=True,
116
+ )
117
+ print(proc.pid)
118
+ PY
119
+ )"
120
+
121
+ READY=0
122
+ for _ in $(seq 1 90); do
123
+ if curl -fsS "http://127.0.0.1:${PORT}/api/canvas/state" >/dev/null 2>&1; then
124
+ READY=1
125
+ break
126
+ fi
127
+ sleep 1
128
+ done
129
+
130
+ if [[ "${READY}" -ne 1 ]]; then
131
+ echo "[published-consumer] server did not become ready. Log follows:" >&2
132
+ cat "${LOG_FILE}" >&2 || true
133
+ exit 1
134
+ fi
135
+
136
+ SEEDED=0
137
+ NODE_COUNT="0"
138
+ for _ in $(seq 1 120); do
139
+ if ! kill -0 "${SERVER_PID}" 2>/dev/null; then
140
+ echo "[published-consumer] seeded demo process exited early. Log follows:" >&2
141
+ cat "${LOG_FILE}" >&2 || true
142
+ exit 1
143
+ fi
144
+
145
+ NODE_COUNT="$(
146
+ curl -fsS "http://127.0.0.1:${PORT}/api/canvas/state" \
147
+ | "${BUN_BIN}" -e 'let raw="";for await (const chunk of Bun.stdin.stream()){raw+=chunk instanceof Uint8Array ? Buffer.from(chunk).toString() : String(chunk);} const state=JSON.parse(raw); console.log(state.nodes.length);'
148
+ )"
149
+
150
+ if [[ "${NODE_COUNT}" -ge 18 ]]; then
151
+ SEEDED=1
152
+ break
153
+ fi
154
+
155
+ sleep 1
156
+ done
157
+
158
+ if [[ "${SEEDED}" -ne 1 ]]; then
159
+ echo "[published-consumer] demo did not finish seeding. Last node count: ${NODE_COUNT}" >&2
160
+ cat "${LOG_FILE}" >&2 || true
161
+ exit 1
162
+ fi
163
+
164
+ echo "[published-consumer] workspace ready"
165
+ echo " url: http://127.0.0.1:${PORT}/workbench"
166
+ echo " node-count: ${NODE_COUNT}"
167
+ echo " temp-workdir: ${WORKDIR}"
168
+ echo " server-log: ${LOG_FILE}"
169
+
170
+ if [[ "${SKIP_PLAYWRIGHT}" -ne 1 ]]; then
171
+ echo "[published-consumer] running browser validation"
172
+ if ! command -v playwright-cli >/dev/null 2>&1; then
173
+ echo "[published-consumer] playwright-cli is required for browser validation." >&2
174
+ echo "Install it with: bun add -g @playwright/cli@latest" >&2
175
+ exit 1
176
+ fi
177
+
178
+ PLAYWRIGHT_SESSION="pc${PORT}"
179
+ PLAYWRIGHT_OPEN_CMD=(playwright-cli "-s=${PLAYWRIGHT_SESSION}" open "http://127.0.0.1:${PORT}/workbench" --browser chrome)
180
+ if [[ "${HEADED}" -eq 1 ]]; then
181
+ PLAYWRIGHT_OPEN_CMD+=(--headed)
182
+ fi
183
+
184
+ (
185
+ cd "${REPO_ROOT}"
186
+ rm -f .playwright-cli/page-*.yml .playwright-cli/page-*.png .playwright-cli/console-*.log 2>/dev/null || true
187
+ "${PLAYWRIGHT_OPEN_CMD[@]}"
188
+ sleep 3
189
+ playwright-cli "-s=${PLAYWRIGHT_SESSION}" snapshot >/dev/null
190
+
191
+ SNAPSHOT_FILE="$(ls -t .playwright-cli/page-*.yml | head -n 1)"
192
+ if [[ -z "${SNAPSHOT_FILE}" ]]; then
193
+ echo "[published-consumer] playwright-cli did not produce a snapshot." >&2
194
+ exit 1
195
+ fi
196
+
197
+ for expected in \
198
+ "Synthetic SDLC Report" \
199
+ "Pipeline Atlas" \
200
+ "SDLC Control Room Artifact" \
201
+ "Control Tower Widgets" \
202
+ "Release Gate Intake" \
203
+ "Service Readiness Matrix" \
204
+ "Lead Time Trend" \
205
+ "Defects by Stage" \
206
+ "Operational Load" \
207
+ "Context (3)" \
208
+ "npm pack" \
209
+ "canvas.buildWebArtifact" \
210
+ "playwright"
211
+ do
212
+ if ! rg -Fq "${expected}" "${SNAPSHOT_FILE}"; then
213
+ echo "[published-consumer] expected browser snapshot to include: ${expected}" >&2
214
+ echo "Snapshot: ${SNAPSHOT_FILE}" >&2
215
+ exit 1
216
+ fi
217
+ done
218
+
219
+ playwright-cli "-s=${PLAYWRIGHT_SESSION}" screenshot >/dev/null
220
+ SCREENSHOT_FILE="$(ls -t .playwright-cli/page-*.png | head -n 1)"
221
+ echo "[published-consumer] browser snapshot: ${SNAPSHOT_FILE}"
222
+ echo "[published-consumer] browser screenshot: ${SCREENSHOT_FILE}"
223
+
224
+ if [[ "${KEEP_RUNNING}" -ne 1 ]]; then
225
+ playwright-cli "-s=${PLAYWRIGHT_SESSION}" close >/dev/null || true
226
+ fi
227
+ )
228
+ fi
229
+
230
+ if [[ "${KEEP_RUNNING}" -eq 1 ]]; then
231
+ trap - EXIT
232
+ echo "[published-consumer] leaving server running"
233
+ echo " PMX_CANVAS_URL=http://127.0.0.1:${PORT}"
234
+ echo " PMX_CONSUMER_DIR=${CONSUMER_DIR}"
235
+ echo " PMX_SERVER_PID=${SERVER_PID}"
236
+ exit 0
237
+ fi
238
+
239
+ cleanup
240
+ trap - EXIT
241
+ echo "[published-consumer] completed"
@@ -0,0 +1,80 @@
1
+ ---
2
+ name: web-artifacts-builder
3
+ description: Suite of tools for creating elaborate, multi-component single-file HTML web artifacts using modern frontend web technologies (React, Tailwind CSS, shadcn/ui). Use for complex artifacts requiring state management, routing, or shadcn/ui components - not for simple single-file HTML/JSX artifacts.
4
+ license: Complete terms in LICENSE.txt
5
+ ---
6
+
7
+ # Web Artifacts Builder
8
+
9
+ To build powerful single-file frontend web artifacts, follow these steps:
10
+ 1. Initialize the frontend repo using `scripts/init-artifact.sh`
11
+ 2. Develop your artifact by editing the generated code
12
+ 3. Bundle all code into a single HTML file using `scripts/bundle-artifact.sh`
13
+ 4. Display artifact to user
14
+ 5. (Optional) Test the artifact
15
+
16
+ **Stack**: React 18 + TypeScript + Vite + Parcel (bundling) + Tailwind CSS + shadcn/ui
17
+
18
+ ## Design & Style Guidelines
19
+
20
+ VERY IMPORTANT: To avoid what is often referred to as "AI slop", avoid using excessive centered layouts, purple gradients, uniform rounded corners, and Inter font.
21
+
22
+ ## Quick Start
23
+
24
+ In `pmx-canvas`, prefer the `canvas_build_web_artifact` MCP tool when available. It uses the same
25
+ bundled runtime scripts, writes reusable source under `.pmx-canvas/artifacts/.web-artifacts/`,
26
+ emits a bundled HTML file under `.pmx-canvas/artifacts/`, and can open the result directly on the
27
+ canvas as an embedded node.
28
+ For browser verification after the build, pair this skill with the local `playwright-cli` skill.
29
+
30
+ ### Step 1: Initialize Project
31
+
32
+ Run the initialization script to create a new React project:
33
+ ```bash
34
+ bash scripts/init-artifact.sh <project-name>
35
+ cd <project-name>
36
+ ```
37
+
38
+ This creates a fully configured project with:
39
+ - ✅ React + TypeScript (via Vite)
40
+ - ✅ Tailwind CSS 3.4.1 with shadcn/ui theming system
41
+ - ✅ Path aliases (`@/`) configured
42
+ - ✅ 40+ shadcn/ui components pre-installed
43
+ - ✅ All Radix UI dependencies included
44
+ - ✅ Parcel configured for bundling (via .parcelrc)
45
+ - ✅ Node 18+ compatibility (auto-detects and pins Vite version)
46
+
47
+ ### Step 2: Develop Your Artifact
48
+
49
+ To build the artifact, edit the generated files. See **Common Development Tasks** below for guidance.
50
+
51
+ ### Step 3: Bundle to Single HTML File
52
+
53
+ To bundle the React app into a single HTML artifact:
54
+ ```bash
55
+ bash scripts/bundle-artifact.sh
56
+ ```
57
+
58
+ This creates `bundle.html` - a self-contained artifact with all JavaScript, CSS, and dependencies inlined. This file can be opened directly in a browser or shared in artifact-capable clients.
59
+
60
+ **Requirements**: Your project must have an `index.html` in the root directory.
61
+
62
+ **What the script does**:
63
+ - Reuses existing bundling dependencies when present; otherwise installs them once
64
+ - Creates `.parcelrc` config with path alias support
65
+ - Builds with Parcel (no source maps) using a quieter log profile
66
+ - Inlines all assets into single HTML using html-inline
67
+
68
+ ### Step 4: Share Artifact with User
69
+
70
+ Finally, share the bundled HTML file with the user or open it in the browser so they can view it.
71
+
72
+ ### Step 5: Testing/Visualizing the Artifact (Optional)
73
+
74
+ Note: This is a completely optional step. Only perform if necessary or requested.
75
+
76
+ To test/visualize the artifact, use available tools (including other Skills or built-in tools like Playwright or Puppeteer). In general, avoid testing the artifact upfront as it adds latency between the request and when the finished artifact can be seen. Test later, after presenting the artifact, if requested or if issues arise.
77
+
78
+ ## Reference
79
+
80
+ - **shadcn/ui components**: https://ui.shadcn.com/docs/components