pmx-canvas 0.2.7 → 0.3.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 (189) hide show
  1. package/CHANGELOG.md +148 -1
  2. package/Readme.md +13 -11
  3. package/dist/canvas/index.js +2 -2
  4. package/dist/json-render/index.css +1 -1
  5. package/dist/types/cli/daemon.d.ts +74 -0
  6. package/dist/types/cli/watch.d.ts +2 -2
  7. package/dist/types/client/canvas/CanvasViewport.d.ts +1 -1
  8. package/dist/types/client/canvas/CommandPalette.d.ts +1 -1
  9. package/dist/types/client/canvas/Minimap.d.ts +1 -1
  10. package/dist/types/client/nodes/FileNode.d.ts +1 -1
  11. package/dist/types/client/nodes/ImageNode.d.ts +1 -1
  12. package/dist/types/client/nodes/InlineFormatBar.d.ts +1 -1
  13. package/dist/types/client/nodes/MarkdownNode.d.ts +1 -1
  14. package/dist/types/client/nodes/PromptNode.d.ts +1 -1
  15. package/dist/types/client/nodes/ResponseNode.d.ts +1 -1
  16. package/dist/types/mcp/canvas-access.d.ts +0 -7
  17. package/dist/types/server/ax-state-manager.d.ts +3 -2
  18. package/dist/types/server/bundled-skills.d.ts +3 -3
  19. package/dist/types/server/canvas-schema.d.ts +1 -1
  20. package/dist/types/server/canvas-state.d.ts +2 -0
  21. package/dist/types/server/ext-app-lookup.d.ts +1 -3
  22. package/dist/types/server/html-primitives.d.ts +1 -1
  23. package/dist/types/server/index.d.ts +4 -4
  24. package/dist/types/server/operations/composites.d.ts +29 -23
  25. package/dist/types/server/operations/http.d.ts +2 -1
  26. package/dist/types/server/operations/index.d.ts +1 -1
  27. package/dist/types/server/operations/ops/ax-read.d.ts +2 -0
  28. package/dist/types/server/operations/ops/canvas-wire.d.ts +2 -0
  29. package/dist/types/server/operations/ops/ext-app.d.ts +2 -0
  30. package/dist/types/shared/ax-intent.d.ts +1 -1
  31. package/docs/RELEASE.md +23 -8
  32. package/docs/ax-host-adapter-contract.md +7 -7
  33. package/docs/ax-state-contract.md +7 -6
  34. package/docs/bun-webview-integration.md +5 -5
  35. package/docs/cli.md +1 -1
  36. package/docs/http-api.md +35 -3
  37. package/docs/mcp.md +121 -100
  38. package/docs/node-types.md +45 -35
  39. package/docs/plans/plan-006-mcp-tool-consolidation.md +3 -1
  40. package/docs/plans/plan-008-registry-finish.md +2 -0
  41. package/docs/plans/plan-009-tech-debt-backlog.md +51 -0
  42. package/docs/screenshot.png +0 -0
  43. package/docs/tech-debt-assessment-2026-06.md +1 -1
  44. package/docs/tech-debt-assessment-2026-07.md +135 -0
  45. package/package.json +5 -2
  46. package/skills/data-analysis/SKILL.md +3 -3
  47. package/skills/frontend-design/SKILL.md +3 -2
  48. package/skills/json-render-mcp/SKILL.md +4 -3
  49. package/skills/playwright-cli/SKILL.md +1 -1
  50. package/skills/pmx-canvas/SKILL.md +12 -7
  51. package/skills/pmx-canvas/evals/evals.json +2 -2
  52. package/skills/pmx-canvas/references/ax-html-control-surface.md +3 -1
  53. package/skills/pmx-canvas/references/excalidraw-diagram-authoring.md +2 -2
  54. package/skills/pmx-canvas/references/full-reference.md +58 -56
  55. package/skills/pmx-canvas/references/html-primitives.md +3 -3
  56. package/skills/tufte-viz/SKILL.md +5 -4
  57. package/skills/web-artifacts-builder/SKILL.md +4 -4
  58. package/src/cli/agent.ts +1861 -1548
  59. package/src/cli/daemon.ts +460 -0
  60. package/src/cli/index.ts +63 -326
  61. package/src/cli/watch.ts +2 -10
  62. package/src/client/App.tsx +48 -46
  63. package/src/client/canvas/AttentionHistory.tsx +11 -1
  64. package/src/client/canvas/CanvasNode.tsx +41 -29
  65. package/src/client/canvas/CanvasViewport.tsx +101 -66
  66. package/src/client/canvas/CommandPalette.tsx +61 -27
  67. package/src/client/canvas/ContextMenu.tsx +13 -20
  68. package/src/client/canvas/ContextPinBar.tsx +1 -5
  69. package/src/client/canvas/ContextPinHud.tsx +1 -6
  70. package/src/client/canvas/DockedNode.tsx +4 -4
  71. package/src/client/canvas/EdgeLayer.tsx +37 -36
  72. package/src/client/canvas/ExpandedNodeOverlay.tsx +69 -45
  73. package/src/client/canvas/FocusFieldLayer.tsx +20 -22
  74. package/src/client/canvas/IntentLayer.tsx +31 -14
  75. package/src/client/canvas/Minimap.tsx +11 -16
  76. package/src/client/canvas/SelectionBar.tsx +4 -11
  77. package/src/client/canvas/ShortcutOverlay.tsx +3 -1
  78. package/src/client/canvas/SnapshotPanel.tsx +77 -95
  79. package/src/client/canvas/auto-fit.ts +15 -14
  80. package/src/client/canvas/snap-guides.ts +12 -12
  81. package/src/client/canvas/use-node-resize.ts +1 -5
  82. package/src/client/canvas/use-pan-zoom.ts +25 -26
  83. package/src/client/ext-app/bridge.ts +3 -12
  84. package/src/client/icons.tsx +63 -20
  85. package/src/client/nodes/ContextNode.tsx +14 -25
  86. package/src/client/nodes/ExtAppFrame.tsx +60 -39
  87. package/src/client/nodes/FileNode.tsx +74 -62
  88. package/src/client/nodes/GroupNode.tsx +4 -6
  89. package/src/client/nodes/HtmlNode.tsx +76 -46
  90. package/src/client/nodes/ImageNode.tsx +18 -27
  91. package/src/client/nodes/InlineFormatBar.tsx +4 -21
  92. package/src/client/nodes/InlineMarkdownEditor.tsx +0 -1
  93. package/src/client/nodes/LedgerNode.tsx +10 -4
  94. package/src/client/nodes/MarkdownNode.tsx +3 -10
  95. package/src/client/nodes/McpAppNode.tsx +26 -22
  96. package/src/client/nodes/MdFormatBar.tsx +10 -7
  97. package/src/client/nodes/PromptNode.tsx +23 -51
  98. package/src/client/nodes/ResponseNode.tsx +3 -13
  99. package/src/client/nodes/StatusNode.tsx +5 -9
  100. package/src/client/nodes/StatusSummary.tsx +2 -8
  101. package/src/client/nodes/WebpageNode.tsx +20 -14
  102. package/src/client/nodes/iframe-document-url.ts +25 -16
  103. package/src/client/nodes/image-warnings.ts +1 -7
  104. package/src/client/nodes/md-format.ts +20 -5
  105. package/src/client/state/attention-bridge.ts +4 -9
  106. package/src/client/state/attention-store.ts +1 -7
  107. package/src/client/state/canvas-store.ts +52 -36
  108. package/src/client/state/intent-bridge.ts +176 -112
  109. package/src/client/state/intent-store.ts +4 -1
  110. package/src/client/state/sse-bridge.ts +53 -70
  111. package/src/json-render/catalog.ts +12 -16
  112. package/src/json-render/charts/components.tsx +16 -20
  113. package/src/json-render/charts/extra-components.tsx +8 -16
  114. package/src/json-render/charts/extra-definitions.ts +1 -2
  115. package/src/json-render/charts/tufte-components.tsx +37 -20
  116. package/src/json-render/charts/tufte-definitions.ts +8 -2
  117. package/src/json-render/renderer/index.tsx +42 -22
  118. package/src/json-render/schema.ts +6 -3
  119. package/src/json-render/server.ts +33 -39
  120. package/src/mcp/canvas-access.ts +40 -121
  121. package/src/mcp/server.ts +206 -271
  122. package/src/server/agent-context.ts +63 -36
  123. package/src/server/ax-context.ts +7 -5
  124. package/src/server/ax-interaction.ts +176 -43
  125. package/src/server/ax-state-manager.ts +185 -41
  126. package/src/server/ax-state.ts +142 -47
  127. package/src/server/bundled-skills.ts +3 -3
  128. package/src/server/canvas-db.ts +213 -95
  129. package/src/server/canvas-operations.ts +177 -120
  130. package/src/server/canvas-provenance.ts +1 -4
  131. package/src/server/canvas-schema.ts +500 -102
  132. package/src/server/canvas-serialization.ts +27 -35
  133. package/src/server/canvas-state.ts +155 -58
  134. package/src/server/chart-template.ts +4 -5
  135. package/src/server/code-graph.ts +20 -7
  136. package/src/server/diagram-presets.ts +28 -29
  137. package/src/server/ext-app-lookup.ts +4 -20
  138. package/src/server/html-node-summary.ts +19 -10
  139. package/src/server/html-primitives.ts +326 -97
  140. package/src/server/html-surface.ts +6 -9
  141. package/src/server/image-source.ts +6 -4
  142. package/src/server/index.ts +321 -218
  143. package/src/server/intent-registry.ts +3 -6
  144. package/src/server/mcp-app-candidate.ts +5 -10
  145. package/src/server/mcp-app-host.ts +14 -38
  146. package/src/server/mcp-app-runtime.ts +12 -20
  147. package/src/server/mutation-history.ts +15 -5
  148. package/src/server/operations/composites.ts +38 -40
  149. package/src/server/operations/http.ts +5 -5
  150. package/src/server/operations/index.ts +7 -1
  151. package/src/server/operations/invoker.ts +4 -3
  152. package/src/server/operations/mcp.ts +29 -36
  153. package/src/server/operations/ops/annotation.ts +122 -10
  154. package/src/server/operations/ops/app.ts +102 -77
  155. package/src/server/operations/ops/ax-await.ts +17 -10
  156. package/src/server/operations/ops/ax-read.ts +347 -0
  157. package/src/server/operations/ops/ax-shared.ts +2 -7
  158. package/src/server/operations/ops/ax-state.ts +32 -14
  159. package/src/server/operations/ops/ax-timeline.ts +32 -19
  160. package/src/server/operations/ops/ax-work.ts +54 -37
  161. package/src/server/operations/ops/batch.ts +39 -14
  162. package/src/server/operations/ops/canvas-wire.ts +91 -0
  163. package/src/server/operations/ops/edges.ts +37 -25
  164. package/src/server/operations/ops/ext-app.ts +346 -0
  165. package/src/server/operations/ops/groups.ts +49 -20
  166. package/src/server/operations/ops/intent.ts +18 -12
  167. package/src/server/operations/ops/json-render.ts +239 -98
  168. package/src/server/operations/ops/nodes.ts +300 -111
  169. package/src/server/operations/ops/query.ts +62 -33
  170. package/src/server/operations/ops/snapshots.ts +35 -26
  171. package/src/server/operations/ops/validate.ts +2 -1
  172. package/src/server/operations/ops/viewport.ts +60 -16
  173. package/src/server/operations/ops/webview.ts +44 -18
  174. package/src/server/operations/registry.ts +2 -3
  175. package/src/server/operations/types.ts +7 -5
  176. package/src/server/operations/webview-runner.ts +1 -3
  177. package/src/server/placement.ts +8 -18
  178. package/src/server/server.ts +121 -1012
  179. package/src/server/spatial-analysis.ts +39 -25
  180. package/src/server/trace-manager.ts +3 -8
  181. package/src/server/web-artifacts.ts +23 -27
  182. package/src/server/webpage-node.ts +5 -13
  183. package/src/shared/auto-arrange.ts +12 -5
  184. package/src/shared/ax-intent.ts +1 -1
  185. package/src/shared/content-height-reporter.ts +8 -6
  186. package/src/shared/ext-app-tool-result.ts +2 -6
  187. package/src/shared/placement.ts +1 -4
  188. package/src/shared/semantic-attention.ts +39 -37
  189. package/src/shared/surface.ts +8 -4
