pmx-canvas 0.1.36 → 0.2.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.
Files changed (91) hide show
  1. package/CHANGELOG.md +447 -0
  2. package/Readme.md +2 -2
  3. package/dist/json-render/index.js +89 -334
  4. package/dist/types/mcp/canvas-access.d.ts +5 -171
  5. package/dist/types/server/ax-state-manager.d.ts +267 -0
  6. package/dist/types/server/ax-state.d.ts +3 -1
  7. package/dist/types/server/canvas-db.d.ts +13 -0
  8. package/dist/types/server/canvas-operations.d.ts +1 -12
  9. package/dist/types/server/canvas-state.d.ts +8 -23
  10. package/dist/types/server/index.d.ts +6 -24
  11. package/dist/types/server/operations/composites.d.ts +121 -0
  12. package/dist/types/server/operations/http.d.ts +7 -0
  13. package/dist/types/server/operations/index.d.ts +8 -0
  14. package/dist/types/server/operations/invoker.d.ts +13 -0
  15. package/dist/types/server/operations/mcp.d.ts +15 -0
  16. package/dist/types/server/operations/ops/annotation.d.ts +2 -0
  17. package/dist/types/server/operations/ops/app.d.ts +33 -0
  18. package/dist/types/server/operations/ops/ax-await.d.ts +2 -0
  19. package/dist/types/server/operations/ops/ax-shared.d.ts +31 -0
  20. package/dist/types/server/operations/ops/ax-state.d.ts +2 -0
  21. package/dist/types/server/operations/ops/ax-timeline.d.ts +2 -0
  22. package/dist/types/server/operations/ops/ax-work.d.ts +2 -0
  23. package/dist/types/server/operations/ops/batch.d.ts +19 -0
  24. package/dist/types/server/operations/ops/edges.d.ts +2 -0
  25. package/dist/types/server/operations/ops/groups.d.ts +2 -0
  26. package/dist/types/server/operations/ops/json-render.d.ts +31 -0
  27. package/dist/types/server/operations/ops/nodes.d.ts +62 -0
  28. package/dist/types/server/operations/ops/query.d.ts +2 -0
  29. package/dist/types/server/operations/ops/snapshots.d.ts +2 -0
  30. package/dist/types/server/operations/ops/validate.d.ts +2 -0
  31. package/dist/types/server/operations/ops/viewport.d.ts +2 -0
  32. package/dist/types/server/operations/ops/webview.d.ts +2 -0
  33. package/dist/types/server/operations/registry.d.ts +15 -0
  34. package/dist/types/server/operations/types.d.ts +116 -0
  35. package/dist/types/server/operations/webview-runner.d.ts +69 -0
  36. package/docs/RELEASE.md +5 -0
  37. package/docs/adr-001-bun-only-runtime.md +46 -0
  38. package/docs/api-stability.md +57 -0
  39. package/docs/ax-host-adapter-contract.md +19 -1
  40. package/docs/ax-state-contract.md +72 -0
  41. package/docs/http-api.md +4 -0
  42. package/docs/mcp.md +61 -12
  43. package/docs/plans/plan-005-operation-registry.md +84 -0
  44. package/docs/plans/plan-006-mcp-tool-consolidation.md +109 -0
  45. package/docs/plans/plan-007-ax-domain.md +99 -0
  46. package/docs/plans/plan-008-registry-finish.md +91 -0
  47. package/docs/tech-debt-assessment-2026-06.md +90 -0
  48. package/package.json +3 -3
  49. package/skills/pmx-canvas/SKILL.md +221 -193
  50. package/skills/pmx-canvas/evals/evals.json +3 -3
  51. package/skills/pmx-canvas/references/ax-html-control-surface.md +93 -0
  52. package/skills/pmx-canvas/references/codex-app-adapter.md +13 -14
  53. package/skills/pmx-canvas/references/github-copilot-app-adapter.md +26 -11
  54. package/src/cli/agent.ts +52 -31
  55. package/src/mcp/canvas-access.ts +30 -830
  56. package/src/mcp/server.ts +162 -2014
  57. package/src/server/ax-context.ts +8 -1
  58. package/src/server/ax-state-manager.ts +826 -0
  59. package/src/server/ax-state.ts +10 -2
  60. package/src/server/canvas-db.ts +35 -0
  61. package/src/server/canvas-operations.ts +2 -328
  62. package/src/server/canvas-schema.ts +2 -2
  63. package/src/server/canvas-state.ts +103 -465
  64. package/src/server/index.ts +54 -190
  65. package/src/server/operations/composites.ts +355 -0
  66. package/src/server/operations/http.ts +103 -0
  67. package/src/server/operations/index.ts +65 -0
  68. package/src/server/operations/invoker.ts +87 -0
  69. package/src/server/operations/mcp.ts +221 -0
  70. package/src/server/operations/ops/annotation.ts +60 -0
  71. package/src/server/operations/ops/app.ts +447 -0
  72. package/src/server/operations/ops/ax-await.ts +216 -0
  73. package/src/server/operations/ops/ax-shared.ts +38 -0
  74. package/src/server/operations/ops/ax-state.ts +249 -0
  75. package/src/server/operations/ops/ax-timeline.ts +381 -0
  76. package/src/server/operations/ops/ax-work.ts +635 -0
  77. package/src/server/operations/ops/batch.ts +365 -0
  78. package/src/server/operations/ops/edges.ts +166 -0
  79. package/src/server/operations/ops/groups.ts +176 -0
  80. package/src/server/operations/ops/json-render.ts +691 -0
  81. package/src/server/operations/ops/nodes.ts +1047 -0
  82. package/src/server/operations/ops/query.ts +281 -0
  83. package/src/server/operations/ops/snapshots.ts +366 -0
  84. package/src/server/operations/ops/validate.ts +37 -0
  85. package/src/server/operations/ops/viewport.ts +219 -0
  86. package/src/server/operations/ops/webview.ts +339 -0
  87. package/src/server/operations/registry.ts +79 -0
  88. package/src/server/operations/types.ts +150 -0
  89. package/src/server/operations/webview-runner.ts +77 -0
  90. package/src/server/server.ts +158 -2255
  91. package/src/server/web-artifacts.ts +6 -2
