pmx-canvas 0.1.18 → 0.1.20

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 (70) hide show
  1. package/CHANGELOG.md +128 -0
  2. package/Readme.md +19 -6
  3. package/dist/canvas/global.css +35 -2
  4. package/dist/canvas/index.js +70 -69
  5. package/dist/json-render/index.js +109 -109
  6. package/dist/types/client/canvas/CanvasViewport.d.ts +1 -1
  7. package/dist/types/client/icons.d.ts +2 -0
  8. package/dist/types/client/state/canvas-store.d.ts +2 -0
  9. package/dist/types/client/types.d.ts +2 -1
  10. package/dist/types/json-render/charts/components.d.ts +5 -1
  11. package/dist/types/json-render/renderer/index.d.ts +1 -0
  12. package/dist/types/json-render/server.d.ts +1 -0
  13. package/dist/types/mcp/canvas-access.d.ts +3 -0
  14. package/dist/types/server/canvas-operations.d.ts +4 -0
  15. package/dist/types/server/canvas-schema.d.ts +19 -3
  16. package/dist/types/server/canvas-serialization.d.ts +1 -0
  17. package/dist/types/server/canvas-state.d.ts +8 -2
  18. package/dist/types/server/html-primitives.d.ts +34 -0
  19. package/dist/types/server/index.d.ts +19 -0
  20. package/docs/RELEASE.md +153 -0
  21. package/docs/bun-webview-integration.md +296 -0
  22. package/docs/cli.md +143 -0
  23. package/docs/evals/e2e-cli-coverage.md +61 -0
  24. package/docs/http-api.md +201 -0
  25. package/docs/mcp.md +137 -0
  26. package/docs/node-types.md +272 -0
  27. package/docs/plans/.gitkeep +0 -0
  28. package/docs/plans/plan-001-semantic-watch-mvp.md +335 -0
  29. package/docs/plans/plan-002-human-attention-layer-design-spec.md +679 -0
  30. package/docs/plans/plan-003-human-attention-layer-implementation-plan.md +572 -0
  31. package/docs/reactive-canvas-proposal.md +578 -0
  32. package/docs/release-review-0.1.0.md +38 -0
  33. package/docs/screenshot.png +0 -0
  34. package/docs/screenshots/demo-workbench-dark.png +0 -0
  35. package/docs/screenshots/demo-workbench-light.png +0 -0
  36. package/docs/screenshots/welcome-dark.png +0 -0
  37. package/docs/screenshots/welcome-light.png +0 -0
  38. package/docs/sdk.md +103 -0
  39. package/package.json +2 -1
  40. package/skills/pmx-canvas/SKILL.md +8 -0
  41. package/src/cli/agent.ts +167 -5
  42. package/src/client/App.tsx +20 -1
  43. package/src/client/canvas/AnnotationLayer.tsx +33 -12
  44. package/src/client/canvas/CanvasViewport.tsx +88 -7
  45. package/src/client/canvas/CommandPalette.tsx +1 -1
  46. package/src/client/canvas/ContextMenu.tsx +2 -2
  47. package/src/client/canvas/ExpandedNodeOverlay.tsx +7 -1
  48. package/src/client/icons.tsx +13 -0
  49. package/src/client/nodes/McpAppNode.tsx +12 -4
  50. package/src/client/state/canvas-store.ts +15 -5
  51. package/src/client/state/sse-bridge.ts +4 -3
  52. package/src/client/theme/global.css +35 -2
  53. package/src/client/types.ts +2 -1
  54. package/src/json-render/charts/components.tsx +41 -7
  55. package/src/json-render/charts/extra-components.tsx +13 -12
  56. package/src/json-render/renderer/index.tsx +1 -0
  57. package/src/json-render/server.ts +3 -1
  58. package/src/mcp/canvas-access.ts +25 -0
  59. package/src/mcp/server.ts +85 -27
  60. package/src/server/agent-context.ts +17 -0
  61. package/src/server/canvas-operations.ts +91 -38
  62. package/src/server/canvas-schema.ts +83 -3
  63. package/src/server/canvas-serialization.ts +9 -2
  64. package/src/server/canvas-state.ts +27 -9
  65. package/src/server/demo-state.json +1143 -0
  66. package/src/server/demo.ts +25 -777
  67. package/src/server/html-primitives.ts +990 -0
  68. package/src/server/index.ts +43 -2
  69. package/src/server/server.ts +140 -14
  70. package/src/server/spatial-analysis.ts +3 -3