@@ -7,8 +7,9 @@
7
7
  *
8
8
  * • Canvas-bound (`_axState`): focus, work items, approval gates, review
9
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).
10
+ * `canvas_view` (`clear` action), replaced by `restore`. Mutators record
11
+ * undo/redo history (via the injected `recordMutation` / `suppressed`
12
+ * callbacks).
12
13
  * • Timeline (audit-only): agent events, evidence, steering. DB-direct, NOT in
13
14
  * `_axState`, NOT history-recorded, NOT snapshotted, retention-bounded.
14
15
  * • Host/session: a single host-capability row in its own table.
@@ -250,8 +251,16 @@ export class AxStateManager {
250
251
  this.deps.recordMutation({
251
252
  operationType: 'addWorkItem',
252
253
  description: `Added work item "${item.title}"`,
253
- forward: this.deps.suppressed(() => { this.applyAxState(applied); this.deps.scheduleSave(); this.deps.notifyChange('ax'); }),
254
- inverse: this.deps.suppressed(() => { this.applyAxState(oldAxState); this.deps.scheduleSave(); this.deps.notifyChange('ax'); }),
254
+ forward: this.deps.suppressed(() => {
255
+ this.applyAxState(applied);
256
+ this.deps.scheduleSave();
257
+ this.deps.notifyChange('ax');
258
+ }),
259
+ inverse: this.deps.suppressed(() => {
260
+ this.applyAxState(oldAxState);
261
+ this.deps.scheduleSave();
262
+ this.deps.notifyChange('ax');
263
+ }),
255
264
  });
256
265
  return applied.workItems.find((w) => w.id === item.id) ?? item;
257
266
  }
