@sapiom/harness 0.1.6 → 0.2.0

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 (185) hide show
  1. package/CHANGELOG.md +90 -0
  2. package/dist/cli/args.d.ts +16 -0
  3. package/dist/cli/args.d.ts.map +1 -0
  4. package/dist/cli/args.js +80 -0
  5. package/dist/cli/args.js.map +1 -0
  6. package/dist/cli/bin.js +12 -65
  7. package/dist/cli/bin.js.map +1 -1
  8. package/dist/cli/settings.d.ts.map +1 -1
  9. package/dist/cli/settings.js +33 -1
  10. package/dist/cli/settings.js.map +1 -1
  11. package/dist/core/adapters/claude-code.d.ts +60 -2
  12. package/dist/core/adapters/claude-code.d.ts.map +1 -1
  13. package/dist/core/adapters/claude-code.js +119 -32
  14. package/dist/core/adapters/claude-code.js.map +1 -1
  15. package/dist/core/adapters/codex.d.ts +21 -2
  16. package/dist/core/adapters/codex.d.ts.map +1 -1
  17. package/dist/core/adapters/codex.js +53 -2
  18. package/dist/core/adapters/codex.js.map +1 -1
  19. package/dist/core/adapters/detect.d.ts +9 -0
  20. package/dist/core/adapters/detect.d.ts.map +1 -1
  21. package/dist/core/adapters/detect.js +9 -0
  22. package/dist/core/adapters/detect.js.map +1 -1
  23. package/dist/core/canvas-body.d.ts +28 -28
  24. package/dist/core/canvas-body.d.ts.map +1 -1
  25. package/dist/core/canvas-body.js +117 -55
  26. package/dist/core/canvas-body.js.map +1 -1
  27. package/dist/core/canvas-derive.d.ts +43 -0
  28. package/dist/core/canvas-derive.d.ts.map +1 -0
  29. package/dist/core/canvas-derive.js +95 -0
  30. package/dist/core/canvas-derive.js.map +1 -0
  31. package/dist/core/canvas-enrichment.d.ts +52 -127
  32. package/dist/core/canvas-enrichment.d.ts.map +1 -1
  33. package/dist/core/canvas-enrichment.js +17 -178
  34. package/dist/core/canvas-enrichment.js.map +1 -1
  35. package/dist/core/canvas-graph.d.ts +40 -1
  36. package/dist/core/canvas-graph.d.ts.map +1 -1
  37. package/dist/core/canvas-graph.js +71 -9
  38. package/dist/core/canvas-graph.js.map +1 -1
  39. package/dist/core/canvas-interconnections.d.ts +26 -8
  40. package/dist/core/canvas-interconnections.d.ts.map +1 -1
  41. package/dist/core/canvas-interconnections.js +132 -24
  42. package/dist/core/canvas-interconnections.js.map +1 -1
  43. package/dist/core/canvas-manifest-check.d.ts.map +1 -1
  44. package/dist/core/canvas-manifest-check.js +15 -2
  45. package/dist/core/canvas-manifest-check.js.map +1 -1
  46. package/dist/core/canvas-render.d.ts +8 -15
  47. package/dist/core/canvas-render.d.ts.map +1 -1
  48. package/dist/core/canvas-render.js +29 -41
  49. package/dist/core/canvas-render.js.map +1 -1
  50. package/dist/core/canvas-run-state.d.ts +41 -0
  51. package/dist/core/canvas-run-state.d.ts.map +1 -1
  52. package/dist/core/canvas-run-state.js +136 -0
  53. package/dist/core/canvas-run-state.js.map +1 -1
  54. package/dist/core/canvas-svg.d.ts +9 -4
  55. package/dist/core/canvas-svg.d.ts.map +1 -1
  56. package/dist/core/canvas-svg.js +84 -13
  57. package/dist/core/canvas-svg.js.map +1 -1
  58. package/dist/core/canvas-template.d.ts +9 -10
  59. package/dist/core/canvas-template.d.ts.map +1 -1
  60. package/dist/core/canvas-template.js +57 -20
  61. package/dist/core/canvas-template.js.map +1 -1
  62. package/dist/core/canvas-watcher.d.ts +22 -1
  63. package/dist/core/canvas-watcher.d.ts.map +1 -1
  64. package/dist/core/canvas-watcher.js +111 -30
  65. package/dist/core/canvas-watcher.js.map +1 -1
  66. package/dist/core/collector/normalizer.d.ts +8 -0
  67. package/dist/core/collector/normalizer.d.ts.map +1 -1
  68. package/dist/core/collector/normalizer.js +8 -0
  69. package/dist/core/collector/normalizer.js.map +1 -1
  70. package/dist/core/collector/store.d.ts +75 -1
  71. package/dist/core/collector/store.d.ts.map +1 -1
  72. package/dist/core/collector/store.js +334 -2
  73. package/dist/core/collector/store.js.map +1 -1
  74. package/dist/core/errors.d.ts +10 -4
  75. package/dist/core/errors.d.ts.map +1 -1
  76. package/dist/core/errors.js +11 -5
  77. package/dist/core/errors.js.map +1 -1
  78. package/dist/core/example-seed.d.ts +8 -0
  79. package/dist/core/example-seed.d.ts.map +1 -1
  80. package/dist/core/example-seed.js +47 -10
  81. package/dist/core/example-seed.js.map +1 -1
  82. package/dist/core/inject/system-prompt.d.ts +8 -0
  83. package/dist/core/inject/system-prompt.d.ts.map +1 -1
  84. package/dist/core/inject/system-prompt.js +3 -1
  85. package/dist/core/inject/system-prompt.js.map +1 -1
  86. package/dist/core/macros.d.ts.map +1 -1
  87. package/dist/core/macros.js +5 -6
  88. package/dist/core/macros.js.map +1 -1
  89. package/dist/core/paths.d.ts +1 -0
  90. package/dist/core/paths.d.ts.map +1 -1
  91. package/dist/core/paths.js +1 -0
  92. package/dist/core/paths.js.map +1 -1
  93. package/dist/core/record-archive.d.ts +187 -0
  94. package/dist/core/record-archive.d.ts.map +1 -0
  95. package/dist/core/record-archive.js +465 -0
  96. package/dist/core/record-archive.js.map +1 -0
  97. package/dist/core/rehydration.d.ts +72 -0
  98. package/dist/core/rehydration.d.ts.map +1 -0
  99. package/dist/core/rehydration.js +72 -0
  100. package/dist/core/rehydration.js.map +1 -0
  101. package/dist/core/resume-brief.d.ts +130 -0
  102. package/dist/core/resume-brief.d.ts.map +1 -0
  103. package/dist/core/resume-brief.js +404 -0
  104. package/dist/core/resume-brief.js.map +1 -0
  105. package/dist/core/rolling-summary.d.ts +130 -0
  106. package/dist/core/rolling-summary.d.ts.map +1 -0
  107. package/dist/core/rolling-summary.js +227 -0
  108. package/dist/core/rolling-summary.js.map +1 -0
  109. package/dist/core/session-manager.d.ts +11 -3
  110. package/dist/core/session-manager.d.ts.map +1 -1
  111. package/dist/core/session-manager.js +56 -7
  112. package/dist/core/session-manager.js.map +1 -1
  113. package/dist/core/session-record.d.ts +165 -0
  114. package/dist/core/session-record.d.ts.map +1 -0
  115. package/dist/core/session-record.js +470 -0
  116. package/dist/core/session-record.js.map +1 -0
  117. package/dist/core/spawn-target.d.ts +12 -0
  118. package/dist/core/spawn-target.d.ts.map +1 -0
  119. package/dist/core/spawn-target.js +187 -0
  120. package/dist/core/spawn-target.js.map +1 -0
  121. package/dist/core/task-manager.d.ts.map +1 -1
  122. package/dist/core/task-manager.js +9 -1
  123. package/dist/core/task-manager.js.map +1 -1
  124. package/dist/core/template-catalog.d.ts +48 -0
  125. package/dist/core/template-catalog.d.ts.map +1 -0
  126. package/dist/core/template-catalog.js +338 -0
  127. package/dist/core/template-catalog.js.map +1 -0
  128. package/dist/core/workflow-registry.d.ts.map +1 -1
  129. package/dist/core/workflow-registry.js +2 -2
  130. package/dist/core/workflow-registry.js.map +1 -1
  131. package/dist/core/workspace-watcher.d.ts.map +1 -1
  132. package/dist/core/workspace-watcher.js +4 -3
  133. package/dist/core/workspace-watcher.js.map +1 -1
  134. package/dist/index.d.ts +12 -0
  135. package/dist/index.d.ts.map +1 -1
  136. package/dist/index.js +21 -0
  137. package/dist/index.js.map +1 -1
  138. package/dist/profiles/default.d.ts.map +1 -1
  139. package/dist/profiles/default.js +9 -14
  140. package/dist/profiles/default.js.map +1 -1
  141. package/dist/server/canvas.d.ts.map +1 -1
  142. package/dist/server/canvas.js +7 -7
  143. package/dist/server/canvas.js.map +1 -1
  144. package/dist/server/fs.d.ts.map +1 -1
  145. package/dist/server/fs.js +17 -1
  146. package/dist/server/fs.js.map +1 -1
  147. package/dist/server/index.d.ts +12 -3
  148. package/dist/server/index.d.ts.map +1 -1
  149. package/dist/server/index.js +321 -50
  150. package/dist/server/index.js.map +1 -1
  151. package/dist/server/ingest.d.ts +11 -0
  152. package/dist/server/ingest.d.ts.map +1 -1
  153. package/dist/server/ingest.js +1 -0
  154. package/dist/server/ingest.js.map +1 -1
  155. package/dist/server/macros.d.ts +4 -6
  156. package/dist/server/macros.d.ts.map +1 -1
  157. package/dist/server/macros.js.map +1 -1
  158. package/dist/server/rest.d.ts +18 -6
  159. package/dist/server/rest.d.ts.map +1 -1
  160. package/dist/server/rest.js +185 -48
  161. package/dist/server/rest.js.map +1 -1
  162. package/dist/server/templates.d.ts +24 -0
  163. package/dist/server/templates.d.ts.map +1 -0
  164. package/dist/server/templates.js +54 -0
  165. package/dist/server/templates.js.map +1 -0
  166. package/dist/shared/types.d.ts +477 -29
  167. package/dist/shared/types.d.ts.map +1 -1
  168. package/dist/shared/types.js +19 -11
  169. package/dist/shared/types.js.map +1 -1
  170. package/dist/web/assets/index-DC65cskq.js +446 -0
  171. package/dist/web/assets/index-xtD-3FFa.css +32 -0
  172. package/dist/web/index.html +2 -2
  173. package/package.json +5 -4
  174. package/dist/core/canvas-enrich.d.ts +0 -115
  175. package/dist/core/canvas-enrich.d.ts.map +0 -1
  176. package/dist/core/canvas-enrich.js +0 -186
  177. package/dist/core/canvas-enrich.js.map +0 -1
  178. package/dist/profiles/canvas-guidelines.d.ts +0 -20
  179. package/dist/profiles/canvas-guidelines.d.ts.map +0 -1
  180. package/dist/profiles/canvas-guidelines.js +0 -48
  181. package/dist/profiles/canvas-guidelines.js.map +0 -1
  182. package/dist/web/assets/index-DCtyI4VW.css +0 -32
  183. package/dist/web/assets/index-WSw5RvYR.js +0 -445
  184. package/dist/web/welcome-hero-dark.png +0 -0
  185. package/dist/web/welcome-hero-light.png +0 -0