@@ -1,167 +1,49 @@
1
- import { type CanvasLayout, type CanvasNodeState, type CanvasSnapshot, type PmxCanvas } from '../server/index.js';
1
+ import { type CanvasLayout, type CanvasNodeState, type PmxCanvas } from '../server/index.js';
2
2
  import type { PmxAxSource } from '../server/ax-state.js';
3
- type AddNodeInput = Parameters<PmxCanvas['addNode']>[0];
4
- type AddWebpageNodeInput = Parameters<PmxCanvas['addWebpageNode']>[0];
3
+ import { type OperationInvoker } from '../server/operations/index.js';
5
4
  type RefreshWebpageNodeResult = Awaited<ReturnType<PmxCanvas['refreshWebpageNode']>>;
6
- type OpenMcpAppInput = Parameters<PmxCanvas['openMcpApp']>[0];
7
- type OpenMcpAppResult = Awaited<ReturnType<PmxCanvas['openMcpApp']>>;
8
- type AddDiagramInput = Parameters<PmxCanvas['addDiagram']>[0];
9
- type AddJsonRenderNodeInput = Parameters<PmxCanvas['addJsonRenderNode']>[0];
10
- type AddJsonRenderNodeResult = ReturnType<PmxCanvas['addJsonRenderNode']>;
11
- type StreamJsonRenderNodeInput = Parameters<PmxCanvas['streamJsonRenderNode']>[0];
12
- type StreamJsonRenderNodeResult = ReturnType<PmxCanvas['streamJsonRenderNode']>;
13
5
  type AddHtmlNodeInput = Parameters<PmxCanvas['addHtmlNode']>[0];
14
6
  type AddHtmlPrimitiveInput = Parameters<PmxCanvas['addHtmlPrimitive']>[0];
15
7
  type AddHtmlPrimitiveResult = ReturnType<PmxCanvas['addHtmlPrimitive']>;
16
- type AddGraphNodeInput = Parameters<PmxCanvas['addGraphNode']>[0];
17
- type AddGraphNodeResult = ReturnType<PmxCanvas['addGraphNode']>;
18
- type UpdateNodePatch = Parameters<PmxCanvas['updateNode']>[1];
19
- type AddEdgeInput = Parameters<PmxCanvas['addEdge']>[0];
20
- type CreateGroupInput = Parameters<PmxCanvas['createGroup']>[0];
21
- type GroupNodesOptions = Parameters<PmxCanvas['groupNodes']>[2];
22
- type ArrangeLayout = Parameters<PmxCanvas['arrange']>[0];
23
- type FocusNodeResult = ReturnType<PmxCanvas['focusNode']>;
24
- type FitViewOptions = Parameters<PmxCanvas['fitView']>[0];
25
- type FitViewResult = ReturnType<PmxCanvas['fitView']>;
26
8
  type AxStateResult = ReturnType<PmxCanvas['getAxState']>;
27
9
  type AxContextResult = ReturnType<PmxCanvas['getAxContext']>;
28
- type SetAxFocusResult = ReturnType<PmxCanvas['setAxFocus']>;
29
- type RecordAxEventInput = Parameters<PmxCanvas['recordAxEvent']>[0];
30
- type RecordAxEventResult = ReturnType<PmxCanvas['recordAxEvent']>;
31
- type SendSteeringResult = ReturnType<PmxCanvas['sendSteering']>;
32
10
  type SubmitAxInteractionInput = Parameters<PmxCanvas['submitAxInteraction']>[0];
33
11
  type SubmitAxInteractionResult = ReturnType<PmxCanvas['submitAxInteraction']>;
34
12
  type GetPendingSteeringResult = ReturnType<PmxCanvas['getPendingSteering']>;
35
13
  type ListElicitationsResult = ReturnType<PmxCanvas['listElicitations']>;
36
- type RequestElicitationInput = Parameters<PmxCanvas['requestElicitation']>[0];
37
- type RequestElicitationResult = ReturnType<PmxCanvas['requestElicitation']>;
38
- type RespondElicitationResult = ReturnType<PmxCanvas['respondElicitation']>;
39
14
  type ListModeRequestsResult = ReturnType<PmxCanvas['listModeRequests']>;
40
- type RequestModeInput = Parameters<PmxCanvas['requestMode']>[0];
41
- type RequestModeResult = ReturnType<PmxCanvas['requestMode']>;
42
- type ResolveModeRequestResult = ReturnType<PmxCanvas['resolveModeRequest']>;
43
15
  type IngestActivityInput = Parameters<PmxCanvas['ingestActivity']>[0];
44
16
  type IngestActivityResult = ReturnType<PmxCanvas['ingestActivity']>;
45
- type AwaitApprovalResult = Awaited<ReturnType<PmxCanvas['awaitApproval']>>;
46
- type AwaitElicitationResult = Awaited<ReturnType<PmxCanvas['awaitElicitation']>>;
47
- type AwaitModeResult = Awaited<ReturnType<PmxCanvas['awaitMode']>>;
48
- type GetCommandRegistryResult = ReturnType<PmxCanvas['getCommandRegistry']>;
49
- type InvokeCommandResult = ReturnType<PmxCanvas['invokeCommand']>;
50
17
  type GetPolicyResult = ReturnType<PmxCanvas['getPolicy']>;
51
- type SetPolicyInput = Parameters<PmxCanvas['setPolicy']>[0];
52
- type SetPolicyResult = ReturnType<PmxCanvas['setPolicy']>;
53
18
  type GetAxTimelineQuery = Parameters<PmxCanvas['getAxTimeline']>[0];