@@ -281,8 +290,16 @@ export class AxStateManager {
281
290
  this.deps.recordMutation({
282
291
  operationType: 'updateWorkItem',
283
292
  description: `Updated work item ${id}`,
284
- forward: this.deps.suppressed(() => { this.applyAxState(applied); this.deps.scheduleSave(); this.deps.notifyChange('ax'); }),
285
- inverse: this.deps.suppressed(() => { this.applyAxState(oldAxState); this.deps.scheduleSave(); this.deps.notifyChange('ax'); }),
293
+ forward: this.deps.suppressed(() => {
294
+ this.applyAxState(applied);
295
+ this.deps.scheduleSave();
296
+ this.deps.notifyChange('ax');
297
+ }),
298
+ inverse: this.deps.suppressed(() => {
299
+ this.applyAxState(oldAxState);
300
+ this.deps.scheduleSave();
301
+ this.deps.notifyChange('ax');
302
+ }),
286
303
  });
287
304
  return applied.workItems.find((w) => w.id === id) ?? null;
288
305
  }
@@ -305,8 +322,16 @@ export class AxStateManager {
305
322
  this.deps.recordMutation({
306
323
  operationType: 'requestApproval',
307
324
  description: `Requested approval "${gate.title}"`,
308
- forward: this.deps.suppressed(() => { this.applyAxState(applied); this.deps.scheduleSave(); this.deps.notifyChange('ax'); }),
309
- inverse: this.deps.suppressed(() => { this.applyAxState(oldAxState); this.deps.scheduleSave(); this.deps.notifyChange('ax'); }),
325
+ forward: this.deps.suppressed(() => {
326
+ this.applyAxState(applied);
327
+ this.deps.scheduleSave();
328
+ this.deps.notifyChange('ax');
329
+ }),
330
+ inverse: this.deps.suppressed(() => {
331
+ this.applyAxState(oldAxState);
332
+ this.deps.scheduleSave();
333
+ this.deps.notifyChange('ax');
334
+ }),
310
335
  });
311
336
  return applied.approvalGates.find((g) => g.id === gate.id) ?? gate;
312
337
  }
