pmx-canvas 0.6.2 → 0.6.4
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/CHANGELOG.md +31 -0
- package/Readme.md +30 -3
- package/dist/canvas/global.css +32 -0
- package/dist/canvas/index.js +68 -66
- package/dist/json-render/index.js +57 -57
- package/dist/types/client/canvas/FeedbackDialog.d.ts +4 -0
- package/dist/types/client/canvas/auto-fit.d.ts +3 -0
- package/dist/types/client/nodes/use-iframe-content-height.d.ts +3 -3
- package/dist/types/client/state/human-store.d.ts +1 -0
- package/dist/types/json-render/catalog.d.ts +20 -20
- package/dist/types/json-render/schema.d.ts +40 -0
- package/dist/types/mcp/skills.d.ts +13 -0
- package/dist/types/server/bundled-skills.d.ts +32 -4
- package/docs/cli.md +7 -2
- package/docs/http-api.md +5 -1
- package/docs/mcp.md +35 -1
- package/docs/node-types.md +43 -1
- package/docs/product-context-vision-2026-09.md +17 -6
- package/docs/product-vision-2026-09.md +136 -41
- package/docs/product-vision-review-2026-09.md +277 -0
- package/package.json +11 -11
- package/skills/json-render-mcp/SKILL.md +118 -2
- package/skills/pmx-canvas/SKILL.md +43 -13
- package/skills/pmx-canvas/evals/evals.json +46 -0
- package/skills/pmx-canvas/references/installing-pmx-canvas.md +5 -5
- package/src/client/canvas/FeedbackDialog.tsx +86 -0
- package/src/client/canvas/ToolRail.tsx +225 -189
- package/src/client/canvas/auto-fit.ts +20 -1
- package/src/client/nodes/use-iframe-content-height.ts +44 -24
- package/src/client/state/human-store.ts +6 -6
- package/src/client/theme/global.css +32 -0
- package/src/json-render/catalog.ts +6 -0
- package/src/json-render/renderer/index.tsx +17 -0
- package/src/json-render/schema.ts +4 -0
- package/src/mcp/server.ts +9 -4
- package/src/mcp/skills.ts +47 -0
- package/src/server/bundled-skills.ts +92 -53
- package/src/server/operations/ops/nodes.ts +43 -11
- package/src/shared/content-height-reporter.ts +4 -2
|
@@ -17,3 +17,6 @@ export declare function shouldContentFitIframeNode(node: CanvasNodeState): boole
|
|
|
17
17
|
* capped at the iframe ceiling.
|
|
18
18
|
*/
|
|
19
19
|
export declare function computeContentGrowHeight(node: CanvasNodeState, contentHeight: number): number | null;
|
|
20
|
+
/** Keep an automatically growing card clear without moving its neighbors or
|
|
21
|
+
* changing its column. Groups and screen-pinned cards retain authored placement. */
|
|
22
|
+
export declare function contentFitPosition(node: CanvasNodeState, height: number, allNodes: CanvasNodeState[]): CanvasNodeState['position'];
|
|
@@ -7,9 +7,9 @@ import type { CanvasNodeState } from '../types';
|
|
|
7
7
|
* because growth is monotonic with a dead-band — cannot oscillate. This is the
|
|
8
8
|
* fix for iframe nodes whose body scrollHeight the parent can't measure.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* Debounce before changing geometry, retaining the latest measurement during a
|
|
11
|
+
* human grab. Read current geometry at application time; persist only this node.
|
|
12
|
+
* Relocations are undoable, height-only adjustments do not fill the undo stack.
|
|
13
13
|
*/
|
|
14
14
|
export declare function useIframeContentHeight(node: CanvasNodeState, iframeRef: {
|
|
15
15
|
current: HTMLIFrameElement | null;
|
|
@@ -6,6 +6,7 @@ export declare const otherHumans: import("@preact/signals-core").ReadonlySignal<
|
|
|
6
6
|
/** Nodes a human took over mid-edit → that human's name, shown as the yield pill for a moment. */
|
|
7
7
|
export declare const yieldedNodes: import("@preact/signals-core").Signal<Map<string, string>>;
|
|
8
8
|
export declare function applyHumanSnapshot(snapshot: Partial<HumanPresenceSnapshot> | null | undefined): void;
|
|
9
|
+
export declare const grabbingNodeId: import("@preact/signals-core").Signal<string | null>;
|
|
9
10
|
/** Report the pointer in world coordinates (throttled); null when it leaves the canvas. */
|
|
10
11
|
export declare function reportHumanCursor(cursor: {
|
|
11
12
|
x: number;
|
|
@@ -449,6 +449,26 @@ export declare const allComponentDefinitions: {
|
|
|
449
449
|
readonly showLabels: true;
|
|
450
450
|
};
|
|
451
451
|
};
|
|
452
|
+
Card: {
|
|
453
|
+
slots: string[];
|
|
454
|
+
description: string;
|
|
455
|
+
props: z.ZodObject<{
|
|
456
|
+
title: z.ZodNullable<z.ZodString>;
|
|
457
|
+
description: z.ZodNullable<z.ZodString>;
|
|
458
|
+
maxWidth: z.ZodNullable<z.ZodEnum<{
|
|
459
|
+
sm: "sm";
|
|
460
|
+
md: "md";
|
|
461
|
+
lg: "lg";
|
|
462
|
+
full: "full";
|
|
463
|
+
}>>;
|
|
464
|
+
centered: z.ZodNullable<z.ZodBoolean>;
|
|
465
|
+
className: z.ZodNullable<z.ZodString>;
|
|
466
|
+
}, z.core.$strip>;
|
|
467
|
+
example: {
|
|
468
|
+
title: string;
|
|
469
|
+
description: string;
|
|
470
|
+
};
|
|
471
|
+
};
|
|
452
472
|
Badge: {
|
|
453
473
|
props: z.ZodObject<{
|
|
454
474
|
text: z.ZodString;
|
|
@@ -491,26 +511,6 @@ export declare const allComponentDefinitions: {
|
|
|
491
511
|
};
|
|
492
512
|
events: string[];
|
|
493
513
|
};
|
|
494
|
-
Card: {
|
|
495
|
-
props: z.ZodObject<{
|
|
496
|
-
title: z.ZodNullable<z.ZodString>;
|
|
497
|
-
description: z.ZodNullable<z.ZodString>;
|
|
498
|
-
maxWidth: z.ZodNullable<z.ZodEnum<{
|
|
499
|
-
sm: "sm";
|
|
500
|
-
md: "md";
|
|
501
|
-
lg: "lg";
|
|
502
|
-
full: "full";
|
|
503
|
-
}>>;
|
|
504
|
-
centered: z.ZodNullable<z.ZodBoolean>;
|
|
505
|
-
className: z.ZodNullable<z.ZodString>;
|
|
506
|
-
}, z.core.$strip>;
|
|
507
|
-
slots: string[];
|
|
508
|
-
description: string;
|
|
509
|
-
example: {
|
|
510
|
-
title: string;
|
|
511
|
-
description: string;
|
|
512
|
-
};
|
|
513
|
-
};
|
|
514
514
|
Stack: {
|
|
515
515
|
props: z.ZodObject<{
|
|
516
516
|
direction: z.ZodNullable<z.ZodEnum<{
|
|
@@ -1,11 +1,31 @@
|
|
|
1
1
|
export declare const schema: import("@json-render/core").Schema<{
|
|
2
2
|
spec: import("@json-render/core").SchemaType<"object", {
|
|
3
3
|
root: import("@json-render/core").SchemaType<"string", unknown>;
|
|
4
|
+
state: {
|
|
5
|
+
optional: true;
|
|
6
|
+
kind: "record";
|
|
7
|
+
inner?: import("@json-render/core").SchemaType<"any", unknown> | undefined;
|
|
8
|
+
};
|
|
4
9
|
elements: import("@json-render/core").SchemaType<"record", import("@json-render/core").SchemaType<"object", {
|
|
5
10
|
type: import("@json-render/core").SchemaType<"ref", string>;
|
|
6
11
|
props: import("@json-render/core").SchemaType<"propsOf", string>;
|
|
7
12
|
children: import("@json-render/core").SchemaType<"array", import("@json-render/core").SchemaType<"string", unknown>>;
|
|
8
13
|
visible: import("@json-render/core").SchemaType<"any", unknown>;
|
|
14
|
+
repeat: {
|
|
15
|
+
optional: true;
|
|
16
|
+
kind: "any";
|
|
17
|
+
inner?: unknown;
|
|
18
|
+
};
|
|
19
|
+
watch: {
|
|
20
|
+
optional: true;
|
|
21
|
+
kind: "record";
|
|
22
|
+
inner?: import("@json-render/core").SchemaType<"any", unknown> | undefined;
|
|
23
|
+
};
|
|
24
|
+
slots: {
|
|
25
|
+
optional: true;
|
|
26
|
+
kind: "record";
|
|
27
|
+
inner?: import("@json-render/core").SchemaType<"array", import("@json-render/core").SchemaType<"string", unknown>> | undefined;
|
|
28
|
+
};
|
|
9
29
|
on: import("@json-render/core").SchemaType<"any", unknown>;
|
|
10
30
|
}>>;
|
|
11
31
|
}>;
|
|
@@ -25,11 +45,31 @@ export declare const schema: import("@json-render/core").Schema<{
|
|
|
25
45
|
export declare const elementTreeSchema: import("@json-render/core").Schema<{
|
|
26
46
|
spec: import("@json-render/core").SchemaType<"object", {
|
|
27
47
|
root: import("@json-render/core").SchemaType<"string", unknown>;
|
|
48
|
+
state: {
|
|
49
|
+
optional: true;
|
|
50
|
+
kind: "record";
|
|
51
|
+
inner?: import("@json-render/core").SchemaType<"any", unknown> | undefined;
|
|
52
|
+
};
|
|
28
53
|
elements: import("@json-render/core").SchemaType<"record", import("@json-render/core").SchemaType<"object", {
|
|
29
54
|
type: import("@json-render/core").SchemaType<"ref", string>;
|
|
30
55
|
props: import("@json-render/core").SchemaType<"propsOf", string>;
|
|
31
56
|
children: import("@json-render/core").SchemaType<"array", import("@json-render/core").SchemaType<"string", unknown>>;
|
|
32
57
|
visible: import("@json-render/core").SchemaType<"any", unknown>;
|
|
58
|
+
repeat: {
|
|
59
|
+
optional: true;
|
|
60
|
+
kind: "any";
|
|
61
|
+
inner?: unknown;
|
|
62
|
+
};
|
|
63
|
+
watch: {
|
|
64
|
+
optional: true;
|
|
65
|
+
kind: "record";
|
|
66
|
+
inner?: import("@json-render/core").SchemaType<"any", unknown> | undefined;
|
|
67
|
+
};
|
|
68
|
+
slots: {
|
|
69
|
+
optional: true;
|
|
70
|
+
kind: "record";
|
|
71
|
+
inner?: import("@json-render/core").SchemaType<"array", import("@json-render/core").SchemaType<"string", unknown>> | undefined;
|
|
72
|
+
};
|
|
33
73
|
on: import("@json-render/core").SchemaType<"any", unknown>;
|
|
34
74
|
}>>;
|
|
35
75
|
}>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
/** SEP-2640 methods are protocol requests, not model-facing canvas tools. */
|
|
3
|
+
export declare function registerSkillExtension(server: McpServer, catalog?: {
|
|
4
|
+
skills: import("../server/bundled-skills.js").SkillEntry[];
|
|
5
|
+
files: Map<string, {
|
|
6
|
+
uri: string;
|
|
7
|
+
mimeType: string;
|
|
8
|
+
} & ({
|
|
9
|
+
text: string;
|
|
10
|
+
} | {
|
|
11
|
+
blob: string;
|
|
12
|
+
})>;
|
|
13
|
+
}): void;
|
|
@@ -16,11 +16,17 @@
|
|
|
16
16
|
* - `canvas://skills` → JSON index
|
|
17
17
|
* - `canvas://skills/<name>` → full markdown content
|
|
18
18
|
*/
|
|
19
|
+
import { z } from 'zod';
|
|
20
|
+
declare const skillFrontmatterSchema: z.ZodObject<{
|
|
21
|
+
name: z.ZodString;
|
|
22
|
+
description: z.ZodString;
|
|
23
|
+
}, z.core.$loose>;
|
|
19
24
|
export interface BundledSkill {
|
|
20
25
|
name: string;
|
|
21
26
|
description: string;
|
|
22
27
|
uri: string;
|
|
23
28
|
filePath: string;
|
|
29
|
+
frontmatter: z.infer<typeof skillFrontmatterSchema>;
|
|
24
30
|
}
|
|
25
31
|
/**
|
|
26
32
|
* Resolve the packaged `skills/` directory. Walks parents from this module
|
|
@@ -32,9 +38,31 @@ export interface BundledSkill {
|
|
|
32
38
|
export declare function findBundledSkillsRoot(): string | null;
|
|
33
39
|
/**
|
|
34
40
|
* Enumerate every `<name>/SKILL.md` under the bundled skills root and return
|
|
35
|
-
* a compact index.
|
|
36
|
-
*
|
|
37
|
-
* break the MCP server's resource listing.
|
|
41
|
+
* a compact index. Invalid packaged skills fail explicitly rather than being
|
|
42
|
+
* silently omitted from the Skills extension's integrity manifest.
|
|
38
43
|
*/
|
|
39
|
-
export declare function listBundledSkills(): BundledSkill[];
|
|
44
|
+
export declare function listBundledSkills(root?: string | null): BundledSkill[];
|
|
40
45
|
export declare function readBundledSkill(name: string): string | null;
|
|
46
|
+
export interface SkillEntry {
|
|
47
|
+
uri: string;
|
|
48
|
+
frontmatter: BundledSkill['frontmatter'];
|
|
49
|
+
resources: Array<{
|
|
50
|
+
uri: string;
|
|
51
|
+
digest: string;
|
|
52
|
+
size: number;
|
|
53
|
+
}>;
|
|
54
|
+
}
|
|
55
|
+
type SkillContent = {
|
|
56
|
+
uri: string;
|
|
57
|
+
mimeType: string;
|
|
58
|
+
} & ({
|
|
59
|
+
text: string;
|
|
60
|
+
} | {
|
|
61
|
+
blob: string;
|
|
62
|
+
});
|
|
63
|
+
/** Capture immutable package bytes once per MCP process, never read caller-supplied paths. */
|
|
64
|
+
export declare function createBundledSkillCatalog(root?: string | null): {
|
|
65
|
+
skills: SkillEntry[];
|
|
66
|
+
files: Map<string, SkillContent>;
|
|
67
|
+
};
|
|
68
|
+
export {};
|
package/docs/cli.md
CHANGED
|
@@ -41,11 +41,16 @@ adapter that uses the app's native follow-up channel.
|
|
|
41
41
|
(who sent it), `$PMX_STEER_TARGET` (your consumer key, or `ALL` for a
|
|
42
42
|
broadcast), and `$PMX_STEER_CREATED_AT` — so the host turn can say who
|
|
43
43
|
steered, whether it was addressed, and how old it is.
|
|
44
|
-
-
|
|
44
|
+
- By default, startup backlog is marked delivered for this consumer without running
|
|
45
|
+
the command. This acknowledgement is not evidence that work was executed. Start the
|
|
46
|
+
pump before accepting new tasks, or review queued instructions and explicitly pass
|
|
47
|
+
`--backlog=deliver` to execute them instead of skipping them.
|
|
45
48
|
- A failing command is retried twice, then the pump exits non-zero and leaves
|
|
46
49
|
the steer pending so a failed host injection cannot look delivered.
|
|
47
50
|
- `--parent <key>` rolls the pumped agent up under an orchestrator's chip;
|
|
48
|
-
`--once`
|
|
51
|
+
`--once` exits after one successful execution, not after skipping startup history.
|
|
52
|
+
It may therefore wait for a new steer; use `--backlog=deliver --once` when you
|
|
53
|
+
intend to execute one reviewed, already-queued instruction.
|
|
49
54
|
- Survives daemon restarts; backs off against pre-0.4.9 servers that ignore
|
|
50
55
|
`waitMs`.
|
|
51
56
|
|
package/docs/http-api.md
CHANGED
|
@@ -88,7 +88,11 @@ curl -X PATCH http://localhost:4313/api/canvas/node/node-abc123 \
|
|
|
88
88
|
```
|
|
89
89
|
|
|
90
90
|
The title follows the new filename unless the node was renamed away from the
|
|
91
|
-
old one (or the patch sets `title` explicitly).
|
|
91
|
+
old one (or the patch sets `title` explicitly). Relative `path` values (including
|
|
92
|
+
`data.path` in batch updates) resolve against the configured canvas workspace,
|
|
93
|
+
not the daemon's working directory; the stored path is absolute. A missing or
|
|
94
|
+
unreadable target fails the update without changing the node or its existing watcher
|
|
95
|
+
(`400` for a direct PATCH; a failed-operation result in a batch).
|
|
92
96
|
|
|
93
97
|
```bash
|
|
94
98
|
# Raw bytes for a binary file node (PDF viewer, downloads)
|
package/docs/mcp.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# MCP reference
|
|
2
2
|
|
|
3
3
|
PMX Canvas ships an MCP stdio server with **22 tools** + **14 core resources**,
|
|
4
|
-
plus per-skill resources at `canvas://skills/<name
|
|
4
|
+
plus per-skill resources at `canvas://skills/<name>` and `skill://<name>/SKILL.md`. The server emits
|
|
5
5
|
`notifications/resources/updated` when canvas state changes — humans pin
|
|
6
6
|
nodes in the browser, agents are notified immediately.
|
|
7
7
|
|
|
@@ -202,6 +202,40 @@ Individual bundled skills are also readable at `canvas://skills/<name>`.
|
|
|
202
202
|
| `canvas://code-graph` | Auto-detected file dependency graph (JS/TS, Python, Go, Rust) |
|
|
203
203
|
| `canvas://skills` | Index of bundled agent skills + per-skill content at `canvas://skills/<name>` |
|
|
204
204
|
|
|
205
|
+
### Skills extension (SEP-2640)
|
|
206
|
+
|
|
207
|
+
PMX advertises `capabilities.extensions["io.modelcontextprotocol/skills"] = {}`
|
|
208
|
+
alongside the base `resources` capability. This adds protocol methods, not canvas tools:
|
|
209
|
+
|
|
210
|
+
| Method | Parameters | Result |
|
|
211
|
+
|--------|------------|--------|
|
|
212
|
+
| `skills/list` | None or `{}` | `{ resultType: "complete", skills: [...] }` |
|
|
213
|
+
| `skills/get` | `{ uri: "skill://pmx-canvas/SKILL.md" }` | `{ resultType: "complete", skill: {...} }` |
|
|
214
|
+
| `resources/read` | `{ uri: "skill://pmx-canvas/references/installing-pmx-canvas.md" }` | Standard resource content |
|
|
215
|
+
|
|
216
|
+
Each skill entry contains its `SKILL.md` URI, full parsed YAML `frontmatter`, and a complete
|
|
217
|
+
`resources` manifest of `{ uri, digest, size }` for every file. Digests are raw-byte SHA-256
|
|
218
|
+
(`sha256:<hex>`); sizes are bytes. UTF-8 files are returned as text, binary files as base64 blobs.
|
|
219
|
+
Resolve relative references against the skill directory. Files are loaded by the host on demand;
|
|
220
|
+
discovery does not load all instructions into model context or start a canvas daemon.
|
|
221
|
+
|
|
222
|
+
The packaged catalog fits in one page, so no `nextCursor` is returned and supplied cursors are
|
|
223
|
+
rejected with `-32602`. Unknown skill/file URIs also return `-32602`. Optional
|
|
224
|
+
`resources/directory/read` is not advertised or implemented; manifests already enumerate files.
|
|
225
|
+
PMX currently negotiates the SDK's supported base protocol (up to `2025-11-25`), so the
|
|
226
|
+
`2026-07-28` list-caching fields are not emitted.
|
|
227
|
+
|
|
228
|
+
The server snapshots packaged files at MCP startup. Restart the MCP process after an upgrade to
|
|
229
|
+
get new instructions and manifests. Invalid frontmatter, symbolic links, non-regular files, and
|
|
230
|
+
skills exceeding 512 files or 16 MiB fail catalog creation. Reads only address captured package
|
|
231
|
+
files, never arbitrary workspace paths. Scripts are served as data and are never executed by these methods.
|
|
232
|
+
|
|
233
|
+
Hosts must implement the extension's origin tagging, integrity verification, activation, and
|
|
234
|
+
approval rules. Reading a resource does not itself activate a skill or authorize local execution.
|
|
235
|
+
Automatic skill loading depends on host support; ordinary resource reads and filesystem installs
|
|
236
|
+
remain available. Use `pmx-canvas skills sync` for installed local mirrors. See the
|
|
237
|
+
[final specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2640-skills-extension.md).
|
|
238
|
+
|
|
205
239
|
## Node interactions (capability-gated)
|
|
206
240
|
|
|
207
241
|
Eligible nodes emit one normalized, validated interaction envelope
|
package/docs/node-types.md
CHANGED
|
@@ -137,7 +137,7 @@ with the server's transport, tool name, and arguments.
|
|
|
137
137
|
|
|
138
138
|
`json-render` nodes turn structured JSON specs into rendered UI panels
|
|
139
139
|
(dashboards, tables, forms, cards) without writing HTML. PMX Canvas ships the
|
|
140
|
-
[`@json-render/*`](https://www.npmjs.com/package/@json-render/core) runtime
|
|
140
|
+
[`@json-render/*`](https://www.npmjs.com/package/@json-render/core) 0.21.0 runtime
|
|
141
141
|
and component catalog (core + react + shadcn).
|
|
142
142
|
|
|
143
143
|
```ts
|
|
@@ -158,6 +158,22 @@ canvas_render({
|
|
|
158
158
|
`outline`. Older saved specs using `label` or status variants such as
|
|
159
159
|
`success`/`warning` are normalized during validation.
|
|
160
160
|
|
|
161
|
+
Specs preserve top-level `state` and element-level `repeat`, `watch`, and
|
|
162
|
+
`slots`. Use `$bindState` with JSON Pointer paths for editable form values;
|
|
163
|
+
`$state` only reads a value. Nested repeats can use `statePath: { "$item": "tasks" }`
|
|
164
|
+
to iterate the current item's tasks. Watchers run after changes, not on mount.
|
|
165
|
+
|
|
166
|
+
Cards keep their body in `children` and accept
|
|
167
|
+
`slots: { header: ['headingId'], footer: ['actionsId'] }`. Slot IDs reference
|
|
168
|
+
entries in `elements`; a custom header replaces the title and description props.
|
|
169
|
+
See the bundled [json-render guide](../skills/json-render-mcp/SKILL.md)
|
|
170
|
+
for a complete state-bound form with watchers and footer actions.
|
|
171
|
+
|
|
172
|
+
Form edits are viewer-local, not saved into the stored spec. Reloading the iframe
|
|
173
|
+
or updating its spec (including streaming patches) resets that state. Finish
|
|
174
|
+
streaming before collecting input, and persist important changes through an
|
|
175
|
+
explicit server interaction.
|
|
176
|
+
|
|
161
177
|
Elements may carry an `on` map (`on.press`, `on.change`, …) binding events to
|
|
162
178
|
actions (`{ action, params }`) — built-in actions (`setState`, `pushState`, …) or
|
|
163
179
|
host-provided handlers. PMX wires AX handlers named after interaction types, so a
|
|
@@ -185,9 +201,35 @@ source + per-viewer nonce + node id) and submits it server-side; `json-render` /
|
|
|
185
201
|
`graph` viewers are sandboxed surfaces, so caller-supplied `nodeIds` are clamped
|
|
186
202
|
to the node's own id. See the [MCP reference](mcp.md#node-interactions-capability-gated).
|
|
187
203
|
|
|
204
|
+
AX handlers are fire-and-forget: `onSuccess` means local dispatch completed,
|
|
205
|
+
not that the server accepted the operation. Confirm acceptance through AX state
|
|
206
|
+
or timeline before showing a saved state or clearing a draft. The built-in
|
|
207
|
+
`validateForm` action returns without calling `onSuccess`; do not chain submission
|
|
208
|
+
through that callback.
|
|
209
|
+
|
|
188
210
|
Use `canvas_render { action: "describe-schema" }` / `canvas_render { action:
|
|
189
211
|
"validate" }` to introspect the component catalog before building a spec.
|
|
190
212
|
|
|
213
|
+
### Automatic sizing of authored iframe cards
|
|
214
|
+
|
|
215
|
+
HTML (except presentation decks), Mermaid, JSON-render, graph, and web-artifact
|
|
216
|
+
cards can grow as their rendered content changes. This changes node geometry;
|
|
217
|
+
**Fit view** only changes the camera. Height measurements include title-bar and
|
|
218
|
+
body padding, grow only up to 1400px, and never change the width. Content beyond
|
|
219
|
+
that limit may still scroll; this is not a general shrink-to-content action.
|
|
220
|
+
|
|
221
|
+
Fitting waits for local or remote human grabs to end. A growing ungrouped,
|
|
222
|
+
screen-unpinned card moves downward if needed to leave a 24px gap from neighboring
|
|
223
|
+
cards, without moving those neighbors. A relocation records one undo step for
|
|
224
|
+
both size and position; height-only adjustments do not add undo entries.
|
|
225
|
+
Grouped or screen-pinned cards retain their positions. Collapsed cards and cards
|
|
226
|
+
marked `strictSize` or `userResized` are not automatically resized. Hosted MCP
|
|
227
|
+
apps and webpage viewers do not use this authored-content fitting behavior.
|
|
228
|
+
|
|
229
|
+
Read the settled node geometry after mounting rather than treating requested
|
|
230
|
+
dimensions as final. Prefer targeted node reads or the CLI's projected layout
|
|
231
|
+
fields over fetching full content merely to check spacing.
|
|
232
|
+
|
|
191
233
|
## HTML nodes
|
|
192
234
|
|
|
193
235
|
`html` nodes render a normal self-contained HTML/JS document in a sandboxed iframe.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Vision extension: boards, personal wiki, and workspace context
|
|
2
2
|
|
|
3
|
-
**Status:** Proposed for discussion, not an implementation commitment.
|
|
3
|
+
**Status:** Proposed for discussion, not an implementation commitment. **Superseded in part, 2026-09-23:** the maintainer decided that boards are the wiki and that the destination is "share this board" ([vision, move 0 and Part 3](product-vision-2026-09.md); reasoning in the [review](product-vision-review-2026-09.md#design-sketch-boards-are-the-wiki)). The separate entity and revision store, the personal wiki as its own surface, and working-versus-confirmed machinery are not planned; boards, cards and the journal play those roles. Still in force: the publication and audience rules and the threat-model corrections, which apply when sharing reaches a second writer (Part 3), and the validation experiment, run on linked boards instead of a wiki.
|
|
4
4
|
**Date:** 2026-09-06
|
|
5
5
|
**Companions:** [Product review](product-review-2026-09.md), [product vision](product-vision-2026-09.md).
|
|
6
6
|
**Request:** Review the existing vision and explore hosted users building their own wiki by describing their work, with their boards contributing context, and cross-cutting organizational context shared within a workspace. Reuse the logic of the personal/context-frame projects inside pmx-canvas's own store rather than depend on an external wiki.
|
|
@@ -10,9 +10,11 @@
|
|
|
10
10
|
|
|
11
11
|
**Work visually with your agents, build understanding as you go, and bring the right knowledge into whatever comes next.**
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
**The board is the human's extended memory and the agent's working memory.** It is a place for the human to do knowledge work, not just prepare context for an agent: research, analysis, dashboards, discovery, planning, coordination, and starting or orchestrating coding and other work. These are examples of its broad purpose, not a closed list. People can use the board to think and work directly, with agents contributing on the same surface.
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
As the work develops, sources, notes, questions, charts, plans, decisions, and outputs accumulate and connect on the board. They contribute to a memory graph and maintained wiki that support both human recall and agent context across tasks. Relevant prior knowledge can then return to a board as material for further work. The board, graph, and wiki are connected views and uses of this knowledge—not three competing sources of truth or three separate filing chores.
|
|
16
|
+
|
|
17
|
+
- **Do and shape the work together.** Read, write, compare evidence, monitor a dashboard, develop a plan, and direct execution on the board. Arrange, connect, pin, and annotate to support human understanding as well as shape agent context. Agents bring questions, proposals, and results back onto the same surface. Spatial layout provides context; not every move or camera gesture expresses intent.
|
|
16
18
|
- **Make memory useful in the next task.** Resume without re-explaining everything. Bring relevant prior learning and authorized cross-team decisions, dependencies, and conflicts into the work—not merely into a growing collection of notes.
|
|
17
19
|
- **Keep context honest as work changes.** Show sources and revisions, surface known changes and conflicts, and make uncertainty and review needs visible. Help people judge what still applies; do not treat a newer timestamp as truth or silently replace confirmed knowledge.
|
|
18
20
|
|
|
@@ -50,12 +52,12 @@ The loop is bidirectional: work produces personal understanding; selected outcom
|
|
|
50
52
|
8. **Treat hosted as more than a login screen.** Revocation, derived-content permissions, backups/restores, uploads, quotas, sandbox isolation, and operational recovery are new responsibilities. Node-level compare-and-set can be a starting conflict policy, but requires visible conflict/retry behavior; it does not settle collaborative text editing.
|
|
51
53
|
9. **Use measurements as evidence, not promises.** The earlier audit describes a particular tree and machine. Current context construction already has text previews and bounded pending steering. The claimed 10,000-token saving depends on what schemas hosts actually load; on-demand help alone does not remove advertised schemas. Measure current payloads before fixing budgets. Net-negative lines are not a user-value release gate.
|
|
52
54
|
|
|
53
|
-
The north star is
|
|
55
|
+
The north star is doing knowledge work on a shared visual surface that extends human memory and supplies agent working memory, with understanding carried into the next task. Validate human usefulness as well as agent behavior: can a person inspect evidence, understand relationships, resume research, monitor a dashboard, or develop and direct a plan? Pins, camera attention, and the time scrubber are mechanisms to validate against that purpose, not the purpose itself.
|
|
54
56
|
|
|
55
57
|
## The user experience
|
|
56
58
|
|
|
57
59
|
1. **Describe your work.** “I lead developer experience, work with these teams, and own these outcomes.” The assistant proposes a small personal home: responsibilities, initiatives, goals, people, and open questions. No mandatory taxonomy or blank-wiki setup project.
|
|
58
|
-
2. **Work on named boards.**
|
|
60
|
+
2. **Work on named boards.** Research, compare evidence, use dashboards, create outputs, and start, plan, or orchestrate coding and other work. Boards remain separate and recoverable. Each board is automatically listed as a source in the owner's context, within its existing permissions; the human can return to it without needing an agent to reconstruct the work.
|
|
59
61
|
3. **Remember without manual filing.** After the user delegates maintenance of specified private sources, the assistant updates existing personal working pages during the task. Source links, a quiet change history, and undo replace a compulsory wiki-edit review queue. Unknowns stay unknown; generated interpretations stay labeled.
|
|
60
62
|
4. **Confirm what matters.** “Keep this as my decision” confirms an exact revision with its evidence and owner. New agent changes remain working revisions, not silently renewed confirmation. Pinning still means attention, not publication.
|
|
61
63
|
5. **Resume with relevant memory.** A new board retrieves labeled personal working knowledge alongside confirmed personal context and authorized workspace knowledge. For shared organizational facts, shared canon has authority; for personal preferences, the person's context applies. Conflicting or newer evidence is shown rather than overwritten.
|
|
@@ -63,11 +65,20 @@ The north star is planning, discovery, analysis, and coordination visually with
|
|
|
63
65
|
|
|
64
66
|
Example: a PM explores options on a discovery board, accepts a decision into personal context, then publishes an appropriately sourced workspace decision. A team lead opens a planning board and receives that decision plus related shared dependencies—not the PM's private stakeholder notes or abandoned brainstorming.
|
|
65
67
|
|
|
68
|
+
### Work becomes memory, and memory supports more work
|
|
69
|
+
|
|
70
|
+
1. **Work on the board:** humans and agents add and use source material, relationships, live views, plans, and results.
|
|
71
|
+
2. **Connect the memory:** retain source and revision links so a person or agent can follow how an observation relates to evidence, a decision, or an outcome. Not every dashboard refresh or scratch note needs a permanent wiki page.
|
|
72
|
+
3. **Maintain understanding:** under the private-maintenance delegation, synthesize useful learning into existing working wiki pages. Preserve uncertainty and rejected alternatives; confirmation and wider sharing remain separate actions.
|
|
73
|
+
4. **Bring it back into work:** humans browse and revisit the graph, wiki, and boards; agents receive relevant, permission-scoped working context. New work adds evidence and can revise the understanding again.
|
|
74
|
+
|
|
75
|
+
The graph holds meaningful connections and provenance; the wiki presents maintained understanding; the board keeps active work spatial and usable. A board can contribute immediately as evidence and working memory without declaring all of its contents authoritative. This loop is the proposed direction, not a claim that automatic graph/wiki maintenance already ships.
|
|
76
|
+
|
|
66
77
|
## One model, distinct scopes
|
|
67
78
|
|
|
68
79
|
| Surface | Responsibility | What it must not imply |
|
|
69
80
|
|---|---|---|
|
|
70
|
-
| Board |
|
|
81
|
+
| Board | Human work surface and extended memory; agent working memory through spatial material, artifacts, asks, and evidence | The human only curates for agents, or everything visible is accepted knowledge |
|
|
71
82
|
| Personal wiki | Durable context owned by one person across boards | Workspace membership grants access |
|
|
72
83
|
| Workspace context | Deliberately shared goals, decisions, ownership, dependencies | A union of everyone's private context |
|
|
73
84
|
| Agent brief | Budgeted, task-specific view over authorized material | A new source of truth or permission grant |
|