54
19
  type GetAxTimelineResult = ReturnType<PmxCanvas['getAxTimeline']>;
55
- type AddWorkItemInput = Parameters<PmxCanvas['addWorkItem']>[0];
56
- type AddWorkItemResult = ReturnType<PmxCanvas['addWorkItem']>;
57
- type UpdateWorkItemPatch = Parameters<PmxCanvas['updateWorkItem']>[1];
58
- type UpdateWorkItemResult = ReturnType<PmxCanvas['updateWorkItem']>;
59
20
  type ListWorkItemsResult = ReturnType<PmxCanvas['listWorkItems']>;
60
- type RequestApprovalInput = Parameters<PmxCanvas['requestApproval']>[0];
61
- type RequestApprovalResult = ReturnType<PmxCanvas['requestApproval']>;
62
- type ResolveApprovalResult = ReturnType<PmxCanvas['resolveApproval']>;
63
21
  type ListApprovalGatesResult = ReturnType<PmxCanvas['listApprovalGates']>;
64
- type AddEvidenceInput = Parameters<PmxCanvas['addEvidence']>[0];
65
- type AddEvidenceResult = ReturnType<PmxCanvas['addEvidence']>;
66
- type AddReviewAnnotationInput = Parameters<PmxCanvas['addReviewAnnotation']>[0];
67
- type AddReviewAnnotationResult = ReturnType<PmxCanvas['addReviewAnnotation']>;
68
- type UpdateReviewAnnotationPatch = Parameters<PmxCanvas['updateReviewAnnotation']>[1];
69
- type UpdateReviewAnnotationResult = ReturnType<PmxCanvas['updateReviewAnnotation']>;
70
22
  type ListReviewAnnotationsResult = ReturnType<PmxCanvas['listReviewAnnotations']>;
71
- type GetHostCapabilityResult = ReturnType<PmxCanvas['getHostCapability']>;
72
- type ReportHostCapabilityResult = ReturnType<PmxCanvas['reportHostCapability']>;
73
- type SearchResult = ReturnType<PmxCanvas['search']>;
74
- type UndoRedoResult = Awaited<ReturnType<PmxCanvas['undo']>>;
75
23
  type HistoryResult = ReturnType<PmxCanvas['getHistory']>;
76
- type SetContextPinsResult = ReturnType<PmxCanvas['setContextPins']>;
77
24
  type RunBatchInput = Parameters<PmxCanvas['runBatch']>[0];
78
25
  type RunBatchResult = Awaited<ReturnType<PmxCanvas['runBatch']>>;
79
- type SnapshotListOptions = Parameters<PmxCanvas['listSnapshots']>[0];
80
- type SnapshotList = ReturnType<PmxCanvas['listSnapshots']>;
81
- type DeleteSnapshotResult = ReturnType<PmxCanvas['deleteSnapshot']>;
82
- type GcSnapshotsOptions = Parameters<PmxCanvas['gcSnapshots']>[0];
83
- type GcSnapshotsResult = ReturnType<PmxCanvas['gcSnapshots']>;
84
- type DiffSnapshotResult = ReturnType<PmxCanvas['diffSnapshot']>;
85
26
  type CodeGraphResult = ReturnType<PmxCanvas['getCodeGraph']>;
86
- type ValidationResult = ReturnType<PmxCanvas['validate']>;
87
- type WebArtifactInput = Parameters<PmxCanvas['buildWebArtifact']>[0];
88
- type WebArtifactResult = Awaited<ReturnType<PmxCanvas['buildWebArtifact']>>;
89
- type AutomationWebViewOptions = Parameters<PmxCanvas['startAutomationWebView']>[0];
90
- type AutomationWebViewStatus = Awaited<ReturnType<PmxCanvas['startAutomationWebView']>>;
91
- type AutomationEvaluateResult = Awaited<ReturnType<PmxCanvas['evaluateAutomationWebView']>>;
27
+ type AutomationWebViewStatus = Awaited<ReturnType<PmxCanvas['getAutomationWebViewStatus']>>;
92
28
  type AutomationScreenshotOptions = Parameters<PmxCanvas['screenshotAutomationWebView']>[0];