@@ -333,8 +358,16 @@ export class AxStateManager {
333
358
  this.deps.recordMutation({
334
359
  operationType: 'resolveApproval',
335
360
  description: `Resolved approval ${id} -> ${decision}`,
336
- forward: this.deps.suppressed(() => { this.applyAxState(applied); this.deps.scheduleSave(); this.deps.notifyChange('ax'); }),
337
- inverse: this.deps.suppressed(() => { this.applyAxState(oldAxState); this.deps.scheduleSave(); this.deps.notifyChange('ax'); }),
361
+ forward: this.deps.suppressed(() => {
362
+ this.applyAxState(applied);
363
+ this.deps.scheduleSave();
364
+ this.deps.notifyChange('ax');
365
+ }),
366
+ inverse: this.deps.suppressed(() => {
367
+ this.applyAxState(oldAxState);
368
+ this.deps.scheduleSave();
369
+ this.deps.notifyChange('ax');
370
+ }),
338
371
  });
339
372
  return applied.approvalGates.find((g) => g.id === id) ?? null;
340
373
  }
@@ -380,8 +413,16 @@ export class AxStateManager {
380
413
  this.deps.recordMutation({
381
414
  operationType: 'addReviewAnnotation',
382
415
  description: `Added review ${annotation.kind} (${annotation.severity})`,
383
- forward: this.deps.suppressed(() => { this.applyAxState(applied); this.deps.scheduleSave(); this.deps.notifyChange('ax'); }),
384
- inverse: this.deps.suppressed(() => { this.applyAxState(oldAxState); this.deps.scheduleSave(); this.deps.notifyChange('ax'); }),
416
+ forward: this.deps.suppressed(() => {
417
+ this.applyAxState(applied);
418
+ this.deps.scheduleSave();
419
+ this.deps.notifyChange('ax');
420
+ }),
421
+ inverse: this.deps.suppressed(() => {
422
+ this.applyAxState(oldAxState);
423
+ this.deps.scheduleSave();
424
+ this.deps.notifyChange('ax');
425
+ }),
385
426
  });
386
427
  return applied.reviewAnnotations.find((r) => r.id === annotation.id) ?? annotation;
387
428
  }
