pmx-canvas 0.11.0 → 0.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/extensions/pmx-canvas/extension.mjs +4 -1
- package/.github/extensions/pmx-canvas/runtime.json +1 -1
- package/.github/extensions/pmx-canvas/tools.json +440 -18
- package/CHANGELOG.md +51 -0
- package/dist/amp-plugin/pmx-canvas/LICENSE +21 -0
- package/dist/amp-plugin/pmx-canvas/THIRD_PARTY_LICENSES.txt +331 -0
- package/dist/amp-plugin/pmx-canvas/index.js +5445 -0
- package/dist/amp-plugin/pmx-canvas/runtime.json +3 -0
- package/dist/amp-plugin/pmx-canvas/shared-runtime.mjs +194 -0
- package/dist/amp-plugin/pmx-canvas/skills/pmx-canvas/SKILL.md +267 -0
- package/dist/amp-plugin/pmx-canvas/skills/pmx-canvas/evals/evals.json +1168 -0
- package/dist/amp-plugin/pmx-canvas/skills/pmx-canvas/evals/fixtures/code-exploration/src/auth/jwt.ts +17 -0
- package/dist/amp-plugin/pmx-canvas/skills/pmx-canvas/evals/fixtures/code-exploration/src/auth/login.ts +12 -0
- package/dist/amp-plugin/pmx-canvas/skills/pmx-canvas/evals/fixtures/code-exploration/src/auth/middleware.ts +13 -0
- package/dist/amp-plugin/pmx-canvas/skills/pmx-canvas/evals/fixtures/code-exploration/src/routes/auth.ts +13 -0
- package/dist/amp-plugin/pmx-canvas/skills/pmx-canvas/evals/fixtures/investigation-board/src/handlers/users.ts +27 -0
- package/dist/amp-plugin/pmx-canvas/skills/pmx-canvas/mcp.json +36 -0
- package/dist/amp-plugin/pmx-canvas/skills/pmx-canvas/references/ax-html-control-surface.md +101 -0
- package/dist/amp-plugin/pmx-canvas/skills/pmx-canvas/references/codex-app-adapter.md +151 -0
- package/dist/amp-plugin/pmx-canvas/skills/pmx-canvas/references/excalidraw-diagram-authoring.md +150 -0
- package/dist/amp-plugin/pmx-canvas/skills/pmx-canvas/references/full-reference.md +1839 -0
- package/dist/amp-plugin/pmx-canvas/skills/pmx-canvas/references/github-copilot-app-adapter.md +223 -0
- package/dist/amp-plugin/pmx-canvas/skills/pmx-canvas/references/html-primitives.md +139 -0
- package/dist/amp-plugin/pmx-canvas/skills/pmx-canvas/references/importing-context.md +132 -0
- package/dist/amp-plugin/pmx-canvas/skills/pmx-canvas/references/installing-pmx-canvas.md +301 -0
- package/dist/amp-plugin/pmx-canvas/skills/pmx-canvas/references/tours-and-recording.md +117 -0
- package/dist/amp-plugin/pmx-canvas/skills/pmx-canvas/references/workbench-workflows.md +908 -0
- package/dist/amp-plugin/pmx-canvas/skills/pmx-canvas-orchestration/SKILL.md +141 -0
- package/dist/amp-plugin/pmx-canvas/skills/pmx-canvas-testing/SKILL.md +266 -0
- package/dist/amp-plugin/pmx-canvas/start-mcp.mjs +14857 -0
- package/dist/amp-plugin/pmx-canvas/tools.json +10963 -0
- package/dist/canvas/chunks/{abnfDiagram-N423BO3Z-p8dtp6va.js → abnfDiagram-N423BO3Z-cwtsds5d.js} +1 -1
- package/dist/canvas/chunks/architecture-TIHT7OUA-x63cwejs.js +1 -0
- package/dist/canvas/chunks/{architectureDiagram-T3A2C74G-5jhmxrzf.js → architectureDiagram-T3A2C74G-b4xc9tpz.js} +3 -3
- package/dist/canvas/chunks/{blockDiagram-VBNYF7ZC-pw1fa9yb.js → blockDiagram-VBNYF7ZC-ahp3yxxs.js} +7 -7
- package/dist/canvas/chunks/{c4Diagram-5PPSVZJV-x07nq0tt.js → c4Diagram-5PPSVZJV-nappnay7.js} +4 -4
- package/dist/canvas/chunks/classDiagram-JCYQIIEL-k1j2xc1t.js +1 -0
- package/dist/canvas/chunks/classDiagram-v2-OCEON4UE-33x08xf2.js +1 -0
- package/dist/canvas/chunks/{cose-bilkent-JH36ORCC-nm39npq0.js → cose-bilkent-JH36ORCC-a428syda.js} +1 -1
- package/dist/canvas/chunks/cynefin-VYW2F7L2-8v6jxfz8.js +1 -0
- package/dist/canvas/chunks/{cynefinDiagram-MW4NZA55-vdxrwahz.js → cynefinDiagram-MW4NZA55-nspsqebj.js} +1 -1
- package/dist/canvas/chunks/{dagre-VZM6K2ZE-bqdm7wpd.js → dagre-VZM6K2ZE-8y6177fh.js} +2 -2
- package/dist/canvas/chunks/{diagram-7IWD3JNH-gs5gpr93.js → diagram-7IWD3JNH-vym028wn.js} +4 -4
- package/dist/canvas/chunks/{diagram-B4RE2ZJO-cgwjg47s.js → diagram-B4RE2ZJO-jddqb8sy.js} +1 -1
- package/dist/canvas/chunks/{diagram-LBJQPF4R-w3vahpav.js → diagram-LBJQPF4R-bjwbpkrn.js} +1 -1
- package/dist/canvas/chunks/{diagram-Q27KOJAE-42837z6h.js → diagram-Q27KOJAE-j6ph6hcx.js} +2 -2
- package/dist/canvas/chunks/{diagram-UB23O5K3-4fz83q59.js → diagram-UB23O5K3-p09w8jej.js} +1 -1
- package/dist/canvas/chunks/{ebnfDiagram-BXEA7PRR-zphtgegj.js → ebnfDiagram-BXEA7PRR-j975ycq5.js} +1 -1
- package/dist/canvas/chunks/{erDiagram-JOGREHBK-zvbbdxp4.js → erDiagram-JOGREHBK-sxp6hjn8.js} +5 -5
- package/dist/canvas/chunks/eventmodeling-45OFAUF4-xzfgn6xg.js +1 -0
- package/dist/canvas/chunks/flowDiagram-UKHOOZJN-2nsmkskb.js +1 -0
- package/dist/canvas/chunks/{ganttDiagram-PKOTCBZU-282jzycm.js → ganttDiagram-PKOTCBZU-4tv230y2.js} +2 -2
- package/dist/canvas/chunks/gitGraph-TEB2WS4Q-macbhand.js +1 -0
- package/dist/canvas/chunks/{gitGraphDiagram-DS77QQ5N-vqqy6p1b.js → gitGraphDiagram-DS77QQ5N-mqgmnw9g.js} +1 -1
- package/dist/canvas/chunks/{index-wgv7en21.js → index-037z5dz2.js} +2 -2
- package/dist/canvas/chunks/{index-w2mra17t.js → index-081n3har.js} +1 -1
- package/dist/canvas/chunks/{index-353m7b0p.js → index-5n03dmb9.js} +1 -1
- package/dist/canvas/chunks/{index-yw8h9vha.js → index-60pgzdqe.js} +1 -1
- package/dist/canvas/chunks/index-8g1vb57n.js +2 -0
- package/dist/canvas/chunks/{index-vv56h019.js → index-8rjes9r6.js} +1 -1
- package/dist/canvas/chunks/{index-nprm96xp.js → index-9022d1n9.js} +1 -1
- package/dist/canvas/chunks/{index-194m3hc3.js → index-9b02042t.js} +1 -1
- package/dist/canvas/chunks/{index-0rk4gp1g.js → index-ap4q4vez.js} +1 -1
- package/dist/canvas/chunks/{index-rh7nv68n.js → index-dyp2nhd3.js} +1 -1
- package/dist/canvas/chunks/index-frvta4tm.js +2 -0
- package/dist/canvas/chunks/{index-s4j678gj.js → index-h9ycj8n2.js} +1 -1
- package/dist/canvas/chunks/{index-fjtdggjn.js → index-mergmj97.js} +2 -2
- package/dist/canvas/chunks/index-nwsya6dj.js +301 -0
- package/dist/canvas/chunks/{index-3cy1bzwh.js → index-nz8qbd1p.js} +1 -1
- package/dist/canvas/chunks/{index-d3b3gqe9.js → index-qhfrazv3.js} +1 -1
- package/dist/canvas/chunks/{index-6qmsnxwy.js → index-v119nznk.js} +4 -4
- package/dist/canvas/chunks/{index-r2fyc9w1.js → index-vpt37m3d.js} +6 -6
- package/dist/canvas/chunks/{index-qj8fxwsf.js → index-y9ma6azy.js} +1 -1
- package/dist/canvas/chunks/{index-tb1wf525.js → index-zx0j3a2z.js} +26 -26
- package/dist/canvas/chunks/info-DKCQHKI2-a0ykzs9z.js +1 -0
- package/dist/canvas/chunks/{infoDiagram-6WML65LV-v1yvggqj.js → infoDiagram-6WML65LV-qv97qq6a.js} +2 -2
- package/dist/canvas/chunks/ishikawaDiagram-WSZJBQD7-p9306gh0.js +70 -0
- package/dist/canvas/chunks/{journeyDiagram-NVQOT4AX-zjcffveh.js → journeyDiagram-NVQOT4AX-sv67zats.js} +5 -5
- package/dist/canvas/chunks/{kanban-definition-27J2QSJJ-dakqtfp1.js → kanban-definition-27J2QSJJ-k2pfam6p.js} +1 -1
- package/dist/canvas/chunks/{mermaid.core-j2geswrd.js → mermaid.core-83r0fdce.js} +4 -4
- package/dist/canvas/chunks/{mindmap-definition-FAOFIHXS-142xhr3k.js → mindmap-definition-FAOFIHXS-vg2newm1.js} +1 -1
- package/dist/canvas/chunks/packet-7NZHBO7P-tqnabcdv.js +1 -0
- package/dist/canvas/chunks/{pegDiagram-VL7TDLO6-5wvk7vsd.js → pegDiagram-VL7TDLO6-k2h7zc5n.js} +1 -1
- package/dist/canvas/chunks/pie-RZYD4A2V-wke6gyhe.js +1 -0
- package/dist/canvas/chunks/{pieDiagram-7S7Q4E2Y-ztdhwycc.js → pieDiagram-7S7Q4E2Y-hg169p1v.js} +2 -2
- package/dist/canvas/chunks/{quadrantDiagram-CIZ2JOQS-c5p9gmg6.js → quadrantDiagram-CIZ2JOQS-bxtvsq0b.js} +5 -5
- package/dist/canvas/chunks/radar-I7S5WNFK-w7ka0drw.js +1 -0
- package/dist/canvas/chunks/railroad-3IZDKUUU-y3vg318x.js +1 -0
- package/dist/canvas/chunks/railroad-abnf-AHOZXSZD-6hqvcz3c.js +1 -0
- package/dist/canvas/chunks/railroad-ebnf-EBAXGLYW-vcae260m.js +1 -0
- package/dist/canvas/chunks/railroad-peg-LSFZ7HO6-0dbyme23.js +1 -0
- package/dist/canvas/chunks/{railroadDiagram-AXF67PYL-xkmqkjwf.js → railroadDiagram-AXF67PYL-njyhcp4p.js} +1 -1
- package/dist/canvas/chunks/{requirementDiagram-LRYGKXZP-9wm2dyaw.js → requirementDiagram-LRYGKXZP-2z6v09gm.js} +4 -4
- package/dist/canvas/chunks/{sankeyDiagram-W5VNT64P-2w19etgb.js → sankeyDiagram-W5VNT64P-15mzam0e.js} +1 -1
- package/dist/canvas/chunks/{sequenceDiagram-SI44F4Z6-0jn0vwmz.js → sequenceDiagram-SI44F4Z6-rbshyd2c.js} +12 -12
- package/dist/canvas/chunks/{sizeCapture-X5ZJPWSS-x75epwdq.js → sizeCapture-X5ZJPWSS-sg26xwts.js} +1 -1
- package/dist/canvas/chunks/{stateDiagram-OKZ733FA-schjpy6d.js → stateDiagram-OKZ733FA-6eahp98e.js} +1 -1
- package/dist/canvas/chunks/stateDiagram-v2-UEYNNEHI-tty0ggn5.js +1 -0
- package/dist/canvas/chunks/{swimlanes-SLNWSIFB-gkw4xce3.js → swimlanes-SLNWSIFB-ze5db10t.js} +1 -1
- package/dist/canvas/chunks/swimlanesDiagram-ULZ7WXOC-thze75gq.js +8 -0
- package/dist/canvas/chunks/{timeline-definition-Z64GVDOM-x7nkcy01.js → timeline-definition-Z64GVDOM-vnp7jyy8.js} +3 -3
- package/dist/canvas/chunks/treeView-QDETBFTQ-6ysffnm6.js +1 -0
- package/dist/canvas/chunks/treemap-6X3UGDF4-m3h9p066.js +1 -0
- package/dist/canvas/chunks/vennDiagram-T6HMQDX7-0qrnb7mj.js +34 -0
- package/dist/canvas/chunks/wardley-OPB4EBWU-dp37drwx.js +1 -0
- package/dist/canvas/chunks/{wardleyDiagram-T6FBY63Y-t1j52t9r.js → wardleyDiagram-T6FBY63Y-8nxg8wqt.js} +4 -4
- package/dist/canvas/chunks/{xychartDiagram-ELKLHX3M-38t16pme.js → xychartDiagram-ELKLHX3M-nj921e7s.js} +5 -5
- package/dist/canvas/global.css +94 -1
- package/dist/canvas/index.js +154 -145
- package/dist/canvas/mcp-app.html +600 -498
- package/dist/json-render/index.css +1 -1
- package/dist/types/client/canvas/BoardMoveDialog.d.ts +2 -0
- package/dist/types/client/canvas/EdgeEditor.d.ts +19 -0
- package/dist/types/client/canvas/GroupNavigation.d.ts +2 -0
- package/dist/types/client/canvas/TextPrompt.d.ts +4 -0
- package/dist/types/client/nodes/PromptNode.d.ts +1 -0
- package/dist/types/client/nodes/ViewerFrame.d.ts +1 -1
- package/dist/types/client/nodes/WorkCard.d.ts +7 -0
- package/dist/types/client/nodes/use-ax-surface-bridge.d.ts +1 -0
- package/dist/types/client/state/canvas-store.d.ts +15 -0
- package/dist/types/client/state/human-store.d.ts +2 -0
- package/dist/types/client/state/intent-bridge.d.ts +4 -2
- package/dist/types/client/state/relation-store.d.ts +11 -0
- package/dist/types/client/types.d.ts +1 -1
- package/dist/types/json-render/catalog.d.ts +2 -2
- package/dist/types/server/agent-presence.d.ts +1 -0
- package/dist/types/server/ax-interaction.d.ts +1 -0
- package/dist/types/server/ax-state-manager.d.ts +10 -2
- package/dist/types/server/board-local.d.ts +4 -0
- package/dist/types/server/board-move.d.ts +38 -0
- package/dist/types/server/canvas-db.d.ts +12 -2
- package/dist/types/server/canvas-operations.d.ts +5 -6
- package/dist/types/server/canvas-provenance.d.ts +1 -1
- package/dist/types/server/canvas-serialization.d.ts +1 -0
- package/dist/types/server/canvas-state.d.ts +84 -20
- package/dist/types/server/card-relocation.d.ts +6 -0
- package/dist/types/server/context-reads.d.ts +3 -1
- package/dist/types/server/human-presence.d.ts +1 -1
- package/dist/types/server/index.d.ts +16 -5
- package/dist/types/server/intent-registry.d.ts +8 -4
- package/dist/types/server/knowledge-lifecycle.d.ts +4 -2
- package/dist/types/server/mutation-history.d.ts +7 -5
- package/dist/types/server/operations/registry.d.ts +2 -0
- package/dist/types/server/trace-manager.d.ts +1 -0
- package/dist/types/shared/ax-kinds.d.ts +6 -0
- package/dist/types/shared/ax-surface-protocol.d.ts +8 -0
- package/dist/types/shared/human-presence.d.ts +1 -0
- package/dist/types/shared/lifecycle-status.d.ts +2 -0
- package/docs/RELEASE.md +21 -14
- package/docs/agent-plugin.md +22 -2
- package/docs/amp-plugin.md +270 -0
- package/docs/cli.md +42 -3
- package/docs/design/GuestName.dc.html +50 -0
- package/docs/design/PluginLogo.svg +7 -0
- package/docs/design/WorkCards.dc.html +39 -0
- package/docs/design/canvas.json +16 -0
- package/docs/design/plugin-logo.png +0 -0
- package/docs/design.md +111 -8
- package/docs/evals/agents-md-sections.md +38 -0
- package/docs/http-api.md +128 -10
- package/docs/mcp.md +61 -9
- package/docs/node-types.md +71 -1
- package/docs/plans/plan-009-tech-debt-backlog.md +1 -1
- package/docs/plans/plan-019-post-0.9-roadmap.md +44 -20
- package/docs/plans/plan-020-wave-5-work-planning.md +553 -0
- package/docs/product-vision-2026-09.md +33 -17
- package/docs/sdk.md +18 -0
- package/package.json +6 -3
- package/plugins/pmx-canvas/assets/preview.png +0 -0
- package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/extension.mjs +4 -1
- package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/runtime.json +1 -1
- package/plugins/pmx-canvas/plugin.json +2 -2
- package/plugins/pmx-canvas/runtime.json +1 -1
- package/plugins/pmx-canvas/tools.json +440 -18
- package/skills/data-analysis/SKILL.md +13 -26
- package/skills/frontend-design/LICENSE.txt +177 -0
- package/skills/frontend-design/SKILL.md +3 -0
- package/skills/pmx-canvas/SKILL.md +248 -842
- package/skills/pmx-canvas/evals/evals.json +110 -5
- package/skills/pmx-canvas/references/full-reference.md +142 -28
- package/skills/pmx-canvas/references/html-primitives.md +7 -0
- package/skills/pmx-canvas/references/installing-pmx-canvas.md +61 -11
- package/skills/pmx-canvas/references/tours-and-recording.md +39 -6
- package/skills/pmx-canvas/references/workbench-workflows.md +908 -0
- package/skills/pmx-canvas-testing/SKILL.md +7 -5
- package/skills/published-consumer-e2e/SKILL.md +25 -8
- package/skills/published-consumer-e2e/scripts/run-published-consumer-e2e.sh +51 -75
- package/skills/web-artifacts-builder/LICENSE.txt +202 -0
- package/skills/web-artifacts-builder/SKILL.md +6 -0
- package/skills/web-artifacts-builder/scripts/bundle-artifact.sh +2 -2
- package/skills/web-artifacts-builder/scripts/init-artifact.sh +8 -8
- package/src/cli/commands/apps.ts +1 -0
- package/src/cli/commands/boards.ts +30 -0
- package/src/client/App.tsx +20 -4
- package/src/client/canvas/AttentionHistory.tsx +10 -2
- package/src/client/canvas/BoardMoveDialog.tsx +225 -0
- package/src/client/canvas/CanvasNode.tsx +45 -2
- package/src/client/canvas/CanvasViewport.tsx +38 -9
- package/src/client/canvas/ContextMenu.tsx +34 -12
- package/src/client/canvas/EdgeEditor.tsx +149 -0
- package/src/client/canvas/EdgeLayer.tsx +87 -16
- package/src/client/canvas/ExpandedNodeOverlay.tsx +4 -0
- package/src/client/canvas/GroupNavigation.tsx +85 -0
- package/src/client/canvas/RelationsPanel.tsx +9 -0
- package/src/client/canvas/SelectionBar.tsx +21 -0
- package/src/client/canvas/SessionPanel.tsx +35 -1
- package/src/client/canvas/TextPrompt.tsx +18 -1
- package/src/client/canvas/TopBar.tsx +30 -0
- package/src/client/canvas/canvas-area.ts +1 -1
- package/src/client/nodes/ExtAppFrame.tsx +26 -10
- package/src/client/nodes/MarkdownNode.tsx +6 -7
- package/src/client/nodes/PromptNode.tsx +32 -3
- package/src/client/nodes/StatusNode.tsx +12 -0
- package/src/client/nodes/StatusSummary.tsx +11 -0
- package/src/client/nodes/ViewerFrame.tsx +21 -10
- package/src/client/nodes/WorkCard.tsx +175 -0
- package/src/client/nodes/use-ax-surface-bridge.ts +18 -14
- package/src/client/state/attention-bridge.ts +5 -0
- package/src/client/state/attention-store.ts +1 -0
- package/src/client/state/canvas-store.ts +185 -15
- package/src/client/state/human-store.ts +22 -2
- package/src/client/state/intent-bridge.ts +19 -5
- package/src/client/state/relation-store.ts +127 -1
- package/src/client/theme/global.css +94 -1
- package/src/client/types.ts +1 -0
- package/src/mcp/server.ts +13 -3
- package/src/server/agent-presence.ts +43 -23
- package/src/server/ax-flow-loop.ts +6 -0
- package/src/server/ax-gate-ttl.ts +8 -1
- package/src/server/ax-interaction.ts +16 -10
- package/src/server/ax-state-manager.ts +17 -4
- package/src/server/ax-wait.ts +20 -6
- package/src/server/board-export.ts +19 -6
- package/src/server/board-local.ts +20 -0
- package/src/server/board-move.ts +297 -0
- package/src/server/canvas-db.ts +262 -160
- package/src/server/canvas-operations.ts +139 -109
- package/src/server/canvas-schema.ts +21 -0
- package/src/server/canvas-serialization.ts +2 -0
- package/src/server/canvas-state.ts +792 -159
- package/src/server/card-relocation.ts +53 -0
- package/src/server/code-graph.ts +4 -3
- package/src/server/context-reads.ts +83 -55
- package/src/server/demo-state.json +35 -15
- package/src/server/file-watcher.ts +30 -10
- package/src/server/human-presence.ts +18 -5
- package/src/server/index.ts +35 -15
- package/src/server/intent-registry.ts +43 -5
- package/src/server/knowledge-lifecycle.ts +32 -9
- package/src/server/lifecycle-status.ts +29 -1
- package/src/server/mcp-app-runtime.ts +26 -7
- package/src/server/mutation-history.ts +37 -8
- package/src/server/operations/composites.ts +6 -3
- package/src/server/operations/mcp-contracts.ts +15 -0
- package/src/server/operations/mcp.ts +36 -9
- package/src/server/operations/ops/annotation.ts +22 -1
- package/src/server/operations/ops/ax-await.ts +1 -0
- package/src/server/operations/ops/ax-timeline.ts +28 -2
- package/src/server/operations/ops/batch.ts +25 -11
- package/src/server/operations/ops/boards.ts +44 -3
- package/src/server/operations/ops/nodes.ts +70 -0
- package/src/server/operations/ops/query.ts +32 -3
- package/src/server/operations/ops/snapshots.ts +1 -0
- package/src/server/operations/registry.ts +49 -4
- package/src/server/server.ts +62 -16
- package/src/server/tour-control.ts +37 -12
- package/src/server/trace-manager.ts +4 -0
- package/src/server/web-artifacts/scripts/bundle-artifact.sh +2 -2
- package/src/server/web-artifacts/scripts/init-artifact.sh +8 -8
- package/src/shared/agent-context.ts +7 -1
- package/src/shared/auto-arrange.ts +5 -4
- package/src/shared/ax-kinds.ts +13 -0
- package/src/shared/ax-surface-protocol.ts +22 -0
- package/src/shared/human-presence.ts +1 -0
- package/src/shared/lifecycle-status.ts +2 -0
- package/dist/canvas/chunks/architecture-TIHT7OUA-9tffvpsv.js +0 -1
- package/dist/canvas/chunks/classDiagram-JCYQIIEL-nc6g5x1r.js +0 -1
- package/dist/canvas/chunks/classDiagram-v2-OCEON4UE-0qnbpwvh.js +0 -1
- package/dist/canvas/chunks/cynefin-VYW2F7L2-ys8p46ts.js +0 -1
- package/dist/canvas/chunks/eventmodeling-45OFAUF4-v9q6dn4c.js +0 -1
- package/dist/canvas/chunks/flowDiagram-UKHOOZJN-yrr5z8tc.js +0 -1
- package/dist/canvas/chunks/gitGraph-TEB2WS4Q-kdwb8m0a.js +0 -1
- package/dist/canvas/chunks/index-1r72hdzb.js +0 -301
- package/dist/canvas/chunks/index-g3pwnqeb.js +0 -2
- package/dist/canvas/chunks/index-rft2hcz5.js +0 -2
- package/dist/canvas/chunks/info-DKCQHKI2-wpzs6sz3.js +0 -1
- package/dist/canvas/chunks/ishikawaDiagram-WSZJBQD7-5hnq1a9p.js +0 -70
- package/dist/canvas/chunks/packet-7NZHBO7P-xn439f0s.js +0 -1
- package/dist/canvas/chunks/pie-RZYD4A2V-0kf16rwh.js +0 -1
- package/dist/canvas/chunks/radar-I7S5WNFK-0g2pz36t.js +0 -1
- package/dist/canvas/chunks/railroad-3IZDKUUU-fcaran6j.js +0 -1
- package/dist/canvas/chunks/railroad-abnf-AHOZXSZD-wgdya41q.js +0 -1
- package/dist/canvas/chunks/railroad-ebnf-EBAXGLYW-gy07a4ka.js +0 -1
- package/dist/canvas/chunks/railroad-peg-LSFZ7HO6-ewk6wtkh.js +0 -1
- package/dist/canvas/chunks/stateDiagram-v2-UEYNNEHI-k8sfp2e7.js +0 -1
- package/dist/canvas/chunks/swimlanesDiagram-ULZ7WXOC-nqysw67j.js +0 -8
- package/dist/canvas/chunks/treeView-QDETBFTQ-cesw6gp0.js +0 -1
- package/dist/canvas/chunks/treemap-6X3UGDF4-zdv4knp9.js +0 -1
- package/dist/canvas/chunks/vennDiagram-T6HMQDX7-x8dqn9yf.js +0 -34
- package/dist/canvas/chunks/wardley-OPB4EBWU-44pdddez.js +0 -1
package/dist/amp-plugin/pmx-canvas/skills/pmx-canvas/evals/fixtures/code-exploration/src/auth/jwt.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const SECRET = process.env.JWT_SECRET ?? 'dev-secret';
|
|
2
|
+
|
|
3
|
+
export interface JwtClaims {
|
|
4
|
+
sub: string;
|
|
5
|
+
exp: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function signJwt(claims: JwtClaims): string {
|
|
9
|
+
const payload = Buffer.from(JSON.stringify(claims)).toString('base64url');
|
|
10
|
+
return `${payload}.${SECRET}`;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function verifyJwt(token: string): JwtClaims | null {
|
|
14
|
+
const [payload, signature] = token.split('.');
|
|
15
|
+
if (signature !== SECRET || !payload) return null;
|
|
16
|
+
return JSON.parse(Buffer.from(payload, 'base64url').toString()) as JwtClaims;
|
|
17
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { signJwt, type JwtClaims } from './jwt';
|
|
2
|
+
|
|
3
|
+
export async function login(username: string, password: string): Promise<string | null> {
|
|
4
|
+
const ok = await checkCredentials(username, password);
|
|
5
|
+
if (!ok) return null;
|
|
6
|
+
const claims: JwtClaims = { sub: username, exp: Date.now() + 3_600_000 };
|
|
7
|
+
return signJwt(claims);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async function checkCredentials(username: string, password: string): Promise<boolean> {
|
|
11
|
+
return Boolean(username) && password.length >= 8;
|
|
12
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { verifyJwt } from './jwt';
|
|
2
|
+
|
|
3
|
+
export interface AuthedRequest {
|
|
4
|
+
headers: Record<string, string>;
|
|
5
|
+
userId?: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function authMiddleware(req: AuthedRequest, next: () => void): void {
|
|
9
|
+
const token = (req.headers.authorization ?? '').replace(/^Bearer /, '');
|
|
10
|
+
const claims = verifyJwt(token);
|
|
11
|
+
if (claims) req.userId = claims.sub;
|
|
12
|
+
next();
|
|
13
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { login } from '../auth/login';
|
|
2
|
+
import { authMiddleware, type AuthedRequest } from '../auth/middleware';
|
|
3
|
+
|
|
4
|
+
export function registerAuthRoutes(router: {
|
|
5
|
+
post(path: string, handler: (req: AuthedRequest) => Promise<unknown>): void;
|
|
6
|
+
use(handler: (req: AuthedRequest, next: () => void) => void): void;
|
|
7
|
+
}): void {
|
|
8
|
+
router.use(authMiddleware);
|
|
9
|
+
router.post('/login', async (req) => {
|
|
10
|
+
const token = await login(req.headers.username ?? '', req.headers.password ?? '');
|
|
11
|
+
return token ? { token } : { error: 'invalid credentials' };
|
|
12
|
+
});
|
|
13
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
|
|
3
|
+
const refreshBus = new EventEmitter();
|
|
4
|
+
|
|
5
|
+
interface UserRequest {
|
|
6
|
+
query: Record<string, string>;
|
|
7
|
+
headers: Record<string, string>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface UserResponse {
|
|
11
|
+
json(body: unknown): void;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* GET /api/users
|
|
16
|
+
*
|
|
17
|
+
* Memory leak: every request registers a `refresh` listener whose closure
|
|
18
|
+
* captures the entire `req` object and is never removed. The heap retains one
|
|
19
|
+
* request per call and the EventEmitter listener count grows without bound.
|
|
20
|
+
*/
|
|
21
|
+
export function getUsers(req: UserRequest, res: UserResponse): void {
|
|
22
|
+
refreshBus.on('refresh', () => {
|
|
23
|
+
// Captures `req` for the lifetime of the process — the leak.
|
|
24
|
+
void req.headers;
|
|
25
|
+
});
|
|
26
|
+
res.json({ users: [] });
|
|
27
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"pmx-canvas": {
|
|
3
|
+
"command": "bun",
|
|
4
|
+
"args": [
|
|
5
|
+
"${AMP_SKILL_DIR}/../../start-mcp.mjs"
|
|
6
|
+
],
|
|
7
|
+
"includeTools": [
|
|
8
|
+
"canvas_connect_workspace",
|
|
9
|
+
"canvas_help",
|
|
10
|
+
"canvas_pin_nodes",
|
|
11
|
+
"canvas_invoke_command",
|
|
12
|
+
"canvas_batch",
|
|
13
|
+
"canvas_import",
|
|
14
|
+
"canvas_snapshot",
|
|
15
|
+
"canvas_board",
|
|
16
|
+
"canvas_node",
|
|
17
|
+
"canvas_render",
|
|
18
|
+
"canvas_edge",
|
|
19
|
+
"canvas_group",
|
|
20
|
+
"canvas_history",
|
|
21
|
+
"canvas_view",
|
|
22
|
+
"canvas_query",
|
|
23
|
+
"canvas_app",
|
|
24
|
+
"canvas_webview",
|
|
25
|
+
"canvas_ax_state",
|
|
26
|
+
"canvas_ax_work",
|
|
27
|
+
"canvas_ax_gate",
|
|
28
|
+
"canvas_ax_timeline",
|
|
29
|
+
"canvas_ax_delivery",
|
|
30
|
+
"canvas_intent",
|
|
31
|
+
"canvas_ax_interaction",
|
|
32
|
+
"canvas_ingest_activity",
|
|
33
|
+
"canvas_screenshot"
|
|
34
|
+
]
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# AX HTML Control Surface — a blessed, copy-paste-safe recipe
|
|
2
|
+
|
|
3
|
+
A canvas `html` node can be a live **AX control surface**: it emits AX interactions
|
|
4
|
+
(create work, request approval, steer the agent, …) and reflects the current AX board
|
|
5
|
+
back, all from inside the sandboxed iframe. The bridge is already injected for you —
|
|
6
|
+
you do **not** need to read `axToken` from the URL or hand-post `pmx-canvas-ax`
|
|
7
|
+
messages. Just opt the node in and use `window.PMX_AX`.
|
|
8
|
+
|
|
9
|
+
## Opt in
|
|
10
|
+
|
|
11
|
+
```js
|
|
12
|
+
// MCP / SDK
|
|
13
|
+
canvas_node({
|
|
14
|
+
action: "add",
|
|
15
|
+
type: "html",
|
|
16
|
+
title: "AX Control Room",
|
|
17
|
+
html: "<!-- see below -->",
|
|
18
|
+
axCapabilities: { enabled: true, allowed: ["ax.work.create", "ax.steer"] },
|
|
19
|
+
});
|
|
20
|
+
// HTTP: POST /api/canvas/node { type:"html", title, html, axCapabilities } (top-level html + axCapabilities both accepted)
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Without `axCapabilities.enabled = true`, `window.PMX_AX` is **not** injected — the node
|
|
24
|
+
renders but can't emit. `allowed` narrows what it may emit (never escalates the type's
|
|
25
|
+
ceiling). Flip an existing node on with `canvas_node({ action: "update", id, axCapabilities: { enabled: true, allowed: [...] } })`.
|
|
26
|
+
|
|
27
|
+
Changing effective capabilities reloads the mounted HTML document in both `src` and
|
|
28
|
+
`srcdoc` modes, including disable/re-enable and allowed-action changes. Unsaved iframe-local
|
|
29
|
+
drafts reset: save important state through durable AX primitives before changing capabilities.
|
|
30
|
+
Wait for the new document, invoke the action, and verify both its acknowledgement and persisted
|
|
31
|
+
result. On 0.8.0, late enabling required a deliberate remount; upgrading fixes that missing bridge.
|
|
32
|
+
|
|
33
|
+
## Three footguns (this is why a hand-rolled node looks "inert")
|
|
34
|
+
|
|
35
|
+
1. **The iframe is sandboxed opaque-origin** (no `allow-same-origin`). `localStorage`,
|
|
36
|
+
`sessionStorage`, and `document.cookie` **throw** — and an uncaught throw at script
|
|
37
|
+
start aborts the whole script, so the node renders blank/inert. Keep state in plain
|
|
38
|
+
JS variables (or `window.PMX_AX.state`); if you must touch storage, wrap it in
|
|
39
|
+
`try/catch`.
|
|
40
|
+
2. **`window.PMX_AX.emit(type, payload)` is async.** It returns a Promise that resolves
|
|
41
|
+
with the result once the canvas acks it. `await` it (or `.then` / `window.PMX_AX.on('ack', cb)`).
|
|
42
|
+
Reading a result synchronously gets you `undefined`.
|
|
43
|
+
3. **`ax.steer` is recorded, not delivered.** A successful emit (`{ ok: true }`) means
|
|
44
|
+
the steer was **queued** on the timeline — it does **not** wake or notify the active
|
|
45
|
+
agent. A cooperating host adapter must drain the delivery queue and call its native
|
|
46
|
+
send to create a visible turn (host-owned). Otherwise the steer is picked up on the
|
|
47
|
+
human's next turn. Label steering buttons honestly ("Queued for the agent's next turn").
|
|
48
|
+
|
|
49
|
+
## Drop-in template (work + steer, with ack + live reflection)
|
|
50
|
+
|
|
51
|
+
```html
|
|
52
|
+
<style>
|
|
53
|
+
body { font: 13px system-ui; margin: 0; padding: 12px; }
|
|
54
|
+
button { cursor: pointer; }
|
|
55
|
+
#s { margin-left: 8px; color: #6b7280; }
|
|
56
|
+
ul { padding-left: 18px; }
|
|
57
|
+
</style>
|
|
58
|
+
<button id="add">+ Work item</button>
|
|
59
|
+
<button id="steer">Steer agent</button>
|
|
60
|
+
<span id="s"></span>
|
|
61
|
+
<ul id="q"></ul>
|
|
62
|
+
<script>
|
|
63
|
+
// In-memory only — NO localStorage/sessionStorage/cookies (sandboxed: they throw).
|
|
64
|
+
const $ = (id) => document.getElementById(id);
|
|
65
|
+
const flash = (msg) => { $('s').textContent = msg; setTimeout(() => { $('s').textContent = ''; }, 1500); };
|
|
66
|
+
|
|
67
|
+
function render(state) {
|
|
68
|
+
const items = (state && state.workItems) || [];
|
|
69
|
+
$('q').innerHTML = items.map((w) => '<li>[' + w.status + '] ' + w.title + '</li>').join('');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
$('add').onclick = async () => {
|
|
73
|
+
const r = await window.PMX_AX.emit('ax.work.create', { title: 'New task' });
|
|
74
|
+
flash(r && r.ok ? 'queued ✓' : ('failed: ' + (r && (r.error || r.code))));
|
|
75
|
+
};
|
|
76
|
+
$('steer').onclick = async () => {
|
|
77
|
+
const r = await window.PMX_AX.emit('ax.steer', { message: 'Prioritize the auth refactor' });
|
|
78
|
+
// Honest: recorded/queued, NOT delivered to the live agent.
|
|
79
|
+
flash(r && r.ok ? 'queued for next turn ✓' : 'failed');
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
// Reflect: seeded once at load, then live via the pmx-ax-update event.
|
|
83
|
+
render(window.PMX_AX && window.PMX_AX.state);
|
|
84
|
+
window.addEventListener('pmx-ax-update', (e) => render(e.detail));
|
|
85
|
+
</script>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## API surface (injected by PMX when opted in)
|
|
89
|
+
|
|
90
|
+
- `window.PMX_AX.emit(type, payload) → Promise<{ ok, primitive?, status?, code?, error? }>`
|
|
91
|
+
— `ok:true` on accept; `ok:false` with `code`/`error` on reject; falls back to an
|
|
92
|
+
`ax-ack-timeout` result after 10s so `await` never hangs.
|
|
93
|
+
- `window.PMX_AX.on('ack', (result, interaction) => …)` — also fires a `pmx-ax-ack`
|
|
94
|
+
CustomEvent; use instead of `await` if you prefer a listener.
|
|
95
|
+
- `window.PMX_AX.state` — compact board snapshot `{ focus, workItems, approvalGates,
|
|
96
|
+
reviewAnnotations, elicitations, modeRequests, policy }` (human review text redacted).
|
|
97
|
+
- `pmx-ax-update` window event — fires with the fresh snapshot on every AX change.
|
|
98
|
+
|
|
99
|
+
Allowed `type`s are gated per node capability (see the node-capability matrix in
|
|
100
|
+
`SKILL.md`). Emits are clamped to the surface's own node; the server re-validates every
|
|
101
|
+
interaction — the bridge is convenience, not a trust boundary.
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# Codex App Adapter
|
|
2
|
+
|
|
3
|
+
Use this reference when PMX Canvas is running natively in the Codex app. The adapter is intentionally
|
|
4
|
+
thin: PMX Canvas remains the state owner, Codex uses MCP for agent operations/context, and the Codex
|
|
5
|
+
in-app Browser renders the live PMX workbench.
|
|
6
|
+
|
|
7
|
+
## Adapter Identity
|
|
8
|
+
|
|
9
|
+
- Host: Codex app
|
|
10
|
+
- Visual surface: Codex in-app Browser opened to the PMX `/workbench` URL
|
|
11
|
+
- Agent surface: PMX Canvas MCP server (`pmx-canvas --mcp`)
|
|
12
|
+
- Fallback surface: PMX Canvas CLI for manual scripts when MCP is unavailable
|
|
13
|
+
- AX source label: `codex`
|
|
14
|
+
|
|
15
|
+
This is not a separate PMX renderer and does not require a Codex extension API. Codex already has
|
|
16
|
+
the two native surfaces PMX needs: MCP resources/tools for the agent, and the in-app Browser for the
|
|
17
|
+
human-visible canvas. Prefer MCP over the CLI for Codex-native use because MCP exposes structured
|
|
18
|
+
tools, resources, and `canvas://ax-context`; use the CLI only as a fallback or for shell scripts.
|
|
19
|
+
|
|
20
|
+
## What The Adapter Does
|
|
21
|
+
|
|
22
|
+
- Opens the live PMX workbench in the Codex in-app Browser.
|
|
23
|
+
- Uses MCP tools/resources for all agent-side operations.
|
|
24
|
+
- Reads `canvas://ax-context` or `canvas_ax_state { action: "get" }` for pinned and focused context.
|
|
25
|
+
- Sets AX focus through `canvas_ax_state { action: "set-focus" }` with `source: "codex"` when the
|
|
26
|
+
focus change comes from Codex-hosted steering.
|
|
27
|
+
- Keeps all persistent PMX state in `.pmx-canvas/canvas.db`; Codex does not own canvas state.
|
|
28
|
+
|
|
29
|
+
## Setup
|
|
30
|
+
|
|
31
|
+
Use MCP as the primary Codex adapter path.
|
|
32
|
+
|
|
33
|
+
Add the PMX MCP server to the Codex workspace config:
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"mcpServers": {
|
|
38
|
+
"canvas": {
|
|
39
|
+
"command": "bunx",
|
|
40
|
+
"args": ["pmx-canvas", "--mcp"]
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
For local repo development, use the source entrypoint instead:
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"mcpServers": {
|
|
51
|
+
"canvas": {
|
|
52
|
+
"command": "bun",
|
|
53
|
+
"args": ["run", "src/mcp/server.ts"]
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The MCP server auto-starts the HTTP workbench on first tool call. Open the returned workbench URL
|
|
60
|
+
in the Codex in-app Browser, usually `http://127.0.0.1:4313/workbench` or
|
|
61
|
+
`http://localhost:4313/workbench`.
|
|
62
|
+
|
|
63
|
+
### Agent presence (cursor + phase chip)
|
|
64
|
+
|
|
65
|
+
Name the agent on the MCP server so its writes, its session, and its cursor share one identity:
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{
|
|
69
|
+
"mcpServers": {
|
|
70
|
+
"canvas": {
|
|
71
|
+
"command": "bunx",
|
|
72
|
+
"args": ["pmx-canvas", "--mcp"],
|
|
73
|
+
"env": { "PMX_CANVAS_AGENT_SOURCE": "codex" }
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Then attach at the start of a task and detach at the end:
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{ "tool": "canvas_ax_state", "action": "set-presence", "attached": true, "label": "Codex", "phase": "idle" }
|
|
83
|
+
{ "tool": "canvas_ax_state", "action": "set-presence", "attached": false }
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
While attached the workbench shows the Codex cursor on the node it last touched and a phase chip
|
|
87
|
+
(`thinking` · `tooling` · `waiting-approval` · `idle`). `tooling` and the cursor position are
|
|
88
|
+
derived from Codex's own MCP writes — nothing per call. Even without `PMX_CANVAS_AGENT_SOURCE`,
|
|
89
|
+
writes arriving as plain `mcp` are attributed to the single attached session.
|
|
90
|
+
|
|
91
|
+
## Codex-Native Workflow
|
|
92
|
+
|
|
93
|
+
1. Open `/workbench` in the Codex in-app Browser as the first visible action. If PMX is not running
|
|
94
|
+
yet, start/connect the MCP server first only long enough to get the workbench URL, then open the
|
|
95
|
+
browser before mutating the board.
|
|
96
|
+
2. Start or keep using the PMX MCP server for agent operations.
|
|
97
|
+
3. Use the browser canvas for human spatial curation: pin nodes, move nodes, group nodes, and
|
|
98
|
+
inspect rendered artifacts.
|
|
99
|
+
4. Use MCP tools for agent operations: create/update nodes, pin nodes, read layout, and read AX
|
|
100
|
+
context.
|
|
101
|
+
5. When Codex wants to mark the current attention target, call
|
|
102
|
+
`canvas_ax_state { action: "set-focus", … }` with:
|
|
103
|
+
|
|
104
|
+
```json
|
|
105
|
+
{
|
|
106
|
+
"nodeIds": ["node-123"],
|
|
107
|
+
"source": "codex"
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Context Contract
|
|
112
|
+
|
|
113
|
+
Codex agents should treat PMX AX context as host-native working context:
|
|
114
|
+
|
|
115
|
+
- `canvas://pinned-context` is the explicit human-curated node set.
|
|
116
|
+
- `canvas://ax-context` combines pins, focus, and surface metadata, plus a compact
|
|
117
|
+
loop-safe `delivery: { pendingSteering, pendingActivity }` lead block
|
|
118
|
+
(`GET /api/canvas/ax/context?consumer=codex` filters out Codex-originated items).
|
|
119
|
+
- `canvas_ax_state { action: "get" }` returns both persisted AX state and agent-ready context.
|
|
120
|
+
- Focus is a current attention target, not a command to ignore the rest of the repository.
|
|
121
|
+
|
|
122
|
+
The adapterless MCP+Browser path is poll-based: there is no automatic prompt injection,
|
|
123
|
+
so a board click does not wake the current turn. Codex agents poll
|
|
124
|
+
`canvas_ax_delivery { action: "claim" }` (steering + `pendingActivity`) and act/ack explicitly. The
|
|
125
|
+
loop-closing surfaces work over MCP today even without a dedicated extension:
|
|
126
|
+
|
|
127
|
+
- **Self-report work** with `canvas_ingest_activity` (the board auto-reacts: a failed
|
|
128
|
+
tool → a blocked work item + review + evidence). Automatic forwarding of Codex's own
|
|
129
|
+
tool hooks would need a Codex adapter; manual ingestion works now.
|
|
130
|
+
- **Block on a decision** with `canvas_ax_gate { kind, action: "await", id }` (it long-polls PMX
|
|
131
|
+
until the human resolves the gate in the Browser or the timeout elapses) instead of looping on
|
|
132
|
+
`canvas_ax_state { action: "get" }`.
|
|
133
|
+
|
|
134
|
+
## Live-Test Checklist
|
|
135
|
+
|
|
136
|
+
1. Open `http://127.0.0.1:4313/workbench` in the Codex in-app Browser first so the user can see
|
|
137
|
+
all later canvas mutations.
|
|
138
|
+
2. Confirm the PMX MCP server is configured for the workspace.
|
|
139
|
+
3. Call `canvas_ax_state { action: "get" }` and confirm it returns `ok: true`.
|
|
140
|
+
4. Add or reuse a node, then pin it from the browser or with `canvas_pin_nodes`.
|
|
141
|
+
5. Read `canvas://ax-context` and confirm the pinned node appears.
|
|
142
|
+
6. Call `canvas_ax_state { action: "set-focus", source: "codex" }` with a real node ID.
|
|
143
|
+
7. Read `canvas_ax_state { action: "get" }` again and confirm `state.focus.source` is `codex`.
|
|
144
|
+
8. Refresh the browser and confirm the workbench still shows the same state.
|
|
145
|
+
|
|
146
|
+
## Adapter Boundary
|
|
147
|
+
|
|
148
|
+
Do not add Codex-specific APIs to PMX Canvas core. Core owns neutral AX primitives; Codex maps them
|
|
149
|
+
through MCP and the in-app Browser. If Codex later exposes a dedicated extension or prompt-injection
|
|
150
|
+
hook, implement that as a separate adapter layer that reads the same `/api/canvas/ax/context` or
|
|
151
|
+
`canvas://ax-context` contract.
|
package/dist/amp-plugin/pmx-canvas/skills/pmx-canvas/references/excalidraw-diagram-authoring.md
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# Excalidraw Diagram Authoring
|
|
2
|
+
|
|
3
|
+
Use this guide when creating diagrams through PMX Canvas with `canvas_app { action: "diagram" }` or
|
|
4
|
+
`pmx-canvas external-app add --kind excalidraw`.
|
|
5
|
+
|
|
6
|
+
Request `width: 720, height: 500` when opening the standard landscape diagram tile. Treat those as
|
|
7
|
+
requested preset dimensions, not authoritative geometry: after the app mounts, query
|
|
8
|
+
`canvas_query { action: "layout" }` and use the node's persisted width and height for placement,
|
|
9
|
+
overlap checks, and any later layout. A hosted app can resize during mount.
|
|
10
|
+
|
|
11
|
+
## Why Text Can Still Drift
|
|
12
|
+
|
|
13
|
+
PMX normalizes canonical Excalidraw bound text (`containerId` / `boundElements`) into the hosted
|
|
14
|
+
app's supported shape-level `label` format before calling Excalidraw. That fixes the payload
|
|
15
|
+
format mismatch, but it does not fix poor diagram geometry.
|
|
16
|
+
|
|
17
|
+
Text can still appear clipped or misplaced when:
|
|
18
|
+
|
|
19
|
+
- A label is too long for its shape.
|
|
20
|
+
- A diamond or ellipse is too small for the label's usable center area.
|
|
21
|
+
- The `cameraUpdate` viewport is too tight or not 4:3.
|
|
22
|
+
- Title, footer, or notes are placed near the camera edge.
|
|
23
|
+
- The caller bypasses PMX and sends raw elements directly to Excalidraw MCP.
|
|
24
|
+
|
|
25
|
+
## Text Format Rules
|
|
26
|
+
|
|
27
|
+
For text inside a rectangle, ellipse, or diamond, use shape-level `label`:
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"type": "rectangle",
|
|
32
|
+
"id": "step-a",
|
|
33
|
+
"x": 100,
|
|
34
|
+
"y": 100,
|
|
35
|
+
"width": 260,
|
|
36
|
+
"height": 90,
|
|
37
|
+
"label": { "text": "Step A", "fontSize": 18 }
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Do not create separate centered text elements for shape labels:
|
|
42
|
+
|
|
43
|
+
```json
|
|
44
|
+
{
|
|
45
|
+
"type": "text",
|
|
46
|
+
"containerId": "step-a",
|
|
47
|
+
"text": "Step A"
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Standalone text is fine for titles, notes, captions, and free-floating annotations. For standalone
|
|
52
|
+
text, `x` is the left edge; `textAlign` does not center it on a point.
|
|
53
|
+
|
|
54
|
+
## Label Length Rules
|
|
55
|
+
|
|
56
|
+
- Use 1-4 words inside shapes.
|
|
57
|
+
- Put detailed explanations in nearby standalone text annotations.
|
|
58
|
+
- Prefer `Bound Text` over `Pattern B: containerId+boundElements only`.
|
|
59
|
+
- If a label needs more than 4 words, either widen the shape or split the idea into a label plus an annotation.
|
|
60
|
+
|
|
61
|
+
## Shape Sizing Rules
|
|
62
|
+
|
|
63
|
+
- Minimum labeled rectangle or ellipse: `180x80`.
|
|
64
|
+
- For 3-5 word labels: `240x90` or larger.
|
|
65
|
+
- For long labels: `320+` width or use an external annotation.
|
|
66
|
+
- Diamonds need more room than rectangles because the usable center area is smaller.
|
|
67
|
+
- Leave at least `30px` gap between shapes and labels/arrows.
|
|
68
|
+
|
|
69
|
+
## Camera Rules
|
|
70
|
+
|
|
71
|
+
Always start with a `cameraUpdate` as the first element.
|
|
72
|
+
|
|
73
|
+
Use 4:3 camera sizes only:
|
|
74
|
+
|
|
75
|
+
- `400x300`
|
|
76
|
+
- `600x450`
|
|
77
|
+
- `800x600`
|
|
78
|
+
- `1200x900`
|
|
79
|
+
- `1600x1200`
|
|
80
|
+
|
|
81
|
+
Camera bounds must include the full diagram plus padding. Leave at least `80px` padding around all
|
|
82
|
+
visible content.
|
|
83
|
+
|
|
84
|
+
Example:
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{ "type": "cameraUpdate", "x": 20, "y": 0, "width": 1200, "height": 900 }
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
If a title, footer, or rightmost label is clipped, the camera is wrong even if the elements are valid.
|
|
91
|
+
|
|
92
|
+
## Good Pattern
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
[
|
|
96
|
+
{ "type": "cameraUpdate", "x": 20, "y": 0, "width": 1200, "height": 900 },
|
|
97
|
+
{
|
|
98
|
+
"type": "rectangle",
|
|
99
|
+
"id": "a",
|
|
100
|
+
"x": 120,
|
|
101
|
+
"y": 160,
|
|
102
|
+
"width": 260,
|
|
103
|
+
"height": 90,
|
|
104
|
+
"backgroundColor": "#a5d8ff",
|
|
105
|
+
"fillStyle": "solid",
|
|
106
|
+
"label": { "text": "Short Label", "fontSize": 18 }
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"type": "rectangle",
|
|
110
|
+
"id": "b",
|
|
111
|
+
"x": 520,
|
|
112
|
+
"y": 160,
|
|
113
|
+
"width": 280,
|
|
114
|
+
"height": 90,
|
|
115
|
+
"backgroundColor": "#b2f2bb",
|
|
116
|
+
"fillStyle": "solid",
|
|
117
|
+
"label": { "text": "Next Step", "fontSize": 18 }
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"type": "arrow",
|
|
121
|
+
"id": "a-to-b",
|
|
122
|
+
"x": 390,
|
|
123
|
+
"y": 205,
|
|
124
|
+
"width": 110,
|
|
125
|
+
"height": 0,
|
|
126
|
+
"points": [[0, 0], [110, 0]],
|
|
127
|
+
"endArrowhead": "arrow",
|
|
128
|
+
"label": { "text": "then", "fontSize": 14 }
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"type": "text",
|
|
132
|
+
"id": "note",
|
|
133
|
+
"x": 120,
|
|
134
|
+
"y": 290,
|
|
135
|
+
"text": "Longer explanation goes here, outside the shape.",
|
|
136
|
+
"fontSize": 16
|
|
137
|
+
}
|
|
138
|
+
]
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Preflight Checklist
|
|
142
|
+
|
|
143
|
+
- Shape text uses `label`, not separate `text` elements.
|
|
144
|
+
- Shape labels are short enough to fit.
|
|
145
|
+
- Long explanations are outside shapes.
|
|
146
|
+
- The first element is a 4:3 `cameraUpdate`.
|
|
147
|
+
- Camera has at least `80px` padding around all visible content.
|
|
148
|
+
- Titles and footers are not near the camera edge.
|
|
149
|
+
- Arrows have explicit `points` and enough space for labels.
|
|
150
|
+
- Calls go through PMX (`canvas_app { action: "diagram" }` or `external-app add --kind excalidraw`) unless you manually apply these rules to raw Excalidraw MCP input.
|