93
29
  export interface CanvasAccess {
94
30
  readonly port: number;
95
31
  readonly remoteBaseUrl: string | null;
32
+ /** Operation-registry invoker (plan-005): local in-process or HTTP, matching the access mode. */
33
+ invoker(): OperationInvoker;
96
34
  getLayout(): Promise<CanvasLayout>;
97
35
  getNode(id: string): Promise<CanvasNodeState | undefined>;
98
- addNode(input: AddNodeInput): Promise<string>;
99
- addWebpageNode(input: AddWebpageNodeInput): Promise<Awaited<ReturnType<PmxCanvas['addWebpageNode']>>>;
100
36
  refreshWebpageNode(id: string, url?: string): Promise<RefreshWebpageNodeResult>;
101
- openMcpApp(input: OpenMcpAppInput): Promise<OpenMcpAppResult>;
102
- addDiagram(input: AddDiagramInput): Promise<OpenMcpAppResult>;
103
- addJsonRenderNode(input: AddJsonRenderNodeInput): Promise<AddJsonRenderNodeResult>;
104
- streamJsonRenderNode(input: StreamJsonRenderNodeInput): Promise<StreamJsonRenderNodeResult>;
105
37
  addHtmlNode(input: AddHtmlNodeInput): Promise<string>;
106
38
  addHtmlPrimitive(input: AddHtmlPrimitiveInput): Promise<AddHtmlPrimitiveResult>;
107
- addGraphNode(input: AddGraphNodeInput): Promise<AddGraphNodeResult>;
108
- buildWebArtifact(input: WebArtifactInput): Promise<WebArtifactResult>;
109
- updateNode(id: string, patch: UpdateNodePatch): Promise<void>;
110
- removeNode(id: string): Promise<void>;
111
- removeAnnotation(id: string): Promise<boolean>;
112
- addEdge(input: AddEdgeInput): Promise<string>;
113
- removeEdge(id: string): Promise<void>;
114
- createGroup(input: CreateGroupInput): Promise<string>;
115
- groupNodes(groupId: string, childIds: string[], options?: GroupNodesOptions): Promise<boolean>;
116
- ungroupNodes(groupId: string): Promise<boolean>;
117
- arrange(layout?: ArrangeLayout): Promise<void>;
118
- focusNode(id: string, options?: {
119
- noPan?: boolean;
120
- }): Promise<FocusNodeResult>;
121
- fitView(options?: FitViewOptions): Promise<FitViewResult>;
122
39
  getAxState(): Promise<AxStateResult>;
123
40
  getAxContext(options?: {
124
41
  consumer?: string;
125
42
  }): Promise<AxContextResult>;
126
- setAxFocus(nodeIds: string[], options?: {
127
- source?: PmxAxSource;
128
- }): Promise<SetAxFocusResult>;
129
- recordAxEvent(input: RecordAxEventInput, options?: {
130
- source?: PmxAxSource;
131
- }): Promise<RecordAxEventResult>;
132
- sendSteering(message: string, options?: {
133
- source?: PmxAxSource;
134
- }): Promise<SendSteeringResult>;
135
43
  getAxTimeline(query?: GetAxTimelineQuery): Promise<GetAxTimelineResult>;
136
- addWorkItem(input: AddWorkItemInput, options?: {
137
- source?: PmxAxSource;
138
- }): Promise<AddWorkItemResult>;
139
- updateWorkItem(id: string, patch: UpdateWorkItemPatch, options?: {
140
- source?: PmxAxSource;
141
- }): Promise<UpdateWorkItemResult>;
142
44
  listWorkItems(): Promise<ListWorkItemsResult>;
143
- requestApproval(input: RequestApprovalInput, options?: {
144
- source?: PmxAxSource;
145
- }): Promise<RequestApprovalResult>;
146
- resolveApproval(id: string, decision: 'approved' | 'rejected', options?: {
147
- resolution?: string;
148
- source?: PmxAxSource;
149
- }): Promise<ResolveApprovalResult>;
150
45
  listApprovalGates(): Promise<ListApprovalGatesResult>;
151
- addEvidence(input: AddEvidenceInput, options?: {
152
- source?: PmxAxSource;
153
- }): Promise<AddEvidenceResult>;
154
- addReviewAnnotation(input: AddReviewAnnotationInput, options?: {
155
- source?: PmxAxSource;
156
- }): Promise<AddReviewAnnotationResult>;
157
- updateReviewAnnotation(id: string, patch: UpdateReviewAnnotationPatch, options?: {
158
- source?: PmxAxSource;
159
- }): Promise<UpdateReviewAnnotationResult>;
160
46
  listReviewAnnotations(): Promise<ListReviewAnnotationsResult>;
161
- getHostCapability(): Promise<GetHostCapabilityResult>;
162
- reportHostCapability(input: unknown, options?: {
163
- source?: PmxAxSource;
164
- }): Promise<ReportHostCapabilityResult>;
165
47
  submitAxInteraction(input: SubmitAxInteractionInput, options?: {
166
48
  source?: PmxAxSource;
167
49
  }): Promise<SubmitAxInteractionResult>;
@@ -169,65 +51,17 @@ export interface CanvasAccess {
169
51
  consumer?: string;
170
52
  limit?: number;
171
53
  }): Promise<GetPendingSteeringResult>;
172
- markSteeringDelivered(id: string): Promise<boolean>;
173
54
  listElicitations(): Promise<ListElicitationsResult>;
174
- requestElicitation(input: RequestElicitationInput, options?: {
175
- source?: PmxAxSource;
176
- }): Promise<RequestElicitationResult>;
177
- respondElicitation(id: string, response: Record<string, unknown>, options?: {
178
- source?: PmxAxSource;
179
- }): Promise<RespondElicitationResult>;
180
55
  listModeRequests(): Promise<ListModeRequestsResult>;
181
- requestMode(input: RequestModeInput, options?: {
182
- source?: PmxAxSource;
183
- }): Promise<RequestModeResult>;
184
- resolveModeRequest(id: string, decision: 'approved' | 'rejected', options?: {
185
- resolution?: string;
186
- source?: PmxAxSource;
187
- }): Promise<ResolveModeRequestResult>;
188
56
  ingestActivity(input: IngestActivityInput, options?: {
189
57
  source?: PmxAxSource;
190
58
  }): Promise<IngestActivityResult>;
191
- awaitApproval(id: string, options?: {
192
- timeoutMs?: number;
193
- }): Promise<AwaitApprovalResult>;
194
- awaitElicitation(id: string, options?: {
195
- timeoutMs?: number;
196
- }): Promise<AwaitElicitationResult>;
197
- awaitMode(id: string, options?: {
198
- timeoutMs?: number;
199
- }): Promise<AwaitModeResult>;
200
- getCommandRegistry(): Promise<GetCommandRegistryResult>;
201
- invokeCommand(name: string, args?: Record<string, unknown> | null, options?: {
202
- source?: PmxAxSource;
203
- }): Promise<InvokeCommandResult>;
204
59
  getPolicy(): Promise<GetPolicyResult>;
205
- setPolicy(patch: SetPolicyInput, options?: {
206
- source?: PmxAxSource;
207
- }): Promise<SetPolicyResult>;
208
- clear(): Promise<void>;
209
- search(query: string): Promise<SearchResult>;
210
- undo(): Promise<UndoRedoResult>;
211
- redo(): Promise<UndoRedoResult>;
212
60
  getHistory(): Promise<HistoryResult>;
213
- setContextPins(nodeIds: string[], mode?: 'set' | 'add' | 'remove'): Promise<SetContextPinsResult>;
214
61
  getPinnedNodeIds(): Promise<string[]>;