@@ -410,8 +451,16 @@ export class AxStateManager {
410
451
  this.deps.recordMutation({
411
452
  operationType: 'updateReviewAnnotation',
412
453
  description: `Updated review ${id}`,
413
- forward: this.deps.suppressed(() => { this.applyAxState(applied); this.deps.scheduleSave(); this.deps.notifyChange('ax'); }),
414
- inverse: this.deps.suppressed(() => { this.applyAxState(oldAxState); this.deps.scheduleSave(); this.deps.notifyChange('ax'); }),
454
+ forward: this.deps.suppressed(() => {
455
+ this.applyAxState(applied);
456
+ this.deps.scheduleSave();
457
+ this.deps.notifyChange('ax');
458
+ }),
459
+ inverse: this.deps.suppressed(() => {
460
+ this.applyAxState(oldAxState);
461
+ this.deps.scheduleSave();
462
+ this.deps.notifyChange('ax');
463
+ }),
415
464
  });
416
465
  return applied.reviewAnnotations.find((r) => r.id === id) ?? null;
417
466
  }
@@ -439,8 +488,16 @@ export class AxStateManager {
439
488
  this.deps.recordMutation({
440
489
  operationType: 'requestElicitation',
441
490
  description: `Requested elicitation "${elicitation.prompt}"`,
442
- forward: this.deps.suppressed(() => { this.applyAxState(applied); this.deps.scheduleSave(); this.deps.notifyChange('ax'); }),
443
- inverse: this.deps.suppressed(() => { this.applyAxState(oldAxState); this.deps.scheduleSave(); this.deps.notifyChange('ax'); }),
491
+ forward: this.deps.suppressed(() => {
492
+ this.applyAxState(applied);
493
+ this.deps.scheduleSave();
494
+ this.deps.notifyChange('ax');
495
+ }),
496
+ inverse: this.deps.suppressed(() => {
497
+ this.applyAxState(oldAxState);
498
+ this.deps.scheduleSave();
499
+ this.deps.notifyChange('ax');
500
+ }),
444
501
  });
445
502
  return applied.elicitations.find((e) => e.id === elicitation.id) ?? elicitation;
446
503
  }