@@ -0,0 +1,572 @@
1
+ ---
2
+ title: Human Attention Layer Implementation Plan
3
+ status: draft
4
+ date: 2026-04-18
5
+ ---
6
+
7
+ # Human Attention Layer Implementation Plan
8
+
9
+ ## Summary
10
+
11
+ This plan turns the human attention layer design spec into a concrete build plan
12
+ for the current PMX Canvas client.
13
+
14
+ It maps the design onto the existing frontend architecture and defines:
15
+
16
+ - exact files to create or modify
17
+ - where semantic interpretation should live
18
+ - how the browser should consume authoritative server signals
19
+ - the recommended build order
20
+ - verification expectations
21
+
22
+ This is an implementation plan, not a final UX spec.
23
+
24
+ ## Constraints
25
+
26
+ The implementation must preserve these rules:
27
+
28
+ - state remains server-authoritative
29
+ - no second browser-only collaboration protocol
30
+ - semantic interpretation must derive from existing SSE and layout state
31
+ - no raw pointer or selection telemetry in the human-facing semantic layer
32
+ - the same semantic model should power both:
33
+ - CLI watcher
34
+ - browser attention layer
35
+
36
+ ## Current Frontend Anchors
37
+
38
+ The current client already has the right structural seams:
39
+
40
+ - [App.tsx](/Users/pepe/dev/pmx-canvas/src/client/App.tsx:1)
41
+ - mounts HUD, viewport, overlays, docked panels, minimap
42
+ - [canvas-store.ts](/Users/pepe/dev/pmx-canvas/src/client/state/canvas-store.ts:1)
43
+ - holds core canvas signals
44
+ - [sse-bridge.ts](/Users/pepe/dev/pmx-canvas/src/client/state/sse-bridge.ts:1)
45
+ - ingests server events and updates local state
46
+ - [CanvasViewport.tsx](/Users/pepe/dev/pmx-canvas/src/client/canvas/CanvasViewport.tsx:1)
47
+ - owns world-space rendering order
48
+ - [CanvasNode.tsx](/Users/pepe/dev/pmx-canvas/src/client/canvas/CanvasNode.tsx:1)
49
+ - owns node-level classes and titlebar controls
50
+ - [global.css](/Users/pepe/dev/pmx-canvas/src/client/theme/global.css:1)
51
+ - already centralizes most canvas chrome and overlay styling
52
+
53
+ These are enough to add the new UX layer without redesigning the app shell.
54
+
55
+ ## Architectural Decision
56
+
57
+ ### Extract shared semantic reduction
58
+
59
+ The semantic logic should **not** stay CLI-only.
60
+
61
+ The current watch reducer in [src/cli/watch.ts](/Users/pepe/dev/pmx-canvas/src/cli/watch.ts:1)
62
+ is a good MVP, but the browser should not import from `src/cli/`.
63
+
64
+ ### Required refactor
65
+
66
+ Create a shared semantic module, for example:
67
+
68
+ - `src/shared/semantic-attention.ts`
69
+
70
+ This module should own:
71
+
72
+ - semantic event types
73
+ - semantic reducer
74
+ - layout diff logic
75
+ - cluster and neighborhood change detection
76
+ - shared compact label helpers if useful
77
+
78
+ The CLI watcher should then consume that shared reducer, and the browser
79
+ attention layer should consume the same reducer.
80
+
81
+ ### What stays CLI-specific
82
+
83
+ Keep these in `src/cli/watch.ts`:
84
+
85
+ - SSE stream parser
86
+ - CLI output formatting
87
+ - `--events` filter parsing
88
+ - `--max-events` control flow
89
+
90
+ ### Why
91
+
92
+ This prevents logic drift between:
93
+
94
+ - `pmx-canvas watch`
95
+ - the browser’s human-facing interpretation UI
96
+
97
+ That alignment is important. The human-facing layer and the agent-facing watcher
98
+ must describe the same meaning changes.
99
+
100
+ ## Proposed File Changes
101
+
102
+ ### New shared module
103
+
104
+ - `src/shared/semantic-attention.ts`
105
+
106
+ Responsibility:
107
+
108
+ - define shared semantic event types
109
+ - expose reducer class or reducer functions
110
+ - accept:
111
+ - previous layout
112
+ - next layout
113
+ - current pin set
114
+ - return:
115
+ - semantic events
116
+ - derived attention state if needed
117
+
118
+ Notes:
119
+
120
+ - this should operate on shape-compatible canvas layout data only
121
+ - avoid browser APIs and avoid Node-only APIs
122
+
123
+ ### New client state module
124
+
125
+ - `src/client/state/attention-store.ts`
126
+
127
+ Responsibility:
128
+
129
+ - hold browser-only attention UI signals
130
+ - expose semantic event queue/history
131
+ - hold current focus field state
132
+ - hold currently emphasized node IDs
133
+ - hold ephemeral toast state
134
+
135
+ Recommended signals:
136
+
137
+ - `attentionFeed`
138
+ - `attentionToast`
139
+ - `attentionHistory`
140
+ - `attentionFocusNodeIds`
141
+ - `attentionNeighborhoodNodeIds`
142
+ - `attentionPulseNodeIds`
143
+ - `attentionFieldVersion` or similar tick for transition timing
144
+
145
+ This should not duplicate layout state. It should only hold presentation state
146
+ derived from semantic changes.
147
+
148
+ ### New client controller module
149
+
150
+ - `src/client/state/attention-bridge.ts`
151
+
152
+ Responsibility:
153
+
154
+ - receive authoritative SSE-backed layout/pin changes
155
+ - call the shared semantic reducer
156
+ - translate semantic events into browser presentation state
157
+
158
+ This module is the browser equivalent of the CLI watch command, but for UI
159
+ state instead of stdout.
160
+
161
+ Why separate it from `attention-store.ts`:
162
+
163
+ - store stays dumb and signal-based
164
+ - bridge owns interpretation and state transitions
165
+
166
+ ### New UI components
167
+
168
+ - `src/client/canvas/AttentionToast.tsx`
169
+ - `src/client/canvas/AttentionHistory.tsx`
170
+ - `src/client/canvas/FocusFieldLayer.tsx`
171
+
172
+ Responsibilities:
173
+
174
+ `AttentionToast.tsx`
175
+ - renders the live semantic feedback surface
176
+ - one primary active message
177
+ - optional short queue
178
+
179
+ `AttentionHistory.tsx`
180
+ - renders the recent interpretation rail
181
+ - 3–8 recent semantic events
182
+ - click/hover affordances can be stubbed or deferred
183
+
184
+ `FocusFieldLayer.tsx`
185
+ - renders the persistent spatial emphasis behind or around:
186
+ - pinned nodes
187
+ - inferred neighborhood nodes
188
+
189
+ This should be world-space aware and tied to current node geometry.
190
+
191
+ ### Existing file updates
192
+
193
+ #### `src/client/state/sse-bridge.ts`
194
+
195
+ Changes:
196
+
197
+ - add support for `context-pins-changed` to `EVENT_HANDLERS`
198
+ - call into `attention-bridge.ts` whenever:
199
+ - `canvas-layout-update` is applied
200
+ - `context-pins-changed` arrives
201
+
202
+ Recommended rule:
203
+
204
+ - let current layout/state update first
205
+ - then feed the normalized next state into the attention bridge
206
+
207
+ Do not render semantic UI straight from raw SSE handler bodies.
208
+
209
+ #### `src/client/state/canvas-store.ts`
210
+
211
+ Changes:
212
+
213
+ - none for core layout semantics unless a tiny helper export is useful
214
+ - do not bloat this file with attention UI state if avoidable
215
+
216
+ This file should remain the canvas truth layer, not the semantic presentation
217
+ layer.
218
+
219
+ #### `src/client/App.tsx`
220
+
221
+ Changes:
222
+
223
+ - mount the new attention UI surfaces
224
+ - recommended placement:
225
+ - `AttentionToast` in HUD layer near toolbar or top-right rail
226
+ - `AttentionHistory` in right-side HUD stack, visually distinct from docked
227
+ content
228
+ - `FocusFieldLayer` mounted adjacent to or inside `CanvasViewport`
229
+
230
+ Potential future cleanup:
231
+
232
+ - once attention history and focus field are strong enough, the current
233
+ `ContextPinHud` and `ContextPinBar` can be reduced or removed
234
+
235
+ Do not remove them in the first pass. Build the new surfaces first, then trim.
236
+
237
+ #### `src/client/canvas/CanvasViewport.tsx`
238
+
239
+ Changes:
240
+
241
+ - render `FocusFieldLayer` in world space
242
+ - ensure rendering order keeps it:
243
+ - above background
244
+ - below nodes and edges, or below nodes but possibly above the base grid
245
+
246
+ Recommended order:
247
+
248
+ 1. background
249
+ 2. focus field
250
+ 3. edges
251
+ 4. nodes
252
+ 5. lasso/drop/snap overlays
253
+
254
+ #### `src/client/canvas/CanvasNode.tsx`
255
+
256
+ Changes:
257
+
258
+ - add classes for semantic emphasis:
259
+ - `attention-pulse`
260
+ - `attention-focus-primary`
261
+ - `attention-focus-secondary`
262
+ - keep these visually distinct from:
263
+ - selection
264
+ - active node
265
+ - context-pinned
266
+
267
+ Do not overload existing `context-pinned` styling to do all the work.
268
+ Pinned-state and semantic-attention-state need to be related but not identical.
269
+
270
+ #### `src/client/theme/global.css`
271
+
272
+ Changes:
273
+
274
+ - add styles for:
275
+ - attention toast
276
+ - attention history rail
277
+ - focus field region
278
+ - node pulse states
279
+ - reduced-motion fallbacks
280
+
281
+ This file should remain the styling center for the first pass.
282
+
283
+ Do not split CSS until the UI stabilizes.
284
+
285
+ #### `src/client/icons.tsx`
286
+
287
+ Optional:
288
+
289
+ - add 1–2 icons if needed for history labels or toast affordances
290
+
291
+ Avoid icon-heavy UI here. The semantic layer should primarily rely on text,
292
+ spacing, and motion.
293
+
294
+ ## Recommended Build Phases
295
+
296
+ ### Phase 0: Shared semantic extraction
297
+
298
+ Goal:
299
+
300
+ - move reducer logic out of CLI-only code into shared space
301
+
302
+ Steps:
303
+
304
+ 1. create `src/shared/semantic-attention.ts`
305
+ 2. move pure semantic event and diff logic there
306
+ 3. update `src/cli/watch.ts` to import shared reducer
307
+ 4. keep existing `cli-watch` tests green
308
+
309
+ Why first:
310
+
311
+ - it guarantees browser and CLI will use the same meaning model
312
+
313
+ ### Phase 1: Browser attention state pipeline
314
+
315
+ Goal:
316
+
317
+ - let the browser compute semantic events from existing SSE/layout changes
318
+
319
+ Steps:
320
+
321
+ 1. add `src/client/state/attention-store.ts`
322
+ 2. add `src/client/state/attention-bridge.ts`
323
+ 3. wire `context-pins-changed` into `sse-bridge.ts`
324
+ 4. feed `canvas-layout-update` and pin changes into the shared reducer
325
+
326
+ Deliverable:
327
+
328
+ - internal browser attention state updates exist, even if not yet rendered
329
+
330
+ Verification:
331
+
332
+ - unit tests around attention bridge behavior
333
+ - ensure no regressions in existing SSE behavior
334
+
335
+ ### Phase 2: Live semantic feedback
336
+
337
+ Goal:
338
+
339
+ - render the first visible “board understood you” surface
340
+
341
+ Steps:
342
+
343
+ 1. build `AttentionToast.tsx`
344
+ 2. mount it in `App.tsx`
345
+ 3. style in `global.css`
346
+ 4. feed semantic events into a one-item active toast queue
347
+
348
+ This is the first user-visible win and should ship before the full history rail.
349
+
350
+ Why:
351
+
352
+ - immediate feedback gives the fastest improvement to human trust
353
+
354
+ ### Phase 3: Focus field
355
+
356
+ Goal:
357
+
358
+ - make the active agent working set visible on the board
359
+
360
+ Steps:
361
+
362
+ 1. build `FocusFieldLayer.tsx`
363
+ 2. derive primary and secondary node IDs from attention state
364
+ 3. render pooled spatial emphasis in `CanvasViewport.tsx`
365
+ 4. add node-level emphasis classes in `CanvasNode.tsx`
366
+
367
+ This phase makes context feel like a working set rather than metadata.
368
+
369
+ This is the most important visual feature after the toast.
370
+
371
+ ### Phase 4: Interpretation history rail
372
+
373
+ Goal:
374
+
375
+ - provide recoverable trust and recent semantic memory
376
+
377
+ Steps:
378
+
379
+ 1. build `AttentionHistory.tsx`
380
+ 2. mount it in right HUD stack in `App.tsx`
381
+ 3. add event coalescing and limit logic in `attention-bridge.ts`
382
+
383
+ This can initially be read-only.
384
+
385
+ Hover/focus affordances can be added later.
386
+
387
+ ### Phase 5: Cleanup and simplification
388
+
389
+ Goal:
390
+
391
+ - reduce redundant older pin UI once the new surfaces are proven
392
+
393
+ Candidates:
394
+
395
+ - shrink or remove `ContextPinHud.tsx`
396
+ - shrink or remove `ContextPinBar.tsx`
397
+
398
+ Do this only after:
399
+
400
+ - focus field is stable
401
+ - attention history is readable
402
+ - semantic toast carries the acknowledgment burden
403
+
404
+ ## State Flow
405
+
406
+ Recommended browser flow:
407
+
408
+ 1. SSE event arrives in `sse-bridge.ts`
409
+ 2. layout/pin state is normalized into `canvas-store`
410
+ 3. `attention-bridge.ts` receives the new authoritative state
411
+ 4. shared semantic reducer compares previous vs next state
412
+ 5. browser attention store updates:
413
+ - toast
414
+ - history
415
+ - focus field node IDs
416
+ - pulse node IDs
417
+
418
+ This keeps the attention layer downstream of the authoritative canvas state.
419
+
420
+ ## UI Placement Recommendations
421
+
422
+ ### AttentionToast
423
+
424
+ Preferred placement:
425
+
426
+ - top-right, near but not inside the toolbar cluster
427
+
428
+ Reason:
429
+
430
+ - visible immediately after interaction
431
+ - close to existing chrome
432
+ - does not obstruct canvas center
433
+
434
+ ### AttentionHistory
435
+
436
+ Preferred placement:
437
+
438
+ - right-side HUD column, above or below docked context/ledger nodes depending on
439
+ actual density
440
+
441
+ Reason:
442
+
443
+ - the right side already reads as “stateful reference area”
444
+ - users can scan history there without masking the board
445
+
446
+ ### FocusFieldLayer
447
+
448
+ Preferred placement:
449
+
450
+ - world space, inside the canvas viewport
451
+
452
+ Reason:
453
+
454
+ - context needs to feel spatial, not dashboarded
455
+
456
+ ## Styling Guidance For Implementation
457
+
458
+ ### Keep
459
+
460
+ - existing dark technical shell as base
461
+ - the current node/chrome system as scaffolding
462
+
463
+ ### Add
464
+
465
+ - stronger semantic hierarchy
466
+ - a distinct palette for:
467
+ - curated context
468
+ - inferred neighborhood
469
+ - semantic acknowledgment
470
+
471
+ ### Avoid
472
+
473
+ - overloading selection styling
474
+ - overusing bright accent everywhere
475
+ - generic toast library aesthetics
476
+ - “AI neon” visuals
477
+
478
+ ## Animation Plan
479
+
480
+ ### v1 Required motion
481
+
482
+ - toast enter/exit
483
+ - one-shot node pulse
484
+ - focus field re-form transition
485
+
486
+ ### v1 Not required
487
+
488
+ - timeline scrubbing
489
+ - multi-stage choreography
490
+ - particle or ambient decorative systems
491
+
492
+ ### Reduced motion
493
+
494
+ Every semantic effect should have a reduced-motion fallback:
495
+
496
+ - swap movement for opacity
497
+ - swap pulses for single-step state emphasis
498
+
499
+ ## Testing Strategy
500
+
501
+ ### Unit
502
+
503
+ Add tests for:
504
+
505
+ - shared semantic reducer after extraction
506
+ - attention bridge:
507
+ - converts semantic events to store state
508
+ - coalesces/suppresses duplicate updates
509
+
510
+ ### Browser smoke
511
+
512
+ After client implementation:
513
+
514
+ - `bun run build`
515
+ - `bun run test:web-canvas`
516
+
517
+ Add at least one browser test covering:
518
+
519
+ 1. pin node
520
+ 2. observe semantic toast
521
+ 3. observe focus field or history update
522
+
523
+ ### Manual validation
524
+
525
+ Use headed browser validation for UX checks when reviewing motion and emphasis.
526
+
527
+ Suggested flows:
528
+
529
+ 1. pin a node
530
+ 2. move a related node nearby
531
+ 3. group two nodes
532
+ 4. connect two nodes
533
+ 5. remove a node
534
+
535
+ For each:
536
+
537
+ - semantic acknowledgment appears
538
+ - affected nodes are visually emphasized
539
+ - history rail updates
540
+ - no noisy duplicate feedback
541
+
542
+ ## Sequencing Recommendation
543
+
544
+ If only one piece can be built first:
545
+
546
+ 1. shared semantic extraction
547
+ 2. live semantic feedback toast
548
+ 3. focus field
549
+ 4. history rail
550
+
551
+ That order gives the best human UX return per unit of implementation effort.
552
+
553
+ ## MVP Completion Criteria
554
+
555
+ The first implementation pass is complete when:
556
+
557
+ - browser derives semantic events from existing authoritative state
558
+ - human sees immediate semantic acknowledgment after meaningful canvas changes
559
+ - active context is visible spatially on the board
560
+ - recent semantic changes are inspectable in a lightweight panel
561
+ - no raw move/select noise is surfaced
562
+
563
+ ## Final Rule
564
+
565
+ If implementation choices force a tradeoff, prefer:
566
+
567
+ - clearer semantic consequence
568
+ over
569
+ - more control chrome
570
+
571
+ The whole point of this layer is to make the human feel that the canvas is a
572
+ shared thinking instrument, not just a board editor.