215
62
  runBatch(operations: RunBatchInput): Promise<RunBatchResult>;
216
- listSnapshots(options?: SnapshotListOptions): Promise<SnapshotList>;
217
- saveSnapshot(name: string): Promise<CanvasSnapshot | null>;
218
- restoreSnapshot(id: string): Promise<{
219
- ok: boolean;
220
- }>;
221
- deleteSnapshot(id: string): Promise<DeleteSnapshotResult>;
222
- gcSnapshots(options?: GcSnapshotsOptions): Promise<GcSnapshotsResult>;
223
- diffSnapshot(idOrName: string): Promise<DiffSnapshotResult>;
224
63
  getCodeGraph(): Promise<CodeGraphResult>;
225
- validate(): Promise<ValidationResult>;
226
64
  getAutomationWebViewStatus(): Promise<AutomationWebViewStatus>;
227
- startAutomationWebView(options?: AutomationWebViewOptions): Promise<AutomationWebViewStatus>;
228
- stopAutomationWebView(): Promise<boolean>;
229
- evaluateAutomationWebView(expression: string): Promise<AutomationEvaluateResult>;
230
- resizeAutomationWebView(width: number, height: number): Promise<AutomationWebViewStatus>;
231
65
  screenshotAutomationWebView(options?: AutomationScreenshotOptions): Promise<Uint8Array>;
232
66
  }
233
67
  export declare function refreshCanvasAccess(access: CanvasAccess): Promise<CanvasAccess>;