@@ -467,8 +524,16 @@ export class AxStateManager {
467
524
  this.deps.recordMutation({
468
525
  operationType: 'respondElicitation',
469
526
  description: `Answered elicitation ${id}`,
470
- forward: this.deps.suppressed(() => { this.applyAxState(applied); this.deps.scheduleSave(); this.deps.notifyChange('ax'); }),
471
- inverse: this.deps.suppressed(() => { this.applyAxState(oldAxState); this.deps.scheduleSave(); this.deps.notifyChange('ax'); }),
527
+ forward: this.deps.suppressed(() => {
528
+ this.applyAxState(applied);
529
+ this.deps.scheduleSave();
530
+ this.deps.notifyChange('ax');
531
+ }),
532
+ inverse: this.deps.suppressed(() => {
533
+ this.applyAxState(oldAxState);
534
+ this.deps.scheduleSave();
535
+ this.deps.notifyChange('ax');
536
+ }),
472
537
  });
473
538
  return applied.elicitations.find((e) => e.id === id) ?? null;
474
539
  }
@@ -491,8 +556,16 @@ export class AxStateManager {
491
556
  this.deps.recordMutation({
492
557
  operationType: 'requestMode',
493
558
  description: `Requested mode "${request.mode}"`,
494
- forward: this.deps.suppressed(() => { this.applyAxState(applied); this.deps.scheduleSave(); this.deps.notifyChange('ax'); }),
495
- inverse: this.deps.suppressed(() => { this.applyAxState(oldAxState); this.deps.scheduleSave(); this.deps.notifyChange('ax'); }),
559
+ forward: this.deps.suppressed(() => {
560
+ this.applyAxState(applied);
561
+ this.deps.scheduleSave();
562
+ this.deps.notifyChange('ax');
563
+ }),
564
+ inverse: this.deps.suppressed(() => {
565
+ this.applyAxState(oldAxState);
566
+ this.deps.scheduleSave();
567
+ this.deps.notifyChange('ax');
568
+ }),
496
569
  });
497
570
  return applied.modeRequests.find((m) => m.id === request.id) ?? request;
498
571
  }
@@ -519,8 +592,16 @@ export class AxStateManager {
519
592
  this.deps.recordMutation({
520
593
  operationType: 'resolveModeRequest',
521
594
  description: `Resolved mode request ${id} -> ${decision}`,
522
- forward: this.deps.suppressed(() => { this.applyAxState(applied); this.deps.scheduleSave(); this.deps.notifyChange('ax'); }),
523
- inverse: this.deps.suppressed(() => { this.applyAxState(oldAxState); this.deps.scheduleSave(); this.deps.notifyChange('ax'); }),
595
+ forward: this.deps.suppressed(() => {
596
+ this.applyAxState(applied);
597
+ this.deps.scheduleSave();
598
+ this.deps.notifyChange('ax');
599
+ }),
600
+ inverse: this.deps.suppressed(() => {
601
+ this.applyAxState(oldAxState);
602
+ this.deps.scheduleSave();
603
+ this.deps.notifyChange('ax');
604
+ }),
524
605
  });
525
606
  return applied.modeRequests.find((m) => m.id === id) ?? null;
526
607
  }
@@ -543,10 +624,19 @@ export class AxStateManager {
543
624
  }
544
625
 
545
626
  /** Invoke a registry-gated PMX command intent — records a timeline event (no execution). */