@@ -1,36 +1,134 @@
1
- import { renderGraphSvg } from "./canvas-svg.js";
1
+ import { renderGraphSvg, usedKinds } from "./canvas-svg.js";
2
2
  function esc(s) {
3
3
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
4
4
  }
5
- /** One workflow's full panel: title/badges header, step/entry stats, SVG
6
- * diagram with any enrichment merged in (summary line, node/edge
7
- * annotations, a "stale" chip when its fingerprint no longer matches). */
8
- export function buildWorkflowPanelHtml(graph, meta, panelEnrichment) {
5
+ const NODE_KIND_LABEL = {
6
+ entry: "entry / active step",
7
+ step: "step",
8
+ pause: "pause / waits for input",
9
+ "terminal-success": "terminal · success",
10
+ "terminal-warn": "terminal · escalation",
11
+ "launched-workflow": "launches another workflow",
12
+ };
13
+ const NODE_KIND_ORDER = [
14
+ "entry",
15
+ "step",
16
+ "pause",
17
+ "terminal-success",
18
+ "terminal-warn",
19
+ "launched-workflow",
20
+ ];
21
+ /**
22
+ * The color/shape key for one diagram: only the node kinds that actually appear
23
+ * (in stable order), plus a cross-workflow row when the graph has cross edges.
24
+ * Returns "" when nothing is worth keying, so the panel omits the footer.
25
+ */
26
+ export function buildLegendHtml(nodeKinds, edgeKinds) {
27
+ const items = NODE_KIND_ORDER.filter((k) => nodeKinds.has(k)).map((k) => `<span class="canvas-legend-item"><span class="canvas-legend-marker canvas-legend-marker--${k}"></span>${NODE_KIND_LABEL[k]}</span>`);
28
+ if (edgeKinds.has("cross")) {
29
+ items.push(`<span class="canvas-legend-item"><span class="canvas-legend-marker canvas-legend-marker--cross"></span>cross-workflow signal/handoff</span>`);
30
+ }
31
+ if (items.length === 0)
32
+ return "";
33
+ return `<footer class="canvas-legend">${items.join("")}</footer>`;
34
+ }
35
+ /**
36
+ * Serializes the graph (enrichment merged) into the JSON payload the app's
37
+ * Steps tab / inspector consumes, embedded as a `<script id="sapiom-graph">`
38
+ * data block that `bootCanvasGraph` (canvas-run-state.ts) posts to the parent.
39
+ *
40
+ * The projection mirrors `renderGraphSvg`'s merge EXACTLY so the Steps tab and
41
+ * the drawn board never disagree: `role` = the node's sublabel (enrichment
42
+ * override first), `description` = the enrichment hover text, and each edge's
43
+ * `label` is keyed `from->to`. Web-only fields the server graph doesn't carry
44
+ * (timeout / input schema / capabilities) are omitted — `parseCanvasGraph`
45
+ * defaults them, so the drill-down degrades to names + roles + branch facts.
46
+ *
47
+ * `<` is escaped to `<` so a label containing `</script>` can't break out
48
+ * of the JSON block; the result is still valid JSON.
49
+ */
50
+ function buildGraphPayload(graph, enrichment) {
51
+ const payload = {
52
+ name: graph.manifestName,
53
+ entry: graph.entry,
54
+ nodes: graph.nodes.map((n) => {
55
+ const details = enrichment?.nodeDetails?.[n.id];
56
+ return {
57
+ id: n.id,
58
+ kind: n.kind,
59
+ label: n.label,
60
+ role: details?.sublabel ?? n.sublabel ?? "",
61
+ // Manifest-authored description (Option A) wins; enrichment is the
62
+ // legacy fallback (currently always undefined).
63
+ description: details?.description ?? n.description ?? "",
64
+ inputSchema: n.inputSchema ?? null,
65
+ capabilities: n.capabilities ?? [],
66
+ timeoutMs: n.timeoutMs ?? null,
67
+ };
68
+ }),
69
+ edges: graph.edges.map((e) => ({
70
+ from: e.from,
71
+ to: e.to,
72
+ kind: e.kind,
73
+ label: enrichment?.edgeLabels?.[`${e.from}->${e.to}`] ?? e.label ?? "",
74
+ })),
75
+ warnings: graph.warnings,
76
+ };
77
+ return JSON.stringify(payload).replace(/</g, "\\u003c");
78
+ }
79
+ /** The workflow-level overview the Canvas tab's bottom panel shows: a
80
+ * deterministic stats line ("N steps · M exits · <entry> entry"), the shape
81
+ * summary as the description, and the graph's validation notes. Embedded as a
82
+ * JSON data block (read by bootCanvasOverview), the same pattern as the step
83
+ * graph — everything here is derived from the graph, no LLM. */
84
+ function buildOverviewPayload(graph, enrichment) {
85
+ const exits = graph.nodes.filter((n) => n.kind === "terminal-success" || n.kind === "terminal-warn").length;
86
+ const steps = graph.nodes.length - exits;
87
+ const entryLabel = graph.nodes.find((n) => n.id === graph.entry)?.label ?? graph.entry;
88
+ const parts = [`${steps} ${steps === 1 ? "step" : "steps"}`];
89
+ if (exits > 0)
90
+ parts.push(`${exits} ${exits === 1 ? "exit" : "exits"}`);
91
+ if (entryLabel)
92
+ parts.push(`${entryLabel} entry`);
93
+ const overview = {
94
+ // Human-authored workflow description from the manifest (Option A); "" when
95
+ // the workflow declares none (the shape summary still renders on the board).
96
+ description: graph.description ?? "",
97
+ stats: parts.join(" · "),
98
+ notes: enrichment?.notes ?? [],
99
+ };
100
+ // JSON in a <script> block: neutralize any "</script>"/"<" in derived text.
101
+ return JSON.stringify(overview).replace(/</g, "\\u003c");
102
+ }
103
+ /** One workflow's full panel: title/badges + summary header and the SVG
104
+ * diagram, with the deterministic enrichment merged in (summary line and
105
+ * node/edge annotations), plus the embedded step-graph payload the Steps tab
106
+ * reads. */
107
+ export function buildWorkflowPanelHtml(graph, meta, enrichment) {
9
108
  const badges = (meta.badges ?? [])
10
109
  .map((b) => `<span class="canvas-badge">${esc(b)}</span>`)
11
110
  .join("");
12
111
  const warningBadge = graph.warnings.length > 0
13
112
  ? `<span class="canvas-badge">${graph.warnings.length} warning${graph.warnings.length === 1 ? "" : "s"}</span>`
14
113
  : "";
15
- const enrichment = panelEnrichment?.enrichment ?? null;
16
- const staleBadge = panelEnrichment?.stale
17
- ? `<span class="canvas-badge canvas-badge--stale">stale — Refresh</span>`
18
- : "";
19
114
  const summary = enrichment?.summary ? `\n <p class="canvas-subtitle">${esc(enrichment.summary)}</p>` : "";
115
+ const used = usedKinds(graph);
116
+ const legend = buildLegendHtml(used.nodeKinds, used.edgeKinds);
117
+ const legendHtml = legend ? `\n ${legend}` : "";
118
+ const graphData = buildGraphPayload(graph, enrichment);
119
+ const overviewData = buildOverviewPayload(graph, enrichment);
20
120
  return `<section class="canvas-panel">
21
121
  <header class="canvas-header">
22
122
  <div class="canvas-title-row">
23
123
  <h1 class="canvas-title">${esc(meta.title)}</h1>
24
- ${badges}${warningBadge}${staleBadge}
124
+ ${badges}${warningBadge}
25
125
  </div>${summary}
26
- <div class="canvas-stats">
27
- <div class="canvas-stat"><span class="canvas-stat-value">${graph.nodes.length}</span><span class="canvas-stat-label">steps</span></div>
28
- <div class="canvas-stat"><span class="canvas-stat-value">${esc(graph.entry)}</span><span class="canvas-stat-label">entry</span></div>
29
- </div>
30
126
  </header>
31
127
  <div class="canvas-diagram-panel">
32
128
  ${renderGraphSvg(graph, enrichment)}
33
- </div>
129
+ </div>${legendHtml}
130
+ <script type="application/json" id="sapiom-graph">${graphData}</script>
131
+ <script type="application/json" id="sapiom-overview">${overviewData}</script>
34
132
  </section>`;
35
133
  }
36
134
  /** A degraded panel for a workflow whose graph couldn't be extracted — never
@@ -49,46 +147,10 @@ export function buildErrorPanelHtml(title, reason) {
49
147
  </div>
50
148
  </section>`;
51
149
  }
52
- const NODE_KIND_LABEL = {
53
- entry: "entry / active step",
54
- step: "step",
55
- pause: "pause / waits for input",
56
- "terminal-success": "terminal · success",
57
- "terminal-warn": "terminal · escalation",
58
- "launched-workflow": "launches another workflow",
59
- };
60
- const NODE_KIND_ORDER = [
61
- "entry",
62
- "step",
63
- "pause",
64
- "terminal-success",
65
- "terminal-warn",
66
- "launched-workflow",
67
- ];
68
- /** Legend footer covering every node/edge kind actually used across every
69
- * rendered panel (aggregate, not per-panel — matches the template's shape). */
70
- export function buildLegendHtml(nodeKinds, edgeKinds) {
71
- const items = NODE_KIND_ORDER.filter((k) => nodeKinds.has(k)).map((k) => `<span class="canvas-legend-item"><span class="canvas-legend-marker canvas-legend-marker--${k}"></span>${NODE_KIND_LABEL[k]}</span>`);
72
- if (edgeKinds.has("cross")) {
73
- items.push(`<span class="canvas-legend-item"><span class="canvas-legend-marker canvas-legend-marker--cross"></span>cross-workflow signal/handoff</span>`);
74
- }
75
- return `<div class="canvas-legend">${items.join("")}</div>`;
76
- }
77
- /** Joins panels + a footer (enrichment notes/cross-workflow tie, legend,
78
- * note) into the final `#canvas-root` body — the string
79
- * `renderCanvasDocument()` wraps. */
150
+ /** Joins the workflow panel(s) into the final `#canvas-root` body — the string
151
+ * `renderCanvasDocument()` wraps. Each panel already carries its own legend
152
+ * footer (see `buildWorkflowPanelHtml`); there is no document-level footer. */
80
153
  export function assembleCanvasBody(input) {
81
- const parts = [...input.panels];
82
- const notesHtml = input.notes && input.notes.length > 0
83
- ? `\n <ul class="canvas-notes">${input.notes.map((n) => `<li>${esc(n)}</li>`).join("")}</ul>`
84
- : "";
85
- const crossHtml = input.crossWorkflow
86
- ? `\n <p class="canvas-cross-workflow">${esc(input.crossWorkflow)}</p>`
87
- : "";
88
- parts.push(`<footer class="canvas-footer">${notesHtml}${crossHtml}
89
- ${input.legend}
90
- <p class="canvas-note">${esc(input.note)}</p>
91
- </footer>`);
92
- return parts.join("\n\n");
154
+ return input.panels.join("\n\n");
93
155
  }
94
156
  //# sourceMappingURL=canvas-body.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"canvas-body.js","sourceRoot":"","sources":["../../src/core/canvas-body.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"canvas-body.js","sourceRoot":"","sources":["../../src/core/canvas-body.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Deterministic canvas enrichment (no LLM, no user token, no file reads, no
3
+ * cache). Given the already-extracted CanvasGraph (core/canvas-graph.ts), it
4
+ * computes the same CanvasEnrichment shape the old AI task returned
5
+ * (core/canvas-enrichment.ts) — a summary line, footer notes, and a
6
+ * cross-workflow tie — entirely from the graph's own structure. Pure and
7
+ * total: the same graph in always yields the same enrichment out, and every
8
+ * string is kept within ENRICHMENT_LIMITS so the layout can't break.
9
+ *
10
+ * What it deliberately does NOT reproduce from the retired AI pass: free-prose
11
+ * per-step descriptions and condition-named edge labels, which needed a reading
12
+ * of the step bodies. The base render already conveys role (node border +
13
+ * classify-derived sublabel) and outcome (edge color), so their absence
14
+ * degrades to "less prose", never "less structure".
15
+ */
16
+ import { type CanvasEnrichment } from "./canvas-enrichment.js";
17
+ import type { CanvasGraph } from "./canvas-graph.js";
18
+ /**
19
+ * A one-line description of the workflow's shape — step count, branch points,
20
+ * and terminal outcomes — the deterministic stand-in for the AI summary. Reads
21
+ * the same graph the diagram is drawn from, so it can never disagree with it.
22
+ */
23
+ export declare function deriveSummary(graph: CanvasGraph): string;
24
+ /**
25
+ * Footer notes: the graph's own validation warnings (unreachable steps, no path
26
+ * to a terminal) — facts worth surfacing that the diagram can't show on its own.
27
+ * Undefined when the graph is clean, capped to the contract's count/length.
28
+ */
29
+ export declare function deriveNotes(graph: CanvasGraph): string[] | undefined;
30
+ /**
31
+ * The cross-workflow tie, derived from the dashed launched-workflow nodes the
32
+ * extraction already merged in (core/canvas-graph.ts's mergeLaunchesIntoGraph,
33
+ * fed by the grep in core/canvas-interconnections.ts). Undefined when this
34
+ * workflow launches none.
35
+ */
36
+ export declare function deriveCrossWorkflow(graph: CanvasGraph): string | undefined;
37
+ /**
38
+ * Builds the deterministic enrichment for a graph. Only sets a field when it
39
+ * has real content, so an annotation-light but valid workflow renders its clean
40
+ * base — matching the "every field optional" contract the AI enrichment had.
41
+ */
42
+ export declare function deriveEnrichment(graph: CanvasGraph): CanvasEnrichment;
43
+ //# sourceMappingURL=canvas-derive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canvas-derive.d.ts","sourceRoot":"","sources":["../../src/core/canvas-derive.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAClF,OAAO,KAAK,EAAE,WAAW,EAA8B,MAAM,mBAAmB,CAAC;AAgBjF;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAuBxD;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,EAAE,GAAG,SAAS,CAMpE;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,CAK1E;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,gBAAgB,CAOrE"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Deterministic canvas enrichment (no LLM, no user token, no file reads, no
3
+ * cache). Given the already-extracted CanvasGraph (core/canvas-graph.ts), it
4
+ * computes the same CanvasEnrichment shape the old AI task returned
5
+ * (core/canvas-enrichment.ts) — a summary line, footer notes, and a
6
+ * cross-workflow tie — entirely from the graph's own structure. Pure and
7
+ * total: the same graph in always yields the same enrichment out, and every
8
+ * string is kept within ENRICHMENT_LIMITS so the layout can't break.
9
+ *
10
+ * What it deliberately does NOT reproduce from the retired AI pass: free-prose
11
+ * per-step descriptions and condition-named edge labels, which needed a reading
12
+ * of the step bodies. The base render already conveys role (node border +
13
+ * classify-derived sublabel) and outcome (edge color), so their absence
14
+ * degrades to "less prose", never "less structure".
15
+ */
16
+ import { ENRICHMENT_LIMITS } from "./canvas-enrichment.js";
17
+ /** Truncates to a hard cap with an ellipsis. The derivations below stay well
18
+ * under their caps; this just makes the same guarantee the contract does. */
19
+ function clamp(value, max) {
20
+ return value.length <= max ? value : `${value.slice(0, max - 1)}…`;
21
+ }
22
+ function countKind(nodes, kind) {
23
+ return nodes.filter((n) => n.kind === kind).length;
24
+ }
25
+ function plural(n, one, many = `${one}s`) {
26
+ return n === 1 ? one : many;
27
+ }
28
+ /**
29
+ * A one-line description of the workflow's shape — step count, branch points,
30
+ * and terminal outcomes — the deterministic stand-in for the AI summary. Reads
31
+ * the same graph the diagram is drawn from, so it can never disagree with it.
32
+ */
33
+ export function deriveSummary(graph) {
34
+ // Real steps only — exclude the dashed launched-workflow placeholders.
35
+ const stepCount = graph.nodes.filter((n) => n.kind !== "launched-workflow").length;
36
+ // A branch point is a step that fans out to multiple successors; the graph
37
+ // marks exactly those edges "branching" (core/canvas-graph.ts's edgesForStep).
38
+ const branchPoints = new Set(graph.edges.filter((e) => e.kind === "branching").map((e) => e.from)).size;
39
+ const success = countKind(graph.nodes, "terminal-success");
40
+ const warn = countKind(graph.nodes, "terminal-warn");
41
+ const parts = [`${stepCount} ${plural(stepCount, "step")}`];
42
+ if (branchPoints > 0)
43
+ parts.push(`${branchPoints} ${plural(branchPoints, "branch point")}`);
44
+ const outcomes = [];
45
+ if (success > 0)
46
+ outcomes.push(`${success} success`);
47
+ if (warn > 0)
48
+ outcomes.push(`${warn} escalation`);
49
+ if (outcomes.length > 0) {
50
+ parts.push(`${outcomes.join(" / ")} ${plural(success + warn, "outcome")}`);
51
+ }
52
+ return clamp(parts.join(" · "), ENRICHMENT_LIMITS.summary);
53
+ }
54
+ /**
55
+ * Footer notes: the graph's own validation warnings (unreachable steps, no path
56
+ * to a terminal) — facts worth surfacing that the diagram can't show on its own.
57
+ * Undefined when the graph is clean, capped to the contract's count/length.
58
+ */
59
+ export function deriveNotes(graph) {
60
+ if (graph.warnings.length === 0)
61
+ return undefined;
62
+ const notes = graph.warnings
63
+ .slice(0, ENRICHMENT_LIMITS.noteCount)
64
+ .map((w) => clamp(w, ENRICHMENT_LIMITS.note));
65
+ return notes.length > 0 ? notes : undefined;
66
+ }
67
+ /**
68
+ * The cross-workflow tie, derived from the dashed launched-workflow nodes the
69
+ * extraction already merged in (core/canvas-graph.ts's mergeLaunchesIntoGraph,
70
+ * fed by the grep in core/canvas-interconnections.ts). Undefined when this
71
+ * workflow launches none.
72
+ */
73
+ export function deriveCrossWorkflow(graph) {
74
+ const launched = graph.nodes.filter((n) => n.kind === "launched-workflow").map((n) => n.label);
75
+ if (launched.length === 0)
76
+ return undefined;
77
+ const unique = [...new Set(launched)].sort();
78
+ return clamp(`Launches ${unique.join(", ")}.`, ENRICHMENT_LIMITS.crossWorkflow);
79
+ }
80
+ /**
81
+ * Builds the deterministic enrichment for a graph. Only sets a field when it
82
+ * has real content, so an annotation-light but valid workflow renders its clean
83
+ * base — matching the "every field optional" contract the AI enrichment had.
84
+ */
85
+ export function deriveEnrichment(graph) {
86
+ const enrichment = { summary: deriveSummary(graph) };
87
+ const notes = deriveNotes(graph);
88
+ if (notes)
89
+ enrichment.notes = notes;
90
+ const crossWorkflow = deriveCrossWorkflow(graph);
91
+ if (crossWorkflow)
92
+ enrichment.crossWorkflow = crossWorkflow;
93
+ return enrichment;
94
+ }
95
+ //# sourceMappingURL=canvas-derive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canvas-derive.js","sourceRoot":"","sources":["../../src/core/canvas-derive.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,23 @@
1
- import { z } from "zod";
2
- import type { CanvasGraph } from "./canvas-graph.js";
1
+ /**
2
+ * The canvas enrichment contract: the optional annotation layer merged on top
3
+ * of a deterministic canvas render — a summary line, per-node sublabels/hover
4
+ * descriptions, edge labels, footer notes, layout hints, and a cross-workflow
5
+ * tie. Every value is a BOUNDED plain string (the limits below are hard caps
6
+ * that keep the SVG layout from breaking); the renderer (core/canvas-svg.ts,
7
+ * core/canvas-body.ts) decides where each field goes.
8
+ *
9
+ * The enrichment is produced DETERMINISTICALLY, in-process, from the extracted
10
+ * graph — see core/canvas-derive.ts. There is no LLM, no user token, no file
11
+ * write, and no cache: it is recomputed from the current sources on every
12
+ * render, so it can never go stale. This module is now just the shared shape +
13
+ * limits both the producer (canvas-derive.ts) and the consumer (canvas-svg.ts,
14
+ * canvas-body.ts) agree on.
15
+ *
16
+ * Layout hints are the one structural field: named groups (rendered as subtle
17
+ * background bands) and per-layer ordering. The renderer applies a hint only
18
+ * when every node id it references actually exists in the graph (see
19
+ * canvas-svg.ts) — ids are validated at render time.
20
+ */
3
21
  export declare const ENRICHMENT_LIMITS: {
4
22
  readonly summary: 160;
5
23
  readonly sublabel: 48;
@@ -10,135 +28,42 @@ export declare const ENRICHMENT_LIMITS: {
10
28
  readonly groupLabel: 48;
11
29
  readonly crossWorkflow: 160;
12
30
  };
13
- export declare const canvasEnrichmentSchema: z.ZodObject<{
31
+ /** Per-node annotations, keyed by node id. */
32
+ export interface CanvasNodeDetail {
33
+ /** Second text line inside the node box. */
34
+ sublabel?: string;
35
+ /** Hover tooltip (SVG <title>) — room for a full sentence. */
36
+ description?: string;
37
+ }
38
+ /**
39
+ * The one structural hint set: named clusters rendered as background bands
40
+ * behind their member nodes, and a preferred left-to-right node order per
41
+ * layout layer (keyed by the layer index as a string). `laneOrder` reorders
42
+ * WITHIN a computed layer only — it can never move a node between layers.
43
+ */
44
+ export interface CanvasLayoutHints {
45
+ groups?: Array<{
46
+ label: string;
47
+ nodeIds: string[];
48
+ }>;
49
+ laneOrder?: Record<string, string[]>;
50
+ }
51
+ /**
52
+ * Everything the enrichment layer can add to a deterministic render. Every
53
+ * field is optional — the base structure render stands on its own without any
54
+ * of it, so a workflow with nothing worth annotating simply renders clean.
55
+ */
56
+ export interface CanvasEnrichment {
14
57
  /** One-liner under the panel header. */
15
- summary: z.ZodOptional<z.ZodString>;
58
+ summary?: string;
16
59
  /** Per-node annotations, keyed by node id. */
17
- nodeDetails: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
18
- /** Second text line inside the node box. */
19
- sublabel: z.ZodOptional<z.ZodString>;
20
- /** Hover tooltip (SVG <title>) — room for a full sentence. */
21
- description: z.ZodOptional<z.ZodString>;
22
- }, "strip", z.ZodTypeAny, {
23
- description?: string | undefined;
24
- sublabel?: string | undefined;
25
- }, {
26
- description?: string | undefined;
27
- sublabel?: string | undefined;
28
- }>>>;
60
+ nodeDetails?: Record<string, CanvasNodeDetail>;
29
61
  /** Edge annotations (intent/condition names), keyed `"<from>-><to>"`. */
30
- edgeLabels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
62
+ edgeLabels?: Record<string, string>;
31
63
  /** Footer facts worth knowing that don't fit the diagram itself. */
32
- notes: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
33
- layoutHints: z.ZodOptional<z.ZodObject<{
34
- /** Named clusters rendered as background bands behind member nodes. */
35
- groups: z.ZodOptional<z.ZodArray<z.ZodObject<{
36
- label: z.ZodString;
37
- nodeIds: z.ZodArray<z.ZodString, "many">;
38
- }, "strip", z.ZodTypeAny, {
39
- label: string;
40
- nodeIds: string[];
41
- }, {
42
- label: string;
43
- nodeIds: string[];
44
- }>, "many">>;
45
- /** Preferred left-to-right node order per layout layer, keyed by the
46
- * layer index as a string. Reorders WITHIN the computed layer only —
47
- * it can never move a node between layers. */
48
- laneOrder: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString, "many">>>;
49
- }, "strip", z.ZodTypeAny, {
50
- groups?: {
51
- label: string;
52
- nodeIds: string[];
53
- }[] | undefined;
54
- laneOrder?: Record<string, string[]> | undefined;
55
- }, {
56
- groups?: {
57
- label: string;
58
- nodeIds: string[];
59
- }[] | undefined;
60
- laneOrder?: Record<string, string[]> | undefined;
61
- }>>;
64
+ notes?: string[];
65
+ layoutHints?: CanvasLayoutHints;
62
66
  /** How this workflow ties into the workspace's other workflows. */
63
- crossWorkflow: z.ZodOptional<z.ZodString>;
64
- }, "strip", z.ZodTypeAny, {
65
- summary?: string | undefined;
66
- nodeDetails?: Record<string, {
67
- description?: string | undefined;
68
- sublabel?: string | undefined;
69
- }> | undefined;
70
- edgeLabels?: Record<string, string> | undefined;
71
- notes?: string[] | undefined;
72
- layoutHints?: {
73
- groups?: {
74
- label: string;
75
- nodeIds: string[];
76
- }[] | undefined;
77
- laneOrder?: Record<string, string[]> | undefined;
78
- } | undefined;
79
- crossWorkflow?: string | undefined;
80
- }, {
81
- summary?: string | undefined;
82
- nodeDetails?: Record<string, {
83
- description?: string | undefined;
84
- sublabel?: string | undefined;
85
- }> | undefined;
86
- edgeLabels?: Record<string, string> | undefined;
87
- notes?: string[] | undefined;
88
- layoutHints?: {
89
- groups?: {
90
- label: string;
91
- nodeIds: string[];
92
- }[] | undefined;
93
- laneOrder?: Record<string, string[]> | undefined;
94
- } | undefined;
95
- crossWorkflow?: string | undefined;
96
- }>;
97
- export type CanvasEnrichment = z.infer<typeof canvasEnrichmentSchema>;
98
- export type CanvasLayoutHints = NonNullable<CanvasEnrichment["layoutHints"]>;
99
- /**
100
- * Validates a candidate enrichment object. Returns null on ANY schema
101
- * violation (oversize string, wrong shape, too many notes) — partial
102
- * salvage is deliberately not attempted, so the contract stays a hard line
103
- * the prompt can state truthfully: "invalid output is thrown away whole."
104
- */
105
- export declare function parseCanvasEnrichment(value: unknown): CanvasEnrichment | null;
106
- /**
107
- * Deterministic repair of the two ways an otherwise-good answer most often
108
- * misses the contract, applied BEFORE strict validation:
109
- * - `null` where the schema means "omit the field"
110
- * - strings a few words over their cap (measured live: sonnet writes
111
- * excellent content but doesn't count characters — a single 160-char note
112
- * against the 140 cap discarded 3 of 4 real enrichments whole), truncated
113
- * to the cap with an ellipsis; extra notes beyond the count cap dropped
114
- *
115
- * The bound the caps exist for — the AI can never blow up the layout with
116
- * unbounded text — is still enforced, just deterministically here instead
117
- * of by rejection. Everything else (wrong shapes, wrong types, unknown
118
- * structure) still fails `parseCanvasEnrichment` and discards the
119
- * enrichment whole.
120
- */
121
- export declare function normalizeCanvasEnrichmentCandidate(value: unknown): unknown;
122
- /**
123
- * What one cache file holds. `sourceFingerprint` is canvas-cache.ts's cheap
124
- * source fingerprint at the moment the enrichment task was SPAWNED — when it
125
- * no longer matches the workflow's current sources, the base diagram
126
- * re-renders immediately from fresh extraction while this enrichment stays
127
- * displayed with a "stale" chip until a re-run replaces it.
128
- */
129
- export interface EnrichmentCacheEntry {
130
- /** The graph the enrichment was generated against (diagnostic context —
131
- * renders always use the freshly extracted graph, never this copy). */
132
- graph: CanvasGraph;
133
- enrichment: CanvasEnrichment;
134
- sourceFingerprint: string;
135
- enrichedAt: string;
67
+ crossWorkflow?: string;
136
68
  }
137
- /** Reads + validates one enrichment cache file. Null for missing, unparsable
138
- * or schema-invalid content — a bad cache degrades to "no enrichment". */
139
- export declare function readEnrichmentCacheFile(filePath: string): Promise<EnrichmentCacheEntry | null>;
140
- export declare function writeEnrichmentCacheFile(filePath: string, entry: EnrichmentCacheEntry): Promise<void>;
141
- /** Deletes one enrichment cache file (the visualize macro's force refresh).
142
- * Missing file is fine — the goal state is "no cache". */
143
- export declare function removeEnrichmentCacheFile(filePath: string): Promise<void>;
144
69
  //# sourceMappingURL=canvas-enrichment.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"canvas-enrichment.d.ts","sourceRoot":"","sources":["../../src/core/canvas-enrichment.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,eAAO,MAAM,iBAAiB;;;;;;;;;CASpB,CAAC;AAIX,eAAO,MAAM,sBAAsB;IAE/B,wCAAwC;;IAExC,8CAA8C;;QAKtC,4CAA4C;;QAE5C,8DAA8D;;;;;;;;;IAMtE,yEAAyE;;IAEzE,oEAAoE;;;QAIhE,uEAAuE;;;;;;;;;;;QAWvE;;uDAE+C;;;;;;;;;;;;;;;IAKnD,mEAAmE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAG7D,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AACtE,MAAM,MAAM,iBAAiB,GAAG,WAAW,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC,CAAC;AAE7E;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,GAAG,IAAI,CAG7E;AAkBD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kCAAkC,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CA6C1E;AAMD;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACnC;4EACwE;IACxE,KAAK,EAAE,WAAW,CAAC;IACnB,UAAU,EAAE,gBAAgB,CAAC;IAC7B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;CACpB;AAmBD;2EAC2E;AAC3E,wBAAsB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAepG;AAED,wBAAsB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAG3G;AAED;2DAC2D;AAC3D,wBAAsB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/E"}
1
+ {"version":3,"file":"canvas-enrichment.d.ts","sourceRoot":"","sources":["../../src/core/canvas-enrichment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,eAAO,MAAM,iBAAiB;;;;;;;;;CASpB,CAAC;AAEX,8CAA8C;AAC9C,MAAM,WAAW,gBAAgB;IAC/B,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CACtC;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAC/C,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,mEAAmE;IACnE,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB"}