@@ -0,0 +1,267 @@
1
+ /**
2
+ * AX state manager.
3
+ *
4
+ * Owns the agent-experience (AX) state that previously lived inline in
5
+ * `CanvasStateManager`. Splits cleanly into the three documented partitions
6
+ * (see `docs/ax-state-contract.md`):
7
+ *
8
+ * • Canvas-bound (`_axState`): focus, work items, approval gates, review
9
+ * annotations, elicitations, mode requests, policy. Snapshotted, cleared by
10
+ * `canvas_clear`, replaced by `restore`. Mutators record undo/redo history
11
+ * (via the injected `recordMutation` / `suppressed` callbacks).
12
+ * • Timeline (audit-only): agent events, evidence, steering. DB-direct, NOT in
13
+ * `_axState`, NOT history-recorded, NOT snapshotted, retention-bounded.
14
+ * • Host/session: a single host-capability row in its own table.
15
+ *
16
+ * `CanvasStateManager` holds one of these and DELEGATES its public AX methods to
17
+ * it, so the SDK/HTTP/MCP surface is byte-stable. The manager takes injected
18
+ * callbacks for everything it does not own: a node-id-validity provider (used by
19
+ * normalization on write), the live DB handle, `scheduleSave`, `notifyChange`,
20
+ * `recordMutation`, and a `suppressed` wrapper for history closures.
21
+ */
22
+ import { type AxTimelineQuery } from './canvas-db.js';
23
+ import { type PmxAxActivityKind, type PmxAxElicitation, type PmxAxModeRequest, type PmxAxMode, type PmxAxCommandDescriptor, type PmxAxPolicy, type PmxAxFocusState, type PmxAxSource, type PmxAxState, type PmxAxWorkItem, type PmxAxWorkItemStatus, type PmxAxApprovalGate, type PmxAxReviewAnnotation, type PmxAxReviewKind, type PmxAxReviewSeverity, type PmxAxReviewStatus, type PmxAxReviewAnchorType, type PmxAxReviewRegion, type PmxAxEvent, type PmxAxEventKind, type PmxAxEvidence, type PmxAxEvidenceKind, type PmxAxSteeringMessage, type PmxAxHostCapability, type PmxAxTimelineSummary } from './ax-state.js';
24
+ import type { CanvasChangeType, MutationRecordInfo } from './canvas-state.js';
25
+ type Database = import('bun:sqlite').Database;
26
+ /** Host-environment hooks the AX manager needs from its owner (CanvasStateManager). */
27
+ export interface AxStateManagerDeps {
28
+ /** Current valid node-id set — used by normalization on write to prune dangling refs. */
29
+ getNodeIds(): Set<string>;
30
+ /** Live DB handle for the timeline tables / host-capability table (null when no workspace). */
31
+ getDb(): Database | null;
32
+ /** Debounced save of the canvas-bound blob (timeline ops do NOT trigger this — they are DB-direct). */
33
+ scheduleSave(): void;
34
+ /** Emit a change notification (drives MCP resource notifications + blocking-wait endpoints). */
35
+ notifyChange(type: CanvasChangeType): void;
36
+ /** Record an undo/redo history entry. */
37
+ recordMutation(info: MutationRecordInfo): void;
38
+ /** Wrap a closure so it runs with mutation recording suppressed (for undo/redo replay). */
39
+ suppressed(fn: () => void): () => void;
40
+ }
41
+ export declare class AxStateManager {
42
+ private readonly deps;
43
+ private _axState;
44
+ private _axHostCapability;
45
+ constructor(deps: AxStateManagerDeps);
46
+ private normalizeForCurrentNodes;
47
+ private applyAxState;
48
+ /** Reset the canvas-bound partition to empty (used by clear() and applyPersistedState()). */
49
+ resetCanvasBound(): void;
50
+ /** Replace the canvas-bound partition from a persisted/restored blob, normalized against current nodes. */
51
+ applyPersistedAx(ax: unknown): void;
52
+ /** Load the host-capability row from its own table (own partition; not snapshotted). */
53
+ loadHostCapabilityFromDb(): void;
54
+ /**
55
+ * Re-normalize the canvas-bound partition against the current node set after a
56
+ * node was removed, and report what the removal orphaned. Work items / approval
57
+ * gates / elicitations / mode requests keep the item but strip the dangling node
58
+ * id ("re-anchored"); node-anchored review annotations are dropped ("removed").
59
+ * Returns the affected ids so the owner can record one audit timeline event.
60
+ */
61
+ revalidateAfterNodeRemoval(removedNodeId: string): {
62
+ reanchoredIds: string[];
63
+ removedReviewIds: string[];
64
+ reanchoredFocus: boolean;
65
+ };
66
+ getAxState(): PmxAxState;
67
+ getAxFocus(): PmxAxFocusState;
68
+ setAxFocus(nodeIds: string[], options?: {
69
+ source?: PmxAxSource;
70
+ recordHistory?: boolean;
71
+ }): PmxAxFocusState;
72
+ clearAxFocus(): PmxAxFocusState;
73
+ getWorkItems(): PmxAxWorkItem[];
74
+ addWorkItem(input: {
75
+ title: string;
76
+ status?: PmxAxWorkItemStatus;
77
+ detail?: string | null;
78
+ nodeIds?: string[];
79
+ }, options?: {
80
+ source?: PmxAxSource;
81
+ }): PmxAxWorkItem;
82
+ updateWorkItem(id: string, patch: {
83
+ title?: string;
84
+ status?: PmxAxWorkItemStatus;
85
+ detail?: string | null;
86
+ nodeIds?: string[];
87
+ }, options?: {
88
+ source?: PmxAxSource;
89
+ }): PmxAxWorkItem | null;
90
+ getApprovalGates(): PmxAxApprovalGate[];
91
+ requestApproval(input: {
92
+ title: string;
93
+ detail?: string | null;
94
+ action?: string | null;
95
+ nodeIds?: string[];
96
+ }, options?: {
97
+ source?: PmxAxSource;
98
+ }): PmxAxApprovalGate;
99
+ resolveApproval(id: string, decision: 'approved' | 'rejected', options?: {
100
+ resolution?: string;
101
+ source?: PmxAxSource;
102
+ }): PmxAxApprovalGate | null;
103
+ getReviewAnnotations(): PmxAxReviewAnnotation[];
104
+ addReviewAnnotation(input: {
105
+ body: string;
106
+ kind?: PmxAxReviewKind;
107
+ severity?: PmxAxReviewSeverity;
108
+ anchorType?: PmxAxReviewAnchorType;
109
+ nodeId?: string | null;
110
+ file?: string | null;
111
+ region?: PmxAxReviewRegion | null;
112
+ author?: string | null;
113
+ }, options?: {
114
+ source?: PmxAxSource;
115
+ }): PmxAxReviewAnnotation | null;
116
+ updateReviewAnnotation(id: string, patch: {
117
+ body?: string;
118
+ status?: PmxAxReviewStatus;
119
+ severity?: PmxAxReviewSeverity;
120
+ kind?: PmxAxReviewKind;
121
+ }, options?: {
122
+ source?: PmxAxSource;
123
+ }): PmxAxReviewAnnotation | null;
124
+ getHostCapability(): PmxAxHostCapability | null;
125
+ getElicitations(): PmxAxElicitation[];
126
+ requestElicitation(input: {
127
+ prompt: string;
128
+ fields?: string[];
129
+ nodeIds?: string[];
130
+ }, options?: {
131
+ source?: PmxAxSource;
132
+ }): PmxAxElicitation;
133
+ respondElicitation(id: string, response: Record<string, unknown>, options?: {
134
+ source?: PmxAxSource;
135
+ }): PmxAxElicitation | null;
136
+ getModeRequests(): PmxAxModeRequest[];
137
+ requestMode(input: {
138
+ mode: PmxAxMode;
139
+ reason?: string | null;
140
+ nodeIds?: string[];
141
+ }, options?: {
142
+ source?: PmxAxSource;
143
+ }): PmxAxModeRequest;
144
+ resolveModeRequest(id: string, decision: 'approved' | 'rejected', options?: {
145
+ resolution?: string;
146
+ source?: PmxAxSource;
147
+ }): PmxAxModeRequest | null;
148
+ getApproval(id: string): PmxAxApprovalGate | null;
149
+ getElicitation(id: string): PmxAxElicitation | null;
150
+ getModeRequest(id: string): PmxAxModeRequest | null;
151
+ getCommandRegistry(): PmxAxCommandDescriptor[];
152
+ /** Invoke a registry-gated PMX command intent — records a timeline event (no execution). */
153
+ invokeCommand(name: string, args?: Record<string, unknown> | null, options?: {
154
+ source?: PmxAxSource;
155
+ }): PmxAxEvent | null;
156
+ getPolicy(): PmxAxPolicy;
157
+ /** Merge a declarative tool/prompt policy patch (canvas-bound, snapshotted). */
158
+ setPolicy(patch: {
159
+ tools?: Partial<PmxAxPolicy['tools']>;
160
+ prompt?: Partial<PmxAxPolicy['prompt']>;
161
+ }, _options?: {
162
+ source?: PmxAxSource;
163
+ }): PmxAxPolicy;
164
+ setHostCapability(input: unknown, _options?: {
165
+ source?: PmxAxSource;
166
+ }): PmxAxHostCapability;
167
+ recordAxEvent(input: {
168
+ kind: PmxAxEventKind;
169
+ summary: string;
170
+ detail?: string | null;
171
+ nodeIds?: string[];
172
+ data?: Record<string, unknown> | null;
173
+ }, options?: {
174
+ source?: PmxAxSource;
175
+ }): PmxAxEvent;
176
+ addEvidence(input: {
177
+ kind: PmxAxEvidenceKind;
178
+ title: string;
179
+ body?: string | null;
180
+ ref?: string | null;
181
+ nodeIds?: string[];
182
+ data?: Record<string, unknown> | null;
183
+ }, options?: {
184
+ source?: PmxAxSource;
185
+ }): PmxAxEvidence;
186
+ recordSteeringMessage(message: string, options?: {
187
+ source?: PmxAxSource;
188
+ }): PmxAxSteeringMessage;
189
+ markSteeringDelivered(id: string): boolean;
190
+ /**
191
+ * Ingest a normalized agent activity (a tool/session event a harness forwards)
192
+ * and apply kind-driven board reactions, so the agent's real work flows back into
193
+ * the board without it remembering to push each item (report primitive A — makes
194
+ * AX bidirectional). Always records a timeline event; then, unless the caller
195
+ * overrides/suppresses via `reactions`, applies defaults by kind/outcome:
196
+ * • failure | error | outcome==='failure' → work item (blocked) + review
197
+ * (finding/error, anchored to a valid nodeId else the `ref` file) + evidence (logs)
198
+ * • tool-result + outcome==='success' → evidence (tool-result)
199
+ * • everything else (tool-start, session-*, command, note) → event only
200
+ * A reaction value of `false` suppresses it; an object overrides its fields/forces it on.
201
+ */
202
+ ingestActivity(input: {
203
+ kind: PmxAxActivityKind;
204
+ title: string;
205
+ summary?: string | null;
206
+ outcome?: 'success' | 'failure';
207
+ ref?: string | null;
208
+ nodeIds?: string[];
209
+ data?: Record<string, unknown> | null;
210
+ reactions?: {
211
+ workItem?: false | {
212
+ status?: PmxAxWorkItemStatus;
213
+ detail?: string | null;
214
+ };
215
+ evidence?: false | {
216
+ kind?: PmxAxEvidenceKind;
217
+ body?: string | null;
218
+ };
219
+ review?: false | {
220
+ severity?: PmxAxReviewSeverity;
221
+ kind?: PmxAxReviewKind;
222
+ anchorType?: PmxAxReviewAnchorType;
223
+ nodeId?: string | null;
224
+ };
225
+ };
226
+ }, options?: {
227
+ source?: PmxAxSource;
228
+ }): {
229
+ event: PmxAxEvent;
230
+ workItem: PmxAxWorkItem | null;
231
+ evidence: PmxAxEvidence | null;
232
+ review: PmxAxReviewAnnotation | null;
233
+ };
234
+ getAxEvents(q?: AxTimelineQuery): PmxAxEvent[];
235
+ getAxEvidence(q?: AxTimelineQuery): PmxAxEvidence[];
236
+ getAxSteering(q?: AxTimelineQuery & {
237
+ onlyPending?: boolean;
238
+ }): PmxAxSteeringMessage[];
239
+ /**
240
+ * Undelivered steering for a consumer (Phase 4 delivery). Excludes messages
241
+ * whose source equals the consumer to prevent delivery loops (e.g. Copilot
242
+ * should not be handed back steering it originated).
243
+ */
244
+ getPendingSteering(options?: {
245
+ consumer?: string;
246
+ limit?: number;
247
+ }): PmxAxSteeringMessage[];
248
+ /**
249
+ * NEWEST undelivered steering first, for the compact AX context lead block (report
250
+ * #57) — so a fresh steer is visible even behind a long backlog. Loop-safe like
251
+ * getPendingSteering, but ordered DESC instead of the FIFO ASC delivery queue.
252
+ */
253
+ getPendingSteeringForContext(options?: {
254
+ consumer?: string;
255
+ limit?: number;
256
+ }): PmxAxSteeringMessage[];
257
+ /** Total undelivered steering for a consumer (loop-safe), for the context backlog counts. */
258
+ getPendingSteeringCount(consumer?: string): number;
259
+ getAxTimelineSummary(): PmxAxTimelineSummary;
260
+ getAxTimeline(q?: AxTimelineQuery): {
261
+ events: PmxAxEvent[];
262
+ evidence: PmxAxEvidence[];
263
+ steering: PmxAxSteeringMessage[];
264
+ summary: PmxAxTimelineSummary;
265
+ };
266
+ }
267
+ export {};
@@ -7,7 +7,7 @@ export interface PmxAxFocusState {
7
7
  updatedAt: string | null;
8
8
  source: PmxAxSource | null;
9
9
  }