546
- invokeCommand(name: string, args: Record<string, unknown> | null = null, options: { source?: PmxAxSource } = {}): PmxAxEvent | null {
627
+ invokeCommand(
628
+ name: string,
629
+ args: Record<string, unknown> | null = null,
630
+ options: { source?: PmxAxSource } = {},
631
+ ): PmxAxEvent | null {
547
632
  if (!isAxCommand(name)) return null;
548
633
  return this.recordAxEvent(
549
- { kind: 'command', summary: name, detail: AX_COMMAND_REGISTRY[name].description, data: { command: name, ...(args ? { args } : {}) } },
634
+ {
635
+ kind: 'command',
636
+ summary: name,
637
+ detail: AX_COMMAND_REGISTRY[name].description,
638
+ data: { command: name, ...(args ? { args } : {}) },
639
+ },
550
640
  options,
551
641
  );
552
642
  }
@@ -572,18 +662,25 @@ export class AxStateManager {
572
662
  this.deps.recordMutation({
573
663
  operationType: 'setPolicy',
574
664
  description: 'Updated AX policy',
575
- forward: this.deps.suppressed(() => { this.applyAxState(applied); this.deps.scheduleSave(); this.deps.notifyChange('ax'); }),
576
- inverse: this.deps.suppressed(() => { this.applyAxState(oldAxState); this.deps.scheduleSave(); this.deps.notifyChange('ax'); }),
665
+ forward: this.deps.suppressed(() => {
666
+ this.applyAxState(applied);
667
+ this.deps.scheduleSave();
668
+ this.deps.notifyChange('ax');
669
+ }),
670
+ inverse: this.deps.suppressed(() => {
671
+ this.applyAxState(oldAxState);
672
+ this.deps.scheduleSave();
673
+ this.deps.notifyChange('ax');
674
+ }),
577
675
  });
578
676
  return applied.policy;
579
677
  }
580
678
 
581
679
  setHostCapability(input: unknown, _options: { source?: PmxAxSource } = {}): PmxAxHostCapability {
582
- const cap = normalizeAxHostCapability(
583
- isRecord(input)
584
- ? { ...input, reportedAt: new Date().toISOString() }
585
- : { reportedAt: new Date().toISOString() },
586
- ) ?? createEmptyAxHostCapability();
680
+ const cap =
681
+ normalizeAxHostCapability(
682
+ isRecord(input) ? { ...input, reportedAt: new Date().toISOString() } : { reportedAt: new Date().toISOString() },
683
+ ) ?? createEmptyAxHostCapability();
587
684
  this._axHostCapability = cap;
588
685
  const db = this.deps.getDb();
589
686
  if (db) {
@@ -599,7 +696,13 @@ export class AxStateManager {
599
696
 
600
697
  // ── Timeline (DB-direct; NOT in _axState; NOT history-recorded) ───
601
698
  recordAxEvent(
602
- input: { kind: PmxAxEventKind; summary: string; detail?: string | null; nodeIds?: string[]; data?: Record<string, unknown> | null },
699
+ input: {
700
+ kind: PmxAxEventKind;
701
+ summary: string;
702
+ detail?: string | null;
703
+ nodeIds?: string[];
704
+ data?: Record<string, unknown> | null;
705
+ },
603
706
  options: { source?: PmxAxSource } = {},
604
707
  ): PmxAxEvent {
605
708
  const draft = createAxEvent(input, options.source ?? 'api');
@@ -618,7 +721,14 @@ export class AxStateManager {
618
721
  }
619
722
 
620
723
  addEvidence(
621
- input: { kind: PmxAxEvidenceKind; title: string; body?: string | null; ref?: string | null; nodeIds?: string[]; data?: Record<string, unknown> | null },
724
+ input: {
725
+ kind: PmxAxEvidenceKind;
726
+ title: string;
727
+ body?: string | null;
728
+ ref?: string | null;
729
+ nodeIds?: string[];
730
+ data?: Record<string, unknown> | null;
731
+ },
622
732
  options: { source?: PmxAxSource } = {},
623
733
  ): PmxAxEvidence {
624
734
  const draft = createAxEvidence(input, options.source ?? 'api');
@@ -689,11 +799,23 @@ export class AxStateManager {
689
799
  reactions?: {
690
800
  workItem?: false | { status?: PmxAxWorkItemStatus; detail?: string | null };
691
801
  evidence?: false | { kind?: PmxAxEvidenceKind; body?: string | null };
692
- review?: false | { severity?: PmxAxReviewSeverity; kind?: PmxAxReviewKind; anchorType?: PmxAxReviewAnchorType; nodeId?: string | null };
802
+ review?:
803
+ | false
804
+ | {
805
+ severity?: PmxAxReviewSeverity;
806
+ kind?: PmxAxReviewKind;
807
+ anchorType?: PmxAxReviewAnchorType;
808
+ nodeId?: string | null;
809
+ };
693
810
  };
694
811
  },
695
812
  options: { source?: PmxAxSource } = {},
696
- ): { event: PmxAxEvent; workItem: PmxAxWorkItem | null; evidence: PmxAxEvidence | null; review: PmxAxReviewAnnotation | null } {
813
+ ): {
814
+ event: PmxAxEvent;
815
+ workItem: PmxAxWorkItem | null;
816
+ evidence: PmxAxEvidence | null;
817
+ review: PmxAxReviewAnnotation | null;
818
+ } {
697
819
  const source = options.source ?? 'api';
698
820
  const summary = input.summary ?? input.title;
699
821
  const isFailure = input.kind === 'failure' || input.kind === 'error' || input.outcome === 'failure';
@@ -725,15 +847,26 @@ export class AxStateManager {
725
847
  // (2) Resolve reactions: kind-driven defaults, overridable per call.
726
848
  const r = input.reactions ?? {};
727
849
  const wantWorkItem = r.workItem === false ? null : (r.workItem ?? (isFailure ? {} : null));
728
- const wantEvidence = r.evidence === false
729
- ? null
730
- : (r.evidence ?? (isFailure ? { kind: 'logs' as PmxAxEvidenceKind } : isToolSuccess ? { kind: 'tool-result' as PmxAxEvidenceKind } : null));
850
+ const wantEvidence =
851
+ r.evidence === false
852
+ ? null
853
+ : (r.evidence ??
854
+ (isFailure
855
+ ? { kind: 'logs' as PmxAxEvidenceKind }
856
+ : isToolSuccess
857
+ ? { kind: 'tool-result' as PmxAxEvidenceKind }
858
+ : null));
731
859
  const wantReview = r.review === false ? null : (r.review ?? (isFailure ? {} : null));
732
860
 
733
861
  let workItem: PmxAxWorkItem | null = null;
734
862
  if (wantWorkItem) {
735
863
  workItem = this.addWorkItem(
736
- { title: input.title, status: wantWorkItem.status ?? 'blocked', detail: wantWorkItem.detail ?? summary, nodeIds },
864
+ {
865
+ title: input.title,
866
+ status: wantWorkItem.status ?? 'blocked',
867
+ detail: wantWorkItem.detail ?? summary,
868
+ nodeIds,
869
+ },
737
870
  { source },
738
871
  );
739
872
  }
@@ -741,7 +874,13 @@ export class AxStateManager {
741
874
  let evidence: PmxAxEvidence | null = null;
742
875
  if (wantEvidence) {
743
876
  evidence = this.addEvidence(
744
- { kind: wantEvidence.kind ?? 'logs', title: input.title, body: wantEvidence.body ?? input.summary ?? null, ref: input.ref ?? null, nodeIds },
877
+ {
878
+ kind: wantEvidence.kind ?? 'logs',
879
+ title: input.title,
880
+ body: wantEvidence.body ?? input.summary ?? null,
881
+ ref: input.ref ?? null,
882
+ nodeIds,
883
+ },
745
884
  { source },
746
885
  );
747
886
  }
@@ -815,7 +954,12 @@ export class AxStateManager {
815
954
  : { recentEvents: [], recentEvidence: [], pendingSteering: [], counts: { events: 0, evidence: 0, steering: 0 } };
816
955
  }
817
956
 
818
- getAxTimeline(q: AxTimelineQuery = {}): { events: PmxAxEvent[]; evidence: PmxAxEvidence[]; steering: PmxAxSteeringMessage[]; summary: PmxAxTimelineSummary } {
957
+ getAxTimeline(q: AxTimelineQuery = {}): {
958
+ events: PmxAxEvent[];
959
+ evidence: PmxAxEvidence[];
960
+ steering: PmxAxSteeringMessage[];
961
+ summary: PmxAxTimelineSummary;
962
+ } {
819
963
  return {
820
964
  events: this.getAxEvents(q),
821
965
  evidence: this.getAxEvidence(q),