10
- export type PmxAxEventKind = 'prompt' | 'assistant-message' | 'tool-start' | 'tool-result' | 'failure' | 'approval' | 'steering' | 'command';
10
+ export type PmxAxEventKind = 'prompt' | 'assistant-message' | 'tool-start' | 'tool-result' | 'failure' | 'approval' | 'steering' | 'command' | 'note';
11
11
  export type PmxAxEvidenceKind = 'logs' | 'tool-result' | 'screenshot' | 'file' | 'diff' | 'test-output';
12
12
  export type PmxAxWorkItemStatus = 'todo' | 'in-progress' | 'blocked' | 'done' | 'cancelled';
13
13
  export type PmxAxApprovalStatus = 'pending' | 'approved' | 'rejected';
@@ -145,6 +145,8 @@ export interface PendingAxActivityItem {
145
145
  }
146
146
  export interface PmxAxDeliveryContext {
147
147
  pendingSteering: PmxAxSteeringMessage[];
148
+ totalPending: number;
149
+ omittedPending: number;
148
150
  pendingActivity: PendingAxActivityItem[];
149
151
  }
150
152
  export interface PmxAxContext {
@@ -53,6 +53,19 @@ export declare function loadPendingAxSteeringFromDB(db: Database, options?: {
53
53
  consumer?: string;
54
54
  limit?: number;
55
55
  }): PmxAxSteeringMessage[];
56
+ /**
57
+ * NEWEST undelivered steering first (report #57) for the compact AX context lead
58
+ * block — so a fresh steer is visible even behind a long backlog. Loop-safe: excludes
59
+ * the consumer's own steering in SQL so the LIMIT applies after loop-prevention.
60
+ * Distinct from loadPendingAxSteeringFromDB (FIFO oldest-first) which the claim/ack
61
+ * delivery queue uses for ordered processing.
62
+ */
63
+ export declare function loadNewestPendingAxSteeringFromDB(db: Database, options?: {
64
+ consumer?: string;
65
+ limit?: number;
66
+ }): PmxAxSteeringMessage[];
67
+ /** Total undelivered steering for a consumer (loop-safe — excludes the consumer's own). */
68
+ export declare function countPendingAxSteeringFromDB(db: Database, consumer?: string): number;
56
69
  export declare function loadAxTimelineSummaryFromDB(db: Database): PmxAxTimelineSummary;
57
70
  export declare function upsertAxHostCapabilityToDB(db: Database, cap: PmxAxHostCapability): void;
58
71
  export declare function loadAxHostCapabilityFromDB(db: Database): PmxAxHostCapability | null;
@@ -3,6 +3,7 @@ import { type GraphNodeInput, type JsonRenderNodeInput, type JsonRenderSpec } fr
3
3
  export type CanvasArrangeMode = 'grid' | 'column' | 'flow';
4
4
  export type CanvasPinMode = 'set' | 'add' | 'remove';
5
5
  export declare function setCanvasLayoutUpdateEmitter(emitter: (() => void) | null): void;
6
+ export declare function emitCanvasLayoutUpdate(): void;
6
7
  export interface CanvasFitViewOptions {
7
8
  width?: number;
8
9
  height?: number;
@@ -82,11 +83,6 @@ interface CanvasCreateGroupInput {
82
83
  color?: string;
83
84
  childLayout?: CanvasArrangeMode;
84
85
  }
85
- export interface CanvasBatchOperation {
86
- op: string;
87
- assign?: string;
88
- args?: Record<string, unknown>;
89
- }
90
86
  interface CanvasNodeLookupInput {
91
87
  id?: string;
92
88
  search?: string;
@@ -262,11 +258,4 @@ export declare function createCanvasGraphNode(input: GraphNodeInput): {
262
258
  node: CanvasNodeState;
263
259
  };
264
260
  export declare function fitCanvasView(options?: CanvasFitViewOptions): CanvasFitViewResult;
265
- export declare function executeCanvasBatch(operations: CanvasBatchOperation[]): Promise<{
266
- ok: boolean;
267
- results: Array<Record<string, unknown>>;
268
- refs: Record<string, unknown>;
269
- failedIndex?: number;
270
- error?: string;
271
- }>;
272
261
  export {};
@@ -142,9 +142,8 @@ declare class CanvasStateManager {
142
142
  private _viewport;
143
143
  private _theme;
144
144
  private _contextPinnedNodeIds;
145
- private _axState;
146
- private _axHostCapability;
147
145
  private _workspaceRoot;
146
+ private readonly ax;
148
147
  private _changeListeners;
149
148
  /**
150
149
  * Register a listener for state changes. Used by MCP server to emit resource
@@ -164,8 +163,6 @@ declare class CanvasStateManager {
164
163
  private suppressed;
165
164
  private recordMutation;
166
165
  private currentNodeIdSet;
167
- private normalizeAxForCurrentNodes;
168
- private applyAxState;
169
166
  private applyResolvedGroupBounds;
170
167
  private getGroupSnapshot;
171
168
  private normalizeNode;
@@ -364,10 +361,10 @@ declare class CanvasStateManager {
364
361
  setPolicy(patch: {
365
362
  tools?: Partial<PmxAxPolicy['tools']>;
366
363
  prompt?: Partial<PmxAxPolicy['prompt']>;
367
- }, _options?: {
364
+ }, options?: {
368
365
  source?: PmxAxSource;
369
366
  }): PmxAxPolicy;
370
- setHostCapability(input: unknown, _options?: {
367
+ setHostCapability(input: unknown, options?: {
371
368
  source?: PmxAxSource;
372
369
  }): PmxAxHostCapability;
373
370
  recordAxEvent(input: {
@@ -393,18 +390,6 @@ declare class CanvasStateManager {
393
390
  source?: PmxAxSource;
394
391
  }): PmxAxSteeringMessage;
395
392
  markSteeringDelivered(id: string): boolean;
396
- /**
397
- * Ingest a normalized agent activity (a tool/session event a harness forwards)
398
- * and apply kind-driven board reactions, so the agent's real work flows back into
399
- * the board without it remembering to push each item (report primitive A — makes
400
- * AX bidirectional). Always records a timeline event; then, unless the caller
401
- * overrides/suppresses via `reactions`, applies defaults by kind/outcome:
402
- * • failure | error | outcome==='failure' → work item (blocked) + review
403
- * (finding/error, anchored to a valid nodeId else the `ref` file) + evidence (logs)
404
- * • tool-result + outcome==='success' → evidence (tool-result)
405
- * • everything else (tool-start, session-*, command, note) → event only
406
- * A reaction value of `false` suppresses it; an object overrides its fields/forces it on.
407
- */
408
393
  ingestActivity(input: {
409
394
  kind: PmxAxActivityKind;
410
395
  title: string;
@@ -442,15 +427,15 @@ declare class CanvasStateManager {
442
427
  getAxSteering(q?: AxTimelineQuery & {
443
428
  onlyPending?: boolean;
444
429
  }): PmxAxSteeringMessage[];
445
- /**
446
- * Undelivered steering for a consumer (Phase 4 delivery). Excludes messages
447
- * whose source equals the consumer to prevent delivery loops (e.g. Copilot
448
- * should not be handed back steering it originated).
449
- */
450
430
  getPendingSteering(options?: {
451
431
  consumer?: string;
452
432
  limit?: number;
453
433
  }): PmxAxSteeringMessage[];
434
+ getPendingSteeringForContext(options?: {
435
+ consumer?: string;
436
+ limit?: number;
437
+ }): PmxAxSteeringMessage[];
438
+ getPendingSteeringCount(consumer?: string): number;
454
439
  getAxTimelineSummary(): PmxAxTimelineSummary;
455
440
  getAxTimeline(q?: AxTimelineQuery): {
456
441
  events: PmxAxEvent[];